summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.bzrignore49
-rw-r--r--BUILD/FINISH.sh2
-rw-r--r--BUILD/SETUP.sh1
-rwxr-xr-xBUILD/compile-ppc10
-rwxr-xr-xBUILD/compile-ppc-debug13
-rwxr-xr-xBUILD/compile-ppc-debug-max13
-rwxr-xr-xBUILD/compile-ppc-max13
-rw-r--r--BitKeeper/etc/logging_ok7
-rwxr-xr-xBuild-tools/Bootstrap4
-rwxr-xr-xBuild-tools/Do-compile17
-rw-r--r--Docs/Images/Makefile.am35
-rw-r--r--Docs/Makefile.am4
-rwxr-xr-xDocs/Support/texi2html98
-rw-r--r--Docs/mysqld_error.txt4
-rw-r--r--Makefile.am8
-rw-r--r--VC++Files/client/mysqladmin.dsp2
-rw-r--r--VC++Files/client/mysqltest.dsp125
-rw-r--r--VC++Files/libmysqld/libmysqld.dsp4
-rw-r--r--VC++Files/mysql-test/mysql_test_run_new.dsp106
-rw-r--r--VC++Files/mysql.dsw24
-rw-r--r--VC++Files/sql/mysqld.dsp4
-rw-r--r--acinclude.m41874
-rw-r--r--client/Makefile.am1
-rw-r--r--client/client_priv.h5
-rw-r--r--client/mysql.cc6
-rw-r--r--client/mysqladmin.cc (renamed from client/mysqladmin.c)68
-rw-r--r--client/mysqlbinlog.cc37
-rw-r--r--client/mysqlcheck.c5
-rw-r--r--client/mysqldump.c585
-rw-r--r--client/mysqltest.c91
-rw-r--r--config/ac-macros/alloca.m468
-rw-r--r--config/ac-macros/character_sets.m4389
-rw-r--r--config/ac-macros/check_cpu.m447
-rw-r--r--config/ac-macros/compiler_flag.m440
-rw-r--r--config/ac-macros/ha_archive.m429
-rw-r--r--config/ac-macros/ha_berkeley.m4267
-rw-r--r--config/ac-macros/ha_example.m430
-rw-r--r--config/ac-macros/ha_innodb.m477
-rw-r--r--config/ac-macros/ha_isam.m415
-rw-r--r--config/ac-macros/ha_ndbcluster.m4144
-rw-r--r--config/ac-macros/ha_tina.m429
-rw-r--r--config/ac-macros/large_file.m4140
-rw-r--r--config/ac-macros/misc.m4647
-rw-r--r--config/ac-macros/mysqlfs.m451
-rw-r--r--config/ac-macros/openssl.m4136
-rw-r--r--config/ac-macros/readline.m461
-rw-r--r--config/ac-macros/zlib.m4105
-rw-r--r--configure.in527
-rw-r--r--dbug/Makefile.am63
-rw-r--r--dbug/dbug.c92
-rw-r--r--dbug/dbug_analyze.c6
-rw-r--r--dbug/dbug_long.h1
-rw-r--r--dbug/example1.c3
-rw-r--r--dbug/example2.c3
-rw-r--r--dbug/example3.c3
-rw-r--r--dbug/main.c39
-rw-r--r--dbug/monty.doc2
-rw-r--r--dbug/my_main.c39
-rw-r--r--dbug/user.r250
-rw-r--r--extra/Makefile.am1
-rw-r--r--extra/charset2html.c (renamed from mysys/charset2html.c)0
-rw-r--r--extra/perror.c2
-rw-r--r--heap/_check.c23
-rw-r--r--heap/heapdef.h4
-rw-r--r--heap/hp_block.c51
-rw-r--r--heap/hp_clear.c1
-rw-r--r--heap/hp_create.c24
-rw-r--r--heap/hp_delete.c14
-rw-r--r--heap/hp_hash.c205
-rw-r--r--heap/hp_rfirst.c1
-rw-r--r--heap/hp_rkey.c2
-rw-r--r--heap/hp_update.c4
-rw-r--r--heap/hp_write.c102
-rw-r--r--include/config-win.h5
-rw-r--r--include/decimal.h10
-rw-r--r--include/heap.h51
-rw-r--r--include/m_ctype.h8
-rw-r--r--include/my_base.h10
-rw-r--r--include/my_dbug.h7
-rw-r--r--include/my_global.h10
-rw-r--r--include/my_handler.h7
-rw-r--r--include/my_list.h4
-rw-r--r--include/my_pthread.h35
-rw-r--r--include/my_sys.h31
-rw-r--r--include/my_time.h5
-rw-r--r--include/mysql.h19
-rw-r--r--include/mysql_com.h8
-rw-r--r--include/mysql_time.h12
-rw-r--r--include/mysqld_error.h30
-rw-r--r--innobase/btr/btr0btr.c479
-rw-r--r--innobase/btr/btr0cur.c546
-rw-r--r--innobase/btr/btr0pcur.c52
-rw-r--r--innobase/btr/btr0sea.c166
-rw-r--r--innobase/buf/buf0buf.c30
-rw-r--r--innobase/buf/buf0flu.c7
-rw-r--r--innobase/buf/buf0lru.c42
-rw-r--r--innobase/buf/buf0rea.c7
-rw-r--r--innobase/configure.in7
-rw-r--r--innobase/data/data0data.c9
-rw-r--r--innobase/data/data0type.c2
-rw-r--r--innobase/dict/dict0boot.c18
-rw-r--r--innobase/dict/dict0crea.c35
-rw-r--r--innobase/dict/dict0dict.c162
-rw-r--r--innobase/dict/dict0load.c192
-rw-r--r--innobase/dict/dict0mem.c9
-rw-r--r--innobase/eval/eval0eval.c18
-rw-r--r--innobase/fil/fil0fil.c57
-rw-r--r--innobase/fsp/fsp0fsp.c2
-rw-r--r--innobase/ibuf/ibuf0ibuf.c420
-rw-r--r--innobase/include/btr0btr.h22
-rw-r--r--innobase/include/btr0btr.ic9
-rw-r--r--innobase/include/btr0cur.h60
-rw-r--r--innobase/include/btr0cur.ic4
-rw-r--r--innobase/include/btr0pcur.h1
-rw-r--r--innobase/include/btr0sea.h13
-rw-r--r--innobase/include/buf0buf.h8
-rw-r--r--innobase/include/buf0flu.ic2
-rw-r--r--innobase/include/buf0lru.h10
-rw-r--r--innobase/include/data0type.ic71
-rw-r--r--innobase/include/db0err.h6
-rw-r--r--innobase/include/dict0dict.h13
-rw-r--r--innobase/include/dict0dict.ic22
-rw-r--r--innobase/include/dict0mem.h12
-rw-r--r--innobase/include/fil0fil.h4
-rw-r--r--innobase/include/lock0lock.h41
-rw-r--r--innobase/include/lock0lock.ic5
-rw-r--r--innobase/include/mtr0log.h33
-rw-r--r--innobase/include/mtr0mtr.h26
-rw-r--r--innobase/include/os0file.h3
-rw-r--r--innobase/include/page0cur.h57
-rw-r--r--innobase/include/page0cur.ic19
-rw-r--r--innobase/include/page0page.h211
-rw-r--r--innobase/include/page0page.ic133
-rw-r--r--innobase/include/rem0cmp.h32
-rw-r--r--innobase/include/rem0cmp.ic6
-rw-r--r--innobase/include/rem0rec.h435
-rw-r--r--innobase/include/rem0rec.ic899
-rw-r--r--innobase/include/row0mysql.h27
-rw-r--r--innobase/include/row0row.h30
-rw-r--r--innobase/include/row0row.ic49
-rw-r--r--innobase/include/row0sel.h1
-rw-r--r--innobase/include/row0upd.h17
-rw-r--r--innobase/include/row0upd.ic6
-rw-r--r--innobase/include/row0vers.h3
-rw-r--r--innobase/include/row0vers.ic70
-rw-r--r--innobase/include/srv0srv.h108
-rw-r--r--innobase/include/trx0rec.h1
-rw-r--r--innobase/include/trx0roll.h9
-rw-r--r--innobase/include/trx0trx.h43
-rw-r--r--innobase/include/trx0undo.h52
-rw-r--r--innobase/include/trx0xa.h182
-rw-r--r--innobase/include/ut0byte.h15
-rw-r--r--innobase/include/ut0byte.ic21
-rw-r--r--innobase/include/ut0mem.h4
-rw-r--r--innobase/lock/lock0lock.c473
-rw-r--r--innobase/log/log0log.c17
-rw-r--r--innobase/log/log0recv.c197
-rw-r--r--innobase/mem/mem0pool.c2
-rw-r--r--innobase/mtr/mtr0log.c157
-rw-r--r--innobase/os/os0file.c58
-rw-r--r--innobase/page/page0cur.c408
-rw-r--r--innobase/page/page0page.c520
-rw-r--r--innobase/pars/pars0pars.c15
-rw-r--r--innobase/rem/rem0cmp.c127
-rw-r--r--innobase/rem/rem0rec.c1063
-rw-r--r--innobase/row/row0ins.c231
-rw-r--r--innobase/row/row0mysql.c98
-rw-r--r--innobase/row/row0purge.c12
-rw-r--r--innobase/row/row0row.c103
-rw-r--r--innobase/row/row0sel.c425
-rw-r--r--innobase/row/row0umod.c6
-rw-r--r--innobase/row/row0undo.c9
-rw-r--r--innobase/row/row0upd.c128
-rw-r--r--innobase/row/row0vers.c106
-rw-r--r--innobase/srv/srv0srv.c145
-rw-r--r--innobase/srv/srv0start.c3
-rw-r--r--innobase/trx/trx0purge.c47
-rw-r--r--innobase/trx/trx0rec.c104
-rw-r--r--innobase/trx/trx0roll.c24
-rw-r--r--innobase/trx/trx0sys.c6
-rw-r--r--innobase/trx/trx0trx.c273
-rw-r--r--innobase/trx/trx0undo.c210
-rw-r--r--innobase/ut/ut0mem.c20
-rw-r--r--innobase/ut/ut0ut.c7
-rw-r--r--isam/.cvsignore10
-rw-r--r--isam/ChangeLog186
-rw-r--r--isam/Makefile.am45
-rw-r--r--isam/_cache.c92
-rw-r--r--isam/_dbug.c132
-rw-r--r--isam/_dynrec.c1247
-rw-r--r--isam/_key.c238
-rw-r--r--isam/_locking.c345
-rw-r--r--isam/_packrec.c1184
-rw-r--r--isam/_page.c143
-rw-r--r--isam/_search.c889
-rw-r--r--isam/_statrec.c265
-rw-r--r--isam/changed.c35
-rw-r--r--isam/close.c92
-rw-r--r--isam/create.c328
-rw-r--r--isam/delete.c615
-rw-r--r--isam/extra.c271
-rw-r--r--isam/info.c77
-rw-r--r--isam/isamchk.c3424
-rw-r--r--isam/isamdef.h418
-rw-r--r--isam/isamlog.c853
-rw-r--r--isam/log.c156
-rwxr-xr-xisam/make-ccc3
-rw-r--r--isam/open.c477
-rw-r--r--isam/pack_isam.c2042
-rw-r--r--isam/panic.c135
-rw-r--r--isam/range.c191
-rw-r--r--isam/rfirst.c34
-rw-r--r--isam/rkey.c63
-rw-r--r--isam/rlast.c34
-rw-r--r--isam/rnext.c67
-rw-r--r--isam/rprev.c64
-rw-r--r--isam/rrnd.c55
-rw-r--r--isam/rsame.c70
-rw-r--r--isam/rsamepos.c59
-rw-r--r--isam/sort.c558
-rw-r--r--isam/static.c45
-rw-r--r--isam/test1.c179
-rw-r--r--isam/test2.c841
-rw-r--r--isam/test3.c494
-rwxr-xr-xisam/test_all30
-rw-r--r--isam/test_all.res30
-rw-r--r--isam/update.c117
-rw-r--r--isam/write.c840
-rw-r--r--libmysql/Makefile.am2
-rw-r--r--libmysql/libmysql.c35
-rw-r--r--libmysql/libmysql.def1
-rw-r--r--libmysqld/Makefile.am13
-rw-r--r--libmysqld/lib_sql.cc2
-rw-r--r--myisam/ft_boolean_search.c26
-rw-r--r--myisam/ft_static.c2
-rw-r--r--myisam/ft_test1.c2
-rw-r--r--myisam/ft_update.c2
-rw-r--r--myisam/mi_check.c15
-rw-r--r--myisam/mi_create.c25
-rw-r--r--myisam/mi_key.c13
-rw-r--r--myisam/mi_packrec.c66
-rw-r--r--myisam/mi_range.c14
-rw-r--r--myisam/mi_rnext_same.c8
-rw-r--r--myisam/mi_search.c10
-rw-r--r--myisam/mi_test1.c8
-rw-r--r--myisam/mi_test3.c4
-rw-r--r--myisam/mi_unique.c53
-rw-r--r--myisam/mi_write.c19
-rw-r--r--myisam/myisamchk.c10
-rw-r--r--myisam/myisampack.c3
-rw-r--r--mysql-test/Makefile.am8
-rw-r--r--mysql-test/include/ctype_common.inc56
-rw-r--r--mysql-test/include/endspace.inc7
-rw-r--r--mysql-test/include/ps_modify.inc5
-rw-r--r--mysql-test/include/varchar.inc162
-rw-r--r--mysql-test/init_db.sql58
-rw-r--r--mysql-test/my_manage.c877
-rw-r--r--mysql-test/my_manage.h133
-rw-r--r--mysql-test/mysql-test-run.sh28
-rw-r--r--mysql-test/mysql_test_run_new.c1769
-rw-r--r--mysql-test/ndb/Makefile.am2
-rw-r--r--mysql-test/ndb/ndbcluster.sh89
-rw-r--r--mysql-test/r/alter_table.result10
-rw-r--r--mysql-test/r/analyse.result36
-rw-r--r--mysql-test/r/ansi.result2
-rw-r--r--mysql-test/r/archive.result1211
-rw-r--r--mysql-test/r/bdb.result394
-rw-r--r--mysql-test/r/binary.result7
-rw-r--r--mysql-test/r/bool.result18
-rw-r--r--mysql-test/r/case.result20
-rw-r--r--mysql-test/r/cast.result26
-rw-r--r--mysql-test/r/consistent_snapshot.result15
-rw-r--r--mysql-test/r/count_distinct.result7
-rw-r--r--mysql-test/r/create.result8
-rw-r--r--mysql-test/r/ctype_big5.result56
-rw-r--r--mysql-test/r/ctype_big5.result.es58
-rw-r--r--mysql-test/r/ctype_latin1.result9
-rw-r--r--mysql-test/r/ctype_mb.result8
-rw-r--r--mysql-test/r/ctype_recoding.result66
-rw-r--r--mysql-test/r/ctype_recoding.result.es242
-rw-r--r--mysql-test/r/ctype_sjis.result11
-rw-r--r--mysql-test/r/ctype_tis620.result106
-rw-r--r--mysql-test/r/ctype_uca.result60
-rw-r--r--mysql-test/r/ctype_uca.result.es2377
-rw-r--r--mysql-test/r/ctype_ucs.result73
-rw-r--r--mysql-test/r/ctype_ujis.result40
-rw-r--r--mysql-test/r/ctype_utf8.result9
-rw-r--r--mysql-test/r/delete.result30
-rw-r--r--mysql-test/r/drop_temp_table.result8
-rw-r--r--mysql-test/r/endspace.result40
-rw-r--r--mysql-test/r/flush_block_commit.result8
-rw-r--r--mysql-test/r/flush_read_lock_kill.result9
-rw-r--r--mysql-test/r/fulltext.result32
-rw-r--r--mysql-test/r/fulltext_order_by.result54
-rw-r--r--mysql-test/r/func_compress.result4
-rw-r--r--mysql-test/r/func_gconcat.result7
-rw-r--r--mysql-test/r/func_group.result16
-rw-r--r--mysql-test/r/func_in.result6
-rw-r--r--mysql-test/r/func_like.result4
-rw-r--r--mysql-test/r/func_str.result65
-rw-r--r--mysql-test/r/func_system.result8
-rw-r--r--mysql-test/r/func_test.result.es185
-rw-r--r--mysql-test/r/func_time.result6
-rw-r--r--mysql-test/r/gis.result74
-rw-r--r--mysql-test/r/grant.result71
-rw-r--r--mysql-test/r/grant2.result162
-rw-r--r--mysql-test/r/group_min_max.result2
-rw-r--r--mysql-test/r/have_moscow_leap_timezone.require2
-rw-r--r--mysql-test/r/have_openssl_1.require2
-rw-r--r--mysql-test/r/having.result202
-rw-r--r--mysql-test/r/heap.result442
-rw-r--r--mysql-test/r/heap_hash.result160
-rw-r--r--mysql-test/r/index_merge_ror_cpk.result2
-rw-r--r--mysql-test/r/information_schema.result536
-rw-r--r--mysql-test/r/information_schema_inno.result19
-rw-r--r--mysql-test/r/innodb.result44
-rw-r--r--mysql-test/r/innodb.result.es1653
-rw-r--r--mysql-test/r/insert_select.result9
-rw-r--r--mysql-test/r/join_outer.result65
-rw-r--r--mysql-test/r/key.result18
-rw-r--r--mysql-test/r/key_cache.result10
-rw-r--r--mysql-test/r/lock_multi.result2
-rw-r--r--mysql-test/r/lowercase_table2.result80
-rw-r--r--mysql-test/r/lowercase_table3.result2
-rw-r--r--mysql-test/r/lowercase_view.result16
-rw-r--r--mysql-test/r/merge.result8
-rw-r--r--mysql-test/r/metadata.result4
-rw-r--r--mysql-test/r/mix_innodb_myisam_binlog.result21
-rw-r--r--mysql-test/r/multi_update.result23
-rw-r--r--mysql-test/r/myisam-blob.result.es59
-rw-r--r--mysql-test/r/myisam.result411
-rw-r--r--mysql-test/r/mysqldump.result44
-rw-r--r--mysql-test/r/mysqltest.result131
-rw-r--r--mysql-test/r/ndb_alter_table.result8
-rw-r--r--mysql-test/r/ndb_autodiscover.result7
-rw-r--r--mysql-test/r/ndb_autodiscover2.result3
-rw-r--r--mysql-test/r/ndb_basic.result159
-rw-r--r--mysql-test/r/ndb_blob.result276
-rw-r--r--mysql-test/r/ndb_charset.result14
-rw-r--r--mysql-test/r/ndb_grant.result444
-rw-r--r--mysql-test/r/ndb_index_ordered.result37
-rw-r--r--mysql-test/r/ndb_index_unique.result98
-rw-r--r--mysql-test/r/ndb_insert.result74
-rw-r--r--mysql-test/r/null.result94
-rw-r--r--mysql-test/r/openssl_1.result6
-rw-r--r--mysql-test/r/order_by.result21
-rw-r--r--mysql-test/r/ps.result36
-rw-r--r--mysql-test/r/ps_10nestset.result11
-rw-r--r--mysql-test/r/ps_1general.result46
-rw-r--r--mysql-test/r/ps_2myisam.result540
-rw-r--r--mysql-test/r/ps_2myisam.result.es3130
-rw-r--r--mysql-test/r/ps_3innodb.result534
-rw-r--r--mysql-test/r/ps_3innodb.result.es3113
-rw-r--r--mysql-test/r/ps_4heap.result546
-rw-r--r--mysql-test/r/ps_4heap.result.es3114
-rw-r--r--mysql-test/r/ps_5merge.result1066
-rw-r--r--mysql-test/r/ps_5merge.result.es6064
-rw-r--r--mysql-test/r/ps_6bdb.result540
-rw-r--r--mysql-test/r/ps_6bdb.result.es3113
-rw-r--r--mysql-test/r/ps_7ndb.result334
-rw-r--r--mysql-test/r/query_cache.result.es15
-rw-r--r--mysql-test/r/range.result27
-rw-r--r--mysql-test/r/rpl_auto_increment.result3
-rw-r--r--mysql-test/r/rpl_charset.result24
-rw-r--r--mysql-test/r/rpl_create_database.result83
-rw-r--r--mysql-test/r/rpl_failed_optimize.result15
-rw-r--r--mysql-test/r/rpl_loaddata_rule_m.result2
-rw-r--r--mysql-test/r/rpl_rewrite_db.result92
-rw-r--r--mysql-test/r/rpl_rotate_logs.result2
-rw-r--r--mysql-test/r/rpl_start_stop_slave.result12
-rw-r--r--mysql-test/r/rpl_timezone.result2
-rw-r--r--mysql-test/r/select.result63
-rw-r--r--mysql-test/r/select.result.es39
-rw-r--r--mysql-test/r/select_found.result2
-rw-r--r--mysql-test/r/show_check.result2
-rw-r--r--mysql-test/r/sp-error.result13
-rw-r--r--mysql-test/r/sp-security.result4
-rw-r--r--mysql-test/r/sp.result12
-rw-r--r--mysql-test/r/sql_mode.result32
-rw-r--r--mysql-test/r/strict.result31
-rw-r--r--mysql-test/r/subselect.result53
-rw-r--r--mysql-test/r/subselect_innodb.result26
-rw-r--r--mysql-test/r/system_mysql_db.result6
-rw-r--r--mysql-test/r/timezone3.result41
-rw-r--r--mysql-test/r/trigger.result16
-rw-r--r--mysql-test/r/type_blob.result45
-rw-r--r--mysql-test/r/type_blob.result.es4
-rw-r--r--mysql-test/r/type_datetime.result11
-rw-r--r--mysql-test/r/type_enum.result44
-rw-r--r--mysql-test/r/type_float.result4
-rw-r--r--mysql-test/r/type_float.result.es6
-rw-r--r--mysql-test/r/type_ranges.result44
-rw-r--r--mysql-test/r/type_ranges.result.es8
-rw-r--r--mysql-test/r/type_varchar.result51
-rw-r--r--mysql-test/r/union.result28
-rw-r--r--mysql-test/r/user_var.result17
-rw-r--r--mysql-test/r/view.result217
-rw-r--r--mysql-test/std_data/Moscow_leapbin0 -> 991 bytes
-rw-r--r--mysql-test/std_data/vchar.frmbin0 -> 8616 bytes
-rw-r--r--mysql-test/t/alter_table.test12
-rw-r--r--mysql-test/t/archive.test11
-rw-r--r--mysql-test/t/bdb-deadlock.tminus57
-rw-r--r--mysql-test/t/bdb.test19
-rw-r--r--mysql-test/t/binary.test7
-rw-r--r--mysql-test/t/bool.test10
-rw-r--r--mysql-test/t/client_test.test2
-rw-r--r--mysql-test/t/comments.test3
-rw-r--r--mysql-test/t/connect.test2
-rw-r--r--mysql-test/t/consistent_snapshot.test41
-rw-r--r--mysql-test/t/count_distinct.test8
-rw-r--r--mysql-test/t/ctype_big5.test12
-rw-r--r--mysql-test/t/ctype_latin1.test7
-rw-r--r--mysql-test/t/ctype_recoding.test48
-rw-r--r--mysql-test/t/ctype_sjis.test11
-rw-r--r--mysql-test/t/ctype_tis620.test35
-rw-r--r--mysql-test/t/ctype_uca.test9
-rw-r--r--mysql-test/t/ctype_ucs.test38
-rw-r--r--mysql-test/t/ctype_ujis.test36
-rw-r--r--mysql-test/t/ctype_utf8.test7
-rw-r--r--mysql-test/t/delete.test30
-rw-r--r--mysql-test/t/endspace.test16
-rw-r--r--mysql-test/t/flush_block_commit.test14
-rw-r--r--mysql-test/t/flush_read_lock_kill-master.opt1
-rw-r--r--mysql-test/t/flush_read_lock_kill.test46
-rw-r--r--mysql-test/t/fulltext.test37
-rw-r--r--mysql-test/t/fulltext_order_by.test12
-rw-r--r--mysql-test/t/func_compress.test5
-rw-r--r--mysql-test/t/func_gconcat.test9
-rw-r--r--mysql-test/t/func_group.test11
-rw-r--r--mysql-test/t/func_in.test7
-rw-r--r--mysql-test/t/func_str.test6
-rw-r--r--mysql-test/t/func_time.test7
-rw-r--r--mysql-test/t/gis.test75
-rw-r--r--mysql-test/t/grant.test61
-rw-r--r--mysql-test/t/grant2.test149
-rw-r--r--mysql-test/t/group_min_max.test2
-rw-r--r--mysql-test/t/having.test195
-rw-r--r--mysql-test/t/heap.test232
-rw-r--r--mysql-test/t/heap_hash.test112
-rw-r--r--mysql-test/t/index_merge_ror_cpk.test2
-rw-r--r--mysql-test/t/information_schema.test276
-rw-r--r--mysql-test/t/information_schema_inno.test16
-rw-r--r--mysql-test/t/innodb.test43
-rw-r--r--mysql-test/t/insert.test10
-rw-r--r--mysql-test/t/insert_select.test13
-rw-r--r--mysql-test/t/join_outer.test91
-rw-r--r--mysql-test/t/key.test28
-rw-r--r--mysql-test/t/key_cache.test11
-rw-r--r--mysql-test/t/lowercase_view.test15
-rw-r--r--mysql-test/t/mix_innodb_myisam_binlog-master.opt1
-rw-r--r--mysql-test/t/mix_innodb_myisam_binlog.test32
-rw-r--r--mysql-test/t/multi_update.test36
-rw-r--r--mysql-test/t/myisam.test20
-rw-r--r--mysql-test/t/mysqldump.test10
-rw-r--r--mysql-test/t/mysqltest.test218
-rw-r--r--mysql-test/t/ndb_autodiscover.test20
-rw-r--r--mysql-test/t/ndb_autodiscover2.test3
-rw-r--r--mysql-test/t/ndb_basic.test168
-rw-r--r--mysql-test/t/ndb_blob.test184
-rw-r--r--mysql-test/t/ndb_charset.test14
-rw-r--r--mysql-test/t/ndb_grant.later383
-rw-r--r--mysql-test/t/ndb_index_ordered.test28
-rw-r--r--mysql-test/t/ndb_index_unique.test62
-rw-r--r--mysql-test/t/ndb_insert.test51
-rw-r--r--mysql-test/t/null.test67
-rw-r--r--mysql-test/t/openssl_1.test6
-rw-r--r--mysql-test/t/order_by.test6
-rw-r--r--mysql-test/t/ps.test30
-rw-r--r--mysql-test/t/ps_10nestset.test13
-rw-r--r--mysql-test/t/ps_1general.test39
-rw-r--r--mysql-test/t/ps_4heap.test6
-rw-r--r--mysql-test/t/ps_7ndb.test358
-rw-r--r--mysql-test/t/range.test19
-rw-r--r--mysql-test/t/rpl000001.test2
-rw-r--r--mysql-test/t/rpl_auto_increment.test2
-rw-r--r--mysql-test/t/rpl_charset.test22
-rw-r--r--mysql-test/t/rpl_create_database-master.opt1
-rw-r--r--mysql-test/t/rpl_create_database-slave.opt1
-rw-r--r--mysql-test/t/rpl_create_database.test71
-rw-r--r--mysql-test/t/rpl_failed_optimize-master.opt1
-rw-r--r--mysql-test/t/rpl_failed_optimize.test18
-rw-r--r--mysql-test/t/rpl_rewrite_db-slave.opt1
-rw-r--r--mysql-test/t/rpl_rewrite_db.test77
-rw-r--r--mysql-test/t/rpl_rotate_logs.test3
-rw-r--r--mysql-test/t/rpl_start_stop_slave.test34
-rw-r--r--mysql-test/t/rpl_timezone.test2
-rw-r--r--mysql-test/t/rpl_until.test2
-rw-r--r--mysql-test/t/select.test59
-rw-r--r--mysql-test/t/show_check.test3
-rw-r--r--mysql-test/t/sp-error.test22
-rw-r--r--mysql-test/t/sp-security.test4
-rw-r--r--mysql-test/t/sp.test17
-rw-r--r--mysql-test/t/sql_mode.test31
-rw-r--r--mysql-test/t/strict.test14
-rw-r--r--mysql-test/t/subselect.test54
-rw-r--r--mysql-test/t/subselect_innodb.test20
-rw-r--r--mysql-test/t/temp_table.test6
-rw-r--r--mysql-test/t/timezone3-master.opt1
-rw-r--r--mysql-test/t/timezone3.test59
-rw-r--r--mysql-test/t/trigger.test23
-rw-r--r--mysql-test/t/type_blob.test22
-rw-r--r--mysql-test/t/type_datetime.test7
-rw-r--r--mysql-test/t/type_enum.test41
-rw-r--r--mysql-test/t/type_float.test3
-rw-r--r--mysql-test/t/type_ranges.test7
-rw-r--r--mysql-test/t/type_varchar.test21
-rw-r--r--mysql-test/t/union.test6
-rw-r--r--mysql-test/t/user_var.test11
-rw-r--r--mysql-test/t/variables.test1
-rw-r--r--mysql-test/t/view.test219
-rw-r--r--mysys/Makefile.am6
-rw-r--r--mysys/charset.c11
-rw-r--r--mysys/default.c152
-rw-r--r--mysys/mf_keycache.c25
-rw-r--r--mysys/mf_keycaches.c2
-rw-r--r--mysys/my_chsize.c10
-rw-r--r--mysys/my_error.c117
-rw-r--r--mysys/my_handler.c18
-rw-r--r--mysys/my_init.c9
-rw-r--r--mysys/my_mmap.c89
-rw-r--r--mysys/ptr_cmp.c39
-rw-r--r--ndb/config/type_ndbapitools.mk.am3
-rw-r--r--ndb/docs/wl2077.txt43
-rwxr-xr-xndb/home/bin/cvschk569
-rw-r--r--ndb/include/Makefile.am8
-rw-r--r--ndb/include/kernel/ndb_limits.h5
-rw-r--r--ndb/include/kernel/signaldata/AccScan.hpp20
-rw-r--r--ndb/include/kernel/signaldata/ArbitSignalData.hpp15
-rw-r--r--ndb/include/kernel/signaldata/BackupImpl.hpp18
-rw-r--r--ndb/include/kernel/signaldata/BackupSignalData.hpp27
-rw-r--r--ndb/include/kernel/signaldata/DictTabInfo.hpp1
-rw-r--r--ndb/include/kernel/signaldata/ScanTab.hpp24
-rw-r--r--ndb/include/kernel/signaldata/TcIndx.hpp374
-rw-r--r--ndb/include/kernel/signaldata/TcKeyReq.hpp16
-rw-r--r--ndb/include/kernel/signaldata/TupFrag.hpp6
-rw-r--r--ndb/include/kernel/signaldata/TuxBound.hpp2
-rw-r--r--ndb/include/mgmapi/mgmapi.h31
-rw-r--r--ndb/include/mgmcommon/ConfigRetriever.hpp27
-rw-r--r--ndb/include/ndb_global.h9
-rw-r--r--ndb/include/ndb_types.h10
-rw-r--r--ndb/include/ndbapi/NdbBlob.hpp47
-rw-r--r--ndb/include/ndbapi/NdbConnection.hpp75
-rw-r--r--ndb/include/ndbapi/NdbDictionary.hpp24
-rw-r--r--ndb/include/ndbapi/NdbIndexOperation.hpp15
-rw-r--r--ndb/include/ndbapi/NdbIndexScanOperation.hpp15
-rw-r--r--ndb/include/ndbapi/NdbOperation.hpp71
-rw-r--r--ndb/include/ndbapi/NdbResultSet.hpp6
-rw-r--r--ndb/include/ndbapi/NdbScanOperation.hpp23
-rw-r--r--ndb/include/ndbapi/ndb_cluster_connection.hpp8
-rw-r--r--ndb/include/ndbapi/ndbapi_limits.h9
-rw-r--r--ndb/include/ndbapi/ndberror.h3
-rw-r--r--ndb/include/portlib/NdbConfig.h (renamed from ndb/include/mgmcommon/NdbConfig.h)0
-rw-r--r--ndb/include/util/Bitmask.hpp34
-rw-r--r--ndb/include/util/SocketServer.hpp4
-rw-r--r--ndb/include/util/md5_hash.hpp11
-rw-r--r--ndb/include/util/ndb_opts.h63
-rw-r--r--ndb/src/Makefile.am2
-rw-r--r--ndb/src/common/Makefile.am2
-rw-r--r--ndb/src/common/Makefile_old15
-rw-r--r--ndb/src/common/debugger/EventLogger.cpp5
-rw-r--r--ndb/src/common/debugger/Makefile_old11
-rw-r--r--ndb/src/common/debugger/signaldata/Makefile_old33
-rw-r--r--ndb/src/common/debugger/signaldata/ScanTab.cpp5
-rw-r--r--ndb/src/common/debugger/signaldata/SignalDataPrint.cpp75
-rw-r--r--ndb/src/common/debugger/signaldata/TcIndx.cpp85
-rw-r--r--ndb/src/common/debugger/signaldata/TcKeyReq.cpp5
-rw-r--r--ndb/src/common/editline/MANIFEST15
-rw-r--r--ndb/src/common/editline/Makefile.am10
-rw-r--r--ndb/src/common/editline/Makefile_old18
-rw-r--r--ndb/src/common/editline/README53
-rw-r--r--ndb/src/common/editline/complete.c211
-rw-r--r--ndb/src/common/editline/editline.3178
-rw-r--r--ndb/src/common/editline/editline.c1514
-rw-r--r--ndb/src/common/editline/editline_internal.h46
-rw-r--r--ndb/src/common/editline/sysunix.c143
-rw-r--r--ndb/src/common/editline/test/Makefile10
-rw-r--r--ndb/src/common/editline/test/testit.c55
-rw-r--r--ndb/src/common/logger/LogHandler.cpp7
-rw-r--r--ndb/src/common/logger/Logger.cpp9
-rw-r--r--ndb/src/common/logger/Makefile_old27
-rw-r--r--ndb/src/common/mgmcommon/ConfigRetriever.cpp181
-rw-r--r--ndb/src/common/mgmcommon/Makefile.am5
-rw-r--r--ndb/src/common/mgmcommon/Makefile_old29
-rw-r--r--ndb/src/common/portlib/Makefile.am3
-rw-r--r--ndb/src/common/portlib/Makefile_old21
-rw-r--r--ndb/src/common/portlib/NdbConfig.c (renamed from ndb/src/common/mgmcommon/NdbConfig.c)2
-rw-r--r--ndb/src/common/portlib/NdbDaemon.c20
-rw-r--r--ndb/src/common/portlib/old_dirs/unix/Makefile_old27
-rw-r--r--ndb/src/common/transporter/Makefile_old43
-rw-r--r--ndb/src/common/transporter/TransporterRegistry.cpp12
-rw-r--r--ndb/src/common/util/Makefile.am4
-rw-r--r--ndb/src/common/util/Makefile_old28
-rw-r--r--ndb/src/common/util/NdbOut.cpp2
-rw-r--r--ndb/src/common/util/NdbSqlUtil.cpp10
-rw-r--r--ndb/src/common/util/SocketServer.cpp15
-rw-r--r--ndb/src/common/util/basestring_vsnprintf.c42
-rw-r--r--ndb/src/common/util/getarg.3315
-rw-r--r--ndb/src/common/util/getarg.3.ps458
-rw-r--r--ndb/src/common/util/md5-rfc1321.txt1179
-rw-r--r--ndb/src/common/util/md5_hash.cpp20
-rw-r--r--ndb/src/common/util/socket_io.cpp39
-rw-r--r--ndb/src/common/util/strlcat.c48
-rw-r--r--ndb/src/common/util/strlcpy.c57
-rw-r--r--ndb/src/common/util/version.c1
-rw-r--r--ndb/src/cw/Makefile_old6
-rw-r--r--ndb/src/cw/cpcc-win32/csharp/AssemblyInfo.cs58
-rw-r--r--ndb/src/cw/cpcc-win32/vb6/frmSplash.frm159
-rw-r--r--ndb/src/cw/cpcd/Makefile_old11
-rw-r--r--ndb/src/cw/cpcd/common.cpp63
-rw-r--r--ndb/src/cw/cpcd/common.hpp3
-rw-r--r--ndb/src/cw/cpcd/main.cpp75
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/list.h56
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/os/inttypes.h53
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/rmlib.h212
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/sci_errno.h216
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/sci_types.h300
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/sisci_api.h2170
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/sisci_demolib.h226
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/sisci_error.h89
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/sisci_types.h133
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/sisci_version.h91
-rw-r--r--ndb/src/external/LINUX.x86/sci/include/version.h25
-rw-r--r--ndb/src/external/SOLARIS.SPARC/sci/include/sisci_api.h2148
-rw-r--r--ndb/src/external/SOLARIS.SPARC/sci/include/sisci_error.h89
-rw-r--r--ndb/src/external/SOLARIS.SPARC/sci/include/sisci_types.h133
-rw-r--r--ndb/src/external/SOLARIS.SPARC/sci/include/sisci_version.h91
-rw-r--r--ndb/src/external/WIN32.x86/sci/include/rmlib.h212
-rw-r--r--ndb/src/external/WIN32.x86/sci/include/scilib.h330
-rw-r--r--ndb/src/external/WIN32.x86/sci/include/sisci_api.h2217
-rw-r--r--ndb/src/external/WIN32.x86/sci/include/sisci_demolib.h226
-rw-r--r--ndb/src/external/WIN32.x86/sci/include/sisci_error.h94
-rw-r--r--ndb/src/external/WIN32.x86/sci/include/sisci_types.h133
-rw-r--r--ndb/src/kernel/Makefile_old5
-rw-r--r--ndb/src/kernel/blocks/ERROR_codes.txt13
-rw-r--r--ndb/src/kernel/blocks/Makefile_old28
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.cpp7
-rw-r--r--ndb/src/kernel/blocks/backup/Backup.hpp1
-rw-r--r--ndb/src/kernel/blocks/backup/BackupInit.cpp1
-rw-r--r--ndb/src/kernel/blocks/backup/Makefile.am2
-rw-r--r--ndb/src/kernel/blocks/backup/Makefile_old18
-rw-r--r--ndb/src/kernel/blocks/backup/restore/Makefile.am16
-rw-r--r--ndb/src/kernel/blocks/cmvmi/Makefile_old9
-rw-r--r--ndb/src/kernel/blocks/dbacc/Dbacc.hpp148
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccInit.cpp3
-rw-r--r--ndb/src/kernel/blocks/dbacc/DbaccMain.cpp2431
-rw-r--r--ndb/src/kernel/blocks/dbacc/Makefile.am2
-rw-r--r--ndb/src/kernel/blocks/dbacc/Makefile_old11
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.cpp23
-rw-r--r--ndb/src/kernel/blocks/dbdict/Dbdict.hpp4
-rw-r--r--ndb/src/kernel/blocks/dbdict/Makefile_old12
-rw-r--r--ndb/src/kernel/blocks/dbdih/Dbdih.hpp1
-rw-r--r--ndb/src/kernel/blocks/dbdih/DbdihMain.cpp23
-rw-r--r--ndb/src/kernel/blocks/dbdih/Makefile_old13
-rw-r--r--ndb/src/kernel/blocks/dblqh/Dblqh.hpp48
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhInit.cpp2
-rw-r--r--ndb/src/kernel/blocks/dblqh/DblqhMain.cpp683
-rw-r--r--ndb/src/kernel/blocks/dblqh/Makefile_old12
-rw-r--r--ndb/src/kernel/blocks/dbtc/Dbtc.hpp25
-rw-r--r--ndb/src/kernel/blocks/dbtc/DbtcMain.cpp245
-rw-r--r--ndb/src/kernel/blocks/dbtc/Makefile_old11
-rw-r--r--ndb/src/kernel/blocks/dbtup/Dbtup.hpp9
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp1
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp24
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp65
-rw-r--r--ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp5
-rw-r--r--ndb/src/kernel/blocks/dbtup/Makefile_old26
-rw-r--r--ndb/src/kernel/blocks/dbtux/Dbtux.hpp9
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp16
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp9
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp7
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp91
-rw-r--r--ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp46
-rw-r--r--ndb/src/kernel/blocks/dbtux/Makefile_old17
-rw-r--r--ndb/src/kernel/blocks/dbtux/Times.txt10
-rw-r--r--ndb/src/kernel/blocks/dbutil/Makefile_old8
-rw-r--r--ndb/src/kernel/blocks/grep/Makefile_old9
-rw-r--r--ndb/src/kernel/blocks/ndbcntr/Makefile_old12
-rw-r--r--ndb/src/kernel/blocks/ndbfs/Makefile_old14
-rw-r--r--ndb/src/kernel/blocks/qmgr/Makefile_old11
-rw-r--r--ndb/src/kernel/blocks/qmgr/QmgrMain.cpp43
-rw-r--r--ndb/src/kernel/blocks/suma/Makefile_old10
-rw-r--r--ndb/src/kernel/blocks/suma/Suma.cpp2
-rw-r--r--ndb/src/kernel/blocks/trix/Makefile_old8
-rw-r--r--ndb/src/kernel/error/ErrorReporter.cpp2
-rw-r--r--ndb/src/kernel/error/Makefile_old12
-rw-r--r--ndb/src/kernel/main.cpp20
-rw-r--r--ndb/src/kernel/vm/Configuration.cpp215
-rw-r--r--ndb/src/kernel/vm/Configuration.hpp5
-rw-r--r--ndb/src/kernel/vm/Emulator.hpp1
-rw-r--r--ndb/src/kernel/vm/LongSignal.hpp2
-rw-r--r--ndb/src/kernel/vm/Makefile_old30
-rw-r--r--ndb/src/mgmapi/LocalConfig.cpp (renamed from ndb/src/common/mgmcommon/LocalConfig.cpp)55
-rw-r--r--ndb/src/mgmapi/LocalConfig.hpp (renamed from ndb/include/mgmcommon/LocalConfig.hpp)1
-rw-r--r--ndb/src/mgmapi/Makefile.am7
-rw-r--r--ndb/src/mgmapi/Makefile_old27
-rw-r--r--ndb/src/mgmapi/mgmapi.cpp269
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.cpp774
-rw-r--r--ndb/src/mgmclient/CommandInterpreter.hpp197
-rw-r--r--ndb/src/mgmclient/Makefile.am22
-rw-r--r--ndb/src/mgmclient/Makefile_old25
-rw-r--r--ndb/src/mgmclient/main.cpp182
-rw-r--r--ndb/src/mgmclient/ndb_mgmclient.h (renamed from ndb/src/common/editline/editline_win32.c)23
-rw-r--r--ndb/src/mgmclient/ndb_mgmclient.hpp (renamed from ndb/src/common/editline/unix.h)22
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.cpp47
-rw-r--r--ndb/src/mgmsrv/CommandInterpreter.hpp31
-rw-r--r--ndb/src/mgmsrv/ConfigInfo.cpp8
-rw-r--r--ndb/src/mgmsrv/InitConfigFileParser.cpp68
-rw-r--r--ndb/src/mgmsrv/Makefile.am2
-rw-r--r--ndb/src/mgmsrv/Makefile_old41
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.cpp242
-rw-r--r--ndb/src/mgmsrv/MgmtSrvr.hpp25
-rw-r--r--ndb/src/mgmsrv/MgmtSrvrConfig.cpp18
-rw-r--r--ndb/src/mgmsrv/Services.cpp109
-rw-r--r--ndb/src/mgmsrv/Services.hpp10
-rw-r--r--ndb/src/mgmsrv/main.cpp173
-rw-r--r--ndb/src/ndbapi/Makefile_old60
-rw-r--r--ndb/src/ndbapi/Ndb.cpp7
-rw-r--r--ndb/src/ndbapi/NdbApiSignal.cpp2
-rw-r--r--ndb/src/ndbapi/NdbBlob.cpp420
-rw-r--r--ndb/src/ndbapi/NdbConnection.cpp72
-rw-r--r--ndb/src/ndbapi/NdbConnectionScan.cpp36
-rw-r--r--ndb/src/ndbapi/NdbDictionary.cpp52
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.cpp100
-rw-r--r--ndb/src/ndbapi/NdbDictionaryImpl.hpp22
-rw-r--r--ndb/src/ndbapi/NdbIndexOperation.cpp435
-rw-r--r--ndb/src/ndbapi/NdbOperation.cpp41
-rw-r--r--ndb/src/ndbapi/NdbOperationDefine.cpp5
-rw-r--r--ndb/src/ndbapi/NdbOperationExec.cpp32
-rw-r--r--ndb/src/ndbapi/NdbOperationSearch.cpp290
-rw-r--r--ndb/src/ndbapi/NdbResultSet.cpp12
-rw-r--r--ndb/src/ndbapi/NdbScanOperation.cpp391
-rw-r--r--ndb/src/ndbapi/Ndbinit.cpp2
-rw-r--r--ndb/src/ndbapi/TransporterFacade.cpp159
-rw-r--r--ndb/src/ndbapi/TransporterFacade.hpp10
-rw-r--r--ndb/src/ndbapi/ndb_cluster_connection.cpp83
-rw-r--r--ndb/src/ndbapi/ndberror.c100
-rw-r--r--ndb/test/include/CpcClient.hpp (renamed from ndb/src/mgmclient/CpcClient.hpp)0
-rw-r--r--ndb/test/include/HugoTransactions.hpp16
-rw-r--r--ndb/test/include/NDBT_Tables.hpp6
-rw-r--r--ndb/test/include/NDBT_Test.hpp4
-rw-r--r--ndb/test/include/NdbRestarter.hpp2
-rw-r--r--ndb/test/include/UtilTransactions.hpp4
-rw-r--r--ndb/test/include/getarg.h (renamed from ndb/include/util/getarg.h)0
-rw-r--r--ndb/test/ndbapi/Makefile.am4
-rw-r--r--ndb/test/ndbapi/Makefile_old49
-rw-r--r--ndb/test/ndbapi/ScanFunctions.hpp20
-rw-r--r--ndb/test/ndbapi/bank/Makefile_old12
-rw-r--r--ndb/test/ndbapi/old_dirs/flexBench/Makefile_old11
-rw-r--r--ndb/test/ndbapi/testBlobs.cpp527
-rw-r--r--ndb/test/ndbapi/testDataBuffers.cpp50
-rw-r--r--ndb/test/ndbapi/testDeadlock.cpp7
-rw-r--r--ndb/test/ndbapi/testDict.cpp89
-rw-r--r--ndb/test/ndbapi/testIndex.cpp24
-rw-r--r--ndb/test/ndbapi/testLcp.cpp8
-rw-r--r--ndb/test/ndbapi/testNdbApi.cpp16
-rw-r--r--ndb/test/ndbapi/testOIBasic.cpp19
-rw-r--r--ndb/test/ndbapi/testPartitioning.cpp189
-rw-r--r--ndb/test/ndbapi/testReadPerf.cpp16
-rw-r--r--ndb/test/ndbapi/testRestartGci.cpp5
-rw-r--r--ndb/test/ndbapi/testScan.cpp139
-rw-r--r--ndb/test/ndbapi/testScanPerf.cpp159
-rw-r--r--ndb/test/ndbapi/testSystemRestart.cpp12
-rw-r--r--ndb/test/odbc/tpcb/Makefile30
-rw-r--r--ndb/test/odbc/tpcb/Makefile_mysql33
-rw-r--r--ndb/test/odbc/tpcb/Makefile_ndb30
-rw-r--r--ndb/test/odbc/tpcb/readme.txt15
-rw-r--r--ndb/test/odbc/tpcb/timesten.h188
-rw-r--r--ndb/test/odbc/tpcb/tpcb.cpp1415
-rw-r--r--ndb/test/odbc/tpcb/ttTime.c366
-rw-r--r--ndb/test/odbc/tpcb/ttTime.h125
-rw-r--r--ndb/test/run-test/Makefile.am4
-rw-r--r--ndb/test/run-test/Makefile_old22
-rw-r--r--ndb/test/run-test/daily-basic-tests.txt500
-rw-r--r--ndb/test/run-test/main.cpp24
-rw-r--r--ndb/test/src/CpcClient.cpp (renamed from ndb/src/mgmclient/CpcClient.cpp)0
-rw-r--r--ndb/test/src/HugoOperations.cpp5
-rw-r--r--ndb/test/src/HugoTransactions.cpp166
-rw-r--r--ndb/test/src/Makefile.am3
-rw-r--r--ndb/test/src/Makefile_old33
-rw-r--r--ndb/test/src/NDBT_Tables.cpp17
-rw-r--r--ndb/test/src/NDBT_Test.cpp5
-rw-r--r--ndb/test/src/NdbBackup.cpp36
-rw-r--r--ndb/test/src/NdbRestarter.cpp45
-rw-r--r--ndb/test/src/NdbSchemaOp.cpp1
-rw-r--r--ndb/test/src/UtilTransactions.cpp23
-rw-r--r--ndb/test/src/getarg.c (renamed from ndb/src/common/util/getarg.c)32
-rw-r--r--ndb/test/tools/Makefile.am4
-rw-r--r--ndb/test/tools/Makefile_old9
-rw-r--r--ndb/test/tools/create_index.cpp2
-rw-r--r--ndb/test/tools/hugoScanRead.cpp50
-rw-r--r--ndb/test/tools/old_dirs/waiter/Makefile_old11
-rw-r--r--ndb/tools/Makefile.am20
-rw-r--r--ndb/tools/Makefile_old12
-rw-r--r--ndb/tools/delete_all.cpp73
-rw-r--r--ndb/tools/desc.cpp82
-rw-r--r--ndb/tools/drop_index.cpp70
-rw-r--r--ndb/tools/drop_tab.cpp77
-rw-r--r--ndb/tools/listTables.cpp107
-rw-r--r--ndb/tools/ndb_test_platform.cpp95
-rw-r--r--ndb/tools/restore/Restore.cpp (renamed from ndb/src/kernel/blocks/backup/restore/Restore.cpp)4
-rw-r--r--ndb/tools/restore/Restore.hpp (renamed from ndb/src/kernel/blocks/backup/restore/Restore.hpp)3
-rw-r--r--ndb/tools/restore/consumer.cpp (renamed from ndb/src/kernel/blocks/backup/restore/consumer.cpp)0
-rw-r--r--ndb/tools/restore/consumer.hpp (renamed from ndb/src/kernel/blocks/backup/restore/consumer.hpp)0
-rw-r--r--ndb/tools/restore/consumer_printer.cpp (renamed from ndb/src/kernel/blocks/backup/restore/consumer_printer.cpp)0
-rw-r--r--ndb/tools/restore/consumer_printer.hpp (renamed from ndb/src/kernel/blocks/backup/restore/consumer_printer.hpp)0
-rw-r--r--ndb/tools/restore/consumer_restore.cpp (renamed from ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp)1
-rw-r--r--ndb/tools/restore/consumer_restore.hpp (renamed from ndb/src/kernel/blocks/backup/restore/consumer_restore.hpp)0
-rw-r--r--ndb/tools/restore/consumer_restorem.cpp (renamed from ndb/src/kernel/blocks/backup/restore/consumer_restorem.cpp)0
-rw-r--r--ndb/tools/restore/restore_main.cpp (renamed from ndb/src/kernel/blocks/backup/restore/main.cpp)199
-rw-r--r--ndb/tools/select_all.cpp129
-rw-r--r--ndb/tools/select_count.cpp82
-rw-r--r--ndb/tools/waiter.cpp123
-rw-r--r--netware/comp_err.def2
-rw-r--r--netware/isamchk.def2
-rw-r--r--netware/isamlog.def2
-rw-r--r--netware/libmysql.def2
-rw-r--r--netware/my_print_defaults.def2
-rw-r--r--netware/myisam_ftdump.def2
-rw-r--r--netware/myisamchk.def2
-rw-r--r--netware/myisamlog.def2
-rw-r--r--netware/myisampack.def2
-rw-r--r--netware/mysql.def2
-rw-r--r--netware/mysql_install.def2
-rw-r--r--netware/mysql_install_db.def2
-rw-r--r--netware/mysql_test_run.def2
-rw-r--r--netware/mysql_waitpid.def2
-rw-r--r--netware/mysqladmin.def2
-rw-r--r--netware/mysqlbinlog.def2
-rw-r--r--netware/mysqlcheck.def2
-rw-r--r--netware/mysqld.def2
-rw-r--r--netware/mysqld_safe.def2
-rw-r--r--netware/mysqldump.def2
-rw-r--r--netware/mysqlimport.def2
-rw-r--r--netware/mysqlshow.def2
-rw-r--r--netware/mysqltest.def2
-rw-r--r--netware/pack_isam.def2
-rw-r--r--netware/perror.def2
-rw-r--r--netware/replace.def2
-rw-r--r--netware/resolve_stack_dump.def2
-rw-r--r--netware/resolveip.def2
-rw-r--r--scripts/fill_help_tables.sh10
-rw-r--r--scripts/mysql_fix_privilege_tables.sh5
-rw-r--r--scripts/mysqld_safe.sh6
-rw-r--r--server-tools/instance-manager/mysqlmanager.cc3
-rw-r--r--server-tools/instance-manager/thread_repository.cc5
-rw-r--r--sql-common/client.c2
-rw-r--r--sql-common/my_time.c30
-rw-r--r--sql/Makefile.am7
-rw-r--r--sql/examples/ha_archive.cc140
-rw-r--r--sql/examples/ha_archive.h42
-rw-r--r--sql/examples/ha_tina.cc13
-rw-r--r--sql/field.cc594
-rw-r--r--sql/field.h94
-rw-r--r--sql/field_conv.cc20
-rw-r--r--sql/filesort.cc7
-rw-r--r--sql/ha_berkeley.cc107
-rw-r--r--sql/ha_heap.cc97
-rw-r--r--sql/ha_heap.h9
-rw-r--r--sql/ha_innodb.cc584
-rw-r--r--sql/ha_innodb.h54
-rw-r--r--sql/ha_isam.cc408
-rw-r--r--sql/ha_isam.h79
-rw-r--r--sql/ha_isammrg.cc210
-rw-r--r--sql/ha_isammrg.h69
-rw-r--r--sql/ha_myisam.cc69
-rw-r--r--sql/ha_myisammrg.cc49
-rw-r--r--sql/ha_myisammrg.h1
-rw-r--r--sql/ha_ndbcluster.cc606
-rw-r--r--sql/ha_ndbcluster.h79
-rw-r--r--sql/handler.cc134
-rw-r--r--sql/handler.h51
-rw-r--r--sql/item.cc1219
-rw-r--r--sql/item.h107
-rw-r--r--sql/item_buff.cc2
-rw-r--r--sql/item_cmpfunc.cc220
-rw-r--r--sql/item_cmpfunc.h22
-rw-r--r--sql/item_create.cc5
-rw-r--r--sql/item_func.cc412
-rw-r--r--sql/item_func.h110
-rw-r--r--sql/item_geofunc.cc18
-rw-r--r--sql/item_geofunc.h8
-rw-r--r--sql/item_row.cc4
-rw-r--r--sql/item_row.h2
-rw-r--r--sql/item_strfunc.cc108
-rw-r--r--sql/item_strfunc.h4
-rw-r--r--sql/item_subselect.cc83
-rw-r--r--sql/item_subselect.h14
-rw-r--r--sql/item_sum.cc145
-rw-r--r--sql/item_sum.h61
-rw-r--r--sql/item_timefunc.cc63
-rw-r--r--sql/item_timefunc.h18
-rw-r--r--sql/item_uniq.h6
-rw-r--r--sql/key.cc28
-rw-r--r--sql/lex.h9
-rw-r--r--sql/lock.cc94
-rw-r--r--sql/log.cc64
-rw-r--r--sql/log_event.cc91
-rw-r--r--sql/log_event.h22
-rw-r--r--sql/mysql_priv.h310
-rw-r--r--sql/mysqld.cc194
-rw-r--r--sql/net_serv.cc14
-rw-r--r--sql/opt_range.cc89
-rw-r--r--sql/opt_sum.cc15
-rw-r--r--sql/parse_file.cc39
-rw-r--r--sql/procedure.cc3
-rw-r--r--sql/procedure.h8
-rw-r--r--sql/protocol.cc66
-rw-r--r--sql/protocol.h4
-rw-r--r--sql/protocol_cursor.cc3
-rw-r--r--sql/repl_failsafe.cc57
-rw-r--r--sql/repl_failsafe.h6
-rw-r--r--sql/set_var.cc98
-rw-r--r--sql/share/czech/errmsg.txt28
-rw-r--r--sql/share/danish/errmsg.txt28
-rw-r--r--sql/share/dutch/errmsg.txt28
-rw-r--r--sql/share/english/errmsg.txt28
-rw-r--r--sql/share/estonian/errmsg.txt28
-rw-r--r--sql/share/french/errmsg.txt30
-rw-r--r--sql/share/german/errmsg.txt26
-rw-r--r--sql/share/greek/errmsg.txt30
-rw-r--r--sql/share/hungarian/errmsg.txt28
-rw-r--r--sql/share/italian/errmsg.txt28
-rw-r--r--sql/share/japanese/errmsg.txt28
-rw-r--r--sql/share/korean/errmsg.txt28
-rw-r--r--sql/share/norwegian-ny/errmsg.txt28
-rw-r--r--sql/share/norwegian/errmsg.txt28
-rw-r--r--sql/share/polish/errmsg.txt28
-rw-r--r--sql/share/portuguese/errmsg.txt30
-rw-r--r--sql/share/romanian/errmsg.txt30
-rw-r--r--sql/share/russian/errmsg.txt30
-rw-r--r--sql/share/serbian/errmsg.txt30
-rw-r--r--sql/share/slovak/errmsg.txt28
-rw-r--r--sql/share/spanish/errmsg.txt34
-rw-r--r--sql/share/swedish/errmsg.txt32
-rw-r--r--sql/share/ukrainian/errmsg.txt30
-rw-r--r--sql/slave.cc51
-rw-r--r--sql/slave.h13
-rw-r--r--sql/sp.cc45
-rw-r--r--sql/sp_head.cc70
-rw-r--r--sql/sp_head.h10
-rw-r--r--sql/sp_pcontext.h2
-rw-r--r--sql/sp_rcontext.cc15
-rw-r--r--sql/spatial.cc4
-rw-r--r--sql/sql_acl.cc1420
-rw-r--r--sql/sql_acl.h18
-rw-r--r--sql/sql_analyse.cc8
-rw-r--r--sql/sql_base.cc590
-rw-r--r--sql/sql_class.cc48
-rw-r--r--sql/sql_class.h77
-rw-r--r--sql/sql_db.cc94
-rw-r--r--sql/sql_delete.cc146
-rw-r--r--sql/sql_derived.cc238
-rw-r--r--sql/sql_do.cc7
-rw-r--r--sql/sql_error.cc20
-rw-r--r--sql/sql_handler.cc65
-rw-r--r--sql/sql_help.cc93
-rw-r--r--sql/sql_insert.cc352
-rw-r--r--sql/sql_lex.cc56
-rw-r--r--sql/sql_lex.h52
-rw-r--r--sql/sql_list.h18
-rw-r--r--sql/sql_load.cc41
-rw-r--r--sql/sql_map.cc8
-rw-r--r--sql/sql_olap.cc3
-rw-r--r--sql/sql_parse.cc1322
-rw-r--r--sql/sql_prepare.cc444
-rw-r--r--sql/sql_rename.cc7
-rw-r--r--sql/sql_repl.cc104
-rw-r--r--sql/sql_repl.h10
-rw-r--r--sql/sql_select.cc641
-rw-r--r--sql/sql_select.h7
-rw-r--r--sql/sql_show.cc3011
-rw-r--r--sql/sql_string.cc32
-rw-r--r--sql/sql_string.h36
-rw-r--r--sql/sql_table.cc679
-rw-r--r--sql/sql_trigger.cc160
-rw-r--r--sql/sql_trigger.h9
-rw-r--r--sql/sql_udf.cc22
-rw-r--r--sql/sql_udf.h3
-rw-r--r--sql/sql_union.cc89
-rw-r--r--sql/sql_update.cc359
-rw-r--r--sql/sql_view.cc290
-rw-r--r--sql/sql_view.h10
-rw-r--r--sql/sql_yacc.yy1013
-rw-r--r--sql/strfunc.cc2
-rw-r--r--sql/structs.h9
-rw-r--r--sql/table.cc345
-rw-r--r--sql/table.h91
-rw-r--r--sql/thr_malloc.cc7
-rw-r--r--sql/unireg.cc4
-rw-r--r--sql/unireg.h4
-rw-r--r--strings/ctype-big5.c36
-rw-r--r--strings/ctype-bin.c21
-rw-r--r--strings/ctype-czech.c30
-rw-r--r--strings/ctype-gbk.c27
-rw-r--r--strings/ctype-latin1.c17
-rw-r--r--strings/ctype-mb.c104
-rw-r--r--strings/ctype-simple.c40
-rw-r--r--strings/ctype-sjis.c40
-rw-r--r--strings/ctype-tis620.c39
-rw-r--r--strings/ctype-uca.c72
-rw-r--r--strings/ctype-ucs2.c99
-rw-r--r--strings/ctype-utf8.c59
-rw-r--r--strings/ctype-win1250ch.c29
-rw-r--r--strings/decimal.c467
-rw-r--r--strings/my_vsnprintf.c27
-rw-r--r--strings/uca-dump.c91
-rw-r--r--tests/client_test.c1985
-rw-r--r--tests/grant.pl4
1008 files changed, 72800 insertions, 59495 deletions
diff --git a/.bzrignore b/.bzrignore
index dec7eb8ffdf..e47629f14ec 100644
--- a/.bzrignore
+++ b/.bzrignore
@@ -9,6 +9,7 @@
*.lo
*.o
*.reject
+*.so
*.spec
*/*_pure_*warnings
*/.pure
@@ -101,7 +102,9 @@ Makefile.in
Makefile.in'
PENDING/*
TAGS
+ac_available_languages_fragment
aclocal.m4
+autom4te-2.53.cache/*
autom4te-2.53.cache/output.0
autom4te-2.53.cache/requests
autom4te-2.53.cache/traces.0
@@ -153,6 +156,7 @@ bdb/db/crdel_auto.c
bdb/db/db_auto.c
bdb/dbinc_auto/*.*
bdb/dbreg/dbreg_auto.c
+bdb/dist/autom4te-2.53.cache/*
bdb/dist/autom4te-2.53.cache/output.0
bdb/dist/autom4te-2.53.cache/requests
bdb/dist/autom4te-2.53.cache/traces.0
@@ -239,12 +243,14 @@ bdb/test/logtrack.list
bdb/txn/txn_auto.c
binary/*
bkpull.log
+bkpull.log*
bkpull.log.2
bkpull.log.3
bkpull.log.4
bkpull.log.5
bkpull.log.6
bkpush.log
+bkpush.log*
build.log
build_tags.sh
client/insert_test
@@ -279,11 +285,20 @@ config.status
configure
configure.lineno
core
+core.*
core.2430
db-*.*.*
+dbug/dbug_analyze
+dbug/example*.r
+dbug/factorial
+dbug/factorial.r
+dbug/main.r
+dbug/output*.r
+dbug/user.ps
dbug/user.t
depcomp
emacs.h
+extra/charset2html
extra/comp_err
extra/my_print_defaults
extra/mysql_install
@@ -296,10 +311,12 @@ extra/resolveip
extra/tztime.cc
fcns.c
fcns.h
+gdbinit
gmon.out
hardcopy.0
heap/hp_test1
heap/hp_test2
+help
help.c
help.h
include/my_config.h
@@ -309,6 +326,7 @@ include/readline
include/readline/*.h
include/readline/readline.h
include/widec.h
+innobase/autom4te-2.53.cache/*
innobase/autom4te-2.53.cache/output.0
innobase/autom4te-2.53.cache/requests
innobase/autom4te-2.53.cache/traces.0
@@ -369,7 +387,9 @@ libmysqld/field_conv.cc
libmysqld/filesort.cc
libmysqld/get_password.c
libmysqld/gstream.cc
+libmysqld/ha_archive.cc
libmysqld/ha_berkeley.cc
+libmysqld/ha_example.cc
libmysqld/ha_heap.cc
libmysqld/ha_innobase.cc
libmysqld/ha_innodb.cc
@@ -377,6 +397,7 @@ libmysqld/ha_isam.cc
libmysqld/ha_isammrg.cc
libmysqld/ha_myisam.cc
libmysqld/ha_myisammrg.cc
+libmysqld/ha_tina.cc
libmysqld/handler.cc
libmysqld/hash_filo.cc
libmysqld/hostname.cc
@@ -435,6 +456,7 @@ libmysqld/sql_db.cc
libmysqld/sql_delete.cc
libmysqld/sql_derived.cc
libmysqld/sql_do.cc
+libmysqld/sql_error.cc
libmysqld/sql_handler.cc
libmysqld/sql_help.cc
libmysqld/sql_insert.cc
@@ -445,6 +467,7 @@ libmysqld/sql_manager.cc
libmysqld/sql_map.cc
libmysqld/sql_olap.cc
libmysqld/sql_parse.cc
+libmysqld/sql_prepare.cc
libmysqld/sql_rename.cc
libmysqld/sql_repl.cc
libmysqld/sql_select.cc
@@ -515,10 +538,12 @@ myisam/test2.MYD
myisam/test2.MYI
mysql-4.0.2-alpha-pc-linux-gnu-i686.tar.gz
mysql-4.0.2-alpha.tar.gz
+mysql-5.0.2-alpha.tar.gz
mysql-max-4.0.2-alpha-pc-linux-gnu-i686.tar.gz
mysql-test/gmon.out
mysql-test/install_test_db
mysql-test/mysql-test-run
+mysql-test/mysql_test_run_new
mysql-test/ndb/ndbcluster
mysql-test/r/*.reject
mysql-test/r/index_merge_load.result
@@ -737,10 +762,25 @@ ndb/tools/ndb_delete_all
ndb/tools/ndb_desc
ndb/tools/ndb_drop_index
ndb/tools/ndb_drop_table
+ndb/tools/ndb_restore
ndb/tools/ndb_select_all
ndb/tools/ndb_select_count
ndb/tools/ndb_show_tables
+ndb/tools/ndb_test_platform
ndb/tools/ndb_waiter
+ndbcluster-1186
+ndbcluster-1186/SCCS
+ndbcluster-1186/config.ini
+ndbcluster-1186/ndb_1.pid
+ndbcluster-1186/ndb_1_out.log
+ndbcluster-1186/ndb_1_signal.log
+ndbcluster-1186/ndb_2.pid
+ndbcluster-1186/ndb_2_out.log
+ndbcluster-1186/ndb_2_signal.log
+ndbcluster-1186/ndb_3.pid
+ndbcluster-1186/ndb_3_cluster.log
+ndbcluster-1186/ndb_3_out.log
+ndbcluster-1186/ndbcluster.pid
pull.log
regex/re
repl-tests/test-repl-ts/repl-timestamp.master.reject
@@ -777,7 +817,11 @@ scripts/mysqldumpslow
scripts/mysqlhotcopy
scripts/safe_mysqld
select_test
+server-tools/instance-manager/client.c
+server-tools/instance-manager/client_settings.h
+server-tools/instance-manager/errmsg.c
server-tools/instance-manager/mysqlmanager
+server-tools/instance-manager/thr_alarm.c
sql-bench/Results-linux/ATIS-mysql_bdb-Linux_2.2.14_my_SMP_i686
sql-bench/bench-count-distinct
sql-bench/bench-init.pl
@@ -939,8 +983,3 @@ vio/test-ssl
vio/test-sslclient
vio/test-sslserver
vio/viotest-ssl
-server-tools/instance-manager/thr_alarm.c
-mysql-5.0.2-alpha.tar.gz
-server-tools/instance-manager/client.c
-server-tools/instance-manager/client_settings.h
-server-tools/instance-manager/errmsg.c
diff --git a/BUILD/FINISH.sh b/BUILD/FINISH.sh
index 094eb8275d6..81defaa7f52 100644
--- a/BUILD/FINISH.sh
+++ b/BUILD/FINISH.sh
@@ -10,7 +10,7 @@ do
done
commands="\
-$make -k clean || true
+$make -k distclean || true
/bin/rm -rf */.deps/*.P config.cache innobase/config.cache bdb/build_unix/config.cache bdb/dist/autom4te.cache autom4te.cache innobase/autom4te.cache;
aclocal || (echo \"Can't execute aclocal\" && exit 1)
diff --git a/BUILD/SETUP.sh b/BUILD/SETUP.sh
index c1f9028b6dd..8fa70aecb6a 100644
--- a/BUILD/SETUP.sh
+++ b/BUILD/SETUP.sh
@@ -45,6 +45,7 @@ cxx_warnings="$global_warnings -Woverloaded-virtual -Wsign-promo -Wreorder -Wcto
alpha_cflags="-mcpu=ev6 -Wa,-mev6" # Not used yet
pentium_cflags="-mcpu=pentiumpro"
+ppc_cflags="-mpowerpc -mcpu=powerpc"
sparc_cflags=""
# be as fast as we can be without losing our ability to backtrace
diff --git a/BUILD/compile-ppc b/BUILD/compile-ppc
new file mode 100755
index 00000000000..d248ecf2677
--- /dev/null
+++ b/BUILD/compile-ppc
@@ -0,0 +1,10 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$ppc_cflags $fast_cflags"
+extra_configs="$static_link"
+strip=yes
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-ppc-debug b/BUILD/compile-ppc-debug
new file mode 100755
index 00000000000..2be11eaaf22
--- /dev/null
+++ b/BUILD/compile-ppc-debug
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$ppc_cflags $debug_cflags"
+c_warnings="$c_warnings $debug_extra_warnings"
+cxx_warnings="$cxx_warnings $debug_extra_warnings"
+extra_configs="$debug_configs "
+
+extra_configs="$extra_configs"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-ppc-debug-max b/BUILD/compile-ppc-debug-max
new file mode 100755
index 00000000000..9d67b46601a
--- /dev/null
+++ b/BUILD/compile-ppc-debug-max
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$ppc_cflags $debug_cflags"
+c_warnings="$c_warnings $debug_extra_warnings"
+cxx_warnings="$cxx_warnings $debug_extra_warnings"
+extra_configs="$debug_configs"
+
+extra_configs="$extra_configs --with-berkeley-db --with-innodb --without-isam --with-embedded-server --with-openssl --with-raid --with-vio --with-ndbcluster"
+
+. "$path/FINISH.sh"
diff --git a/BUILD/compile-ppc-max b/BUILD/compile-ppc-max
new file mode 100755
index 00000000000..f7193eb8aca
--- /dev/null
+++ b/BUILD/compile-ppc-max
@@ -0,0 +1,13 @@
+#! /bin/sh
+
+path=`dirname $0`
+. "$path/SETUP.sh"
+
+extra_flags="$ppc_cflags $fast_cflags -g"
+#strip=yes
+
+extra_configs="$extra_configs --with-innodb --with-berkeley-db \
+ --with-embedded-server --enable-thread-safe-client \
+ --with-openssl --with-vio --with-raid --with-ndbcluster"
+
+. "$path/FINISH.sh"
diff --git a/BitKeeper/etc/logging_ok b/BitKeeper/etc/logging_ok
index e7152099ed3..11a49cee843 100644
--- a/BitKeeper/etc/logging_ok
+++ b/BitKeeper/etc/logging_ok
@@ -90,6 +90,7 @@ jcole@mugatu.jcole.us
jcole@mugatu.spaceapes.com
jcole@sarvik.tfr.cafe.ee
jcole@tetra.spaceapes.com
+jimw@mysql.com
joerg@mysql.com
joreland@mysql.com
jorge@linux.jorge.mysql.com
@@ -98,12 +99,15 @@ kaj@work.mysql.com
kent@mysql.com
konstantin@mysql.com
kostja@oak.local
+lars@mysql.com
lenz@kallisto.mysql.com
lenz@mysql.com
magnus@neptunus.(none)
magnus@shellback.(none)
marko@hundin.mysql.fi
+mats@mysql.com
matt@mysql.com
+matthias@three.local.lan
miguel@hegel.(none)
miguel@hegel.br
miguel@hegel.local
@@ -140,6 +144,7 @@ msvensson@build.mysql.com
mwagner@cash.mwagner.org
mwagner@evoq.mwagner.org
mwagner@here.mwagner.org
+mwagner@mysql.com
mwagner@work.mysql.com
mydev@mysql.com
mysql@home.(none)
@@ -154,6 +159,7 @@ nick@mysql.com
nick@nick.leippe.com
papa@gbichot.local
patg@krsna.patg.net
+patg@patrick-galbraiths-computer.local
paul@central.snake.net
paul@ice.local
paul@ice.snake.net
@@ -201,6 +207,7 @@ tim@bitch.mysql.fi
tim@black.box
tim@hundin.mysql.fi
tim@sand.box
+tim@siva.hindu.god
tim@threads.polyesthetic.msg
tim@white.box
tim@work.mysql.com
diff --git a/Build-tools/Bootstrap b/Build-tools/Bootstrap
index 8cad093bc5f..a7d347ba32f 100755
--- a/Build-tools/Bootstrap
+++ b/Build-tools/Bootstrap
@@ -288,6 +288,10 @@ unless ($opt_skip_manual)
system ("bk cat $opt_docdir/Docs/$file.texi > $target_dir/Docs/$file.texi") == 0
or &abort("Could not update $file.texi in $target_dir/Docs/!");
}
+ system ("rm -f $target_dir/Docs/Images/Makefile*") == 0
+ or &abort("Could not remove Makefiles in $target_dir/Docs/Images/!");
+ system ("cp $opt_docdir/Docs/Images/*.* $target_dir/Docs/Images") == 0
+ or &abort("Could not copy image files in $target_dir/Docs/Images/!");
}
#
diff --git a/Build-tools/Do-compile b/Build-tools/Do-compile
index f3c20c81a9f..f8e91efd70d 100755
--- a/Build-tools/Do-compile
+++ b/Build-tools/Do-compile
@@ -10,7 +10,7 @@ use Sys::Hostname;
$opt_distribution=$opt_user=$opt_config_env=$opt_config_extra_env="";
$opt_dbd_options=$opt_perl_options=$opt_config_options=$opt_make_options=$opt_suffix="";
$opt_tmp=$opt_version_suffix="";
-$opt_bundled_zlib=$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_cluster=$opt_with_debug=$opt_no_benchmark=$opt_no_mysqltest=$opt_without_embedded=$opt_readline=0;
+$opt_bundled_zlib=$opt_help=$opt_delete=$opt_debug=$opt_stage=$opt_no_test=$opt_no_perl=$opt_one_error=$opt_with_low_memory=$opt_fast_benchmark=$opt_static_client=$opt_static_server=$opt_static_perl=$opt_sur=$opt_with_small_disk=$opt_local_perl=$opt_tcpip=$opt_build_thread=$opt_use_old_distribution=$opt_enable_shared=$opt_no_crash_me=$opt_no_strip=$opt_with_archive=$opt_with_cluster=$opt_with_debug=$opt_no_benchmark=$opt_no_mysqltest=$opt_without_embedded=$opt_readline=0;
$opt_innodb=$opt_bdb=$opt_raid=$opt_libwrap=$opt_clearlogs=0;
GetOptions(
@@ -37,6 +37,7 @@ GetOptions(
"no-test",
"no-mysqltest",
"no-benchmark",
+ "one-error",
"perl-files=s",
"perl-options=s",
"raid",
@@ -52,6 +53,7 @@ GetOptions(
"use-old-distribution",
"user=s",
"version-suffix=s",
+ "with-archive",
"with-cluster",
"with-debug",
"with-low-memory",
@@ -272,6 +274,7 @@ if ($opt_stage <= 1)
$opt_config_options.= " --with-libedit";
}
$opt_config_options.= " --with-embedded-server" unless ($opt_without_embedded);
+ $opt_config_options.= " --with-archive-storage-engine" if ($opt_with_archive);
$opt_config_options.= " --with-ndbcluster" if ($opt_with_cluster);
# Only enable InnoDB when requested (required to be able to
@@ -310,6 +313,7 @@ if ($opt_stage <= 2)
$command=$make;
$command.= " $opt_make_options" if (defined($opt_make_options) && $opt_make_options ne "");
safe_system($command);
+ print LOG "Do-compile: Build successful\n";
}
#
@@ -372,11 +376,14 @@ $ENV{"LD_LIBRARY_PATH"}= ("$test_dir/lib" .
if ($opt_stage <= 5 && !$opt_no_test && !$opt_no_mysqltest)
{
my $flags= "";
+ my $force= "";
$flags.= " --with-ndbcluster" if ($opt_with_cluster);
+ $flags.= " --force" if (!$opt_one_error);
log_timestamp();
system("mkdir $bench_tmpdir") if (! -d $bench_tmpdir);
safe_cd("${test_dir}/mysql-test");
check_system("./mysql-test-run $flags --tmpdir=$bench_tmpdir --master_port=$mysql_tcp_port --slave_port=$slave_port --ndbcluster_port=$ndbcluster_port --manager-port=$manager_port --no-manager --sleep=10", "tests were successful");
+ # 'mysql-test-run' writes its own final message for log evaluation.
}
#
@@ -555,7 +562,10 @@ Do not run any tests.
Do not run the benchmark test (written in perl)
--no-mysqltest
-Do not run the the mysql-test-run test (Same as 'make test')
+Do not run the mysql-test-run test (Same as 'make test')
+
+--one-error
+Terminate the mysql-test-run test after the first difference (default: use '--force')
--no-perl
Do not compile or install Perl modules, use the system installed ones
@@ -601,6 +611,9 @@ If user is empty then no mail is sent.
--version-suffix=suffix
Set name suffix (e.g. 'com' or '-max') for a distribution
+--with archive
+Enable the Archive storage Engine
+
--with cluster
Compile and test with NDB Cluster enabled
diff --git a/Docs/Images/Makefile.am b/Docs/Images/Makefile.am
new file mode 100644
index 00000000000..b57d701d8a0
--- /dev/null
+++ b/Docs/Images/Makefile.am
@@ -0,0 +1,35 @@
+# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
+#
+# This library is free software; you can redistribute it and/or
+# modify it under the terms of the GNU Library General Public
+# License as published by the Free Software Foundation; either
+# version 2 of the License, or (at your option) any later version.
+#
+# This library 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
+# Library General Public License for more details.
+#
+# You should have received a copy of the GNU Library General Public
+# License along with this library; if not, write to the Free
+# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
+# MA 02111-1307, USA
+
+## Process this file with automake to create Makefile.in
+
+# This is a dummy file to satisfy the hierarchy of Makefiles.
+# When a release is built, the true Makefile will be copied
+# together with the "real" files in this directory.
+
+EXTRA_DIST =
+
+# Nothing to create in this dummy directory.
+all:
+ :
+
+# Nothing to cleanup in this dummy directory.
+clean:
+ :
+
+# Don't update the files from bitkeeper
+%::SCCS/s.%
diff --git a/Docs/Makefile.am b/Docs/Makefile.am
index 034cec3b133..681046543bd 100644
--- a/Docs/Makefile.am
+++ b/Docs/Makefile.am
@@ -9,7 +9,7 @@
# If you know how to fix any of this more elegantly please mail
# docs@mysql.com
-TEXI2HTML_FLAGS = -iso -number
+TEXI2HTML_FLAGS = -iso -number -acc
DVIPS = dvips
MAKEINFO = @MAKEINFO@
TEXINFO_TEX = Support/texinfo.tex
@@ -24,6 +24,8 @@ BUILT_SOURCES = $(targets) manual_toc.html include.texi
EXTRA_DIST = $(noinst_SCRIPTS) $(BUILT_SOURCES) mysqld_error.txt \
INSTALL-BINARY reservedwords.texi internals.texi
+SUBDIRS = Images
+
all: $(targets) txt_files
txt_files: ../INSTALL-SOURCE ../COPYING ../INSTALL-WIN-SOURCE ../EXCEPTIONS-CLIENT \
diff --git a/Docs/Support/texi2html b/Docs/Support/texi2html
index 8067d8f72ce..f13c006c7dc 100755
--- a/Docs/Support/texi2html
+++ b/Docs/Support/texi2html
@@ -1,4 +1,4 @@
-#!PATH_TO_PERL -*- perl -*-
+#!/usr/bin/perl
# Add path to perl on the previous line and make this executable
# if you want to use this as a normal script.
'di ';
@@ -12,7 +12,7 @@
#-##############################################################################
# @(#)texi2html 1.52 971230 Written (mainly) by Lionel Cons, Lionel.Cons@cern.ch
-# Enhanced by David Axmark, david@detron.se
+# Enhanced by David Axmark
# The man page for this program is included at the end of this file and can be
# viewed using the command 'nroff -man texi2html'.
@@ -40,8 +40,7 @@ $NODESRE = '[^@{}:\'`"]+'; # RE for a list of node names
$XREFRE = '[^@{}]+'; # RE for a xref (should use NODERE)
$ERROR = "***"; # prefix for errors and warnings
-$THISPROG = "texi2html 1.52 (hacked by david\@detron.se)"; # program name and version
-$HOMEPAGE = "http://www.mathematik.uni-kl.de/~obachman/Texi2html/"; # program home page
+$THISPROG = "texi2html 1.52 (with additions by MySQL AB)"; # program name and version
$TODAY = &pretty_date; # like "20 September 1993"
$SPLITTAG = "<!-- SPLIT HERE -->\n"; # tag to know where to split
$PROTECTTAG = "_ThisIsProtected_"; # tag to recognize protected sections
@@ -114,10 +113,12 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E
#
%accent_map = (
'"', 'uml',
+ '\'', 'acute',
+ ',{', 'cedil',
'~', 'tilde',
'^', 'circ',
'`', 'grave',
- '\'', 'acute',
+ 'ringaccent{', 'ring',
);
#
@@ -125,7 +126,7 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E
#
%simple_map = (
# cf. makeinfo.c
- "*", "<BR>", # HTML+
+ "*", "<br />", # HTML+
" ", " ",
"\n", "\n",
"|", "",
@@ -134,6 +135,8 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E
"!", "!",
"?", "?",
".", ".",
+ # @- means "allow word break", not &mdash;
+ "-", "",
);
#
@@ -141,9 +144,10 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E
#
%things_map = (
'TeX', 'TeX',
- 'br', '<P>', # paragraph break
+ 'br', '<p>', # paragraph break
'bullet', '*',
'copyright', '(C)',
+ 'registeredsymbol', '(R)',
'dots', '...',
'equiv', '==',
'error', 'error-->',
@@ -161,27 +165,28 @@ $html2_doctype = '<!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML 2.0 Strict Level 2//E
%style_map = (
'asis', '',
'b', 'B',
- 'cite', 'CITE',
- 'code', 'CODE',
+ 'cite', 'cite',
+ 'code', 'code',
+ 'command', 'code',
'ctrl', '&do_ctrl', # special case
- 'dfn', 'STRONG', # DFN tag is illegal in the standard
+ 'dfn', 'strong', # DFN tag is illegal in the standard
'dmn', '', # useless
'email', '&fix_email', # special
- 'emph', 'EM',
- 'file', '"TT', # will put quotes, cf. &apply_style
- 'i', 'I',
- 'kbd', 'KBD',
- 'key', 'KBD',
+ 'emph', 'em',
+ 'file', '"tt', # will put quotes, cf. &apply_style
+ 'i', 'i',
+ 'kbd', 'kbd',
+ 'key', 'kbd',
'r', '', # unsupported
- 'samp', '"SAMP', # will put quotes, cf. &apply_style
+ 'samp', '"samp', # will put quotes, cf. &apply_style
'sc', '&do_sc', # special case
- 'strong', 'STRONG',
- 't', 'TT',
+ 'strong', 'strong',
+ 't', 'tt',
'titlefont', '', # useless
'image', '&fix_image', # Image
'url', '&fix_url', # URL
'uref', '&fix_uref', # URL Reference
- 'var', 'VAR',
+ 'var', 'var',
'w', '', # unsupported
);
@@ -317,6 +322,7 @@ $usage = <<EOT;
This is $THISPROG
To convert a Texinfo file to HMTL: $0 [options] file
where options can be:
+-acc : convert @"-like accents to &entities;
-expandinfo : use \@ifinfo sections, not \@iftex
-glossary : handle a glossary
-invisible name: use 'name' as an invisible anchor
@@ -445,11 +451,15 @@ $html_num = 0;
if ($use_iso) {
$things_map{'bullet'} = "&bull;";
$things_map{'copyright'} = "&copy;";
+ $things_map{'registeredsymbol'} = "&reg;";
$things_map{'dots'} = "&hellip;";
$things_map{'equiv'} = "&equiv;";
$things_map{'expansion'} = "&rarr;";
$things_map{'point'} = "&lowast;";
$things_map{'result'} = "&rArr;";
+ $things_map{'ss'} = "&szlig;";
+ $things_map{'o'} = "&oslash;";
+ $things_map{'O'} = "&Oslash;";
}
#
@@ -505,23 +515,27 @@ $html_element = ''; # current HTML element
# watch out for regexps, / and escaped characters!
$subst_code = '';
foreach (keys(%simple_map)) {
- ($re = $_) =~ s/(\W)/\\$1/g; # protect regexp chars
- $subst_code .= "s/\\\@$re/$simple_map{$_}/g;\n";
+ $re = quotemeta $_; # protect regexp chars
+ $sub = quotemeta $simple_map{$_};
+ $subst_code .= "s/\\\@$re/$sub/g;\n";
}
foreach (keys(%things_map)) {
- $subst_code .= "s/\\\@$_\\{\\}/$things_map{$_}/g;\n";
+ $re = quotemeta $_; # protect regexp chars
+ $sub = quotemeta $things_map{$_};
+ $subst_code .= "s/\\\@$re\\{\\}/$sub/g;\n";
}
if ($use_acc) {
# accentuated characters
foreach (keys(%accent_map)) {
+ my $brace = /{$/ ? '}' : '';
if ($_ eq "`") {
$subst_code .= "s/$;3";
} elsif ($_ eq "'") {
$subst_code .= "s/$;4";
} else {
- $subst_code .= "s/\\\@\\$_";
+ $subst_code .= "s/\\\@\\Q$_\\E";
}
- $subst_code .= "([aeiou])/&\${1}$accent_map{$_};/gi;\n";
+ $subst_code .= "(\\w)$brace/&\${1}$accent_map{$_};/gi;\n";
}
}
eval("sub simple_substitutions { $subst_code }");
@@ -703,7 +717,7 @@ READ_LINE: while ($_ = &next_line)
s/{[^{}]+}//g);
print "# Multitable with $multitable_cols columns\n"
if $debug and $DEBUG_USER;
- push(@lines, &debug("<TABLE BORDER WIDTH=\"100%\">\n", __LINE__));
+ push(@lines, &debug("<TABLE BORDER>\n", __LINE__));
} else {
warn "$ERROR Bad table line: $_";
}
@@ -873,7 +887,7 @@ READ_LINE: while ($_ = &next_line)
&simple_substitutions;
s/\@value{($VARRE)}/$value{$1}/eg;
s/\@footnote\{/\@footnote$docu_doc\{/g; # mark footnotes, cf. pass 4
- s|\s+\@tab\s*| </TD><TD> |g if ($in_multitable);
+ s/(^|\s+)\@tab\s*/ <\/TD><TD> /g if ($in_multitable);
#
# analyze the tag again
@@ -885,7 +899,7 @@ READ_LINE: while ($_ = &next_line)
$name =~ s/\s+$//;
$level = $sec2level{$tag};
$name = &update_sec_num($tag, $level) . " $name"
- if $number_sections && $tag !~ /^unnumbered/;
+ if $number_sections && $tag !~ /^unnumbered/ && $tag ne 'subsubheading';
if ($tag =~ /heading$/) {
push(@lines, &html_debug("\n", __LINE__));
if ($html_element ne 'body') {
@@ -1079,7 +1093,7 @@ EOC
push(@lines, &debug("</TD></TR>\n", __LINE__))
unless $html_element eq 'TABLE';
&html_pop_if('TR');
- $what =~ s|\s+\@tab\s*| </TD><TD> |g;
+ $what =~ s/(^|\s+)\@tab\s*/ <\/TD><TD> /g;
push(@lines, &debug("<TR><TD>$what\n", __LINE__));
&html_push('TR');
if ($deferred_ref)
@@ -1463,11 +1477,7 @@ print "# end of pass 4\n" if $verbose;
# #
#---############################################################################
-$header = <<EOT;
-<!-- This HTML file has been created by $THISPROG
- from $docu on $TODAY -->
-EOT
-
+ $header = '';
$full_title = $value{'_title'} || $value{'_settitle'} || "Untitled Document";
$title = $value{'_settitle'} || $full_title;
$_ = &substitute_style($full_title);
@@ -1815,8 +1825,10 @@ sub fix_image
die "error in image: '$text'" unless defined($1);
$arg1 = $1;
$arg1 =~ s/@@/@/g;
- $ext = "jpg" if -f "$arg1.jpg";
- $ext = "gif" if -f "$arg1.gif";
+ foreach (@include_dirs) {
+ $ext = "jpg" if -f "$_/$arg1.jpg";
+ $ext = "gif" if -f "$_/$arg1.gif";
+ }
if (defined($ext))
{
"<IMG SRC=\"$arg1.$ext\">";
@@ -2010,7 +2022,7 @@ sub print_toplevel_header
{
local($_);
- &print_header; # pass given arg...
+ &print_header unless $opt_empty_headers; # pass given arg...
print FILE $full_title;
if ($value{'_subtitle'}) {
$value{'_subtitle'} =~ s/\n+$//;
@@ -2042,13 +2054,7 @@ EOT
sub print_toplevel_footer
{
- &print_ruler;
- print FILE <<EOT;
-This document was generated on $TODAY using the
-<A HREF=\"$HOMEPAGE\">texi2html</A>
-translator version 1.52 (extended by davida\@detron.se).</P>
-EOT
- &print_footer;
+ &print_footer unless $opt_empty_headers;
}
sub protect_texi
@@ -2065,8 +2071,10 @@ sub protect_html
{
local($what) = @_;
# protect & < >
- # Avoid loop in & replacement. This instead bugs out for &# in text..
- $what =~ s/\&([^#]|$)/\&\#38;$1/g;
+ # hack for the two entity-like variable reference in existing examples
+ $what =~ s/\&(length|ts);/\&\#38;$1;/g;
+ # this leaves alone entities, but encodes standalone ampersands
+ $what =~ s/\&(?!([a-z0-9]+|#\d+);)/\&\#38;/ig;
$what =~ s/\</\&\#60;/g;
$what =~ s/\>/\&\#62;/g;
# but recognize some HTML things
diff --git a/Docs/mysqld_error.txt b/Docs/mysqld_error.txt
index c164e8bd3a0..6370d8aac46 100644
--- a/Docs/mysqld_error.txt
+++ b/Docs/mysqld_error.txt
@@ -539,8 +539,8 @@ character-set=latin1
"Using storage engine %s for table '%s'",
#define ER_CANT_AGGREGATE_2COLLATIONS 1267
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-#define ER_DROP_USER 1268
-"Can't drop one or more of the requested users",
+#define ER_HANDLE_USER 1268
+"Operation %s failed for %d of the requested users",
#define ER_REVOKE_GRANTS 1269
"Can't revoke all privileges, grant for one or more of the requested users",
#define ER_CANT_AGGREGATE_3COLLATIONS 1270
diff --git a/Makefile.am b/Makefile.am
index efd8914ba9c..8c643c8a484 100644
--- a/Makefile.am
+++ b/Makefile.am
@@ -22,15 +22,15 @@ AUTOMAKE_OPTIONS = foreign
EXTRA_DIST = INSTALL-SOURCE README COPYING EXCEPTIONS-CLIENT
SUBDIRS = . include @docs_dirs@ @zlib_dir@ \
@readline_topdir@ sql-common \
- @thread_dirs@ pstack @sql_client_dirs@ \
- @sql_server_dirs@ scripts man tests \
+ @thread_dirs@ pstack \
+ @sql_server_dirs@ @sql_client_dirs@ scripts man tests \
netware @libmysqld_dirs@ \
@bench_dirs@ support-files @fs_dirs@ @tools_dirs@
DIST_SUBDIRS = . include @docs_dirs@ zlib \
@readline_topdir@ sql-common \
- @thread_dirs@ pstack @sql_client_dirs@ \
- @sql_server_dirs@ scripts @man_dirs@ tests SSL\
+ @thread_dirs@ pstack \
+ @sql_server_dirs@ @sql_client_dirs@ scripts @man_dirs@ tests SSL\
BUILD netware os2 @libmysqld_dirs@ \
@bench_dirs@ support-files @fs_dirs@ @tools_dirs@
diff --git a/VC++Files/client/mysqladmin.dsp b/VC++Files/client/mysqladmin.dsp
index a7e4404e253..7a0b3bec1a7 100644
--- a/VC++Files/client/mysqladmin.dsp
+++ b/VC++Files/client/mysqladmin.dsp
@@ -115,7 +115,7 @@ LINK32=xilink6.exe
# Name "mysqladmin - Win32 classic"
# Begin Source File
-SOURCE=.\mysqladmin.c
+SOURCE=.\mysqladmin.cpp
# End Source File
# End Target
# End Project
diff --git a/VC++Files/client/mysqltest.dsp b/VC++Files/client/mysqltest.dsp
new file mode 100644
index 00000000000..badd61a70b9
--- /dev/null
+++ b/VC++Files/client/mysqltest.dsp
@@ -0,0 +1,125 @@
+# Microsoft Developer Studio Project File - Name="mysqltest" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Console Application" 0x0103
+
+CFG=mysqltest - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysqltest.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysqltest.mak" CFG="mysqltest - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysqltest - Win32 Debug" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqltest - Win32 classic" (based on "Win32 (x86) Console Application")
+!MESSAGE "mysqltest - Win32 Release" (based on "Win32 (x86) Console Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysqltest - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir ".\debug"
+# PROP BASE Intermediate_Dir ".\debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir ".\debug"
+# PROP Intermediate_Dir ".\debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "USE_TLS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /c /GX
+# ADD CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "SAFEMALLOC" /D "SAFE_MUTEX" /D "_CONSOLE" /D "_WINDOWS" /D "USE_TLS" /D "_MBCS" /Fp".\debug/mysqltest.pch" /Fo".\debug/" /Fd".\debug/" /GZ /c /GX
+# ADD BASE MTL /nologo /tlb".\debug\mysqltest.tlb" /win32
+# ADD MTL /nologo /tlb".\debug\mysqltest.tlb" /win32
+# ADD BASE RSC /l 1033 /d "_DEBUG"
+# ADD RSC /l 1033 /d "_DEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib odbc32.lib odbccp32.lib mysys.lib /nologo /out:"..\client_debug\mysqltest.exe" /incremental:no /libpath:"..\lib_debug\" /debug /pdb:".\debug\mysqltest.pdb" /pdbtype:sept /subsystem:console /MACHINE:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib odbc32.lib odbccp32.lib mysys.lib /nologo /out:"..\client_debug\mysqltest.exe" /incremental:no /libpath:"..\lib_debug\" /debug /pdb:".\debug\mysqltest.pdb" /pdbtype:sept /subsystem:console /MACHINE:I386
+
+!ELSEIF "$(CFG)" == "mysqltest - Win32 classic"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\classic"
+# PROP BASE Intermediate_Dir ".\classic"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\classic"
+# PROP Intermediate_Dir ".\classic"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "../include" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /c /GX
+# ADD CPP /nologo /MT /I "../include" /I "../" /W3 /Ob1 /G6 /D "_CONSOLE" /D "_WINDOWS" /D "LICENSE=Commercial" /D "DBUG_OFF" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\classic/mysqltest.pch" /Fo".\classic/" /Fd".\classic/" /c /GX
+# ADD BASE MTL /nologo /tlb".\classic\mysqltest.tlb" /win32
+# ADD MTL /nologo /tlb".\classic\mysqltest.tlb" /win32
+# ADD BASE RSC /l 1033 /d "NDEBUG"
+# ADD RSC /l 1033 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib odbc32.lib odbccp32.lib /nologo /out:"..\client_classic\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\classic\mysqltest.pdb" /pdbtype:sept /subsystem:console /MACHINE:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib odbc32.lib odbccp32.lib /nologo /out:"..\client_classic\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\classic\mysqltest.pdb" /pdbtype:sept /subsystem:console /MACHINE:I386
+
+!ELSEIF "$(CFG)" == "mysqltest - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir ".\release"
+# PROP BASE Intermediate_Dir ".\release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir ".\release"
+# PROP Intermediate_Dir ".\release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MT /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /c /GX
+# ADD CPP /nologo /MT /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_CONSOLE" /D "_WINDOWS" /D "NDEBUG" /D "_MBCS" /GF /Gy /Fp".\release/mysqltest.pch" /Fo".\release/" /Fd".\release/" /c /GX
+# ADD BASE MTL /nologo /tlb".\release\mysqltest.tlb" /win32
+# ADD MTL /nologo /tlb".\release\mysqltest.tlb" /win32
+# ADD BASE RSC /l 1033 /d "NDEBUG"
+# ADD RSC /l 1033 /d "NDEBUG"
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib odbc32.lib odbccp32.lib /nologo /out:"..\client_release\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\release\mysqltest.pdb" /pdbtype:sept /subsystem:console /MACHINE:I386
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib mysqlclient.lib wsock32.lib odbc32.lib odbccp32.lib /nologo /out:"..\client_release\mysqltest.exe" /incremental:no /libpath:"..\lib_release\" /pdb:".\release\mysqltest.pdb" /pdbtype:sept /subsystem:console /MACHINE:I386
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysqltest - Win32 Debug"
+# Name "mysqltest - Win32 classic"
+# Name "mysqltest - Win32 Release"
+# Begin Source File
+
+SOURCE=..\libmysql\manager.c
+# End Source File
+# Begin Source File
+
+SOURCE=.\mysqltest.c
+# End Source File
+# End Target
+# End Project
+
diff --git a/VC++Files/libmysqld/libmysqld.dsp b/VC++Files/libmysqld/libmysqld.dsp
index 6b0e29f08fd..16ab7d63abc 100644
--- a/VC++Files/libmysqld/libmysqld.dsp
+++ b/VC++Files/libmysqld/libmysqld.dsp
@@ -544,6 +544,10 @@ SOURCE=..\sql\sql_test.cpp
# End Source File
# Begin Source File
+SOURCE=..\sql\sql_trigger.cpp
+# End Source File
+# Begin Source File
+
SOURCE=..\sql\sql_udf.cpp
# End Source File
# Begin Source File
diff --git a/VC++Files/mysql-test/mysql_test_run_new.dsp b/VC++Files/mysql-test/mysql_test_run_new.dsp
new file mode 100644
index 00000000000..bbdabb98a37
--- /dev/null
+++ b/VC++Files/mysql-test/mysql_test_run_new.dsp
@@ -0,0 +1,106 @@
+# Microsoft Developer Studio Project File - Name="mysql_test_run_new" - Package Owner=<4>
+# Microsoft Developer Studio Generated Build File, Format Version 6.00
+# ** DO NOT EDIT **
+
+# TARGTYPE "Win32 (x86) Application" 0x0101
+
+CFG=mysql_test_run_new - Win32 Debug
+!MESSAGE This is not a valid makefile. To build this project using NMAKE,
+!MESSAGE use the Export Makefile command and run
+!MESSAGE
+!MESSAGE NMAKE /f "mysql_test_run_new.mak".
+!MESSAGE
+!MESSAGE You can specify a configuration when running NMAKE
+!MESSAGE by defining the macro CFG on the command line. For example:
+!MESSAGE
+!MESSAGE NMAKE /f "mysql_test_run_new.mak" CFG="mysql_test_run_new - Win32 Debug"
+!MESSAGE
+!MESSAGE Possible choices for configuration are:
+!MESSAGE
+!MESSAGE "mysql_test_run_new - Win32 Debug" (based on "Win32 (x86) Application")
+!MESSAGE "mysql_test_run_new - Win32 Release" (based on "Win32 (x86) Application")
+!MESSAGE
+
+# Begin Project
+# PROP AllowPerConfigDependencies 0
+# PROP Scc_ProjName ""
+# PROP Scc_LocalPath ""
+CPP=cl.exe
+MTL=midl.exe
+RSC=rc.exe
+
+!IF "$(CFG)" == "mysql_test_run_new - Win32 Debug"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 1
+# PROP BASE Output_Dir "Debug"
+# PROP BASE Intermediate_Dir "Debug"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 1
+# PROP Output_Dir "Debug"
+# PROP Intermediate_Dir "Debug"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\debug/mysql_test_run.pch" /Fo".\debug/" /Fd".\debug/" /GZ /c /GX
+# ADD CPP /nologo /MTd /I "../include" /I "../" /Z7 /W3 /Od /G6 /D "_DEBUG" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /Fp".\debug/mysql_test_run.pch" /Fo".\debug/" /Fd".\debug/" /GZ /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1033
+# ADD RSC /l 1033
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\mysql-test\mysql_test_run_new.exe" /debug /pdb:".\debug\mysql_test_run_new.pdb" /pdbtype:sept /map /mapinfo:exports /subsystem:windows
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\mysql-test\mysql_test_run_new.exe" /debug /pdb:".\debug\mysql_test_run_new.pdb" /pdbtype:sept /map /mapinfo:exports /subsystem:windows
+
+!ELSEIF "$(CFG)" == "mysql_test_run_new - Win32 Release"
+
+# PROP BASE Use_MFC 0
+# PROP BASE Use_Debug_Libraries 0
+# PROP BASE Output_Dir "Release"
+# PROP BASE Intermediate_Dir "Release"
+# PROP BASE Target_Dir ""
+# PROP Use_MFC 0
+# PROP Use_Debug_Libraries 0
+# PROP Output_Dir "Release"
+# PROP Intermediate_Dir "Release"
+# PROP Target_Dir ""
+# ADD BASE CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fo".\release/" /Fd".\release/" /c /GX
+# ADD CPP /nologo /MTd /I "../include" /I "../" /W3 /Ob1 /G6 /D "DBUG_OFF" /D "_WINDOWS" /D "SAFE_MUTEX" /D "USE_TLS" /D "MYSQL_CLIENT" /D "__WIN__" /D "_WIN32" /GF /Gy /Fo".\release/" /Fd".\release/" /c /GX
+# ADD BASE MTL /nologo /win32
+# ADD MTL /nologo /win32
+# ADD BASE RSC /l 1033
+# ADD RSC /l 1033
+BSC32=bscmake.exe
+# ADD BASE BSC32 /nologo
+# ADD BSC32 /nologo
+LINK32=link.exe
+# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\mysql-test\mysql_test_run_new.exe" /pdbtype:sept /subsystem:windows
+# ADD LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib Ws2_32.lib /nologo /out:"..\mysql-test\mysql_test_run_new.exe" /pdbtype:sept /subsystem:windows
+
+!ENDIF
+
+# Begin Target
+
+# Name "mysql_test_run_new - Win32 Debug"
+# Name "mysql_test_run_new - Win32 Release"
+# Begin Source File
+
+SOURCE=my_create_tables.c
+# End Source File
+# Begin Source File
+
+SOURCE=my_manage.c
+# End Source File
+# Begin Source File
+
+SOURCE=my_manage.h
+# End Source File
+# Begin Source File
+
+SOURCE=mysql_test_run_new.c
+# End Source File
+# End Target
+# End Project
+
diff --git a/VC++Files/mysql.dsw b/VC++Files/mysql.dsw
index 61a466174b6..222b09c3d80 100644
--- a/VC++Files/mysql.dsw
+++ b/VC++Files/mysql.dsw
@@ -816,6 +816,30 @@ Package=<4>
###############################################################################
+Project: "mysqltest"=.\client\mysqltest.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
+Project: "mysql_test_run_new"=.\mysql-test\mysql_test_run_new.dsp - Package Owner=<4>
+
+Package=<5>
+{{{
+}}}
+
+Package=<4>
+{{{
+}}}
+
+###############################################################################
+
Global:
Package=<5>
diff --git a/VC++Files/sql/mysqld.dsp b/VC++Files/sql/mysqld.dsp
index c4475427823..ac0a241d661 100644
--- a/VC++Files/sql/mysqld.dsp
+++ b/VC++Files/sql/mysqld.dsp
@@ -1779,6 +1779,10 @@ SOURCE=.\sql_test.cpp
# End Source File
# Begin Source File
+SOURCE=.\sql_trigger.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\sql_udf.cpp
# End Source File
# Begin Source File
diff --git a/acinclude.m4 b/acinclude.m4
deleted file mode 100644
index 7f25b447f10..00000000000
--- a/acinclude.m4
+++ /dev/null
@@ -1,1874 +0,0 @@
-# Local macros for automake & autoconf
-
-
-AC_DEFUN([MYSQL_CHECK_READLINE_DECLARES_HIST_ENTRY], [
- AC_CACHE_CHECK([HIST_ENTRY is declared in readline/readline.h], mysql_cv_hist_entry_declared,
- AC_TRY_COMPILE(
- [
- #include "stdio.h"
- #include "readline/readline.h"
- ],
- [
- HIST_ENTRY entry;
- ],
- [
- mysql_cv_hist_entry_declared=yes
- AC_DEFINE_UNQUOTED(HAVE_HIST_ENTRY, [1],
- [HIST_ENTRY is defined in the outer libeditreadline])
- ],
- [mysql_cv_libedit_interface=no]
- )
- )
-])
-
-AC_DEFUN([MYSQL_CHECK_LIBEDIT_INTERFACE], [
- AC_CACHE_CHECK([libedit variant of rl_completion_entry_function], mysql_cv_libedit_interface,
- AC_TRY_COMPILE(
- [
- #include "stdio.h"
- #include "readline/readline.h"
- ],
- [
- char res= *(*rl_completion_entry_function)(0,0);
- completion_matches(0,0);
- ],
- [
- mysql_cv_libedit_interface=yes
- AC_DEFINE_UNQUOTED([USE_LIBEDIT_INTERFACE], [1],
- [used libedit interface (can we dereference result of rl_completion_entry_function)])
- ],
- [mysql_cv_libedit_interface=no]
- )
- )
-])
-
-AC_DEFUN([MYSQL_CHECK_NEW_RL_INTERFACE], [
- AC_CACHE_CHECK([defined rl_compentry_func_t and rl_completion_func_t], mysql_cv_new_rl_interface,
- AC_TRY_COMPILE(
- [
- #include "stdio.h"
- #include "readline/readline.h"
- ],
- [
- rl_completion_func_t *func1= (rl_completion_func_t*)0;
- rl_compentry_func_t *func2= (rl_compentry_func_t*)0;
- ],
- [
- mysql_cv_new_rl_interface=yes
- AC_DEFINE_UNQUOTED([USE_NEW_READLINE_INTERFACE], [1],
- [used new readline interface (are rl_completion_func_t and rl_compentry_func_t defined)])
- ],
- [mysql_cv_new_rl_interface=no]
- )
- )
-])
-
-# A local version of AC_CHECK_SIZEOF that includes sys/types.h
-dnl MYSQL_CHECK_SIZEOF(TYPE [, CROSS-SIZE])
-AC_DEFUN([MYSQL_CHECK_SIZEOF],
-[changequote(<<, >>)dnl
-dnl The name to #define.
-define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
-dnl The cache variable name.
-define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
-changequote([, ])dnl
-AC_MSG_CHECKING(size of $1)
-AC_CACHE_VAL(AC_CV_NAME,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-#if STDC_HEADERS
-#include <stdlib.h>
-#include <stddef.h>
-#endif
-main()
-{
- FILE *f=fopen("conftestval", "w");
- if (!f) exit(1);
- fprintf(f, "%d\n", sizeof($1));
- exit(0);
-}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$2], , , AC_CV_NAME=$2))])dnl
-AC_MSG_RESULT($AC_CV_NAME)
-AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [ ])
-undefine([AC_TYPE_NAME])dnl
-undefine([AC_CV_NAME])dnl
-])
-
-#---START: Used in for client configure
-AC_DEFUN([MYSQL_TYPE_ACCEPT],
-[ac_save_CXXFLAGS="$CXXFLAGS"
-AC_CACHE_CHECK([base type of last arg to accept], mysql_cv_btype_last_arg_accept,
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-if test "$ac_cv_prog_gxx" = "yes"
-then
- CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'`
-fi
-mysql_cv_btype_last_arg_accept=none
-[AC_TRY_COMPILE([#if defined(inline)
-#undef inline
-#endif
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-],
-[int a = accept(1, (struct sockaddr *) 0, (socklen_t *) 0); return (a != 0);],
-mysql_cv_btype_last_arg_accept=socklen_t)]
-if test "$mysql_cv_btype_last_arg_accept" = "none"; then
-[AC_TRY_COMPILE([#if defined(inline)
-#undef inline
-#endif
-#include <stdlib.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-],
-[int a = accept(1, (struct sockaddr *) 0, (size_t *) 0); return (a != 0);],
-mysql_cv_btype_last_arg_accept=size_t)]
-fi
-if test "$mysql_cv_btype_last_arg_accept" = "none"; then
-mysql_cv_btype_last_arg_accept=int
-fi)
-AC_LANG_RESTORE
-AC_DEFINE_UNQUOTED([SOCKET_SIZE_TYPE], [$mysql_cv_btype_last_arg_accept],
- [The base type of the last arg to accept])
-CXXFLAGS="$ac_save_CXXFLAGS"
-])
-#---END:
-
-dnl Find type of qsort
-AC_DEFUN([MYSQL_TYPE_QSORT],
-[AC_CACHE_CHECK([return type of qsort], mysql_cv_type_qsort,
-[AC_TRY_COMPILE([#include <stdlib.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-void qsort(void *base, size_t nel, size_t width,
- int (*compar) (const void *, const void *));
-],
-[int i;], mysql_cv_type_qsort=void, mysql_cv_type_qsort=int)])
-AC_DEFINE_UNQUOTED([RETQSORTTYPE], [$mysql_cv_type_qsort],
- [The return type of qsort (int or void).])
-if test "$mysql_cv_type_qsort" = "void"
-then
- AC_DEFINE_UNQUOTED([QSORT_TYPE_IS_VOID], [1], [qsort returns void])
-fi
-])
-
-AC_DEFUN([MYSQL_TIMESPEC_TS],
-[AC_CACHE_CHECK([if struct timespec has a ts_sec member], mysql_cv_timespec_ts,
-[AC_TRY_COMPILE([#include <pthread.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[struct timespec abstime;
-
-abstime.ts_sec = time(NULL)+1;
-abstime.ts_nsec = 0;
-], mysql_cv_timespec_ts=yes, mysql_cv_timespec_ts=no)])
-if test "$mysql_cv_timespec_ts" = "yes"
-then
- AC_DEFINE([HAVE_TIMESPEC_TS_SEC], [1],
- [Timespec has a ts_sec instead of tv_sev])
-fi
-])
-
-AC_DEFUN([MYSQL_TZNAME],
-[AC_CACHE_CHECK([if we have tzname variable], mysql_cv_tzname,
-[AC_TRY_COMPILE([#include <time.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[ tzset();
- return tzname[0] != 0;
-], mysql_cv_tzname=yes, mysql_cv_tzname=no)])
-if test "$mysql_cv_tzname" = "yes"
-then
- AC_DEFINE([HAVE_TZNAME], [1], [Have the tzname variable])
-fi
-])
-
-
-dnl Define zlib paths to point at bundled zlib
-
-AC_DEFUN([MYSQL_USE_BUNDLED_ZLIB], [
-ZLIB_INCLUDES="-I\$(top_srcdir)/zlib"
-ZLIB_LIBS="\$(top_builddir)/zlib/libz.la"
-zlib_dir="zlib"
-AC_SUBST([zlib_dir])
-mysql_cv_compress="yes"
-])
-
-dnl Auxiliary macro to check for zlib at given path
-
-AC_DEFUN([MYSQL_CHECK_ZLIB_DIR], [
-save_INCLUDES="$INCLUDES"
-save_LIBS="$LIBS"
-INCLUDES="$INCLUDES $ZLIB_INCLUDES"
-LIBS="$LIBS $ZLIB_LIBS"
-AC_CACHE_VAL([mysql_cv_compress],
- [AC_TRY_LINK([#include <zlib.h>],
- [int link_test() { return compress(0, (unsigned long*) 0, "", 0); }],
- [mysql_cv_compress="yes"
- AC_MSG_RESULT([ok])],
- [mysql_cv_compress="no"])
- ])
-INCLUDES="$save_INCLUDES"
-LIBS="$save_LIBS"
-])
-
-dnl MYSQL_CHECK_ZLIB_WITH_COMPRESS
-dnl ------------------------------------------------------------------------
-dnl @synopsis MYSQL_CHECK_ZLIB_WITH_COMPRESS
-dnl
-dnl Provides the following configure options:
-dnl --with-zlib-dir=DIR
-dnl Possible DIR values are:
-dnl - "no" - the macro will disable use of compression functions
-dnl - "bundled" - means use zlib bundled along with MySQL sources
-dnl - empty, or not specified - the macro will try default system
-dnl library (if present), and in case of error will fall back to
-dnl bundled zlib
-dnl - zlib location prefix - given location prefix, the macro expects
-dnl to find the library headers in $prefix/include, and binaries in
-dnl $prefix/lib. If zlib headers or binaries weren't found at $prefix, the
-dnl macro bails out with error.
-dnl
-dnl If the library was found, this function #defines HAVE_COMPRESS
-dnl and configure variables ZLIB_INCLUDES (i.e. -I/path/to/zlib/include) and
-dnl ZLIB_LIBS (i. e. -L/path/to/zlib/lib -lz).
-
-AC_DEFUN([MYSQL_CHECK_ZLIB_WITH_COMPRESS], [
-AC_MSG_CHECKING([for zlib compression library])
-case $SYSTEM_TYPE in
-*netware* | *modesto*)
- AC_MSG_RESULT(ok)
- AC_DEFINE([HAVE_COMPRESS], [1], [Define to enable compression support])
- ;;
- *)
- AC_ARG_WITH([zlib-dir],
- AC_HELP_STRING([--with-zlib-dir=DIR],
- [Provide MySQL with a custom location of
- compression library. Given DIR, zlib binary is
- assumed to be in $DIR/lib and header files
- in $DIR/include.]),
- [mysql_zlib_dir=${withval}],
- [mysql_zlib_dir=""])
- case "$mysql_zlib_dir" in
- "no")
- mysql_cv_compress="no"
- AC_MSG_RESULT([disabled])
- ;;
- "bundled")
- MYSQL_USE_BUNDLED_ZLIB
- AC_MSG_RESULT([using bundled zlib])
- ;;
- "")
- ZLIB_INCLUDES=""
- ZLIB_LIBS="-lz"
- MYSQL_CHECK_ZLIB_DIR
- if test "$mysql_cv_compress" = "no"; then
- MYSQL_USE_BUNDLED_ZLIB
- AC_MSG_RESULT([system-wide zlib not found, using one bundled with MySQL])
- fi
- ;;
- *)
- if test -f "$mysql_zlib_dir/lib/libz.a" -a \
- -f "$mysql_zlib_dir/include/zlib.h"; then
- ZLIB_INCLUDES="-I$mysql_zlib_dir/include"
- ZLIB_LIBS="-L$mysql_zlib_dir/lib -lz"
- MYSQL_CHECK_ZLIB_DIR
- fi
- if test "x$mysql_cv_compress" != "xyes"; then
- AC_MSG_ERROR([headers or binaries were not found in $mysql_zlib_dir/{include,lib}])
- fi
- ;;
- esac
- if test "$mysql_cv_compress" = "yes"; then
- AC_SUBST([ZLIB_LIBS])
- AC_SUBST([ZLIB_INCLUDES])
- AC_DEFINE([HAVE_COMPRESS], [1], [Define to enable compression support])
- fi
- ;;
-esac
-])
-
-dnl ------------------------------------------------------------------------
-
-#---START: Used in for client configure
-AC_DEFUN([MYSQL_CHECK_ULONG],
-[AC_MSG_CHECKING(for type ulong)
-AC_CACHE_VAL(ac_cv_ulong,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-main()
-{
- ulong foo;
- foo++;
- exit(0);
-}], ac_cv_ulong=yes, ac_cv_ulong=no, ac_cv_ulong=no)])
-AC_MSG_RESULT($ac_cv_ulong)
-if test "$ac_cv_ulong" = "yes"
-then
- AC_DEFINE([HAVE_ULONG], [1], [system headers define ulong])
-fi
-])
-
-AC_DEFUN([MYSQL_CHECK_UCHAR],
-[AC_MSG_CHECKING(for type uchar)
-AC_CACHE_VAL(ac_cv_uchar,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-main()
-{
- uchar foo;
- foo++;
- exit(0);
-}], ac_cv_uchar=yes, ac_cv_uchar=no, ac_cv_uchar=no)])
-AC_MSG_RESULT($ac_cv_uchar)
-if test "$ac_cv_uchar" = "yes"
-then
- AC_DEFINE([HAVE_UCHAR], [1], [system headers define uchar])
-fi
-])
-
-AC_DEFUN([MYSQL_CHECK_UINT],
-[AC_MSG_CHECKING(for type uint)
-AC_CACHE_VAL(ac_cv_uint,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-main()
-{
- uint foo;
- foo++;
- exit(0);
-}], ac_cv_uint=yes, ac_cv_uint=no, ac_cv_uint=no)])
-AC_MSG_RESULT($ac_cv_uint)
-if test "$ac_cv_uint" = "yes"
-then
- AC_DEFINE([HAVE_UINT], [1], [system headers define uint])
-fi
-])
-
-
-AC_DEFUN([MYSQL_CHECK_IN_ADDR_T],
-[AC_MSG_CHECKING(for type in_addr_t)
-AC_CACHE_VAL(ac_cv_in_addr_t,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-#include <sys/socket.h>
-#include <netinet/in.h>
-#include <arpa/inet.h>
-
-int main(int argc, char **argv)
-{
- in_addr_t foo;
- exit(0);
-}], ac_cv_in_addr_t=yes, ac_cv_in_addr_t=no, ac_cv_in_addr_t=no)])
-AC_MSG_RESULT($ac_cv_in_addr_t)
-if test "$ac_cv_in_addr_t" = "yes"
-then
- AC_DEFINE([HAVE_IN_ADDR_T], [1], [system headers define in_addr_t])
-fi
-])
-
-
-AC_DEFUN([MYSQL_PTHREAD_YIELD],
-[AC_CACHE_CHECK([if pthread_yield takes zero arguments], ac_cv_pthread_yield_zero_arg,
-[AC_TRY_LINK([#define _GNU_SOURCE
-#include <pthread.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[
- pthread_yield();
-], ac_cv_pthread_yield_zero_arg=yes, ac_cv_pthread_yield_zero_arg=yeso)])
-if test "$ac_cv_pthread_yield_zero_arg" = "yes"
-then
- AC_DEFINE([HAVE_PTHREAD_YIELD_ZERO_ARG], [1],
- [pthread_yield that doesn't take any arguments])
-fi
-]
-[AC_CACHE_CHECK([if pthread_yield takes 1 argument], ac_cv_pthread_yield_one_arg,
-[AC_TRY_LINK([#define _GNU_SOURCE
-#include <pthread.h>
-#ifdef __cplusplus
-extern "C"
-#endif
-],
-[
- pthread_yield(0);
-], ac_cv_pthread_yield_one_arg=yes, ac_cv_pthread_yield_one_arg=no)])
-if test "$ac_cv_pthread_yield_one_arg" = "yes"
-then
- AC_DEFINE([HAVE_PTHREAD_YIELD_ONE_ARG], [1],
- [pthread_yield function with one argument])
-fi
-]
-)
-
-
-
-#---END:
-
-AC_DEFUN([MYSQL_CHECK_FP_EXCEPT],
-[AC_MSG_CHECKING(for type fp_except)
-AC_CACHE_VAL(ac_cv_fp_except,
-[AC_TRY_RUN([#include <stdio.h>
-#include <sys/types.h>
-#include <ieeefp.h>
-main()
-{
- fp_except foo;
- foo++;
- exit(0);
-}], ac_cv_fp_except=yes, ac_cv_fp_except=no, ac_cv_fp_except=no)])
-AC_MSG_RESULT($ac_cv_fp_except)
-if test "$ac_cv_fp_except" = "yes"
-then
- AC_DEFINE([HAVE_FP_EXCEPT], [1], [fp_except from ieeefp.h])
-fi
-])
-
-# From fileutils-3.14/aclocal.m4
-
-# @defmac AC_PROG_CC_STDC
-# @maindex PROG_CC_STDC
-# @ovindex CC
-# If the C compiler in not in ANSI C mode by default, try to add an option
-# to output variable @code{CC} to make it so. This macro tries various
-# options that select ANSI C on some system or another. It considers the
-# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
-# handles function prototypes correctly.
-#
-# Patched by monty to only check if __STDC__ is defined. With the original
-# check it's impossible to get things to work with the Sunpro compiler from
-# Workshop 4.2
-#
-# If you use this macro, you should check after calling it whether the C
-# compiler has been set to accept ANSI C; if not, the shell variable
-# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
-# code in ANSI C, you can make an un-ANSIfied copy of it by using the
-# program @code{ansi2knr}, which comes with Ghostscript.
-# @end defmac
-
-AC_DEFUN([AM_PROG_CC_STDC],
-[AC_REQUIRE([AC_PROG_CC])
-AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
-AC_CACHE_VAL(am_cv_prog_cc_stdc,
-[am_cv_prog_cc_stdc=no
-ac_save_CC="$CC"
-# Don't try gcc -ansi; that turns off useful extensions and
-# breaks some systems' header files.
-# AIX -qlanglvl=ansi
-# Ultrix and OSF/1 -std1
-# HP-UX -Aa -D_HPUX_SOURCE
-# SVR4 -Xc -D__EXTENSIONS__
-# removed "-Xc -D__EXTENSIONS__" beacause sun c++ does not like it.
-for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE"
-do
- CC="$ac_save_CC $ac_arg"
- AC_TRY_COMPILE(
-[#if !defined(__STDC__)
-choke me
-#endif
-/* DYNIX/ptx V4.1.3 can't compile sys/stat.h with -Xc -D__EXTENSIONS__. */
-#ifdef _SEQUENT_
-# include <sys/types.h>
-# include <sys/stat.h>
-#endif
-], [
-int test (int i, double x);
-struct s1 {int (*f) (int a);};
-struct s2 {int (*f) (double a);};],
-[am_cv_prog_cc_stdc="$ac_arg"; break])
-done
-CC="$ac_save_CC"
-])
-AC_MSG_RESULT($am_cv_prog_cc_stdc)
-case "x$am_cv_prog_cc_stdc" in
- x|xno) ;;
- *) CC="$CC $am_cv_prog_cc_stdc" ;;
-esac
-])
-
-#
-# Check to make sure that the build environment is sane.
-#
-
-AC_DEFUN([AM_SANITY_CHECK],
-[AC_MSG_CHECKING([whether build environment is sane])
-sleep 1
-echo timestamp > conftestfile
-# Do this in a subshell so we don't clobber the current shell's
-# arguments. FIXME: maybe try `-L' hack like GETLOADAVG test?
-if (set X `ls -t $srcdir/configure conftestfile`; test "[$]2" = conftestfile)
-then
- # Ok.
- :
-else
- AC_MSG_ERROR([newly created file is older than distributed files!
-Check your system clock])
-fi
-rm -f conftest*
-AC_MSG_RESULT(yes)])
-
-# Orginal from bash-2.0 aclocal.m4, Changed to use termcap last by monty.
-
-AC_DEFUN([MYSQL_CHECK_LIB_TERMCAP],
-[
-AC_CACHE_VAL(mysql_cv_termcap_lib,
-[AC_CHECK_LIB(ncurses, tgetent, mysql_cv_termcap_lib=libncurses,
- [AC_CHECK_LIB(curses, tgetent, mysql_cv_termcap_lib=libcurses,
- [AC_CHECK_LIB(termcap, tgetent, mysql_cv_termcap_lib=libtermcap,
- mysql_cv_termcap_lib=NOT_FOUND)])])])
-AC_MSG_CHECKING(for termcap functions library)
-if test "$mysql_cv_termcap_lib" = "NOT_FOUND"; then
-AC_MSG_ERROR([No curses/termcap library found])
-elif test "$mysql_cv_termcap_lib" = "libtermcap"; then
-TERMCAP_LIB=-ltermcap
-elif test "$mysql_cv_termcap_lib" = "libncurses"; then
-TERMCAP_LIB=-lncurses
-else
-TERMCAP_LIB=-lcurses
-fi
-AC_MSG_RESULT($TERMCAP_LIB)
-])
-
-dnl Check type of signal routines (posix, 4.2bsd, 4.1bsd or v7)
-AC_DEFUN([MYSQL_SIGNAL_CHECK],
-[AC_REQUIRE([AC_TYPE_SIGNAL])
-AC_MSG_CHECKING(for type of signal functions)
-AC_CACHE_VAL(mysql_cv_signal_vintage,
-[
- AC_TRY_LINK([#include <signal.h>],[
- sigset_t ss;
- struct sigaction sa;
- sigemptyset(&ss); sigsuspend(&ss);
- sigaction(SIGINT, &sa, (struct sigaction *) 0);
- sigprocmask(SIG_BLOCK, &ss, (sigset_t *) 0);
- ], mysql_cv_signal_vintage=posix,
- [
- AC_TRY_LINK([#include <signal.h>], [
- int mask = sigmask(SIGINT);
- sigsetmask(mask); sigblock(mask); sigpause(mask);
- ], mysql_cv_signal_vintage=4.2bsd,
- [
- AC_TRY_LINK([
- #include <signal.h>
- RETSIGTYPE foo() { }], [
- int mask = sigmask(SIGINT);
- sigset(SIGINT, foo); sigrelse(SIGINT);
- sighold(SIGINT); sigpause(SIGINT);
- ], mysql_cv_signal_vintage=svr3, mysql_cv_signal_vintage=v7
- )]
- )]
-)
-])
-AC_MSG_RESULT($mysql_cv_signal_vintage)
-if test "$mysql_cv_signal_vintage" = posix; then
-AC_DEFINE(HAVE_POSIX_SIGNALS, [1],
- [Signal handling is POSIX (sigset/sighold, etc)])
-elif test "$mysql_cv_signal_vintage" = "4.2bsd"; then
-AC_DEFINE([HAVE_BSD_SIGNALS], [1], [BSD style signals])
-elif test "$mysql_cv_signal_vintage" = svr3; then
-AC_DEFINE(HAVE_USG_SIGHOLD, [1], [sighold() is present and usable])
-fi
-])
-
-AC_DEFUN([MYSQL_CHECK_GETPW_FUNCS],
-[AC_MSG_CHECKING(whether programs are able to redeclare getpw functions)
-AC_CACHE_VAL(mysql_cv_can_redecl_getpw,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <pwd.h>
-extern struct passwd *getpwent();], [struct passwd *z; z = getpwent();],
- mysql_cv_can_redecl_getpw=yes,mysql_cv_can_redecl_getpw=no)])
-AC_MSG_RESULT($mysql_cv_can_redecl_getpw)
-if test "$mysql_cv_can_redecl_getpw" = "no"; then
-AC_DEFINE(HAVE_GETPW_DECLS, [1], [getpwent() declaration present])
-fi
-])
-
-AC_DEFUN([MYSQL_HAVE_TIOCGWINSZ],
-[AC_MSG_CHECKING(for TIOCGWINSZ in sys/ioctl.h)
-AC_CACHE_VAL(mysql_cv_tiocgwinsz_in_ioctl,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/ioctl.h>], [int x = TIOCGWINSZ;],
- mysql_cv_tiocgwinsz_in_ioctl=yes,mysql_cv_tiocgwinsz_in_ioctl=no)])
-AC_MSG_RESULT($mysql_cv_tiocgwinsz_in_ioctl)
-if test "$mysql_cv_tiocgwinsz_in_ioctl" = "yes"; then
-AC_DEFINE([GWINSZ_IN_SYS_IOCTL], [1],
- [READLINE: your system defines TIOCGWINSZ in sys/ioctl.h.])
-fi
-])
-
-AC_DEFUN([MYSQL_HAVE_FIONREAD],
-[AC_MSG_CHECKING(for FIONREAD in sys/ioctl.h)
-AC_CACHE_VAL(mysql_cv_fionread_in_ioctl,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/ioctl.h>], [int x = FIONREAD;],
- mysql_cv_fionread_in_ioctl=yes,mysql_cv_fionread_in_ioctl=no)])
-AC_MSG_RESULT($mysql_cv_fionread_in_ioctl)
-if test "$mysql_cv_fionread_in_ioctl" = "yes"; then
-AC_DEFINE([FIONREAD_IN_SYS_IOCTL], [1], [Do we have FIONREAD])
-fi
-])
-
-AC_DEFUN([MYSQL_HAVE_TIOCSTAT],
-[AC_MSG_CHECKING(for TIOCSTAT in sys/ioctl.h)
-AC_CACHE_VAL(mysql_cv_tiocstat_in_ioctl,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <sys/ioctl.h>], [int x = TIOCSTAT;],
- mysql_cv_tiocstat_in_ioctl=yes,mysql_cv_tiocstat_in_ioctl=no)])
-AC_MSG_RESULT($mysql_cv_tiocstat_in_ioctl)
-if test "$mysql_cv_tiocstat_in_ioctl" = "yes"; then
-AC_DEFINE(TIOCSTAT_IN_SYS_IOCTL, [1],
- [declaration of TIOCSTAT in sys/ioctl.h])
-fi
-])
-
-AC_DEFUN([MYSQL_STRUCT_DIRENT_D_INO],
-[AC_REQUIRE([AC_HEADER_DIRENT])
-AC_MSG_CHECKING(if struct dirent has a d_ino member)
-AC_CACHE_VAL(mysql_cv_dirent_has_dino,
-[AC_TRY_COMPILE([
-#include <stdio.h>
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#if defined(HAVE_DIRENT_H)
-# include <dirent.h>
-#else
-# define dirent direct
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif /* SYSNDIR */
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif /* SYSDIR */
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif /* HAVE_DIRENT_H */
-],[
-struct dirent d; int z; z = d.d_ino;
-], mysql_cv_dirent_has_dino=yes, mysql_cv_dirent_has_dino=no)])
-AC_MSG_RESULT($mysql_cv_dirent_has_dino)
-if test "$mysql_cv_dirent_has_dino" = "yes"; then
-AC_DEFINE(STRUCT_DIRENT_HAS_D_INO, [1],
- [d_ino member present in struct dirent])
-fi
-])
-
-AC_DEFUN([MYSQL_STRUCT_DIRENT_D_NAMLEN],
-[AC_REQUIRE([AC_HEADER_DIRENT])
-AC_MSG_CHECKING(if struct dirent has a d_namlen member)
-AC_CACHE_VAL(mysql_cv_dirent_has_dnamlen,
-[AC_TRY_COMPILE([
-#include <stdio.h>
-#include <sys/types.h>
-#ifdef HAVE_UNISTD_H
-# include <unistd.h>
-#endif /* HAVE_UNISTD_H */
-#if defined(HAVE_DIRENT_H)
-# include <dirent.h>
-#else
-# define dirent direct
-# ifdef HAVE_SYS_NDIR_H
-# include <sys/ndir.h>
-# endif /* SYSNDIR */
-# ifdef HAVE_SYS_DIR_H
-# include <sys/dir.h>
-# endif /* SYSDIR */
-# ifdef HAVE_NDIR_H
-# include <ndir.h>
-# endif
-#endif /* HAVE_DIRENT_H */
-],[
-struct dirent d; int z; z = (int)d.d_namlen;
-], mysql_cv_dirent_has_dnamlen=yes, mysql_cv_dirent_has_dnamlen=no)])
-AC_MSG_RESULT($mysql_cv_dirent_has_dnamlen)
-if test "$mysql_cv_dirent_has_dnamlen" = "yes"; then
-AC_DEFINE(STRUCT_DIRENT_HAS_D_NAMLEN, [1],
- [d_namlen member present in struct dirent])
-fi
-])
-
-
-AC_DEFUN([MYSQL_TYPE_SIGHANDLER],
-[AC_MSG_CHECKING([whether signal handlers are of type void])
-AC_CACHE_VAL(mysql_cv_void_sighandler,
-[AC_TRY_COMPILE([#include <sys/types.h>
-#include <signal.h>
-#ifdef signal
-#undef signal
-#endif
-#ifdef __cplusplus
-extern "C"
-#endif
-void (*signal ()) ();],
-[int i;], mysql_cv_void_sighandler=yes, mysql_cv_void_sighandler=no)])dnl
-AC_MSG_RESULT($mysql_cv_void_sighandler)
-if test "$mysql_cv_void_sighandler" = "yes"; then
-AC_DEFINE(VOID_SIGHANDLER, [1], [sighandler type is void (*signal ()) ();])
-fi
-])
-
-AC_DEFUN([MYSQL_CXX_BOOL],
-[
-AC_REQUIRE([AC_PROG_CXX])
-AC_MSG_CHECKING(if ${CXX} supports bool types)
-AC_CACHE_VAL(mysql_cv_have_bool,
-[
-AC_LANG_SAVE
-AC_LANG_CPLUSPLUS
-AC_TRY_COMPILE(,[bool b = true;],
-mysql_cv_have_bool=yes,
-mysql_cv_have_bool=no)
-AC_LANG_RESTORE
-])
-AC_MSG_RESULT($mysql_cv_have_bool)
-if test "$mysql_cv_have_bool" = yes; then
-AC_DEFINE([HAVE_BOOL], [1], [bool is not defined by all C++ compilators])
-fi
-])dnl
-
-AC_DEFUN([MYSQL_STACK_DIRECTION],
- [AC_CACHE_CHECK(stack direction for C alloca, ac_cv_c_stack_direction,
- [AC_TRY_RUN([#include <stdlib.h>
- int find_stack_direction ()
- {
- static char *addr = 0;
- auto char dummy;
- if (addr == 0)
- {
- addr = &dummy;
- return find_stack_direction ();
- }
- else
- return (&dummy > addr) ? 1 : -1;
- }
- int main ()
- {
- exit (find_stack_direction() < 0);
- }], ac_cv_c_stack_direction=1, ac_cv_c_stack_direction=-1,
- ac_cv_c_stack_direction=0)])
- AC_DEFINE_UNQUOTED(STACK_DIRECTION, $ac_cv_c_stack_direction)
-])dnl
-
-AC_DEFUN([MYSQL_FUNC_ALLOCA],
-[
-# Since we have heard that alloca fails on IRIX never define it on a
-# SGI machine
-if test ! "$host_vendor" = "sgi"
-then
- AC_REQUIRE_CPP()dnl Set CPP; we run AC_EGREP_CPP conditionally.
- # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
- # for constant arguments. Useless!
- AC_CACHE_CHECK([for working alloca.h], ac_cv_header_alloca_h,
- [AC_TRY_LINK([#include <alloca.h>], [char *p = alloca(2 * sizeof(int));],
- ac_cv_header_alloca_h=yes, ac_cv_header_alloca_h=no)])
- if test "$ac_cv_header_alloca_h" = "yes"
- then
- AC_DEFINE(HAVE_ALLOCA, 1)
- fi
-
- AC_CACHE_CHECK([for alloca], ac_cv_func_alloca_works,
- [AC_TRY_LINK([
- #ifdef __GNUC__
- # define alloca __builtin_alloca
- #else
- # if HAVE_ALLOCA_H
- # include <alloca.h>
- # else
- # ifdef _AIX
- #pragma alloca
- # else
- # ifndef alloca /* predefined by HP cc +Olibcalls */
- char *alloca ();
- # endif
- # endif
- # endif
- #endif
- ], [char *p = (char *) alloca(1);],
- ac_cv_func_alloca_works=yes, ac_cv_func_alloca_works=no)])
- if test "$ac_cv_func_alloca_works" = "yes"; then
- AC_DEFINE([HAVE_ALLOCA], [1], [If we have a working alloca() implementation])
- fi
-
- if test "$ac_cv_func_alloca_works" = "no"; then
- # The SVR3 libPW and SVR4 libucb both contain incompatible functions
- # that cause trouble. Some versions do not even contain alloca or
- # contain a buggy version. If you still want to use their alloca,
- # use ar to extract alloca.o from them instead of compiling alloca.c.
- ALLOCA=alloca.o
- AC_DEFINE(C_ALLOCA, 1)
-
- AC_CACHE_CHECK(whether alloca needs Cray hooks, ac_cv_os_cray,
- [AC_EGREP_CPP(webecray,
- [#if defined(CRAY) && ! defined(CRAY2)
- webecray
- #else
- wenotbecray
- #endif
- ], ac_cv_os_cray=yes, ac_cv_os_cray=no)])
- if test "$ac_cv_os_cray" = "yes"; then
- for ac_func in _getb67 GETB67 getb67; do
- AC_CHECK_FUNC($ac_func, [AC_DEFINE_UNQUOTED(CRAY_STACKSEG_END, $ac_func)
- break])
- done
- fi
- fi
- AC_SUBST(ALLOCA)dnl
-else
- AC_MSG_RESULT("Skipped alloca tests")
-fi
-])
-
-AC_DEFUN([MYSQL_CHECK_LONGLONG_TO_FLOAT],
-[
-AC_MSG_CHECKING(if conversion of longlong to float works)
-AC_CACHE_VAL(ac_cv_conv_longlong_to_float,
-[AC_TRY_RUN([#include <stdio.h>
-typedef long long longlong;
-main()
-{
- longlong ll=1;
- float f;
- FILE *file=fopen("conftestval", "w");
- f = (float) ll;
- fprintf(file,"%g\n",f);
- fclose(file);
- exit (0);
-}], ac_cv_conv_longlong_to_float=`cat conftestval`, ac_cv_conv_longlong_to_float=0, ifelse([$2], , , ac_cv_conv_longlong_to_float=$2))])dnl
-if test "$ac_cv_conv_longlong_to_float" = "1" -o "$ac_cv_conv_longlong_to_float" = "yes"
-then
- ac_cv_conv_longlong_to_float=yes
-else
- ac_cv_conv_longlong_to_float=no
-fi
-AC_MSG_RESULT($ac_cv_conv_longlong_to_float)
-])
-
-AC_DEFUN([MYSQL_CHECK_CPU],
-[AC_CACHE_CHECK([if compiler supports optimizations for current cpu],
-mysql_cv_cpu,[
-
-ac_save_CFLAGS="$CFLAGS"
-if test -r /proc/cpuinfo ; then
- cpuinfo="cat /proc/cpuinfo"
- cpu_family=`$cpuinfo | grep 'cpu family' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1`
- cpu_vendor=`$cpuinfo | grep 'vendor_id' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1`
-fi
-if test "$cpu_vendor" = "AuthenticAMD"; then
- if test $cpu_family -ge 6; then
- cpu_set="athlon pentiumpro k5 pentium i486 i386";
- elif test $cpu_family -eq 5; then
- cpu_set="k5 pentium i486 i386";
- elif test $cpu_family -eq 4; then
- cpu_set="i486 i386"
- else
- cpu_set="i386"
- fi
-elif test "$cpu_vendor" = "GenuineIntel"; then
- if test $cpu_family -ge 6; then
- cpu_set="pentiumpro pentium i486 i386";
- elif test $cpu_family -eq 5; then
- cpu_set="pentium i486 i386";
- elif test $cpu_family -eq 4; then
- cpu_set="i486 i386"
- else
- cpu_set="i386"
- fi
-fi
-
-for ac_arg in $cpu_set;
-do
- CFLAGS="$ac_save_CFLAGS -mcpu=$ac_arg -march=$ac_arg -DCPU=$ac_arg"
- AC_TRY_COMPILE([],[int i],mysql_cv_cpu=$ac_arg; break;, mysql_cv_cpu="unknown")
-done
-
-if test "$mysql_cv_cpu" = "unknown"
-then
- CFLAGS="$ac_save_CFLAGS"
- AC_MSG_RESULT(none)
-else
- AC_MSG_RESULT($mysql_cv_cpu)
-fi
-]]))
-
-AC_DEFUN([MYSQL_CHECK_VIO], [
- AC_ARG_WITH([vio],
- [ --with-vio Include the Virtual IO support],
- [vio="$withval"],
- [vio=no])
-
- if test "$vio" = "yes"
- then
- vio_dir="vio"
- vio_libs="../vio/libvio.la"
- AC_DEFINE(HAVE_VIO, 1)
- else
- vio_dir=""
- vio_libs=""
- fi
- AC_SUBST([vio_dir])
- AC_SUBST([vio_libs])
-])
-
-AC_DEFUN([MYSQL_FIND_OPENSSL], [
- incs="$1"
- libs="$2"
- case "$incs---$libs" in
- ---)
- for d in /usr/ssl/include /usr/local/ssl/include /usr/include \
-/usr/include/ssl /opt/ssl/include /opt/openssl/include \
-/usr/local/ssl/include /usr/local/include /usr/freeware/include ; do
- if test -f $d/openssl/ssl.h ; then
- OPENSSL_INCLUDE=-I$d
- fi
- done
-
- for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \
-/usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib \
-/usr/freeware/lib32 /usr/local/lib/ ; do
- if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl.dylib ; then
- OPENSSL_LIB=$d
- fi
- done
- ;;
- ---* | *---)
- AC_MSG_ERROR([if either 'includes' or 'libs' is specified, both must be specified])
- ;;
- * )
- if test -f $incs/openssl/ssl.h ; then
- OPENSSL_INCLUDE=-I$incs
- fi
- if test -f $libs/libssl.a || test -f $libs/libssl.so || test -f $libs/libssl.dylib ; then
- OPENSSL_LIB=$libs
- fi
- ;;
- esac
-
- # On RedHat 9 we need kerberos to compile openssl
- for d in /usr/kerberos/include
- do
- if test -f $d/krb5.h ; then
- OPENSSL_KERBEROS_INCLUDE="$d"
- fi
- done
-
-
- if test -z "$OPENSSL_LIB" -o -z "$OPENSSL_INCLUDE" ; then
- echo "Could not find an installation of OpenSSL"
- if test -n "$OPENSSL_LIB" ; then
- if test "$IS_LINUX" = "true"; then
- echo "Looks like you've forgotten to install OpenSSL development RPM"
- fi
- fi
- exit 1
- fi
-
-])
-
-AC_DEFUN([MYSQL_CHECK_OPENSSL], [
-AC_MSG_CHECKING(for OpenSSL)
- AC_ARG_WITH([openssl],
- [ --with-openssl[=DIR] Include the OpenSSL support],
- [openssl="$withval"],
- [openssl=no])
-
- AC_ARG_WITH([openssl-includes],
- [
- --with-openssl-includes=DIR
- Find OpenSSL headers in DIR],
- [openssl_includes="$withval"],
- [openssl_includes=""])
-
- AC_ARG_WITH([openssl-libs],
- [
- --with-openssl-libs=DIR
- Find OpenSSL libraries in DIR],
- [openssl_libs="$withval"],
- [openssl_libs=""])
-
- if test "$openssl" != "no"
- then
- if test "$openssl" != "yes"
- then
- if test -z "$openssl_includes"
- then
- openssl_includes="$openssl/include"
- fi
- if test -z "$openssl_libs"
- then
- openssl_libs="$openssl/lib"
- fi
- fi
- MYSQL_FIND_OPENSSL([$openssl_includes], [$openssl_libs])
- #force VIO use
- vio_dir="vio"
- vio_libs="../vio/libvio.la"
- AC_DEFINE([HAVE_VIO], [1], [Virtual IO])
- AC_MSG_RESULT(yes)
- openssl_libs="-L$OPENSSL_LIB -lssl -lcrypto"
- # Don't set openssl_includes to /usr/include as this gives us a lot of
- # compiler warnings when using gcc 3.x
- openssl_includes=""
- if test "$OPENSSL_INCLUDE" != "-I/usr/include"
- then
- openssl_includes="$OPENSSL_INCLUDE"
- fi
- if test "$OPENSSL_KERBEROS_INCLUDE"
- then
- openssl_includes="$openssl_includes -I$OPENSSL_KERBEROS_INCLUDE"
- fi
- AC_DEFINE([HAVE_OPENSSL], [1], [OpenSSL])
-
- # openssl-devel-0.9.6 requires dlopen() and we can't link staticly
- # on many platforms (We should actually test this here, but it's quite
- # hard) to do as we are doing libtool for linking.
- using_static=""
- case "$CLIENT_EXTRA_LDFLAGS $MYSQLD_EXTRA_LDFLAGS" in
- *-all-static*) using_static="yes" ;;
- esac
- if test "$using_static" = "yes"
- then
- echo "You can't use the --all-static link option when using openssl."
- exit 1
- fi
- NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS $openssl_libs"
- else
- AC_MSG_RESULT(no)
- if test ! -z "$openssl_includes"
- then
- AC_MSG_ERROR(Can't have --with-openssl-includes without --with-openssl);
- fi
- if test ! -z "$openssl_libs"
- then
- AC_MSG_ERROR(Can't have --with-openssl-libs without --with-openssl);
- fi
- fi
- AC_SUBST(openssl_libs)
- AC_SUBST(openssl_includes)
-])
-
-
-AC_DEFUN([MYSQL_CHECK_MYSQLFS], [
- AC_ARG_WITH([mysqlfs],
- [
- --with-mysqlfs Include the corba-based MySQL file system],
- [mysqlfs="$withval"],
- [mysqlfs=no])
-
-dnl Call MYSQL_CHECK_ORBIT even if mysqlfs == no, so that @orbit_*@
-dnl get substituted.
- MYSQL_CHECK_ORBIT
-
- AC_MSG_CHECKING(if we should build MySQLFS)
- fs_dirs=""
- if test "$mysqlfs" = "yes"
- then
- if test -n "$orbit_exec_prefix"
- then
- fs_dirs=fs
- AC_MSG_RESULT([yes])
- else
- AC_MSG_RESULT(disabled because ORBIT, the CORBA ORB, was not found)
- fi
- else
- AC_MSG_RESULT([no])
- fi
- AC_SUBST([fs_dirs])
-])
-
-AC_DEFUN([MYSQL_CHECK_ORBIT], [
-AC_MSG_CHECKING(for ORBit)
-orbit_config_path=`which orbit-config`
-if test -n "$orbit_config_path" -a $? = 0
-then
- orbit_exec_prefix=`orbit-config --exec-prefix`
- orbit_includes=`orbit-config --cflags server`
- orbit_libs=`orbit-config --libs server`
- orbit_idl="$orbit_exec_prefix/bin/orbit-idl"
- AC_MSG_RESULT(found!)
- AC_DEFINE([HAVE_ORBIT], [1], [ORBIT])
-else
- orbit_exec_prefix=
- orbit_includes=
- orbit_libs=
- orbit_idl=
- AC_MSG_RESULT(not found)
-fi
-AC_SUBST(orbit_includes)
-AC_SUBST(orbit_libs)
-AC_SUBST(orbit_idl)
-])
-
-AC_DEFUN([MYSQL_CHECK_ISAM], [
- AC_ARG_WITH([isam], [
- --with-isam Enable the ISAM table type],
- [with_isam="$withval"],
- [with_isam=no])
-
- isam_libs=
- if test X"$with_isam" = X"yes"
- then
- AC_DEFINE([HAVE_ISAM], [1], [Using old ISAM tables])
- isam_libs="\$(top_builddir)/isam/libnisam.a\
- \$(top_builddir)/merge/libmerge.a"
- fi
- AC_SUBST(isam_libs)
-])
-
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_BDB
-dnl Sets HAVE_BERKELEY_DB if inst library is found
-dnl Makes sure db version is correct.
-dnl Looks in $srcdir for Berkeley distribution if not told otherwise
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_CHECK_BDB], [
- AC_ARG_WITH([berkeley-db],
- [
- --with-berkeley-db[=DIR]
- Use BerkeleyDB located in DIR],
- [bdb="$withval"],
- [bdb=no])
-
- AC_ARG_WITH([berkeley-db-includes],
- [
- --with-berkeley-db-includes=DIR
- Find Berkeley DB headers in DIR],
- [bdb_includes="$withval"],
- [bdb_includes=default])
-
- AC_ARG_WITH([berkeley-db-libs],
- [
- --with-berkeley-db-libs=DIR
- Find Berkeley DB libraries in DIR],
- [bdb_libs="$withval"],
- [bdb_libs=default])
-
- AC_MSG_CHECKING([for BerkeleyDB])
-
-dnl SORT OUT THE SUPPLIED ARGUMENTS TO DETERMINE WHAT TO DO
-dnl echo "DBG1: bdb='$bdb'; incl='$bdb_includes'; lib='$bdb_libs'"
- have_berkeley_db=no
- case "$bdb" in
- no )
- mode=no
- AC_MSG_RESULT([no])
- ;;
- yes | default )
- case "$bdb_includes---$bdb_libs" in
- default---default )
- mode=search-$bdb
- AC_MSG_RESULT([searching...])
- ;;
- default---* | *---default | yes---* | *---yes )
- AC_MSG_ERROR([if either 'includes' or 'libs' is specified, both must be specified])
- ;;
- * )
- mode=supplied-two
- AC_MSG_RESULT([supplied])
- ;;
- esac
- ;;
- * )
- mode=supplied-one
- AC_MSG_RESULT([supplied])
- ;;
- esac
-
-dnl echo "DBG2: [$mode] bdb='$bdb'; incl='$bdb_includes'; lib='$bdb_libs'"
-
- case $mode in
- no )
- bdb_includes=
- bdb_libs=
- bdb_libs_with_path=
- ;;
- supplied-two )
- MYSQL_CHECK_INSTALLED_BDB([$bdb_includes], [$bdb_libs])
- case $bdb_dir_ok in
- installed ) mode=yes ;;
- * ) AC_MSG_ERROR([didn't find valid BerkeleyDB: $bdb_dir_ok]) ;;
- esac
- ;;
- supplied-one )
- MYSQL_CHECK_BDB_DIR([$bdb])
- case $bdb_dir_ok in
- source ) mode=compile ;;
- installed ) mode=yes ;;
- * ) AC_MSG_ERROR([didn't find valid BerkeleyDB: $bdb_dir_ok]) ;;
- esac
- ;;
- search-* )
- MYSQL_SEARCH_FOR_BDB
- case $bdb_dir_ok in
- source ) mode=compile ;;
- installed ) mode=yes ;;
- * )
- # not found
- case $mode in
- *-yes ) AC_MSG_ERROR([no suitable BerkeleyDB found]) ;;
- * ) mode=no ;;
- esac
- bdb_includes=
- bdb_libs=
- bdb_libs_with_path=
- ;;
- esac
- ;;
- *)
- AC_MSG_ERROR([impossible case condition '$mode': please report this to bugs@lists.mysql.com])
- ;;
- esac
-
-dnl echo "DBG3: [$mode] bdb='$bdb'; incl='$bdb_includes'; lib='$bdb_libs'"
- case $mode in
- no )
- AC_MSG_RESULT([Not using Berkeley DB])
- ;;
- yes )
- have_berkeley_db="yes"
- AC_MSG_RESULT([Using Berkeley DB in '$bdb_includes'])
- ;;
- compile )
- have_berkeley_db="$bdb"
- AC_MSG_RESULT([Compiling Berekeley DB in '$have_berkeley_db'])
- ;;
- * )
- AC_MSG_ERROR([impossible case condition '$mode': please report this to bugs@lists.mysql.com])
- ;;
- esac
-
- AC_SUBST(bdb_includes)
- AC_SUBST(bdb_libs)
- AC_SUBST(bdb_libs_with_path)
-])
-
-AC_DEFUN([MYSQL_CHECK_INSTALLED_BDB], [
-dnl echo ["MYSQL_CHECK_INSTALLED_BDB ($1) ($2)"]
- inc="$1"
- lib="$2"
- if test -f "$inc/db.h"
- then
- MYSQL_CHECK_BDB_VERSION([$inc/db.h],
- [.*#define[ ]*], [[ ][ ]*])
-
- if test X"$bdb_version_ok" = Xyes; then
- save_LDFLAGS="$LDFLAGS"
- LDFLAGS="-L$lib $LDFLAGS"
- AC_CHECK_LIB(db,db_env_create, [
- bdb_dir_ok=installed
- MYSQL_TOP_BUILDDIR([inc])
- MYSQL_TOP_BUILDDIR([lib])
- bdb_includes="-I$inc"
- bdb_libs="-L$lib -ldb"
- bdb_libs_with_path="$lib/libdb.a"
- ])
- LDFLAGS="$save_LDFLAGS"
- else
- bdb_dir_ok="$bdb_version_ok"
- fi
- else
- bdb_dir_ok="no db.h file in '$inc'"
- fi
-])
-
-AC_DEFUN([MYSQL_CHECK_BDB_DIR], [
-dnl ([$bdb])
-dnl echo ["MYSQL_CHECK_BDB_DIR ($1)"]
- dir="$1"
-
- MYSQL_CHECK_INSTALLED_BDB([$dir/include], [$dir/lib])
-
- if test X"$bdb_dir_ok" != Xinstalled; then
- # test to see if it's a source dir
- rel="$dir/dist/RELEASE"
- if test -f "$rel"; then
- MYSQL_CHECK_BDB_VERSION([$rel], [], [=])
- if test X"$bdb_version_ok" = Xyes; then
- bdb_dir_ok=source
- bdb="$dir"
- MYSQL_TOP_BUILDDIR([dir])
- bdb_includes="-I$dir/build_unix"
- bdb_libs="-L$dir/build_unix -ldb"
- bdb_libs_with_path="$dir/build_unix/libdb.a"
- else
- bdb_dir_ok="$bdb_version_ok"
- fi
- else
- bdb_dir_ok="'$dir' doesn't look like a BDB directory ($bdb_dir_ok)"
- fi
- fi
-])
-
-AC_DEFUN([MYSQL_SEARCH_FOR_BDB], [
-dnl echo ["MYSQL_SEARCH_FOR_BDB"]
- bdb_dir_ok="no BerkeleyDB found"
-
- for test_dir in $srcdir/bdb $srcdir/db-*.*.* /usr/local/BerkeleyDB*; do
-dnl echo "-----------> Looking at ($test_dir; `cd $test_dir && pwd`)"
- MYSQL_CHECK_BDB_DIR([$test_dir])
- if test X"$bdb_dir_ok" = Xsource || test X"$bdb_dir_ok" = Xinstalled; then
-dnl echo "-----------> Found it ($bdb), ($srcdir)"
-dnl This is needed so that 'make distcheck' works properly (VPATH build).
-dnl VPATH build won't work if bdb is not under the source tree; but in
-dnl that case, hopefully people will just make and install inside the
-dnl tree, or install BDB first, and then use the installed version.
- case "$bdb" in
- "$srcdir/"* ) bdb=`echo "$bdb" | sed -e "s,^$srcdir/,,"` ;;
- esac
- break
- fi
- done
-])
-
-dnl MYSQL_CHECK_BDB_VERSION takes 3 arguments:
-dnl 1) the file to look in
-dnl 2) the search pattern before DB_VERSION_XXX
-dnl 3) the search pattern between DB_VERSION_XXX and the number
-dnl It assumes that the number is the last thing on the line
-AC_DEFUN([MYSQL_CHECK_BDB_VERSION], [
- db_major=`sed -e '/^[$2]DB_VERSION_MAJOR[$3]/ !d' -e 's///' [$1]`
- db_minor=`sed -e '/^[$2]DB_VERSION_MINOR[$3]/ !d' -e 's///' [$1]`
- db_patch=`sed -e '/^[$2]DB_VERSION_PATCH[$3]/ !d' -e 's///' [$1]`
- test -z "$db_major" && db_major=0
- test -z "$db_minor" && db_minor=0
- test -z "$db_patch" && db_patch=0
-
- # This is ugly, but about as good as it can get
-# mysql_bdb=
-# if test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 3
-# then
-# mysql_bdb=h
-# elif test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 9
-# then
-# want_bdb_version="3.2.9a" # hopefully this will stay up-to-date
-# mysql_bdb=a
-# fi
-
-dnl RAM:
-want_bdb_version="4.1.24"
-bdb_version_ok=yes
-
-# if test -n "$mysql_bdb" && \
-# grep "DB_VERSION_STRING.*:.*$mysql_bdb: " [$1] > /dev/null
-# then
-# bdb_version_ok=yes
-# else
-# bdb_version_ok="invalid version $db_major.$db_minor.$db_patch"
-# bdb_version_ok="$bdb_version_ok (must be version 3.2.3h or $want_bdb_version)"
-# fi
-])
-
-AC_DEFUN([MYSQL_TOP_BUILDDIR], [
- case "$[$1]" in
- /* ) ;; # don't do anything with an absolute path
- "$srcdir"/* )
- # If BDB is under the source directory, we need to look under the
- # build directory for bdb/build_unix.
- # NOTE: I'm being lazy, and assuming the user did not specify
- # something like --with-berkeley-db=bdb (it would be missing "./").
- [$1]="\$(top_builddir)/"`echo "$[$1]" | sed -e "s,^$srcdir/,,"`
- ;;
- * )
- AC_MSG_ERROR([The BDB directory must be directly under the MySQL source directory, or be specified using the full path. ('$srcdir'; '$[$1]')])
- ;;
- esac
- if test X"$[$1]" != "/"
- then
- [$1]=`echo $[$1] | sed -e 's,/$,,'`
- fi
-])
-
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_BDB SECTION
-dnl ---------------------------------------------------------------------------
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_INNODB
-dnl Sets HAVE_INNOBASE_DB if --with-innodb is used
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_CHECK_INNODB], [
- AC_ARG_WITH([innodb],
- [
- --without-innodb Do not include the InnoDB table handler],
- [innodb="$withval"],
- [innodb=yes])
-
- AC_MSG_CHECKING([for Innodb])
-
- have_innodb=no
- innodb_includes=
- innodb_libs=
- case "$innodb" in
- yes )
- AC_MSG_RESULT([Using Innodb])
- AC_DEFINE([HAVE_INNOBASE_DB], [1], [Using Innobase DB])
- have_innodb="yes"
- innodb_includes="-I../innobase/include"
- innodb_system_libs=""
-dnl Some libs are listed several times, in order for gcc to sort out
-dnl circular references.
- innodb_libs="\
- \$(top_builddir)/innobase/usr/libusr.a\
- \$(top_builddir)/innobase/srv/libsrv.a\
- \$(top_builddir)/innobase/dict/libdict.a\
- \$(top_builddir)/innobase/que/libque.a\
- \$(top_builddir)/innobase/srv/libsrv.a\
- \$(top_builddir)/innobase/ibuf/libibuf.a\
- \$(top_builddir)/innobase/row/librow.a\
- \$(top_builddir)/innobase/pars/libpars.a\
- \$(top_builddir)/innobase/btr/libbtr.a\
- \$(top_builddir)/innobase/trx/libtrx.a\
- \$(top_builddir)/innobase/read/libread.a\
- \$(top_builddir)/innobase/usr/libusr.a\
- \$(top_builddir)/innobase/buf/libbuf.a\
- \$(top_builddir)/innobase/ibuf/libibuf.a\
- \$(top_builddir)/innobase/eval/libeval.a\
- \$(top_builddir)/innobase/log/liblog.a\
- \$(top_builddir)/innobase/fsp/libfsp.a\
- \$(top_builddir)/innobase/fut/libfut.a\
- \$(top_builddir)/innobase/fil/libfil.a\
- \$(top_builddir)/innobase/lock/liblock.a\
- \$(top_builddir)/innobase/mtr/libmtr.a\
- \$(top_builddir)/innobase/page/libpage.a\
- \$(top_builddir)/innobase/rem/librem.a\
- \$(top_builddir)/innobase/thr/libthr.a\
- \$(top_builddir)/innobase/sync/libsync.a\
- \$(top_builddir)/innobase/data/libdata.a\
- \$(top_builddir)/innobase/mach/libmach.a\
- \$(top_builddir)/innobase/ha/libha.a\
- \$(top_builddir)/innobase/dyn/libdyn.a\
- \$(top_builddir)/innobase/mem/libmem.a\
- \$(top_builddir)/innobase/sync/libsync.a\
- \$(top_builddir)/innobase/ut/libut.a\
- \$(top_builddir)/innobase/os/libos.a\
- \$(top_builddir)/innobase/ut/libut.a"
-
- AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
- ;;
- * )
- AC_MSG_RESULT([Not using Innodb])
- ;;
- esac
-
- AC_SUBST(innodb_includes)
- AC_SUBST(innodb_libs)
- AC_SUBST(innodb_system_libs)
-])
-
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_INNODB SECTION
-dnl ---------------------------------------------------------------------------
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_EXAMPLEDB
-dnl Sets HAVE_EXAMPLE_DB if --with-example-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_EXAMPLEDB], [
- AC_ARG_WITH([example-storage-engine],
- [
- --with-example-storage-engine
- Enable the Example Storage Engine],
- [exampledb="$withval"],
- [exampledb=no])
- AC_MSG_CHECKING([for example storage engine])
-
- case "$exampledb" in
- yes )
- AC_DEFINE([HAVE_EXAMPLE_DB], [1], [Builds Example DB])
- AC_MSG_RESULT([yes])
- [exampledb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [exampledb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_EXAMPLE SECTION
-dnl ---------------------------------------------------------------------------
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_ARCHIVEDB
-dnl Sets HAVE_ARCHIVE_DB if --with-archive-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_ARCHIVEDB], [
- AC_ARG_WITH([archive-storage-engine],
- [
- --with-archive-storage-engine
- Enable the Archive Storage Engine],
- [archivedb="$withval"],
- [archivedb=no])
- AC_MSG_CHECKING([for archive storage engine])
-
- case "$archivedb" in
- yes )
- AC_DEFINE([HAVE_ARCHIVE_DB], [1], [Builds Archive Storage Engine])
- AC_MSG_RESULT([yes])
- [archivedb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [archivedb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_ARCHIVE SECTION
-dnl ---------------------------------------------------------------------------
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_CSVDB
-dnl Sets HAVE_CSV_DB if --with-csv-storage-engine is used
-dnl ---------------------------------------------------------------------------
-AC_DEFUN([MYSQL_CHECK_CSVDB], [
- AC_ARG_WITH([csv-storage-engine],
- [
- --with-csv-storage-engine
- Enable the CSV Storage Engine],
- [csvdb="$withval"],
- [csvdb=no])
- AC_MSG_CHECKING([for csv storage engine])
-
- case "$csvdb" in
- yes )
- AC_DEFINE([HAVE_CSV_DB], [1], [Builds the CSV Storage Engine])
- AC_MSG_RESULT([yes])
- [csvdb=yes]
- ;;
- * )
- AC_MSG_RESULT([no])
- [csvdb=no]
- ;;
- esac
-
-])
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_CSV SECTION
-dnl ---------------------------------------------------------------------------
-
-
-dnl ---------------------------------------------------------------------------
-dnl Macro: MYSQL_CHECK_NDBCLUSTER
-dnl Sets HAVE_NDBCLUSTER_DB if --with-ndbcluster is used
-dnl ---------------------------------------------------------------------------
-
-AC_DEFUN([MYSQL_CHECK_NDB_OPTIONS], [
- AC_ARG_WITH([ndb-sci],
- AC_HELP_STRING([--with-ndb-sci=DIR],
- [Provide MySQL with a custom location of
- sci library. Given DIR, sci library is
- assumed to be in $DIR/lib and header files
- in $DIR/include.]),
- [mysql_sci_dir=${withval}],
- [mysql_sci_dir=""])
-
- case "$mysql_sci_dir" in
- "no" )
- have_ndb_sci=no
- AC_MSG_RESULT([-- not including sci transporter])
- ;;
- * )
- if test -f "$mysql_sci_dir/lib/libsisci.a" -a \
- -f "$mysql_sci_dir/include/sisci_api.h"; then
- NDB_SCI_INCLUDES="-I$mysql_sci_dir/include"
- NDB_SCI_LIBS="-L$mysql_sci_dir/lib -lsisci"
- AC_MSG_RESULT([-- including sci transporter])
- AC_DEFINE([NDB_SCI_TRANSPORTER], [1],
- [Including Ndb Cluster DB sci transporter])
- AC_SUBST(NDB_SCI_INCLUDES)
- AC_SUBST(NDB_SCI_LIBS)
- have_ndb_sci="yes"
- AC_MSG_RESULT([found sci transporter in $mysql_sci_dir/{include, lib}])
- else
- AC_MSG_RESULT([could not find sci transporter in $mysql_sci_dir/{include, lib}])
- fi
- ;;
- esac
-
- AC_ARG_WITH([ndb-shm],
- [
- --with-ndb-shm Include the NDB Cluster shared memory transporter],
- [ndb_shm="$withval"],
- [ndb_shm=no])
- AC_ARG_WITH([ndb-test],
- [
- --with-ndb-test Include the NDB Cluster ndbapi test programs],
- [ndb_test="$withval"],
- [ndb_test=no])
- AC_ARG_WITH([ndb-docs],
- [
- --with-ndb-docs Include the NDB Cluster ndbapi and mgmapi documentation],
- [ndb_docs="$withval"],
- [ndb_docs=no])
- AC_ARG_WITH([ndb-port-base],
- [
- --with-ndb-port-base Base port for NDB Cluster],
- [ndb_port_base="$withval"],
- [ndb_port_base="default"])
-
- AC_MSG_CHECKING([for NDB Cluster options])
- AC_MSG_RESULT([])
-
- have_ndb_shm=no
- case "$ndb_shm" in
- yes )
- AC_MSG_RESULT([-- including shared memory transporter])
- AC_DEFINE([NDB_SHM_TRANSPORTER], [1],
- [Including Ndb Cluster DB shared memory transporter])
- have_ndb_shm="yes"
- ;;
- * )
- AC_MSG_RESULT([-- not including shared memory transporter])
- ;;
- esac
-
- have_ndb_test=no
- case "$ndb_test" in
- yes )
- AC_MSG_RESULT([-- including ndbapi test programs])
- have_ndb_test="yes"
- ;;
- * )
- AC_MSG_RESULT([-- not including ndbapi test programs])
- ;;
- esac
-
- have_ndb_docs=no
- case "$ndb_docs" in
- yes )
- AC_MSG_RESULT([-- including ndbapi and mgmapi documentation])
- have_ndb_docs="yes"
- ;;
- * )
- AC_MSG_RESULT([-- not including ndbapi and mgmapi documentation])
- ;;
- esac
-
- AC_MSG_RESULT([done.])
-])
-
-AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [
- AC_ARG_WITH([ndbcluster],
- [
- --with-ndbcluster Include the NDB Cluster table handler],
- [ndbcluster="$withval"],
- [ndbcluster=no])
-
- AC_MSG_CHECKING([for NDB Cluster])
-
- have_ndbcluster=no
- ndbcluster_includes=
- ndbcluster_libs=
- case "$ndbcluster" in
- yes )
- AC_MSG_RESULT([Using NDB Cluster])
- AC_DEFINE([HAVE_NDBCLUSTER_DB], [1], [Using Ndb Cluster DB])
- have_ndbcluster="yes"
- ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi"
- ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a"
- ndbcluster_system_libs=""
- MYSQL_CHECK_NDB_OPTIONS
- ;;
- * )
- AC_MSG_RESULT([Not using NDB Cluster])
- ;;
- esac
-
- AM_CONDITIONAL([HAVE_NDBCLUSTER_DB], [ test "$have_ndbcluster" = "yes" ])
- AC_SUBST(ndbcluster_includes)
- AC_SUBST(ndbcluster_libs)
- AC_SUBST(ndbcluster_system_libs)
-])
-
-dnl ---------------------------------------------------------------------------
-dnl END OF MYSQL_CHECK_NDBCLUSTER SECTION
-dnl ---------------------------------------------------------------------------
-
-
-dnl By default, many hosts won't let programs access large files;
-dnl one must use special compiler options to get large-file access to work.
-dnl For more details about this brain damage please see:
-dnl http://www.sas.com/standards/large.file/x_open.20Mar96.html
-
-dnl Written by Paul Eggert <eggert@twinsun.com>.
-
-dnl Internal subroutine of AC_SYS_LARGEFILE.
-dnl AC_SYS_LARGEFILE_FLAGS(FLAGSNAME)
-AC_DEFUN([AC_SYS_LARGEFILE_FLAGS],
- [AC_CACHE_CHECK([for $1 value to request large file support],
- ac_cv_sys_largefile_$1,
- [if ($GETCONF LFS_$1) >conftest.1 2>conftest.2 && test ! -s conftest.2
- then
- ac_cv_sys_largefile_$1=`cat conftest.1`
- else
- ac_cv_sys_largefile_$1=no
- ifelse($1, CFLAGS,
- [case "$host_os" in
- # HP-UX 10.20 requires -D__STDC_EXT__ with gcc 2.95.1.
-changequote(, )dnl
- hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
-changequote([, ])dnl
- if test "$GCC" = yes; then
- case `$CC --version 2>/dev/null` in
- 2.95.*) ac_cv_sys_largefile_CFLAGS=-D__STDC_EXT__ ;;
- esac
- fi
- ;;
- # IRIX 6.2 and later require cc -n32.
-changequote(, )dnl
- irix6.[2-9]* | irix6.1[0-9]* | irix[7-9].* | irix[1-9][0-9]*)
-changequote([, ])dnl
- if test "$GCC" != yes; then
- ac_cv_sys_largefile_CFLAGS=-n32
- fi
- esac
- if test "$ac_cv_sys_largefile_CFLAGS" != no; then
- ac_save_CC="$CC"
- CC="$CC $ac_cv_sys_largefile_CFLAGS"
- AC_TRY_LINK(, , , ac_cv_sys_largefile_CFLAGS=no)
- CC="$ac_save_CC"
- fi])
- fi
- rm -f conftest*])])
-
-dnl Internal subroutine of AC_SYS_LARGEFILE.
-dnl AC_SYS_LARGEFILE_SPACE_APPEND(VAR, VAL)
-AC_DEFUN([AC_SYS_LARGEFILE_SPACE_APPEND],
- [case $2 in
- no) ;;
- ?*)
- case "[$]$1" in
- '') $1=$2 ;;
- *) $1=[$]$1' '$2 ;;
- esac ;;
- esac])
-
-dnl Internal subroutine of AC_SYS_LARGEFILE.
-dnl AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, CACHE-VAR, COMMENT, CODE-TO-SET-DEFAULT)
-AC_DEFUN([AC_SYS_LARGEFILE_MACRO_VALUE],
- [AC_CACHE_CHECK([for $1], $2,
- [$2=no
-changequote(, )dnl
- for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
- case "$ac_flag" in
- -D$1)
- $2=1 ;;
- -D$1=*)
- $2=`expr " $ac_flag" : '[^=]*=\(.*\)'` ;;
- esac
- done
- $4
-changequote([, ])dnl
- ])
- if test "[$]$2" != no; then
- AC_DEFINE_UNQUOTED([$1], [$]$2, [$3])
- fi])
-
-AC_DEFUN([MYSQL_SYS_LARGEFILE],
- [AC_REQUIRE([AC_CANONICAL_HOST])
- AC_ARG_ENABLE(largefile,
- [ --disable-largefile Omit support for large files])
- if test "$enable_largefile" != no; then
- AC_CHECK_TOOL(GETCONF, getconf)
- AC_SYS_LARGEFILE_FLAGS(CFLAGS)
- AC_SYS_LARGEFILE_FLAGS(LDFLAGS)
- AC_SYS_LARGEFILE_FLAGS(LIBS)
-
- for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
- case "$ac_flag" in
- no) ;;
- -D_FILE_OFFSET_BITS=*) ;;
- -D_LARGEFILE_SOURCE | -D_LARGEFILE_SOURCE=*) ;;
- -D_LARGE_FILES | -D_LARGE_FILES=*) ;;
- -D?* | -I?*)
- AC_SYS_LARGEFILE_SPACE_APPEND(CPPFLAGS, "$ac_flag") ;;
- *)
- AC_SYS_LARGEFILE_SPACE_APPEND(CFLAGS, "$ac_flag") ;;
- esac
- done
- AC_SYS_LARGEFILE_SPACE_APPEND(LDFLAGS, "$ac_cv_sys_largefile_LDFLAGS")
- AC_SYS_LARGEFILE_SPACE_APPEND(LIBS, "$ac_cv_sys_largefile_LIBS")
-
- AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS,
- ac_cv_sys_file_offset_bits,
- [Number of bits in a file offset, on hosts where this is settable.],
- [case "$host_os" in
- # HP-UX 10.20 and later
- hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
- ac_cv_sys_file_offset_bits=64 ;;
- # We can't declare _FILE_OFFSET_BITS here as this will cause
- # compile errors as AC_PROG_CC adds include files in confdefs.h
- # We solve this (until autoconf is fixed) by instead declaring it
- # as define instead
- solaris2.[8,9])
- CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64"
- CXXFLAGS="$CXXFLAGS -D_FILE_OFFSET_BITS=64"
- ac_cv_sys_file_offset_bits=no ;;
- esac])
- AC_SYS_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE,
- ac_cv_sys_largefile_source,
- [makes fseeko etc. visible, on some hosts.],
- [case "$host_os" in
- # HP-UX 10.20 and later
- hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
- ac_cv_sys_largefile_source=1 ;;
- esac])
- AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES,
- ac_cv_sys_large_files,
- [Large files support on AIX-style hosts.],
- [case "$host_os" in
- # AIX 4.2 and later
- aix4.[2-9]* | aix4.1[0-9]* | aix[5-9].* | aix[1-9][0-9]*)
- ac_cv_sys_large_files=1 ;;
- esac])
- fi
- ])
-
-
-# Local version of _AC_PROG_CXX_EXIT_DECLARATION that does not
-# include #stdlib.h as default as this breaks things on Solaris
-# (Conflicts with pthreads and big file handling)
-
-m4_define([_AC_PROG_CXX_EXIT_DECLARATION],
-[for ac_declaration in \
- ''\
- 'extern "C" void std::exit (int) throw (); using std::exit;' \
- 'extern "C" void std::exit (int); using std::exit;' \
- 'extern "C" void exit (int) throw ();' \
- 'extern "C" void exit (int);' \
- 'void exit (int);' \
- '#include <stdlib.h>'
-do
- _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include <stdlib.h>
-$ac_declaration],
- [exit (42);])],
- [],
- [continue])
- _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_declaration],
- [exit (42);])],
- [break])
-done
-rm -f conftest*
-if test -n "$ac_declaration"; then
- echo '#ifdef __cplusplus' >>confdefs.h
- echo $ac_declaration >>confdefs.h
- echo '#endif' >>confdefs.h
-fi
-])# _AC_PROG_CXX_EXIT_DECLARATION
-
-dnl ---------------------------------------------------------------------------
-
diff --git a/client/Makefile.am b/client/Makefile.am
index 7fdba8f43d8..0362c2f3358 100644
--- a/client/Makefile.am
+++ b/client/Makefile.am
@@ -27,6 +27,7 @@ bin_PROGRAMS = mysql mysqladmin mysqlcheck mysqlshow \
noinst_HEADERS = sql_string.h completion_hash.h my_readline.h \
client_priv.h
mysql_SOURCES = mysql.cc readline.cc sql_string.cc completion_hash.cc
+mysqladmin_SOURCES = mysqladmin.cc
mysql_LDADD = @readline_link@ @TERMCAP_LIB@ $(LDADD) $(CXXLDFLAGS)
mysqlbinlog_LDADD = $(LDADD) $(CXXLDFLAGS)
mysql_DEPENDENCIES= $(LIBRARIES) $(pkglib_LTLIBRARIES) $(DEPLIB)
diff --git a/client/client_priv.h b/client/client_priv.h
index f16ec0e802b..e86a56f58c1 100644
--- a/client/client_priv.h
+++ b/client/client_priv.h
@@ -45,5 +45,8 @@ enum options_client
OPT_COMPATIBLE, OPT_RECONNECT, OPT_DELIMITER, OPT_SECURE_AUTH,
OPT_OPEN_FILES_LIMIT, OPT_SET_CHARSET, OPT_CREATE_OPTIONS,
OPT_START_POSITION, OPT_STOP_POSITION, OPT_START_DATETIME, OPT_STOP_DATETIME,
- OPT_SIGINT_IGNORE, OPT_HEXBLOB
+ OPT_SIGINT_IGNORE, OPT_HEXBLOB, OPT_ORDER_BY_PRIMARY
+#ifdef HAVE_NDBCLUSTER_DB
+ ,OPT_NDBCLUSTER,OPT_NDB_CONNECTSTRING
+#endif
};
diff --git a/client/mysql.cc b/client/mysql.cc
index 358b13e652b..8e9dd84c8f0 100644
--- a/client/mysql.cc
+++ b/client/mysql.cc
@@ -1609,7 +1609,7 @@ static void print_help_item(MYSQL_ROW *cur, int num_name, int num_cat, char *las
char ccat= (*cur)[num_cat][0];
if (*last_char != ccat)
{
- put_info(ccat == 'Y' ? "categories :" : "topics :", INFO_INFO);
+ put_info(ccat == 'Y' ? "categories:" : "topics:", INFO_INFO);
*last_char= ccat;
}
tee_fprintf(PAGER, " %s\n", (*cur)[num_name]);
@@ -1676,8 +1676,8 @@ static int com_server_help(String *buffer __attribute__((unused)),
if (num_fields == 2)
{
- put_info("Many help items for your request exist", INFO_INFO);
- put_info("To make a more specific request, please type 'help <item>',\nwhere item is one of next", INFO_INFO);
+ put_info("Many help items for your request exist.", INFO_INFO);
+ put_info("To make a more specific request, please type 'help <item>',\nwhere item is one of the following", INFO_INFO);
num_name= 0;
num_cat= 1;
last_char= '_';
diff --git a/client/mysqladmin.c b/client/mysqladmin.cc
index bccbf29ef83..924af3a9977 100644
--- a/client/mysqladmin.c
+++ b/client/mysqladmin.cc
@@ -16,7 +16,6 @@
/* maintaince of mysql databases */
-
#include "client_priv.h"
#include <signal.h>
#ifdef THREAD
@@ -25,6 +24,10 @@
#include <sys/stat.h>
#include <mysql.h>
+#ifdef LATER_HAVE_NDBCLUSTER_DB
+#include "../ndb/src/mgmclient/ndb_mgmclient.h"
+#endif
+
#define ADMIN_VERSION "8.41"
#define MAX_MYSQL_VAR 256
#define SHUTDOWN_DEF_TIMEOUT 3600 /* Wait for shutdown */
@@ -42,6 +45,10 @@ static uint tcp_port = 0, option_wait = 0, option_silent=0, nr_iterations,
opt_count_iterations= 0;
static ulong opt_connect_timeout, opt_shutdown_timeout;
static my_string unix_port=0;
+#ifdef LATER_HAVE_NDBCLUSTER_DB
+static my_bool opt_ndbcluster=0;
+static char *opt_ndb_connectstring=0;
+#endif
#ifdef HAVE_SMEM
static char *shared_memory_base_name=0;
@@ -94,6 +101,9 @@ enum commands {
ADMIN_PING, ADMIN_EXTENDED_STATUS, ADMIN_FLUSH_STATUS,
ADMIN_FLUSH_PRIVILEGES, ADMIN_START_SLAVE, ADMIN_STOP_SLAVE,
ADMIN_FLUSH_THREADS, ADMIN_OLD_PASSWORD
+#ifdef LATER_HAVE_NDBCLUSTER_DB
+ ,ADMIN_NDB_MGM
+#endif
};
static const char *command_names[]= {
"create", "drop", "shutdown",
@@ -104,14 +114,21 @@ static const char *command_names[]= {
"ping", "extended-status", "flush-status",
"flush-privileges", "start-slave", "stop-slave",
"flush-threads","old-password",
+#ifdef LATER_HAVE_NDBCLUSTER_DB
+ "ndb-mgm",
+#endif
NullS
};
static TYPELIB command_typelib=
-{ array_elements(command_names)-1,"commands", command_names};
+{ array_elements(command_names)-1,"commands", command_names, NULL};
static struct my_option my_long_options[] =
{
+#ifdef __NETWARE__
+ {"autoclose", 'a', " Auto close the screen on exit for NetWare",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"count", 'c',
"Number of iterations to make. This works with -i (--sleep) only.",
(gptr*) &nr_iterations, (gptr*) &nr_iterations, 0, GET_UINT,
@@ -184,6 +201,14 @@ static struct my_option my_long_options[] =
{"shutdown_timeout", OPT_SHUTDOWN_TIMEOUT, "", (gptr*) &opt_shutdown_timeout,
(gptr*) &opt_shutdown_timeout, 0, GET_ULONG, REQUIRED_ARG,
SHUTDOWN_DEF_TIMEOUT, 0, 3600*12, 0, 1, 0},
+#ifdef LATER_HAVE_NDBCLUSTER_DB
+ {"ndbcluster", OPT_NDBCLUSTER, ""
+ "", (gptr*) &opt_ndbcluster,
+ (gptr*) &opt_ndbcluster, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"ndb-connectstring", OPT_NDB_CONNECTSTRING, ""
+ "", (gptr*) &opt_ndb_connectstring,
+ (gptr*) &opt_ndb_connectstring, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -197,6 +222,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
int error = 0;
switch(optid) {
+#ifdef __NETWARE__
+ case 'a':
+ setscreenmode(SCR_AUTOCLOSE_ON_EXIT); // auto close the screen /
+ break;
+#endif
case 'c':
opt_count_iterations= 1;
break;
@@ -587,7 +617,7 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
{
char *pos,buff[40];
ulong sec;
- pos=strchr(status,' ');
+ pos= (char*) strchr(status,' ');
*pos++=0;
printf("%s\t\t\t",status); /* print label */
if ((status=str2int(pos,10,0,LONG_MAX,(long*) &sec)))
@@ -795,10 +825,17 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
if (argv[1][0])
{
+ char *pw= argv[1];
+#ifdef __WIN__
+ uint pw_len= strlen(pw);
+ if (pw_len > 1 && pw[0] == '\'' && pw[pw_len-1] == '\'')
+ printf("Warning: single quotes were not trimmed from the password by"
+ " your command\nline client, as you might have expected.\n");
+#endif
if (find_type(argv[0], &command_typelib, 2) == ADMIN_OLD_PASSWORD)
- make_scrambled_password_323(crypted_pw, argv[1]);
+ make_scrambled_password_323(crypted_pw, pw);
else
- make_scrambled_password(crypted_pw, argv[1]);
+ make_scrambled_password(crypted_pw, pw);
}
else
crypted_pw[0]=0; /* No password */
@@ -882,6 +919,24 @@ static int execute_commands(MYSQL *mysql,int argc, char **argv)
}
mysql->reconnect=1; /* Automatic reconnect is default */
break;
+#ifdef LATER_HAVE_NDBCLUSTER_DB
+ case ADMIN_NDB_MGM:
+ {
+ if (argc < 2)
+ {
+ my_printf_error(0,"Too few arguments to ndb-mgm",MYF(ME_BELL));
+ return 1;
+ }
+ {
+ Ndb_mgmclient_handle cmd=
+ ndb_mgmclient_handle_create(opt_ndb_connectstring);
+ ndb_mgmclient_execute(cmd, --argc, ++argv);
+ ndb_mgmclient_handle_destroy(cmd);
+ }
+ argc= 0;
+ }
+ break;
+#endif
default:
my_printf_error(0,"Unknown command: '%-.60s'",MYF(ME_BELL),argv[0]);
return 1;
@@ -1248,3 +1303,6 @@ static my_bool wait_pidfile(char *pidfile, time_t last_modified,
}
DBUG_RETURN(error);
}
+#ifdef __GNUC__
+FIX_GCC_LINKING_PROBLEM
+#endif
diff --git a/client/mysqlbinlog.cc b/client/mysqlbinlog.cc
index 31588d5b013..1c10ece92dd 100644
--- a/client/mysqlbinlog.cc
+++ b/client/mysqlbinlog.cc
@@ -61,7 +61,7 @@ static const char *load_default_groups[]= { "mysqlbinlog","client",0 };
void sql_print_error(const char *format, ...);
-static bool one_database=0, to_last_remote_log= 0;
+static bool one_database=0, to_last_remote_log= 0, disable_log_bin= 0;
static const char* database= 0;
static my_bool force_opt= 0, short_form= 0, remote_opt= 0;
static ulonglong offset = 0;
@@ -229,7 +229,7 @@ int Load_log_processor::load_old_format_file(NET* net, const char*server_fname,
for (;;)
{
- uint packet_len = my_net_read(net);
+ ulong packet_len = my_net_read(net);
if (packet_len == 0)
{
if (my_net_write(net, "", 0) || net_flush(net))
@@ -251,7 +251,13 @@ int Load_log_processor::load_old_format_file(NET* net, const char*server_fname,
return -1;
}
- if (my_write(file, (byte*) net->read_pos, packet_len,MYF(MY_WME|MY_NABP)))
+ if (packet_len > UINT_MAX)
+ {
+ sql_print_error("Illegal length of packet read from net");
+ return -1;
+ }
+ if (my_write(file, (byte*) net->read_pos,
+ (uint) packet_len, MYF(MY_WME|MY_NABP)))
return -1;
}
@@ -489,6 +495,13 @@ static struct my_option my_long_options[] =
{"database", 'd', "List entries for just this database (local log only).",
(gptr*) &database, (gptr*) &database, 0, GET_STR_ALLOC, REQUIRED_ARG,
0, 0, 0, 0, 0, 0},
+ {"disable-log-bin", 'D', "Disable binary log. This is useful, if you "
+ "enabled --to-last-log and are sending the output to the same MySQL server. "
+ "This way you could avoid an endless loop. You would also like to use it "
+ "when restoring after a crash to avoid duplication of the statements you "
+ "already have. NOTE: you will need a SUPER privilege to use this option.",
+ (gptr*) &disable_log_bin, (gptr*) &disable_log_bin, 0, GET_BOOL,
+ NO_ARG, 0, 0, 0, 0, 0, 0},
{"force-read", 'f', "Force reading unknown binlog events.",
(gptr*) &force_opt, (gptr*) &force_opt, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
@@ -850,7 +863,15 @@ could be out of memory");
*/
int4store(buf, (uint32)start_position);
int2store(buf + BIN_LOG_HEADER_SIZE, binlog_flags);
- logname_len = (uint) strlen(logname);
+
+ size_s tlen = strlen(logname);
+ if (tlen > UINT_MAX)
+ {
+ fprintf(stderr,"Log name too long\n");
+ error= 1;
+ goto err;
+ }
+ logname_len = (uint) tlen;
int4store(buf + 6, 0);
memcpy(buf + 10, logname, logname_len);
if (simple_command(mysql, COM_BINLOG_DUMP, buf, logname_len + 10, 1))
@@ -1204,6 +1225,11 @@ int main(int argc, char** argv)
fprintf(result_file,
"/*!40019 SET @@session.max_insert_delayed_threads=0*/;\n");
+
+ if (disable_log_bin)
+ fprintf(result_file,
+ "/*!32316 SET @OLD_SQL_LOG_BIN=@@SQL_LOG_BIN, SQL_LOG_BIN=0*/;\n");
+
for (save_stop_position= stop_position, stop_position= ~(my_off_t)0 ;
(--argc >= 0) && !stop_passed ; )
{
@@ -1218,6 +1244,9 @@ int main(int argc, char** argv)
start_position= BIN_LOG_HEADER_SIZE;
}
+ if (disable_log_bin)
+ fprintf(result_file, "/*!32316 SET SQL_LOG_BIN=@OLD_SQL_LOG_BIN*/;\n");
+
if (tmpdir.list)
free_tmpdir(&tmpdir);
if (result_file != stdout)
diff --git a/client/mysqlcheck.c b/client/mysqlcheck.c
index 8182b95fb83..c670b84db44 100644
--- a/client/mysqlcheck.c
+++ b/client/mysqlcheck.c
@@ -81,8 +81,13 @@ static struct my_option my_long_options[] =
"To check several databases. Note the difference in usage; In this case no tables are given. All name arguments are regarded as databasenames.",
(gptr*) &opt_databases, (gptr*) &opt_databases, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
+#ifdef DBUG_OFF
+ {"debug", '#', "This is a non-debug version. Catch this and exit.",
+ 0, 0, 0, GET_DISABLED, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#else
{"debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+#endif
{"default-character-set", OPT_DEFAULT_CHARSET,
"Set the default character set.", (gptr*) &default_charset,
(gptr*) &default_charset, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
diff --git a/client/mysqldump.c b/client/mysqldump.c
index af271343ab9..9d35de2c953 100644
--- a/client/mysqldump.c
+++ b/client/mysqldump.c
@@ -37,7 +37,7 @@
** 10 Jun 2003: SET NAMES and --no-set-names by Alexander Barkov
*/
-#define DUMP_VERSION "10.8"
+#define DUMP_VERSION "10.9"
#include <my_global.h>
#include <my_sys.h>
@@ -75,25 +75,27 @@ static ulong find_set(TYPELIB *lib, const char *x, uint length,
static char *field_escape(char *to,const char *from,uint length);
static my_bool verbose=0,tFlag=0,cFlag=0,dFlag=0,quick= 1, extended_insert= 1,
- lock_tables=1,ignore_errors=0,flush_logs=0,replace=0,
- ignore=0,opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
+ lock_tables=1,ignore_errors=0,flush_logs=0,
+ opt_drop=1,opt_keywords=0,opt_lock=1,opt_compress=0,
opt_delayed=0,create_options=1,opt_quoted=0,opt_databases=0,
- opt_alldbs=0,opt_create_db=0,opt_first_slave=0,opt_set_charset,
- opt_autocommit=0,opt_master_data,opt_disable_keys=1,opt_xml=0,
+ opt_alldbs=0,opt_create_db=0,opt_lock_all_tables=0,opt_set_charset,
+ opt_autocommit=0,opt_disable_keys=1,opt_xml=0,
opt_delete_master_logs=0, tty_password=0,
opt_single_transaction=0, opt_comments= 0, opt_compact= 0,
- opt_hex_blob=0;
+ opt_hex_blob=0, opt_order_by_primary=0;
static ulong opt_max_allowed_packet, opt_net_buffer_length;
static MYSQL mysql_connection,*sock=0;
static char insert_pat[12 * 1024],*opt_password=0,*current_user=0,
*current_host=0,*path=0,*fields_terminated=0,
*lines_terminated=0, *enclosed=0, *opt_enclosed=0, *escaped=0,
- *where=0,
+ *where=0, *order_by=0,
*opt_compatible_mode_str= 0,
*err_ptr= 0;
static char compatible_mode_normal_str[255];
static ulong opt_compatible_mode= 0;
-static uint opt_mysql_port= 0, err_len= 0;
+#define MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL 1
+#define MYSQL_OPT_MASTER_DATA_COMMENTED_SQL 2
+static uint opt_mysql_port= 0, err_len= 0, opt_master_data;
static my_string opt_mysql_unix_port=0;
static int first_error=0;
static DYNAMIC_STRING extended_row;
@@ -126,7 +128,7 @@ const char *compatible_mode_names[]=
(1<<10) /* ANSI */\
)
TYPELIB compatible_mode_typelib= {array_elements(compatible_mode_names) - 1,
- "", compatible_mode_names};
+ "", compatible_mode_names, NULL};
static struct my_option my_long_options[] =
@@ -150,6 +152,9 @@ static struct my_option my_long_options[] =
{"character-sets-dir", OPT_CHARSETS_DIR,
"Directory where character sets are.", (gptr*) &charsets_dir,
(gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"comments", 'i', "Write additional information.",
+ (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG,
+ 1, 0, 0, 0, 0, 0},
{"compatible", OPT_COMPATIBLE,
"Change the dump to be compatible with a given mode. By default tables are dumped in a format optimized for MySQL. Legal modes are: ansi, mysql323, mysql40, postgresql, oracle, mssql, db2, maxdb, no_key_options, no_table_options, no_field_options. One can use several modes separated by commas. Note: Requires MySQL server version 4.1.0 or higher. This option is ignored with earlier server versions.",
(gptr*) &opt_compatible_mode_str, (gptr*) &opt_compatible_mode_str, 0,
@@ -185,8 +190,9 @@ static struct my_option my_long_options[] =
(gptr*) &opt_delayed, (gptr*) &opt_delayed, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"delete-master-logs", OPT_DELETE_MASTER_LOGS,
- "Delete logs on master after backup. This automatically enables --first-slave.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ "Delete logs on master after backup. This automatically enables --master-data.",
+ (gptr*) &opt_delete_master_logs, (gptr*) &opt_delete_master_logs, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"disable-keys", 'K',
"'/*!40000 ALTER TABLE tb_name DISABLE KEYS */; and '/*!40000 ALTER TABLE tb_name ENABLE KEYS */; will be put in the output.", (gptr*) &opt_disable_keys,
(gptr*) &opt_disable_keys, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
@@ -205,13 +211,18 @@ static struct my_option my_long_options[] =
(gptr*) &opt_enclosed, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0 ,0, 0},
{"fields-escaped-by", OPT_ESC, "Fields in the i.file are escaped by ...",
(gptr*) &escaped, (gptr*) &escaped, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"first-slave", 'x', "Locks all tables across all databases.",
- (gptr*) &opt_first_slave, (gptr*) &opt_first_slave, 0, GET_BOOL, NO_ARG,
+ {"first-slave", 'x', "Deprecated, renamed to --lock-all-tables.",
+ (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
{"flush-logs", 'F', "Flush logs file in server before starting dump. "
- "Note that if you dump many databases at once (using the option "
- "--databases= or --all-databases), the logs will be flushed for "
- "each database dumped.",
+ "Note that if you dump many databases at once (using the option "
+ "--databases= or --all-databases), the logs will be flushed for "
+ "each database dumped. The exception is when using --lock-all-tables "
+ "or --master-data: "
+ "in this case the logs will be flushed only once, corresponding "
+ "to the moment all tables are locked. So if you want your dump and "
+ "the log flush to happen at the same exact moment you should use "
+ "--lock-all-tables or --master-data with --flush-logs",
(gptr*) &flush_logs, (gptr*) &flush_logs, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0,
0, 0},
{"force", 'f', "Continue even if we get an sql-error.",
@@ -219,24 +230,45 @@ static struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0},
{"help", '?', "Display this help message and exit.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
+ {"hex-blob", OPT_HEXBLOB, "Dump binary strings (BINARY, "
+ "VARBINARY, BLOB) in hexadecimal format.",
+ (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"host", 'h', "Connect to host.", (gptr*) &current_host,
(gptr*) &current_host, 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"lines-terminated-by", OPT_LTB, "Lines in the i.file are terminated by ...",
(gptr*) &lines_terminated, (gptr*) &lines_terminated, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"lock-all-tables", 'x', "Locks all tables across all databases. This "
+ "is achieved by taking a global read lock for the duration of the whole "
+ "dump. Automatically turns --single-transaction and --lock-tables off.",
+ (gptr*) &opt_lock_all_tables, (gptr*) &opt_lock_all_tables, 0, GET_BOOL, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
{"lock-tables", 'l', "Lock all tables for read.", (gptr*) &lock_tables,
(gptr*) &lock_tables, 0, GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0},
{"master-data", OPT_MASTER_DATA,
- "This causes the master position and filename to be appended to your output. This automatically enables --first-slave.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
+ "This causes the binary log position and filename to be appended to the "
+ "output. If equal to 1, will print it as a CHANGE MASTER command; if equal"
+ " to 2, that command will be prefixed with a comment symbol. "
+ "This option will turn --lock-all-tables on, unless "
+ "--single-transaction is specified too (in which case a "
+ "global read lock is only taken a short time at the beginning of the dump "
+ "- don't forget to read about --single-transaction below). In all cases "
+ "any action on logs will happen at the exact moment of the dump."
+ "Option automatically turns --lock-tables off.",
+ (gptr*) &opt_master_data, (gptr*) &opt_master_data, 0,
+ GET_UINT, OPT_ARG, 0, 0, MYSQL_OPT_MASTER_DATA_COMMENTED_SQL, 0, 0, 0},
+ {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
+ (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0,
+ GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
+ (longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
+ {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
+ (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0,
+ GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
+ MALLOC_OVERHEAD-1024, 1024, 0},
{"no-autocommit", OPT_AUTOCOMMIT,
"Wrap tables with autocommit/commit statements.",
(gptr*) &opt_autocommit, (gptr*) &opt_autocommit, 0, GET_BOOL, NO_ARG,
0, 0, 0, 0, 0, 0},
- {"single-transaction", OPT_TRANSACTION,
- "Dump all tables in single transaction to get consistent snapshot. Mutually exclusive with --lock-tables.",
- (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0,
- GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"no-create-db", 'n',
"'CREATE DATABASE /*!32312 IF NOT EXISTS*/ db_name;' will not be put in the output. The above line will be added otherwise, if --databases or --all-databases option was given.}.",
(gptr*) &opt_create_db, (gptr*) &opt_create_db, 0, GET_BOOL, NO_ARG, 0, 0,
@@ -248,13 +280,6 @@ static struct my_option my_long_options[] =
{"no-set-names", 'N',
"Deprecated. Use --skip-set-charset instead.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"set-charset", OPT_SET_CHARSET,
- "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.",
- (gptr*) &opt_set_charset, (gptr*) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
- 0, 0, 0, 0, 0},
- {"set-variable", 'O',
- "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"opt", OPT_OPTIMIZE,
"Same as --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys. Enabled by default, disable with --skip-opt.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
@@ -278,17 +303,40 @@ static struct my_option my_long_options[] =
{"result-file", 'r',
"Direct output to a given file. This option should be used in MSDOS, because it prevents new line '\\n' from being converted to '\\r\\n' (carriage return + line feed).",
0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"set-charset", OPT_SET_CHARSET,
+ "Add 'SET NAMES default_character_set' to the output. Enabled by default; suppress with --skip-set-charset.",
+ (gptr*) &opt_set_charset, (gptr*) &opt_set_charset, 0, GET_BOOL, NO_ARG, 1,
+ 0, 0, 0, 0, 0},
+ {"set-variable", 'O',
+ "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
+ 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#ifdef HAVE_SMEM
{"shared-memory-base-name", OPT_SHARED_MEMORY_BASE_NAME,
"Base name of shared memory.", (gptr*) &shared_memory_base_name, (gptr*) &shared_memory_base_name,
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
+ /*
+ Note that the combination --single-transaction --master-data
+ will give bullet-proof binlog position only if server >=4.1.3. That's the
+ old "FLUSH TABLES WITH READ LOCK does not block commit" fixed bug.
+ */
+ {"single-transaction", OPT_TRANSACTION,
+ "Creates a consistent snapshot by dumping all tables in a single "
+ "transaction. Works ONLY for tables stored in storage engines which "
+ "support multiversioning (currently only InnoDB does); the dump is NOT "
+ "guaranteed to be consistent for other storage engines. Option "
+ "automatically turns off --lock-tables.",
+ (gptr*) &opt_single_transaction, (gptr*) &opt_single_transaction, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"skip-opt", OPT_SKIP_OPTIMIZATION,
"Disable --opt. Disables --add-drop-table, --add-locks, --create-options, --quick, --extended-insert, --lock-tables, --set-charset, and --disable-keys.",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"socket", 'S', "Socket file to use for connection.",
(gptr*) &opt_mysql_unix_port, (gptr*) &opt_mysql_unix_port, 0, GET_STR,
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"order-by-primary", OPT_ORDER_BY_PRIMARY,
+ "Sorts each table's rows by primary key, or first unique key, if such a key exists. Useful when dumping a MyISAM table to be loaded into an InnoDB table, but will make the dump itself take considerably longer.",
+ (gptr*) &opt_order_by_primary, (gptr*) &opt_order_by_primary, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
#include <sslopt-longopts.h>
{"tab",'T',
"Creates tab separated textfile for each table to given path. (creates .sql and .txt files). NOTE: This only works if mysqldump is run on the same machine as the mysqld daemon.",
@@ -308,19 +356,6 @@ static struct my_option my_long_options[] =
(gptr*) &where, (gptr*) &where, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"xml", 'X', "Dump a database as well formed XML.", 0, 0, 0, GET_NO_ARG,
NO_ARG, 0, 0, 0, 0, 0, 0},
- {"max_allowed_packet", OPT_MAX_ALLOWED_PACKET, "",
- (gptr*) &opt_max_allowed_packet, (gptr*) &opt_max_allowed_packet, 0,
- GET_ULONG, REQUIRED_ARG, 24*1024*1024, 4096,
- (longlong) 2L*1024L*1024L*1024L, MALLOC_OVERHEAD, 1024, 0},
- {"net_buffer_length", OPT_NET_BUFFER_LENGTH, "",
- (gptr*) &opt_net_buffer_length, (gptr*) &opt_net_buffer_length, 0,
- GET_ULONG, REQUIRED_ARG, 1024*1024L-1025, 4096, 16*1024L*1024L,
- MALLOC_OVERHEAD-1024, 1024, 0},
- {"comments", 'i', "Write additional information.",
- (gptr*) &opt_comments, (gptr*) &opt_comments, 0, GET_BOOL, NO_ARG,
- 1, 0, 0, 0, 0, 0},
- {"hex-blob", OPT_HEXBLOB, "Dump BLOBs in HEX. this mode does not work with extended-insert",
- (gptr*) &opt_hex_blob, (gptr*) &opt_hex_blob, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
@@ -338,6 +373,7 @@ static int dump_databases(char **);
static int dump_all_databases();
static char *quote_name(const char *name, char *buff, my_bool force);
static const char *check_if_ignore_table(const char *table_name);
+static char *primary_key_fields(const char *table_name);
static my_bool getViewStructure(char *table, char* db);
static my_bool dump_all_views_in_db(char *database);
@@ -476,14 +512,6 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
{
switch (optid) {
- case OPT_MASTER_DATA:
- opt_master_data=1;
- opt_first_slave=1;
- break;
- case OPT_DELETE_MASTER_LOGS:
- opt_delete_master_logs=1;
- opt_first_slave=1;
- break;
case 'p':
if (argument)
{
@@ -528,10 +556,13 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
case '?':
usage();
exit(0);
+ case (int) OPT_MASTER_DATA:
+ if (!argument) /* work like in old versions */
+ opt_master_data= MYSQL_OPT_MASTER_DATA_EFFECTIVE_SQL;
+ break;
case (int) OPT_OPTIMIZE:
extended_insert= opt_drop= opt_lock= quick= create_options=
opt_disable_keys= lock_tables= opt_set_charset= 1;
- if (opt_single_transaction) lock_tables=0;
break;
case (int) OPT_SKIP_OPTIMIZATION:
extended_insert= opt_drop= opt_lock= quick= create_options=
@@ -627,18 +658,25 @@ static int get_options(int *argc, char ***argv)
"%s: You must use option --tab with --fields-...\n", my_progname);
return(1);
}
- if (opt_single_transaction)
+
+ /* Ensure consistency of the set of binlog & locking options */
+ if (opt_delete_master_logs && !opt_master_data)
+ opt_master_data= MYSQL_OPT_MASTER_DATA_COMMENTED_SQL;
+ if (opt_single_transaction && opt_lock_all_tables)
+ {
+ fprintf(stderr, "%s: You can't use --single-transaction and "
+ "--lock-all-tables at the same time.\n", my_progname);
+ return(1);
+ }
+ if (opt_master_data)
+ opt_lock_all_tables= !opt_single_transaction;
+ if (opt_single_transaction || opt_lock_all_tables)
lock_tables= 0;
if (enclosed && opt_enclosed)
{
fprintf(stderr, "%s: You can't use ..enclosed.. and ..optionally-enclosed.. at the same time.\n", my_progname);
return(1);
}
- if (replace && ignore)
- {
- fprintf(stderr, "%s: You can't use --ignore (-i) and --replace (-r) at the same time.\n",my_progname);
- return(1);
- }
if ((opt_databases || opt_alldbs) && path)
{
fprintf(stderr,
@@ -674,6 +712,36 @@ static void DBerror(MYSQL *mysql, const char *when)
} /* DBerror */
+/*
+ Sends a query to server, optionally reads result, prints error message if
+ some.
+
+ SYNOPSIS
+ mysql_query_with_error_report()
+ mysql_con connection to use
+ res if non zero, result will be put there with mysql_store_result
+ query query to send to server
+
+ RETURN VALUES
+ 0 query sending and (if res!=0) result reading went ok
+ 1 error
+*/
+
+static int mysql_query_with_error_report(MYSQL *mysql_con, MYSQL_RES **res,
+ const char *query)
+{
+ if (mysql_query(mysql_con, query) ||
+ (res && !((*res)= mysql_store_result(mysql_con))))
+ {
+ my_printf_error(0, "%s: Couldn't execute '%s': %s (%d)",
+ MYF(0), my_progname, query,
+ mysql_error(mysql_con), mysql_errno(mysql_con));
+ return 1;
+ }
+ return 0;
+}
+
+
static void safe_exit(int error)
{
if (!first_error)
@@ -689,7 +757,6 @@ static void safe_exit(int error)
/*
** dbConnect -- connects to the host and selects DB.
-** Also checks whether the tablename is a valid table name.
*/
static int dbConnect(char *host, char *user,char *passwd)
{
@@ -721,12 +788,15 @@ static int dbConnect(char *host, char *user,char *passwd)
DBerror(&mysql_connection, "when trying to connect");
return 1;
}
+ /*
+ As we're going to set SQL_MODE, it would be lost on reconnect, so we
+ cannot reconnect.
+ */
+ sock->reconnect= 0;
sprintf(buff, "/*!40100 SET @@SQL_MODE=\"%s\" */",
compatible_mode_normal_str);
- if (mysql_query(sock, buff))
+ if (mysql_query_with_error_report(sock, 0, buff))
{
- fprintf(stderr, "%s: Can't set the compatible mode %s (error %s)\n",
- my_progname, compatible_mode_normal_str, mysql_error(sock));
mysql_close(sock);
safe_exit(EX_MYSQLERR);
return 1;
@@ -824,7 +894,7 @@ static char *quote_for_like(const char *name, char *buff)
len - its length
DESCRIPTION
- Quote '<' '>' '&' '\"' singns and print a string to the xml_file.
+ Quote '<' '>' '&' '\"' chars and print a string to the xml_file.
*/
static void print_quoted_xml(FILE *xml_file, const char *str, ulong len)
@@ -965,7 +1035,11 @@ static uint getTableStructure(char *table, char* db)
result_table= quote_name(table, table_buff, 1);
opt_quoted_table= quote_name(table, table_buff2, 0);
- if (!opt_xml && !mysql_query(sock,insert_pat))
+
+ if (opt_order_by_primary)
+ order_by = primary_key_fields(opt_quoted_table);
+
+ if (!opt_xml && !mysql_query_with_error_report(sock, 0, insert_pat))
{
/* using SHOW CREATE statement */
if (!tFlag)
@@ -975,10 +1049,8 @@ static uint getTableStructure(char *table, char* db)
MYSQL_FIELD *field;
sprintf(buff,"show create table %s", result_table);
- if (mysql_query(sock, buff))
+ if (mysql_query_with_error_report(sock, 0, buff))
{
- fprintf(stderr, "%s: Can't get CREATE TABLE for table %s (%s)\n",
- my_progname, result_table, mysql_error(sock));
safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
}
@@ -1023,10 +1095,8 @@ static uint getTableStructure(char *table, char* db)
mysql_free_result(tableRes);
}
sprintf(insert_pat,"show fields from %s", result_table);
- if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock)))
+ if (mysql_query_with_error_report(sock, &tableRes, insert_pat))
{
- fprintf(stderr, "%s: Can't get info about table: %s\nerror: %s\n",
- my_progname, result_table, mysql_error(sock));
if (path)
my_fclose(sql_file, MYF(MY_WME));
safe_exit(EX_MYSQLERR);
@@ -1066,10 +1136,8 @@ static uint getTableStructure(char *table, char* db)
my_progname, mysql_error(sock));
sprintf(insert_pat,"show fields from %s", result_table);
- if (mysql_query(sock,insert_pat) || !(tableRes=mysql_store_result(sock)))
+ if (mysql_query_with_error_report(sock, &tableRes, insert_pat))
{
- fprintf(stderr, "%s: Can't get info about table: %s\nerror: %s\n",
- my_progname, result_table, mysql_error(sock));
safe_exit(EX_MYSQLERR);
DBUG_RETURN(0);
}
@@ -1163,7 +1231,7 @@ static uint getTableStructure(char *table, char* db)
char buff[20+FN_REFLEN];
uint keynr,primary_key;
sprintf(buff,"show keys from %s", result_table);
- if (mysql_query(sock, buff))
+ if (mysql_query_with_error_report(sock, &tableRes, buff))
{
if (mysql_errno(sock) == ER_WRONG_OBJECT)
{
@@ -1179,7 +1247,6 @@ static uint getTableStructure(char *table, char* db)
DBUG_RETURN(0);
}
- tableRes=mysql_store_result(sock);
/* Find first which key is primary key */
keynr=0;
primary_key=INT_MAX;
@@ -1243,7 +1310,7 @@ static uint getTableStructure(char *table, char* db)
char show_name_buff[FN_REFLEN];
sprintf(buff,"show table status like %s",
quote_for_like(table, show_name_buff));
- if (mysql_query(sock, buff))
+ if (mysql_query_with_error_report(sock, &tableRes, buff))
{
if (mysql_errno(sock) != ER_PARSE_ERROR)
{ /* If old MySQL version */
@@ -1253,8 +1320,7 @@ static uint getTableStructure(char *table, char* db)
result_table,mysql_error(sock));
}
}
- else if (!(tableRes=mysql_store_result(sock)) ||
- !(row=mysql_fetch_row(tableRes)))
+ else if (!(row=mysql_fetch_row(tableRes)))
{
fprintf(stderr,
"Error: Couldn't read status information for table %s (%s)\n",
@@ -1407,10 +1473,6 @@ static void dumpTable(uint numFields, char *table)
sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * INTO OUTFILE '%s'",
filename);
end= strend(query);
- if (replace)
- end= strmov(end, " REPLACE");
- if (ignore)
- end= strmov(end, " IGNORE");
if (fields_terminated || enclosed || opt_enclosed || escaped)
end= strmov(end, " FIELDS");
@@ -1423,10 +1485,17 @@ static void dumpTable(uint numFields, char *table)
sprintf(buff," FROM %s", result_table);
end= strmov(end,buff);
- if (where)
+ if (where || order_by)
{
- query= alloc_query_str((ulong) (strlen(where) + (end - query) + 10));
- end= strxmov(query, query_buf, " WHERE ", where, NullS);
+ query = alloc_query_str((ulong) ((end - query) + 1 +
+ (where ? strlen(where) + 7 : 0) +
+ (order_by ? strlen(order_by) + 10 : 0)));
+ end = strmov(query, query_buf);
+
+ if (where)
+ end = strxmov(end, " WHERE ", where, NullS);
+ if (order_by)
+ end = strxmov(end, " ORDER BY ", order_by, NullS);
}
if (mysql_real_query(sock, query, (uint) (end - query)))
{
@@ -1444,37 +1513,45 @@ static void dumpTable(uint numFields, char *table)
}
sprintf(query, "SELECT /*!40001 SQL_NO_CACHE */ * FROM %s",
result_table);
- if (where)
+ if (where || order_by)
{
- if (!opt_xml && opt_comments)
+ query = alloc_query_str((ulong) (strlen(query) + 1 +
+ (where ? strlen(where) + 7 : 0) +
+ (order_by ? strlen(order_by) + 10 : 0)));
+ end = strmov(query, query_buf);
+
+ if (where)
{
- fprintf(md_result_file,"-- WHERE: %s\n",where);
- check_io(md_result_file);
+ if (!opt_xml && opt_comments)
+ {
+ fprintf(md_result_file, "-- WHERE: %s\n", where);
+ check_io(md_result_file);
+ }
+ end = strxmov(end, " WHERE ", where, NullS);
+ }
+ if (order_by)
+ {
+ if (!opt_xml && opt_comments)
+ {
+ fprintf(md_result_file, "-- ORDER BY: %s\n", order_by);
+ check_io(md_result_file);
+ }
+ end = strxmov(end, " ORDER BY ", order_by, NullS);
}
- query= alloc_query_str((ulong) (strlen(where) + strlen(query) + 10));
- strxmov(query, query_buf, " WHERE ", where, NullS);
}
if (!opt_xml && !opt_compact)
{
fputs("\n", md_result_file);
check_io(md_result_file);
}
- if (mysql_query(sock, query))
- {
+ if (mysql_query_with_error_report(sock, 0, query))
DBerror(sock, "when retrieving data from server");
- error= EX_CONSCHECK;
- goto err;
- }
if (quick)
res=mysql_use_result(sock);
else
res=mysql_store_result(sock);
if (!res)
- {
DBerror(sock, "when retrieving data from server");
- error= EX_CONSCHECK;
- goto err;
- }
if (verbose)
fprintf(stderr, "-- Retrieving rows...\n");
if (mysql_num_fields(res) != numFields)
@@ -1543,13 +1620,16 @@ static void dumpTable(uint numFields, char *table)
/*
63 is my_charset_bin. If charsetnr is not 63,
we have not a BLOB but a TEXT column.
- we'll dump it in hex only BLOB columns.
+ we'll dump in hex only BLOB columns.
*/
is_blob= (opt_hex_blob && field->charsetnr == 63 &&
- (field->type == FIELD_TYPE_BLOB ||
- field->type == FIELD_TYPE_LONG_BLOB ||
- field->type == FIELD_TYPE_MEDIUM_BLOB ||
- field->type == FIELD_TYPE_TINY_BLOB)) ? 1 : 0;
+ (field->type == MYSQL_TYPE_STRING ||
+ field->type == MYSQL_TYPE_VAR_STRING ||
+ field->type == MYSQL_TYPE_VARCHAR ||
+ field->type == MYSQL_TYPE_BLOB ||
+ field->type == MYSQL_TYPE_LONG_BLOB ||
+ field->type == MYSQL_TYPE_MEDIUM_BLOB ||
+ field->type == MYSQL_TYPE_TINY_BLOB)) ? 1 : 0;
if (extended_insert)
{
ulong length = lengths[i];
@@ -1564,6 +1644,13 @@ static void dumpTable(uint numFields, char *table)
{
if (!IS_NUM_FIELD(field))
{
+ /*
+ "length * 2 + 2" is OK for both HEX and non-HEX modes:
+ - In HEX mode we need exactly 2 bytes per character
+ plus 2 bytes for '0x' prefix.
+ - In non-HEX mode we need up to 2 bytes per character,
+ plus 2 bytes for leading and trailing '\'' characters.
+ */
if (dynstr_realloc(&extended_row,length * 2+2))
{
fputs("Aborting dump (out of memory)",stderr);
@@ -1572,15 +1659,11 @@ static void dumpTable(uint numFields, char *table)
}
if (opt_hex_blob && is_blob)
{
- ulong counter;
- unsigned char *ptr= row[i];
dynstr_append(&extended_row, "0x");
- for (counter = 0; counter < lengths[i]; counter++)
- {
- char xx[3];
- sprintf(xx, "%02X", ptr[counter]);
- dynstr_append(&extended_row, xx);
- }
+ extended_row.length+= mysql_hex_string(extended_row.str +
+ extended_row.length,
+ row[i], length);
+ extended_row.str[extended_row.length]= '\0';
}
else
{
@@ -1643,16 +1726,12 @@ static void dumpTable(uint numFields, char *table)
fputs("</field>\n", md_result_file);
}
else if (opt_hex_blob && is_blob)
- { /* sakaik got this idea. */
- ulong counter;
- char xx[4];
- unsigned char *ptr= row[i];
+ {
+ /* sakaik got the idea to to provide blob's in hex notation. */
+ char *ptr= row[i], *end= ptr+ lengths[i];
fputs("0x", md_result_file);
- for (counter = 0; counter < lengths[i]; counter++)
- {
- sprintf(xx, "%02X", ptr[counter]);
- fputs(xx, md_result_file);
- }
+ for (; ptr < end ; ptr++)
+ fprintf(md_result_file, "%02X", *ptr);
}
else
unescape(md_result_file, row[i], lengths[i]);
@@ -1769,6 +1848,8 @@ static void dumpTable(uint numFields, char *table)
err:
if (query != query_buf)
my_free(query, MYF(MY_ALLOW_ZERO_PTR));
+ if (order_by)
+ my_free(order_by, MYF(0));
safe_exit(error);
return;
} /* dumpTable */
@@ -1804,13 +1885,8 @@ static int dump_all_databases()
MYSQL_RES *tableres;
int result=0;
- if (mysql_query(sock, "SHOW DATABASES") ||
- !(tableres = mysql_store_result(sock)))
- {
- my_printf_error(0, "Error: Couldn't execute 'SHOW DATABASES': %s",
- MYF(0), mysql_error(sock));
+ if (mysql_query_with_error_report(sock, &tableres, "SHOW DATABASES"))
return 1;
- }
while ((row = mysql_fetch_row(tableres)))
{
if (dump_all_tables_in_db(row[0]))
@@ -1884,10 +1960,10 @@ static int init_dumping(char *database)
MYSQL_ROW row;
MYSQL_RES *dbinfo;
- sprintf(qbuf,"SHOW CREATE DATABASE WITH IF NOT EXISTS %s",
+ sprintf(qbuf,"SHOW CREATE DATABASE IF NOT EXISTS %s",
qdatabase);
- if (mysql_query(sock, qbuf) || !(dbinfo = mysql_store_result(sock)))
+ if (mysql_query_with_error_report(sock, &dbinfo, qbuf))
{
/* Old server version, dump generic CREATE DATABASE */
fprintf(md_result_file,
@@ -1956,7 +2032,7 @@ static int dump_all_tables_in_db(char *database)
check_io(md_result_file);
}
if (lock_tables)
- mysql_query(sock,"UNLOCK TABLES");
+ mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
return 0;
} /* dump_all_tables_in_db */
@@ -2062,11 +2138,86 @@ static int dump_selected_tables(char *db, char **table_names, int tables)
check_io(md_result_file);
}
if (lock_tables)
- mysql_query(sock,"UNLOCK TABLES");
+ mysql_query_with_error_report(sock, 0, "UNLOCK TABLES");
return 0;
} /* dump_selected_tables */
+static int do_show_master_status(MYSQL *mysql_con)
+{
+ MYSQL_ROW row;
+ MYSQL_RES *master;
+ const char *comment_prefix=
+ (opt_master_data == MYSQL_OPT_MASTER_DATA_COMMENTED_SQL) ? "-- " : "";
+ if (mysql_query_with_error_report(mysql_con, &master, "SHOW MASTER STATUS"))
+ {
+ my_printf_error(0, "Error: Couldn't execute 'SHOW MASTER STATUS': %s",
+ MYF(0), mysql_error(mysql_con));
+ return 1;
+ }
+ else
+ {
+ row = mysql_fetch_row(master);
+ if (row && row[0] && row[1])
+ {
+ if (opt_comments)
+ fprintf(md_result_file,
+ "\n--\n-- Position to start replication or point-in-time "
+ "recovery from\n--\n\n");
+ fprintf(md_result_file,
+ "%sCHANGE MASTER TO MASTER_LOG_FILE='%s', MASTER_LOG_POS=%s;\n",
+ comment_prefix, row[0], row[1]);
+ check_io(md_result_file);
+ }
+ mysql_free_result(master);
+ }
+ return 0;
+}
+
+
+static int do_flush_tables_read_lock(MYSQL *mysql_con)
+{
+ /*
+ We do first a FLUSH TABLES. If a long update is running, the FLUSH TABLES
+ will wait but will not stall the whole mysqld, and when the long update is
+ done the FLUSH TABLES WITH READ LOCK will start and succeed quickly. So,
+ FLUSH TABLES is to lower the probability of a stage where both mysqldump
+ and most client connections are stalled. Of course, if a second long
+ update starts between the two FLUSHes, we have that bad stall.
+ */
+ return
+ ( mysql_query_with_error_report(mysql_con, 0, "FLUSH TABLES") ||
+ mysql_query_with_error_report(mysql_con, 0,
+ "FLUSH TABLES WITH READ LOCK") );
+}
+
+
+static int do_unlock_tables(MYSQL *mysql_con)
+{
+ return mysql_query_with_error_report(mysql_con, 0, "UNLOCK TABLES");
+}
+
+
+static int do_reset_master(MYSQL *mysql_con)
+{
+ return mysql_query_with_error_report(mysql_con, 0, "RESET MASTER");
+}
+
+
+static int start_transaction(MYSQL *mysql_con, my_bool consistent_read_now)
+{
+ /*
+ We use BEGIN for old servers. --single-transaction --master-data will fail
+ on old servers, but that's ok as it was already silently broken (it didn't
+ do a consistent read, so better tell people frankly, with the error).
+ */
+ return (mysql_query_with_error_report(mysql_con, 0,
+ consistent_read_now ?
+ "START TRANSACTION "
+ "WITH CONSISTENT SNAPSHOT" :
+ "BEGIN"));
+}
+
static ulong find_set(TYPELIB *lib, const char *x, uint length,
char **err_pos, uint *err_len)
@@ -2164,7 +2315,7 @@ static const char *check_if_ignore_table(const char *table_name)
sprintf(buff,"show table status like %s",
quote_for_like(table_name, show_name_buff));
- if (mysql_query(sock, buff))
+ if (mysql_query_with_error_report(sock, &res, buff))
{
if (mysql_errno(sock) != ER_PARSE_ERROR)
{ /* If old MySQL version */
@@ -2175,8 +2326,7 @@ static const char *check_if_ignore_table(const char *table_name)
return 0; /* assume table is ok */
}
}
- if (!(res= mysql_store_result(sock)) ||
- !(row= mysql_fetch_row(res)))
+ if (!(row= mysql_fetch_row(res)))
{
fprintf(stderr,
"Error: Couldn't read status information for table %s (%s)\n",
@@ -2197,6 +2347,80 @@ static const char *check_if_ignore_table(const char *table_name)
return result;
}
+/*
+ Get string of comma-separated primary key field names
+
+ SYNOPSIS
+ char *primary_key_fields(const char *table_name)
+ RETURNS pointer to allocated buffer (must be freed by caller)
+ table_name quoted table name
+
+ DESCRIPTION
+ Use SHOW KEYS FROM table_name, allocate a buffer to hold the
+ field names, and then build that string and return the pointer
+ to that buffer.
+
+ Returns NULL if there is no PRIMARY or UNIQUE key on the table,
+ or if there is some failure. It is better to continue to dump
+ the table unsorted, rather than exit without dumping the data.
+*/
+static char *primary_key_fields(const char *table_name)
+{
+ MYSQL_RES *res = NULL;
+ MYSQL_ROW row;
+ /* SHOW KEYS FROM + table name * 2 (escaped) + 2 quotes + \0 */
+ char show_keys_buff[15 + 64 * 2 + 3];
+ uint result_length = 0;
+ char *result = 0;
+
+ sprintf(show_keys_buff, "SHOW KEYS FROM %s", table_name);
+ if (mysql_query(sock, show_keys_buff) ||
+ !(res = mysql_store_result(sock)))
+ {
+ fprintf(stderr, "Warning: Couldn't read keys from table %s;"
+ " records are NOT sorted (%s)\n",
+ table_name, mysql_error(sock));
+ /* Don't exit, because it's better to print out unsorted records */
+ goto cleanup;
+ }
+
+ /*
+ * Figure out the length of the ORDER BY clause result.
+ * Note that SHOW KEYS is ordered: a PRIMARY key is always the first
+ * row, and UNIQUE keys come before others. So we only need to check
+ * the first key, not all keys.
+ */
+ if ((row = mysql_fetch_row(res)) && atoi(row[1]) == 0)
+ {
+ /* Key is unique */
+ do
+ result_length += strlen(row[4]) + 1; /* + 1 for ',' or \0 */
+ while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1);
+ }
+
+ /* Build the ORDER BY clause result */
+ if (result_length) {
+ char *end;
+ /* result (terminating \0 is already in result_length) */
+ result = my_malloc(result_length + 10, MYF(MY_WME));
+ if (!result) {
+ fprintf(stderr, "Error: Not enough memory to store ORDER BY clause\n");
+ goto cleanup;
+ }
+ mysql_data_seek(res, 0);
+ row = mysql_fetch_row(res);
+ end = strmov(result, row[4]);
+ while ((row = mysql_fetch_row(res)) && atoi(row[3]) > 1)
+ end = strxmov(end, ",", row[4], NullS);
+ }
+
+cleanup:
+ if (res)
+ mysql_free_result(res);
+
+ return result;
+}
+
/*
Getting VIEW structure
@@ -2294,8 +2518,6 @@ static my_bool getViewStructure(char *table, char* db)
int main(int argc, char **argv)
{
- MYSQL_ROW row;
- MYSQL_RES *master;
compatible_mode_normal_str[0]= 0;
MY_INIT(argv[0]);
@@ -2309,28 +2531,24 @@ int main(int argc, char **argv)
if (!path)
write_header(md_result_file, *argv);
- if (opt_first_slave)
- {
- lock_tables=0; /* No other locks needed */
- if (mysql_query(sock, "FLUSH TABLES WITH READ LOCK"))
- {
- my_printf_error(0, "Error: Couldn't execute 'FLUSH TABLES WITH READ LOCK': %s",
- MYF(0), mysql_error(sock));
- my_end(0);
- return(first_error);
- }
- }
- else if (opt_single_transaction)
+ if ((opt_lock_all_tables || opt_master_data) &&
+ do_flush_tables_read_lock(sock))
+ goto err;
+ if (opt_single_transaction && start_transaction(sock, test(opt_master_data)))
+ goto err;
+ if (opt_delete_master_logs && do_reset_master(sock))
+ goto err;
+ if (opt_lock_all_tables || opt_master_data)
{
- /* There is no sense to start transaction if all tables are locked */
- if (mysql_query(sock, "BEGIN"))
- {
- my_printf_error(0, "Error: Couldn't execute 'BEGIN': %s",
- MYF(0), mysql_error(sock));
- my_end(0);
- return(first_error);
- }
+ if (flush_logs && mysql_refresh(sock, REFRESH_LOG))
+ goto err;
+ flush_logs= 0; /* not anymore; that would not be sensible */
}
+ if (opt_master_data && do_show_master_status(sock))
+ goto err;
+ if (opt_single_transaction && do_unlock_tables(sock)) /* unlock but no commit! */
+ goto err;
+
if (opt_alldbs)
dump_all_databases();
else if (argc > 1 && !opt_databases)
@@ -2343,57 +2561,16 @@ int main(int argc, char **argv)
/* One or more databases, all tables */
dump_databases(argv);
}
-
- if (opt_first_slave)
- {
- if (opt_delete_master_logs && mysql_query(sock, "FLUSH MASTER"))
- {
- my_printf_error(0, "Error: Couldn't execute 'FLUSH MASTER': %s",
- MYF(0), mysql_error(sock));
- }
- if (opt_master_data)
- {
- if (mysql_query(sock, "SHOW MASTER STATUS") ||
- !(master = mysql_store_result(sock)))
- my_printf_error(0, "Error: Couldn't execute 'SHOW MASTER STATUS': %s",
- MYF(0), mysql_error(sock));
- else
- {
- row = mysql_fetch_row(master);
- if (row && row[0] && row[1])
- {
- if (opt_comments)
- fprintf(md_result_file,
- "\n--\n-- Position to start replication from\n--\n\n");
- fprintf(md_result_file,
- "CHANGE MASTER TO MASTER_LOG_FILE='%s', \
-MASTER_LOG_POS=%s ;\n",row[0],row[1]);
- check_io(md_result_file);
- }
- mysql_free_result(master);
- }
- }
- if (mysql_query(sock, "UNLOCK TABLES"))
- my_printf_error(0, "Error: Couldn't execute 'UNLOCK TABLES': %s",
- MYF(0), mysql_error(sock));
- }
- else if (opt_single_transaction) /* Just to make it beautiful enough */
#ifdef HAVE_SMEM
my_free(shared_memory_base_name,MYF(MY_ALLOW_ZERO_PTR));
#endif
- {
- /*
- In case we were locking all tables, we did not start transaction
- so there is no need to commit it.
- */
-
- /* This should just free locks as we did not change anything */
- if (mysql_query(sock, "COMMIT"))
- {
- my_printf_error(0, "Error: Couldn't execute 'COMMIT': %s",
- MYF(0), mysql_error(sock));
- }
- }
+ /*
+ No reason to explicitely COMMIT the transaction, neither to explicitely
+ UNLOCK TABLES: these will be automatically be done by the server when we
+ disconnect now. Saves some code here, some network trips, adds nothing to
+ server.
+ */
+err:
dbDisconnect(current_host);
if (!path)
write_footer(md_result_file);
diff --git a/client/mysqltest.c b/client/mysqltest.c
index 420d5316cd4..bc99d4d38f3 100644
--- a/client/mysqltest.c
+++ b/client/mysqltest.c
@@ -42,7 +42,7 @@
**********************************************************************/
-#define MTEST_VERSION "2.3"
+#define MTEST_VERSION "2.4"
#include <my_global.h>
#include <mysql_embed.h>
@@ -243,6 +243,7 @@ VAR var_reg[10];
HASH var_hash;
my_bool disable_query_log=0, disable_result_log=0, disable_warnings=0;
my_bool disable_info= 1; /* By default off */
+my_bool abort_on_error= 1;
struct connection cons[MAX_CONS];
struct connection* cur_con, *next_con, *cons_end;
@@ -274,6 +275,7 @@ Q_ENABLE_WARNINGS, Q_DISABLE_WARNINGS,
Q_ENABLE_INFO, Q_DISABLE_INFO,
Q_ENABLE_METADATA, Q_DISABLE_METADATA,
Q_EXEC, Q_DELIMITER,
+Q_DISABLE_ABORT_ON_ERROR, Q_ENABLE_ABORT_ON_ERROR,
Q_DISPLAY_VERTICAL_RESULTS, Q_DISPLAY_HORIZONTAL_RESULTS,
Q_QUERY_VERTICAL, Q_QUERY_HORIZONTAL,
Q_START_TIMER, Q_END_TIMER,
@@ -282,7 +284,7 @@ Q_EXIT,
Q_UNKNOWN, /* Unknown command. */
Q_COMMENT, /* Comments, ignored. */
-Q_COMMENT_WITH_COMMAND,
+Q_COMMENT_WITH_COMMAND
};
/* this should really be called command */
@@ -353,6 +355,8 @@ const char *command_names[]=
"disable_metadata",
"exec",
"delimiter",
+ "disable_abort_on_error",
+ "enable_abort_on_error",
"vertical_results",
"horizontal_results",
"query_vertical",
@@ -741,7 +745,7 @@ err:
DBUG_RETURN(0);
}
-static VAR* var_obtain(char* name, int len)
+static VAR *var_obtain(const char* name, int len)
{
VAR* v;
if ((v = (VAR*)hash_search(&var_hash, name, len)))
@@ -751,28 +755,33 @@ static VAR* var_obtain(char* name, int len)
return v;
}
-int var_set(char* var_name, char* var_name_end, char* var_val,
- char* var_val_end)
+int var_set(const char *var_name, const char *var_name_end,
+ const char *var_val, const char *var_val_end)
{
int digit;
VAR* v;
+ DBUG_ENTER("var_set");
+ DBUG_PRINT("enter", ("var_name: '%.*s' = '%.*s' (length: %d)",
+ (int) (var_name_end - var_name), var_name,
+ (int) (var_val_end - var_val), var_val,
+ (int) (var_val_end - var_val)));
+
if (*var_name++ != '$')
- {
- --var_name;
- *var_name_end = 0;
- die("Variable name in %s does not start with '$'", var_name);
- }
+ {
+ var_name--;
+ die("Variable name in %s does not start with '$'", var_name);
+ }
digit = *var_name - '0';
if (!(digit < 10 && digit >= 0))
- {
- v = var_obtain(var_name, var_name_end - var_name);
- }
+ {
+ v = var_obtain(var_name, (uint) (var_name_end - var_name));
+ }
else
- v = var_reg + digit;
-
- return eval_expr(v, var_val, (const char**)&var_val_end);
+ v = var_reg + digit;
+ DBUG_RETURN(eval_expr(v, var_val, (const char**)&var_val_end));
}
+
int open_file(const char* name)
{
char buff[FN_REFLEN];
@@ -942,7 +951,6 @@ static void do_exec(struct st_query* q)
while (fgets(buf, sizeof(buf), res_file))
replace_dynstr_append_mem(ds, buf, strlen(buf));
}
-
error= pclose(res_file);
if (error != 0)
@@ -1241,6 +1249,22 @@ int do_let(struct st_query* q)
return var_set(var_name, var_name_end, var_val_start, q->end);
}
+
+/*
+ Store an integer (typically the returncode of the last SQL)
+ statement in the mysqltest builtin variable $mysql_errno, by
+ simulating of a user statement "let $mysql_errno= <integer>"
+*/
+
+int var_set_errno(int sql_errno)
+{
+ const char *var_name= "$mysql_errno";
+ char var_val[21];
+ uint length= my_sprintf(var_val, (var_val, "%d", sql_errno));
+ return var_set(var_name, var_name + 12, var_val, var_val + length);
+}
+
+
int do_rpl_probe(struct st_query* q __attribute__((unused)))
{
DBUG_ENTER("do_rpl_probe");
@@ -1249,12 +1273,14 @@ int do_rpl_probe(struct st_query* q __attribute__((unused)))
DBUG_RETURN(0);
}
+
int do_enable_rpl_parse(struct st_query* q __attribute__((unused)))
{
mysql_enable_rpl_parse(&cur_con->mysql);
return 0;
}
+
int do_disable_rpl_parse(struct st_query* q __attribute__((unused)))
{
mysql_disable_rpl_parse(&cur_con->mysql);
@@ -1998,7 +2024,7 @@ int read_query(struct st_query** q_ptr)
memcpy((gptr) q->expected_errno, (gptr) global_expected_errno,
sizeof(global_expected_errno));
q->expected_errors= global_expected_errors;
- q->abort_on_error= global_expected_errors == 0;
+ q->abort_on_error= (global_expected_errors == 0 && abort_on_error);
bzero((gptr) global_expected_errno, sizeof(global_expected_errno));
global_expected_errors=0;
if (p[0] == '-' && p[1] == '-')
@@ -2407,7 +2433,7 @@ static int run_query(MYSQL *mysql, struct st_query *q, int flags)
if (ps_protocol_enabled && disable_info &&
(flags & QUERY_SEND) && (flags & QUERY_REAP) && ps_match_re(q->query))
- return run_query_stmt (mysql, q, flags);
+ return run_query_stmt(mysql, q, flags);
return run_query_normal(mysql, q, flags);
}
@@ -2644,6 +2670,13 @@ end:
dynstr_free(&ds_tmp);
if (q->type == Q_EVAL)
dynstr_free(&eval_query);
+
+ /*
+ We save the return code (mysql_errno(mysql)) from the last call sent
+ to the server into the mysqltest builtin variable $mysql_errno. This
+ variable then can be used from the test case itself.
+ */
+ var_set_errno(mysql_errno(mysql));
DBUG_RETURN(error);
}
@@ -2993,6 +3026,7 @@ end:
dynstr_free(&ds_tmp);
if (q->type == Q_EVAL)
dynstr_free(&eval_query);
+ var_set_errno(mysql_stmt_errno(stmt));
mysql_stmt_close(stmt);
DBUG_RETURN(error);
}
@@ -3300,7 +3334,7 @@ static VAR* var_from_env(const char *name, const char *def_val)
if (!(tmp = getenv(name)))
tmp = def_val;
- v = var_init(0, name, 0, tmp, 0);
+ v = var_init(0, name, strlen(name), tmp, strlen(tmp));
my_hash_insert(&var_hash, (byte*)v);
return v;
}
@@ -3319,7 +3353,8 @@ static void init_var_hash(MYSQL *mysql)
my_hash_insert(&var_hash, (byte*) v);
v= var_init(0,"SERVER_VERSION", 0, mysql_get_server_info(mysql), 0);
my_hash_insert(&var_hash, (byte*) v);
-
+ v= var_init(0,"DB", 2, db, 0);
+ my_hash_insert(&var_hash, (byte*) v);
DBUG_VOID_RETURN;
}
@@ -3396,6 +3431,13 @@ int main(int argc, char **argv)
init_var_hash(&cur_con->mysql);
+ /*
+ Initialize $mysql_errno with -1, so we can
+ - distinguish it from valid values ( >= 0 ) and
+ - detect if there was never a command sent to the server
+ */
+ var_set_errno(-1);
+
while (!abort_flag && !read_query(&q))
{
int current_line_inc = 1, processed = 0;
@@ -3415,6 +3457,8 @@ int main(int argc, char **argv)
case Q_DISABLE_RPL_PARSE: do_disable_rpl_parse(q); break;
case Q_ENABLE_QUERY_LOG: disable_query_log=0; break;
case Q_DISABLE_QUERY_LOG: disable_query_log=1; break;
+ case Q_ENABLE_ABORT_ON_ERROR: abort_on_error=1; break;
+ case Q_DISABLE_ABORT_ON_ERROR: abort_on_error=0; break;
case Q_ENABLE_RESULT_LOG: disable_result_log=0; break;
case Q_DISABLE_RESULT_LOG: disable_result_log=1; break;
case Q_ENABLE_WARNINGS: disable_warnings=0; break;
@@ -4476,8 +4520,7 @@ static void get_replace_column(struct st_query *q)
my_free(start, MYF(0));
}
-#ifdef __NETWARE__
-
+#if defined(__NETWARE__) || defined(__WIN__)
/*
Substitute environment variables with text.
@@ -4573,4 +4616,4 @@ FILE *my_popen(const char *cmd, const char *mode __attribute__((unused)))
return res_file;
}
-#endif /* __NETWARE__ */
+#endif /* __NETWARE__ or __WIN__*/
diff --git a/config/ac-macros/alloca.m4 b/config/ac-macros/alloca.m4
new file mode 100644
index 00000000000..8c730dd671f
--- /dev/null
+++ b/config/ac-macros/alloca.m4
@@ -0,0 +1,68 @@
+AC_DEFUN([MYSQL_FUNC_ALLOCA],
+[
+# Since we have heard that alloca fails on IRIX never define it on a
+# SGI machine
+if test ! "$host_vendor" = "sgi"
+then
+ AC_REQUIRE_CPP()dnl Set CPP; we run AC_EGREP_CPP conditionally.
+ # The Ultrix 4.2 mips builtin alloca declared by alloca.h only works
+ # for constant arguments. Useless!
+ AC_CACHE_CHECK([for working alloca.h], ac_cv_header_alloca_h,
+ [AC_TRY_LINK([#include <alloca.h>], [char *p = alloca(2 * sizeof(int));],
+ ac_cv_header_alloca_h=yes, ac_cv_header_alloca_h=no)])
+ if test "$ac_cv_header_alloca_h" = "yes"
+ then
+ AC_DEFINE(HAVE_ALLOCA, 1)
+ fi
+
+ AC_CACHE_CHECK([for alloca], ac_cv_func_alloca_works,
+ [AC_TRY_LINK([
+ #ifdef __GNUC__
+ # define alloca __builtin_alloca
+ #else
+ # if HAVE_ALLOCA_H
+ # include <alloca.h>
+ # else
+ # ifdef _AIX
+ #pragma alloca
+ # else
+ # ifndef alloca /* predefined by HP cc +Olibcalls */
+ char *alloca ();
+ # endif
+ # endif
+ # endif
+ #endif
+ ], [char *p = (char *) alloca(1);],
+ ac_cv_func_alloca_works=yes, ac_cv_func_alloca_works=no)])
+ if test "$ac_cv_func_alloca_works" = "yes"; then
+ AC_DEFINE([HAVE_ALLOCA], [1], [If we have a working alloca() implementation])
+ fi
+
+ if test "$ac_cv_func_alloca_works" = "no"; then
+ # The SVR3 libPW and SVR4 libucb both contain incompatible functions
+ # that cause trouble. Some versions do not even contain alloca or
+ # contain a buggy version. If you still want to use their alloca,
+ # use ar to extract alloca.o from them instead of compiling alloca.c.
+ ALLOCA=alloca.o
+ AC_DEFINE(C_ALLOCA, 1)
+
+ AC_CACHE_CHECK(whether alloca needs Cray hooks, ac_cv_os_cray,
+ [AC_EGREP_CPP(webecray,
+ [#if defined(CRAY) && ! defined(CRAY2)
+ webecray
+ #else
+ wenotbecray
+ #endif
+ ], ac_cv_os_cray=yes, ac_cv_os_cray=no)])
+ if test "$ac_cv_os_cray" = "yes"; then
+ for ac_func in _getb67 GETB67 getb67; do
+ AC_CHECK_FUNC($ac_func, [AC_DEFINE_UNQUOTED(CRAY_STACKSEG_END, $ac_func)
+ break])
+ done
+ fi
+ fi
+ AC_SUBST(ALLOCA)dnl
+else
+ AC_MSG_RESULT("Skipped alloca tests")
+fi
+])
diff --git a/config/ac-macros/character_sets.m4 b/config/ac-macros/character_sets.m4
new file mode 100644
index 00000000000..77081639897
--- /dev/null
+++ b/config/ac-macros/character_sets.m4
@@ -0,0 +1,389 @@
+dnl In order to add new charset, you must add charset name to
+dnl this CHARSETS_AVAILABLE list and sql/share/charsets/Index.xml.
+dnl If the character set uses strcoll or other special handling,
+dnl you must also create strings/ctype-$charset_name.c
+
+AC_DIVERT_PUSH(0)
+
+define(CHARSETS_AVAILABLE0,binary)
+define(CHARSETS_AVAILABLE1,armscii8 ascii big5 cp1250 cp1251 cp1256 cp1257)
+define(CHARSETS_AVAILABLE2,cp850 cp852 cp866 dec8 euckr gb2312 gbk geostd8)
+define(CHARSETS_AVAILABLE3,greek hebrew hp8 keybcs2 koi8r koi8u)
+define(CHARSETS_AVAILABLE4,latin1 latin2 latin5 latin7 macce macroman)
+define(CHARSETS_AVAILABLE5,sjis swe7 tis620 ucs2 ujis utf8)
+
+DEFAULT_CHARSET=latin1
+CHARSETS_AVAILABLE="CHARSETS_AVAILABLE0 CHARSETS_AVAILABLE1 CHARSETS_AVAILABLE2 CHARSETS_AVAILABLE3 CHARSETS_AVAILABLE4 CHARSETS_AVAILABLE5"
+CHARSETS_COMPLEX="big5 cp1250 euckr gb2312 gbk latin1 latin2 sjis tis620 ucs2 ujis utf8"
+
+AC_DIVERT_POP
+
+AC_ARG_WITH(charset,
+ [ --with-charset=CHARSET
+ Default character set, use one of:
+ CHARSETS_AVAILABLE0
+ CHARSETS_AVAILABLE1
+ CHARSETS_AVAILABLE2
+ CHARSETS_AVAILABLE3
+ CHARSETS_AVAILABLE4
+ CHARSETS_AVAILABLE5],
+ [default_charset="$withval"],
+ [default_charset="$DEFAULT_CHARSET"])
+
+AC_ARG_WITH(collation,
+ [ --with-collation=COLLATION
+ Default collation],
+ [default_collation="$withval"],
+ [default_collation="default"])
+
+
+AC_ARG_WITH(extra-charsets,
+ [ --with-extra-charsets=CHARSET[,CHARSET,...]
+ Use charsets in addition to default (none, complex,
+ all, or a list selected from the above sets)],
+ [extra_charsets="$withval"],
+ [extra_charsets="none"])
+
+
+AC_MSG_CHECKING("character sets")
+
+CHARSETS="$default_charset latin1 utf8"
+
+if test "$extra_charsets" = no; then
+ CHARSETS="$CHARSETS"
+elif test "$extra_charsets" = none; then
+ CHARSETS="$CHARSETS"
+elif test "$extra_charsets" = complex; then
+ CHARSETS="$CHARSETS $CHARSETS_COMPLEX"
+ AC_DEFINE([DEFINE_ALL_CHARACTER_SETS],1,[all charsets are available])
+elif test "$extra_charsets" = all; then
+ CHARSETS="$CHARSETS $CHARSETS_AVAILABLE"
+ AC_DEFINE([DEFINE_ALL_CHARACTER_SETS],1,[all charsets are available])
+else
+ EXTRA_CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'`
+ CHARSETS="$CHARSETS $EXTRA_CHARSETS"
+fi
+
+for cs in $CHARSETS
+do
+ case $cs in
+ armscii8)
+ AC_DEFINE(HAVE_CHARSET_armscii8, 1,
+ [Define to enable charset armscii8])
+ ;;
+ ascii)
+ AC_DEFINE(HAVE_CHARSET_ascii, 1,
+ [Define to enable ascii character set])
+ ;;
+ big5)
+ AC_DEFINE(HAVE_CHARSET_big5, 1, [Define to enable charset big5])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, [1], [ ])
+ ;;
+ binary)
+ ;;
+ cp1250)
+ AC_DEFINE(HAVE_CHARSET_cp1250, 1, [Define to enable cp1250])
+ ;;
+ cp1251)
+ AC_DEFINE(HAVE_CHARSET_cp1251, 1, [Define to enable charset cp1251])
+ ;;
+ cp1256)
+ AC_DEFINE(HAVE_CHARSET_cp1256, 1, [Define to enable charset cp1256])
+ ;;
+ cp1257)
+ AC_DEFINE(HAVE_CHARSET_cp1257, 1, [Define to enable charset cp1257])
+ ;;
+ cp850)
+ AC_DEFINE(HAVE_CHARSET_cp850, 1, [Define to enable charset cp850])
+ ;;
+ cp852)
+ AC_DEFINE(HAVE_CHARSET_cp852, 1, [Define to enable charset cp852])
+ ;;
+ cp866)
+ AC_DEFINE(HAVE_CHARSET_cp866, 1, [Define to enable charset cp866])
+ ;;
+ dec8)
+ AC_DEFINE(HAVE_CHARSET_dec8, 1, [Define to enable charset dec8])
+ ;;
+ euckr)
+ AC_DEFINE(HAVE_CHARSET_euckr, 1, [Define to enable charset euckr])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ gb2312)
+ AC_DEFINE(HAVE_CHARSET_gb2312, 1, [Define to enable charset gb2312])
+ AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ gbk)
+ AC_DEFINE(HAVE_CHARSET_gbk, 1, [Define to enable charset gbk])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ geostd8)
+ AC_DEFINE(HAVE_CHARSET_geostd8, 1, [Define to enable charset geostd8])
+ ;;
+ greek)
+ AC_DEFINE(HAVE_CHARSET_greek, 1, [Define to enable charset greek])
+ ;;
+ hebrew)
+ AC_DEFINE(HAVE_CHARSET_hebrew, 1, [Define to enable charset hebrew])
+ ;;
+ hp8)
+ AC_DEFINE(HAVE_CHARSET_hp8, 1, [Define to enable charset hp8])
+ ;;
+ keybcs2)
+ AC_DEFINE(HAVE_CHARSET_keybcs2, 1, [Define to enable charset keybcs2])
+ ;;
+ koi8r)
+ AC_DEFINE(HAVE_CHARSET_koi8r, 1, [Define to enable charset koi8r])
+ ;;
+ koi8u)
+ AC_DEFINE(HAVE_CHARSET_koi8u, 1, [Define to enable charset koi8u])
+ ;;
+ latin1)
+ AC_DEFINE(HAVE_CHARSET_latin1, 1, [Define to enable charset latin1])
+ ;;
+ latin2)
+ AC_DEFINE(HAVE_CHARSET_latin2, 1, [Define to enable charset latin2])
+ ;;
+ latin5)
+ AC_DEFINE(HAVE_CHARSET_latin5, 1, [Define to enable charset latin5])
+ ;;
+ latin7)
+ AC_DEFINE(HAVE_CHARSET_latin7, 1, [Define to enable charset latin7])
+ ;;
+ macce)
+ AC_DEFINE(HAVE_CHARSET_macce, 1, [Define to enable charset macce])
+ ;;
+ macroman)
+ AC_DEFINE(HAVE_CHARSET_macroman, 1,
+ [Define to enable charset macroman])
+ ;;
+ sjis)
+ AC_DEFINE(HAVE_CHARSET_sjis, 1, [Define to enable charset sjis])
+ AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ swe7)
+ AC_DEFINE(HAVE_CHARSET_swe7, 1, [Define to enable charset swe7])
+ ;;
+ tis620)
+ AC_DEFINE(HAVE_CHARSET_tis620, 1, [Define to enable charset tis620])
+ ;;
+ ucs2)
+ AC_DEFINE(HAVE_CHARSET_ucs2, 1, [Define to enable charset ucs2])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ ujis)
+ AC_DEFINE(HAVE_CHARSET_ujis, 1, [Define to enable charset ujis])
+ AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ utf8)
+ AC_DEFINE(HAVE_CHARSET_utf8, 1, [Define to enable ut8])
+ AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
+ AC_DEFINE(USE_MB_IDENT, 1)
+ ;;
+ *)
+ AC_MSG_ERROR([Charset '$cs' not available. (Available are: $CHARSETS_AVAILABLE).
+ See the Installation chapter in the Reference Manual.]);
+ esac
+done
+
+
+ default_charset_collations=""
+
+case $default_charset in
+ armscii8)
+ default_charset_default_collation="armscii8_general_ci"
+ default_charset_collations="armscii8_general_ci armscii8_bin"
+ ;;
+ ascii)
+ default_charset_default_collation="ascii_general_ci"
+ default_charset_collations="ascii_general_ci ascii_bin"
+ ;;
+ big5)
+ default_charset_default_collation="big5_chinese_ci"
+ default_charset_collations="big5_chinese_ci big5_bin"
+ ;;
+ binary)
+ default_charset_default_collation="binary"
+ default_charset_collations="binary"
+ ;;
+ cp1250)
+ default_charset_default_collation="cp1250_general_ci"
+ default_charset_collations="cp1250_general_ci cp1250_czech_cs cp1250_bin"
+ ;;
+ cp1251)
+ default_charset_default_collation="cp1251_general_ci"
+ default_charset_collations="cp1251_general_ci cp1251_general_cs cp1251_bin cp1251_bulgarian_ci cp1251_ukrainian_ci"
+ ;;
+ cp1256)
+ default_charset_default_collation="cp1256_general_ci"
+ default_charset_collations="cp1256_general_ci cp1256_bin"
+ ;;
+ cp1257)
+ default_charset_default_collation="cp1257_general_ci"
+ default_charset_collations="cp1257_general_ci cp1257_lithuanian_ci cp1257_bin"
+ ;;
+ cp850)
+ default_charset_default_collation="cp850_general_ci"
+ default_charset_collations="cp850_general_ci cp850_bin"
+ ;;
+ cp852)
+ default_charset_default_collation="cp852_general_ci"
+ default_charset_collations="cp852_general_ci cp852_bin"
+ ;;
+ cp866)
+ default_charset_default_collation="cp866_general_ci"
+ default_charset_collations="cp866_general_ci cp866_bin"
+ ;;
+ dec8)
+ default_charset_default_collation="dec8_swedish_ci"
+ default_charset_collations="dec8_swedish_ci dec8_bin"
+ ;;
+ euckr)
+ default_charset_default_collation="euckr_korean_ci"
+ default_charset_collations="euckr_korean_ci euckr_bin"
+ ;;
+ gb2312)
+ default_charset_default_collation="gb2312_chinese_ci"
+ default_charset_collations="gb2312_chinese_ci gb2312_bin"
+ ;;
+ gbk)
+ default_charset_default_collation="gbk_chinese_ci"
+ default_charset_collations="gbk_chinese_ci gbk_bin"
+ ;;
+ geostd8)
+ default_charset_default_collation="geostd8_general_ci"
+ default_charset_collations="geostd8_general_ci geostd8_bin"
+ ;;
+ greek)
+ default_charset_default_collation="greek_general_ci"
+ default_charset_collations="greek_general_ci greek_bin"
+ ;;
+ hebrew)
+ default_charset_default_collation="hebrew_general_ci"
+ default_charset_collations="hebrew_general_ci hebrew_bin"
+ ;;
+ hp8)
+ default_charset_default_collation="hp8_english_ci"
+ default_charset_collations="hp8_english_ci hp8_bin"
+ ;;
+ keybcs2)
+ default_charset_default_collation="keybcs2_general_ci"
+ default_charset_collations="keybcs2_general_ci keybcs2_bin"
+ ;;
+ koi8r)
+ default_charset_default_collation="koi8r_general_ci"
+ default_charset_collations="koi8r_general_ci koi8r_bin"
+ ;;
+ koi8u)
+ default_charset_default_collation="koi8u_general_ci"
+ default_charset_collations="koi8u_general_ci koi8u_bin"
+ ;;
+ latin1)
+ default_charset_default_collation="latin1_swedish_ci"
+ default_charset_collations="latin1_general_ci latin1_general_cs latin1_bin latin1_german1_ci latin1_german2_ci latin1_danish_ci latin1_swedish_ci"
+ ;;
+ latin2)
+ default_charset_default_collation="latin2_general_ci"
+ default_charset_collations="latin2_general_ci latin2_bin latin2_czech_cs latin2_hungarian_ci latin2_croatian_ci"
+ ;;
+ latin5)
+ default_charset_default_collation="latin5_turkish_ci"
+ default_charset_collations="latin5_turkish_ci latin5_bin"
+ ;;
+ latin7)
+ default_charset_default_collation="latin7_general_ci"
+ default_charset_collations="latin7_general_ci latin7_general_cs latin7_bin latin7_estonian_cs"
+ ;;
+ macce)
+ default_charset_default_collation="macce_general_ci"
+ default_charset_collations="macce_general_ci macce_bin"
+ ;;
+ macroman)
+ default_charset_default_collation="macroman_general_ci"
+ default_charset_collations="macroman_general_ci macroman_bin"
+ ;;
+ sjis)
+ default_charset_default_collation="sjis_japanese_ci"
+ default_charset_collations="sjis_japanese_ci sjis_bin"
+ ;;
+ swe7)
+ default_charset_default_collation="swe7_swedish_ci"
+ default_charset_collations="swe7_swedish_ci swe7_bin"
+ ;;
+ tis620)
+ default_charset_default_collation="tis620_thai_ci"
+ default_charset_collations="tis620_thai_ci tis620_bin"
+ ;;
+ ucs2)
+ default_charset_default_collation="ucs2_general_ci"
+ define(UCSC1, ucs2_general_ci ucs2_bin)
+ define(UCSC2, ucs2_czech_ci ucs2_danish_ci)
+ define(UCSC3, ucs2_estonian_ci ucs2_icelandic_ci)
+ define(UCSC4, ucs2_latvian_ci ucs2_lithuanian_ci)
+ define(UCSC5, ucs2_persian_ci ucs2_polish_ci ucs2_romanian_ci)
+ define(UCSC6, ucs2_slovak_ci ucs2_slovenian_ci)
+ define(UCSC7, ucs2_spanish2_ci ucs2_spanish_ci)
+ define(UCSC8, ucs2_swedish_ci ucs2_turkish_ci)
+ define(UCSC9, ucs2_unicode_ci)
+ UCSC="UCSC1 UCSC2 UCSC3 UCSC4 UCSC5 UCSC6 UCSC7 UCSC8 UCSC9"
+ default_charset_collations="$UCSC"
+ ;;
+ ujis)
+ default_charset_default_collation="ujis_japanese_ci"
+ default_charset_collations="ujis_japanese_ci ujis_bin"
+ ;;
+ utf8)
+ default_charset_default_collation="utf8_general_ci"
+ define(UTFC1, utf8_general_ci utf8_bin)
+ define(UTFC2, utf8_czech_ci utf8_danish_ci)
+ define(UTFC3, utf8_estonian_ci utf8_icelandic_ci)
+ define(UTFC4, utf8_latvian_ci utf8_lithuanian_ci)
+ define(UTFC5, utf8_persian_ci utf8_polish_ci utf8_romanian_ci)
+ define(UTFC6, utf8_slovak_ci utf8_slovenian_ci)
+ define(UTFC7, utf8_spanish2_ci utf8_spanish_ci)
+ define(UTFC8, utf8_swedish_ci utf8_turkish_ci)
+ define(UTFC9, utf8_unicode_ci)
+ UTFC="UTFC1 UTFC2 UTFC3 UTFC4 UTFC5 UTFC6 UTFC7 UTFC8 UTFC9"
+ default_charset_collations="$UTFC"
+ ;;
+ *)
+ AC_MSG_ERROR([Charset $cs not available. (Available are: $CHARSETS_AVAILABLE).
+ See the Installation chapter in the Reference Manual.]);
+esac
+
+if test "$default_collation" = default; then
+ default_collation=$default_charset_default_collation
+fi
+
+valid_default_collation=no
+for cl in $default_charset_collations
+do
+ if test x"$cl" = x"$default_collation"
+ then
+ valid_default_collation=yes
+ break
+ fi
+done
+
+if test x$valid_default_collation = xyes
+then
+ AC_MSG_RESULT([default: $default_charset, collation: $default_collation; compiled in: $CHARSETS])
+else
+ AC_MSG_ERROR([
+ Collation $default_collation is not valid for character set $default_charset.
+ Valid collations are: $default_charset_collations.
+ See the Installation chapter in the Reference Manual.
+ ]);
+fi
+
+AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_CHARSET_NAME], ["$default_charset"],
+ [Define the default charset name])
+AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_COLLATION_NAME], ["$default_collation"],
+ [Define the default charset name])
diff --git a/config/ac-macros/check_cpu.m4 b/config/ac-macros/check_cpu.m4
new file mode 100644
index 00000000000..d551f47769e
--- /dev/null
+++ b/config/ac-macros/check_cpu.m4
@@ -0,0 +1,47 @@
+AC_DEFUN([MYSQL_CHECK_CPU],
+[AC_CACHE_CHECK([if compiler supports optimizations for current cpu],
+mysql_cv_cpu,[
+
+ac_save_CFLAGS="$CFLAGS"
+if test -r /proc/cpuinfo ; then
+ cpuinfo="cat /proc/cpuinfo"
+ cpu_family=`$cpuinfo | grep 'cpu family' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1`
+ cpu_vendor=`$cpuinfo | grep 'vendor_id' | cut -d ':' -f 2 | cut -d ' ' -f 2 | head -1`
+fi
+if test "$cpu_vendor" = "AuthenticAMD"; then
+ if test $cpu_family -ge 6; then
+ cpu_set="athlon pentiumpro k5 pentium i486 i386";
+ elif test $cpu_family -eq 5; then
+ cpu_set="k5 pentium i486 i386";
+ elif test $cpu_family -eq 4; then
+ cpu_set="i486 i386"
+ else
+ cpu_set="i386"
+ fi
+elif test "$cpu_vendor" = "GenuineIntel"; then
+ if test $cpu_family -ge 6; then
+ cpu_set="pentiumpro pentium i486 i386";
+ elif test $cpu_family -eq 5; then
+ cpu_set="pentium i486 i386";
+ elif test $cpu_family -eq 4; then
+ cpu_set="i486 i386"
+ else
+ cpu_set="i386"
+ fi
+fi
+
+for ac_arg in $cpu_set;
+do
+ CFLAGS="$ac_save_CFLAGS -mcpu=$ac_arg -march=$ac_arg -DCPU=$ac_arg"
+ AC_TRY_COMPILE([],[int i],mysql_cv_cpu=$ac_arg; break;, mysql_cv_cpu="unknown")
+done
+
+if test "$mysql_cv_cpu" = "unknown"
+then
+ CFLAGS="$ac_save_CFLAGS"
+ AC_MSG_RESULT(none)
+else
+ AC_MSG_RESULT($mysql_cv_cpu)
+fi
+])])
+
diff --git a/config/ac-macros/compiler_flag.m4 b/config/ac-macros/compiler_flag.m4
new file mode 100644
index 00000000000..a236f61a198
--- /dev/null
+++ b/config/ac-macros/compiler_flag.m4
@@ -0,0 +1,40 @@
+# option, cache_name, variable,
+# code to execute if yes, code to exectute if fail
+AC_DEFUN([AC_SYS_COMPILER_FLAG],
+[
+ AC_MSG_CHECKING($1)
+ OLD_CFLAGS="[$]CFLAGS"
+ AC_CACHE_VAL(mysql_cv_option_$2,
+ [
+ CFLAGS="[$]OLD_CFLAGS $1"
+ AC_TRY_RUN([int main(){exit(0);}],mysql_cv_option_$2=yes,mysql_cv_option_$2=no,mysql_cv_option_$2=no)
+ ])
+
+ CFLAGS="[$]OLD_CFLAGS"
+
+ if test x"[$]mysql_cv_option_$2" = "xyes" ; then
+ $3="[$]$3 $1"
+ AC_MSG_RESULT(yes)
+ $5
+ else
+ AC_MSG_RESULT(no)
+ $4
+ fi
+])
+
+# arch, option, cache_name, variable
+AC_DEFUN([AC_SYS_CPU_COMPILER_FLAG],
+[
+ if test "`uname -m 2>/dev/null`" = "$1" ; then
+ AC_SYS_COMPILER_FLAG($2,$3,$4)
+ fi
+])
+
+# os, option, cache_name, variable
+AC_DEFUN([AC_SYS_OS_COMPILER_FLAG],
+[
+ if test "x$mysql_cv_sys_os" = "x$1" ; then
+ AC_SYS_COMPILER_FLAG($2,$3,$4)
+ fi
+])
+
diff --git a/config/ac-macros/ha_archive.m4 b/config/ac-macros/ha_archive.m4
new file mode 100644
index 00000000000..2d2558ea600
--- /dev/null
+++ b/config/ac-macros/ha_archive.m4
@@ -0,0 +1,29 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_ARCHIVEDB
+dnl Sets HAVE_ARCHIVE_DB if --with-archive-storage-engine is used
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_ARCHIVEDB], [
+ AC_ARG_WITH([archive-storage-engine],
+ [
+ --with-archive-storage-engine
+ Enable the Archive Storage Engine],
+ [archivedb="$withval"],
+ [archivedb=no])
+ AC_MSG_CHECKING([for archive storage engine])
+
+ case "$archivedb" in
+ yes )
+ AC_DEFINE([HAVE_ARCHIVE_DB], [1], [Builds Archive Storage Engine])
+ AC_MSG_RESULT([yes])
+ [archivedb=yes]
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ [archivedb=no]
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_ARCHIVE SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_berkeley.m4 b/config/ac-macros/ha_berkeley.m4
new file mode 100644
index 00000000000..732c7730816
--- /dev/null
+++ b/config/ac-macros/ha_berkeley.m4
@@ -0,0 +1,267 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_BDB
+dnl Sets HAVE_BERKELEY_DB if inst library is found
+dnl Makes sure db version is correct.
+dnl Looks in $srcdir for Berkeley distribution if not told otherwise
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_CHECK_BDB], [
+ AC_ARG_WITH([berkeley-db],
+ [
+ --with-berkeley-db[=DIR]
+ Use BerkeleyDB located in DIR],
+ [bdb="$withval"],
+ [bdb=no])
+
+ AC_ARG_WITH([berkeley-db-includes],
+ [
+ --with-berkeley-db-includes=DIR
+ Find Berkeley DB headers in DIR],
+ [bdb_includes="$withval"],
+ [bdb_includes=default])
+
+ AC_ARG_WITH([berkeley-db-libs],
+ [
+ --with-berkeley-db-libs=DIR
+ Find Berkeley DB libraries in DIR],
+ [bdb_libs="$withval"],
+ [bdb_libs=default])
+
+ AC_MSG_CHECKING([for BerkeleyDB])
+
+dnl SORT OUT THE SUPPLIED ARGUMENTS TO DETERMINE WHAT TO DO
+dnl echo "DBG1: bdb='$bdb'; incl='$bdb_includes'; lib='$bdb_libs'"
+ have_berkeley_db=no
+ case "$bdb" in
+ no )
+ mode=no
+ AC_MSG_RESULT([no])
+ ;;
+ yes | default )
+ case "$bdb_includes---$bdb_libs" in
+ default---default )
+ mode=search-$bdb
+ AC_MSG_RESULT([searching...])
+ ;;
+ default---* | *---default | yes---* | *---yes )
+ AC_MSG_ERROR([if either 'includes' or 'libs' is specified, both must be specified])
+ ;;
+ * )
+ mode=supplied-two
+ AC_MSG_RESULT([supplied])
+ ;;
+ esac
+ ;;
+ * )
+ mode=supplied-one
+ AC_MSG_RESULT([supplied])
+ ;;
+ esac
+
+dnl echo "DBG2: [$mode] bdb='$bdb'; incl='$bdb_includes'; lib='$bdb_libs'"
+
+ case $mode in
+ no )
+ bdb_includes=
+ bdb_libs=
+ bdb_libs_with_path=
+ ;;
+ supplied-two )
+ MYSQL_CHECK_INSTALLED_BDB([$bdb_includes], [$bdb_libs])
+ case $bdb_dir_ok in
+ installed ) mode=yes ;;
+ * ) AC_MSG_ERROR([didn't find valid BerkeleyDB: $bdb_dir_ok]) ;;
+ esac
+ ;;
+ supplied-one )
+ MYSQL_CHECK_BDB_DIR([$bdb])
+ case $bdb_dir_ok in
+ source ) mode=compile ;;
+ installed ) mode=yes ;;
+ * ) AC_MSG_ERROR([didn't find valid BerkeleyDB: $bdb_dir_ok]) ;;
+ esac
+ ;;
+ search-* )
+ MYSQL_SEARCH_FOR_BDB
+ case $bdb_dir_ok in
+ source ) mode=compile ;;
+ installed ) mode=yes ;;
+ * )
+ # not found
+ case $mode in
+ *-yes ) AC_MSG_ERROR([no suitable BerkeleyDB found]) ;;
+ * ) mode=no ;;
+ esac
+ bdb_includes=
+ bdb_libs=
+ bdb_libs_with_path=
+ ;;
+ esac
+ ;;
+ *)
+ AC_MSG_ERROR([impossible case condition '$mode': please report this to bugs@lists.mysql.com])
+ ;;
+ esac
+
+dnl echo "DBG3: [$mode] bdb='$bdb'; incl='$bdb_includes'; lib='$bdb_libs'"
+ case $mode in
+ no )
+ AC_MSG_RESULT([Not using Berkeley DB])
+ ;;
+ yes )
+ have_berkeley_db="yes"
+ AC_MSG_RESULT([Using Berkeley DB in '$bdb_includes'])
+ ;;
+ compile )
+ have_berkeley_db="$bdb"
+ AC_MSG_RESULT([Compiling Berekeley DB in '$have_berkeley_db'])
+ ;;
+ * )
+ AC_MSG_ERROR([impossible case condition '$mode': please report this to bugs@lists.mysql.com])
+ ;;
+ esac
+
+ AC_SUBST(bdb_includes)
+ AC_SUBST(bdb_libs)
+ AC_SUBST(bdb_libs_with_path)
+])
+
+AC_DEFUN([MYSQL_CHECK_INSTALLED_BDB], [
+dnl echo ["MYSQL_CHECK_INSTALLED_BDB ($1) ($2)"]
+ inc="$1"
+ lib="$2"
+ if test -f "$inc/db.h"
+ then
+ MYSQL_CHECK_BDB_VERSION([$inc/db.h],
+ [.*#define[ ]*], [[ ][ ]*])
+
+ if test X"$bdb_version_ok" = Xyes; then
+ save_LDFLAGS="$LDFLAGS"
+ LDFLAGS="-L$lib $LDFLAGS"
+ AC_CHECK_LIB(db,db_env_create, [
+ bdb_dir_ok=installed
+ MYSQL_TOP_BUILDDIR([inc])
+ MYSQL_TOP_BUILDDIR([lib])
+ bdb_includes="-I$inc"
+ bdb_libs="-L$lib -ldb"
+ bdb_libs_with_path="$lib/libdb.a"
+ ])
+ LDFLAGS="$save_LDFLAGS"
+ else
+ bdb_dir_ok="$bdb_version_ok"
+ fi
+ else
+ bdb_dir_ok="no db.h file in '$inc'"
+ fi
+])
+
+AC_DEFUN([MYSQL_CHECK_BDB_DIR], [
+dnl ([$bdb])
+dnl echo ["MYSQL_CHECK_BDB_DIR ($1)"]
+ dir="$1"
+
+ MYSQL_CHECK_INSTALLED_BDB([$dir/include], [$dir/lib])
+
+ if test X"$bdb_dir_ok" != Xinstalled; then
+ # test to see if it's a source dir
+ rel="$dir/dist/RELEASE"
+ if test -f "$rel"; then
+ MYSQL_CHECK_BDB_VERSION([$rel], [], [=])
+ if test X"$bdb_version_ok" = Xyes; then
+ bdb_dir_ok=source
+ bdb="$dir"
+ MYSQL_TOP_BUILDDIR([dir])
+ bdb_includes="-I$dir/build_unix"
+ bdb_libs="-L$dir/build_unix -ldb"
+ bdb_libs_with_path="$dir/build_unix/libdb.a"
+ else
+ bdb_dir_ok="$bdb_version_ok"
+ fi
+ else
+ bdb_dir_ok="'$dir' doesn't look like a BDB directory ($bdb_dir_ok)"
+ fi
+ fi
+])
+
+AC_DEFUN([MYSQL_SEARCH_FOR_BDB], [
+dnl echo ["MYSQL_SEARCH_FOR_BDB"]
+ bdb_dir_ok="no BerkeleyDB found"
+
+ for test_dir in $srcdir/bdb $srcdir/db-*.*.* /usr/local/BerkeleyDB*; do
+dnl echo "-----------> Looking at ($test_dir; `cd $test_dir && pwd`)"
+ MYSQL_CHECK_BDB_DIR([$test_dir])
+ if test X"$bdb_dir_ok" = Xsource || test X"$bdb_dir_ok" = Xinstalled; then
+dnl echo "-----------> Found it ($bdb), ($srcdir)"
+dnl This is needed so that 'make distcheck' works properly (VPATH build).
+dnl VPATH build won't work if bdb is not under the source tree; but in
+dnl that case, hopefully people will just make and install inside the
+dnl tree, or install BDB first, and then use the installed version.
+ case "$bdb" in
+ "$srcdir/"* ) bdb=`echo "$bdb" | sed -e "s,^$srcdir/,,"` ;;
+ esac
+ break
+ fi
+ done
+])
+
+dnl MYSQL_CHECK_BDB_VERSION takes 3 arguments:
+dnl 1) the file to look in
+dnl 2) the search pattern before DB_VERSION_XXX
+dnl 3) the search pattern between DB_VERSION_XXX and the number
+dnl It assumes that the number is the last thing on the line
+AC_DEFUN([MYSQL_CHECK_BDB_VERSION], [
+ db_major=`sed -e '/^[$2]DB_VERSION_MAJOR[$3]/ !d' -e 's///' [$1]`
+ db_minor=`sed -e '/^[$2]DB_VERSION_MINOR[$3]/ !d' -e 's///' [$1]`
+ db_patch=`sed -e '/^[$2]DB_VERSION_PATCH[$3]/ !d' -e 's///' [$1]`
+ test -z "$db_major" && db_major=0
+ test -z "$db_minor" && db_minor=0
+ test -z "$db_patch" && db_patch=0
+
+ # This is ugly, but about as good as it can get
+# mysql_bdb=
+# if test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 3
+# then
+# mysql_bdb=h
+# elif test $db_major -eq 3 && test $db_minor -eq 2 && test $db_patch -eq 9
+# then
+# want_bdb_version="3.2.9a" # hopefully this will stay up-to-date
+# mysql_bdb=a
+# fi
+
+dnl RAM:
+want_bdb_version="4.1.24"
+bdb_version_ok=yes
+
+# if test -n "$mysql_bdb" && \
+# grep "DB_VERSION_STRING.*:.*$mysql_bdb: " [$1] > /dev/null
+# then
+# bdb_version_ok=yes
+# else
+# bdb_version_ok="invalid version $db_major.$db_minor.$db_patch"
+# bdb_version_ok="$bdb_version_ok (must be version 3.2.3h or $want_bdb_version)"
+# fi
+])
+
+AC_DEFUN([MYSQL_TOP_BUILDDIR], [
+ case "$[$1]" in
+ /* ) ;; # don't do anything with an absolute path
+ "$srcdir"/* )
+ # If BDB is under the source directory, we need to look under the
+ # build directory for bdb/build_unix.
+ # NOTE: I'm being lazy, and assuming the user did not specify
+ # something like --with-berkeley-db=bdb (it would be missing "./").
+ [$1]="\$(top_builddir)/"`echo "$[$1]" | sed -e "s,^$srcdir/,,"`
+ ;;
+ * )
+ AC_MSG_ERROR([The BDB directory must be directly under the MySQL source directory, or be specified using the full path. ('$srcdir'; '$[$1]')])
+ ;;
+ esac
+ if test X"$[$1]" != "/"
+ then
+ [$1]=`echo $[$1] | sed -e 's,/$,,'`
+ fi
+])
+
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_BDB SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_example.m4 b/config/ac-macros/ha_example.m4
new file mode 100644
index 00000000000..f8067931ce6
--- /dev/null
+++ b/config/ac-macros/ha_example.m4
@@ -0,0 +1,30 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_EXAMPLEDB
+dnl Sets HAVE_EXAMPLE_DB if --with-example-storage-engine is used
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_EXAMPLEDB], [
+ AC_ARG_WITH([example-storage-engine],
+ [
+ --with-example-storage-engine
+ Enable the Example Storage Engine],
+ [exampledb="$withval"],
+ [exampledb=no])
+ AC_MSG_CHECKING([for example storage engine])
+
+ case "$exampledb" in
+ yes )
+ AC_DEFINE([HAVE_EXAMPLE_DB], [1], [Builds Example DB])
+ AC_MSG_RESULT([yes])
+ [exampledb=yes]
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ [exampledb=no]
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_EXAMPLE SECTION
+dnl ---------------------------------------------------------------------------
+
diff --git a/config/ac-macros/ha_innodb.m4 b/config/ac-macros/ha_innodb.m4
new file mode 100644
index 00000000000..17f0fab3e90
--- /dev/null
+++ b/config/ac-macros/ha_innodb.m4
@@ -0,0 +1,77 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_INNODB
+dnl Sets HAVE_INNOBASE_DB if --with-innodb is used
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_CHECK_INNODB], [
+ AC_ARG_WITH([innodb],
+ [
+ --without-innodb Do not include the InnoDB table handler],
+ [innodb="$withval"],
+ [innodb=yes])
+
+ AC_MSG_CHECKING([for Innodb])
+
+ have_innodb=no
+ innodb_includes=
+ innodb_libs=
+ case "$innodb" in
+ yes )
+ AC_MSG_RESULT([Using Innodb])
+ AC_DEFINE([HAVE_INNOBASE_DB], [1], [Using Innobase DB])
+ have_innodb="yes"
+ innodb_includes="-I../innobase/include"
+ innodb_system_libs=""
+dnl Some libs are listed several times, in order for gcc to sort out
+dnl circular references.
+ innodb_libs="\
+ \$(top_builddir)/innobase/usr/libusr.a\
+ \$(top_builddir)/innobase/srv/libsrv.a\
+ \$(top_builddir)/innobase/dict/libdict.a\
+ \$(top_builddir)/innobase/que/libque.a\
+ \$(top_builddir)/innobase/srv/libsrv.a\
+ \$(top_builddir)/innobase/ibuf/libibuf.a\
+ \$(top_builddir)/innobase/row/librow.a\
+ \$(top_builddir)/innobase/pars/libpars.a\
+ \$(top_builddir)/innobase/btr/libbtr.a\
+ \$(top_builddir)/innobase/trx/libtrx.a\
+ \$(top_builddir)/innobase/read/libread.a\
+ \$(top_builddir)/innobase/usr/libusr.a\
+ \$(top_builddir)/innobase/buf/libbuf.a\
+ \$(top_builddir)/innobase/ibuf/libibuf.a\
+ \$(top_builddir)/innobase/eval/libeval.a\
+ \$(top_builddir)/innobase/log/liblog.a\
+ \$(top_builddir)/innobase/fsp/libfsp.a\
+ \$(top_builddir)/innobase/fut/libfut.a\
+ \$(top_builddir)/innobase/fil/libfil.a\
+ \$(top_builddir)/innobase/lock/liblock.a\
+ \$(top_builddir)/innobase/mtr/libmtr.a\
+ \$(top_builddir)/innobase/page/libpage.a\
+ \$(top_builddir)/innobase/rem/librem.a\
+ \$(top_builddir)/innobase/thr/libthr.a\
+ \$(top_builddir)/innobase/sync/libsync.a\
+ \$(top_builddir)/innobase/data/libdata.a\
+ \$(top_builddir)/innobase/mach/libmach.a\
+ \$(top_builddir)/innobase/ha/libha.a\
+ \$(top_builddir)/innobase/dyn/libdyn.a\
+ \$(top_builddir)/innobase/mem/libmem.a\
+ \$(top_builddir)/innobase/sync/libsync.a\
+ \$(top_builddir)/innobase/ut/libut.a\
+ \$(top_builddir)/innobase/os/libos.a\
+ \$(top_builddir)/innobase/ut/libut.a"
+
+ AC_CHECK_LIB(rt, aio_read, [innodb_system_libs="-lrt"])
+ ;;
+ * )
+ AC_MSG_RESULT([Not using Innodb])
+ ;;
+ esac
+
+ AC_SUBST(innodb_includes)
+ AC_SUBST(innodb_libs)
+ AC_SUBST(innodb_system_libs)
+])
+
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_INNODB SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_isam.m4 b/config/ac-macros/ha_isam.m4
new file mode 100644
index 00000000000..5e354dfa624
--- /dev/null
+++ b/config/ac-macros/ha_isam.m4
@@ -0,0 +1,15 @@
+AC_DEFUN([MYSQL_CHECK_ISAM], [
+ AC_ARG_WITH([isam], [
+ --with-isam Enable the ISAM table type],
+ [with_isam="$withval"],
+ [with_isam=no])
+
+ isam_libs=
+ if test X"$with_isam" = X"yes"
+ then
+ AC_DEFINE([HAVE_ISAM], [1], [Using old ISAM tables])
+ isam_libs="\$(top_builddir)/isam/libnisam.a\
+ \$(top_builddir)/merge/libmerge.a"
+ fi
+ AC_SUBST(isam_libs)
+])
diff --git a/config/ac-macros/ha_ndbcluster.m4 b/config/ac-macros/ha_ndbcluster.m4
new file mode 100644
index 00000000000..aea6f37ae2a
--- /dev/null
+++ b/config/ac-macros/ha_ndbcluster.m4
@@ -0,0 +1,144 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_NDBCLUSTER
+dnl Sets HAVE_NDBCLUSTER_DB if --with-ndbcluster is used
+dnl ---------------------------------------------------------------------------
+
+AC_DEFUN([MYSQL_CHECK_NDB_OPTIONS], [
+ AC_ARG_WITH([ndb-sci],
+ AC_HELP_STRING([--with-ndb-sci=DIR],
+ [Provide MySQL with a custom location of
+ sci library. Given DIR, sci library is
+ assumed to be in $DIR/lib and header files
+ in $DIR/include.]),
+ [mysql_sci_dir=${withval}],
+ [mysql_sci_dir=""])
+
+ case "$mysql_sci_dir" in
+ "no" )
+ have_ndb_sci=no
+ AC_MSG_RESULT([-- not including sci transporter])
+ ;;
+ * )
+ if test -f "$mysql_sci_dir/lib/libsisci.a" -a \
+ -f "$mysql_sci_dir/include/sisci_api.h"; then
+ NDB_SCI_INCLUDES="-I$mysql_sci_dir/include"
+ NDB_SCI_LIBS="-L$mysql_sci_dir/lib -lsisci"
+ AC_MSG_RESULT([-- including sci transporter])
+ AC_DEFINE([NDB_SCI_TRANSPORTER], [1],
+ [Including Ndb Cluster DB sci transporter])
+ AC_SUBST(NDB_SCI_INCLUDES)
+ AC_SUBST(NDB_SCI_LIBS)
+ have_ndb_sci="yes"
+ AC_MSG_RESULT([found sci transporter in $mysql_sci_dir/{include, lib}])
+ else
+ AC_MSG_RESULT([could not find sci transporter in $mysql_sci_dir/{include, lib}])
+ fi
+ ;;
+ esac
+
+ AC_ARG_WITH([ndb-shm],
+ [
+ --with-ndb-shm Include the NDB Cluster shared memory transporter],
+ [ndb_shm="$withval"],
+ [ndb_shm=no])
+ AC_ARG_WITH([ndb-test],
+ [
+ --with-ndb-test Include the NDB Cluster ndbapi test programs],
+ [ndb_test="$withval"],
+ [ndb_test=no])
+ AC_ARG_WITH([ndb-docs],
+ [
+ --with-ndb-docs Include the NDB Cluster ndbapi and mgmapi documentation],
+ [ndb_docs="$withval"],
+ [ndb_docs=no])
+ AC_ARG_WITH([ndb-port],
+ [
+ --with-ndb-port Port for NDB Cluster management server],
+ [ndb_port="$withval"],
+ [ndb_port="default"])
+ AC_ARG_WITH([ndb-port-base],
+ [
+ --with-ndb-port-base Base port for NDB Cluster transporters],
+ [ndb_port_base="$withval"],
+ [ndb_port_base="default"])
+
+ AC_MSG_CHECKING([for NDB Cluster options])
+ AC_MSG_RESULT([])
+
+ have_ndb_shm=no
+ case "$ndb_shm" in
+ yes )
+ AC_MSG_RESULT([-- including shared memory transporter])
+ AC_DEFINE([NDB_SHM_TRANSPORTER], [1],
+ [Including Ndb Cluster DB shared memory transporter])
+ have_ndb_shm="yes"
+ ;;
+ * )
+ AC_MSG_RESULT([-- not including shared memory transporter])
+ ;;
+ esac
+
+ have_ndb_test=no
+ case "$ndb_test" in
+ yes )
+ AC_MSG_RESULT([-- including ndbapi test programs])
+ have_ndb_test="yes"
+ ;;
+ * )
+ AC_MSG_RESULT([-- not including ndbapi test programs])
+ ;;
+ esac
+
+ have_ndb_docs=no
+ case "$ndb_docs" in
+ yes )
+ AC_MSG_RESULT([-- including ndbapi and mgmapi documentation])
+ have_ndb_docs="yes"
+ ;;
+ * )
+ AC_MSG_RESULT([-- not including ndbapi and mgmapi documentation])
+ ;;
+ esac
+
+ AC_MSG_RESULT([done.])
+])
+
+AC_DEFUN([MYSQL_CHECK_NDBCLUSTER], [
+ AC_ARG_WITH([ndbcluster],
+ [
+ --with-ndbcluster Include the NDB Cluster table handler],
+ [ndbcluster="$withval"],
+ [ndbcluster=no])
+
+ AC_MSG_CHECKING([for NDB Cluster])
+
+ have_ndbcluster=no
+ ndbcluster_includes=
+ ndbcluster_libs=
+ ndb_mgmclient_libs=
+ case "$ndbcluster" in
+ yes )
+ AC_MSG_RESULT([Using NDB Cluster])
+ AC_DEFINE([HAVE_NDBCLUSTER_DB], [1], [Using Ndb Cluster DB])
+ have_ndbcluster="yes"
+ ndbcluster_includes="-I../ndb/include -I../ndb/include/ndbapi"
+ ndbcluster_libs="\$(top_builddir)/ndb/src/.libs/libndbclient.a"
+ ndbcluster_system_libs=""
+ ndb_mgmclient_libs="\$(top_builddir)/ndb/src/mgmclient/libndbmgmclient.la"
+ MYSQL_CHECK_NDB_OPTIONS
+ ;;
+ * )
+ AC_MSG_RESULT([Not using NDB Cluster])
+ ;;
+ esac
+
+ AM_CONDITIONAL([HAVE_NDBCLUSTER_DB], [ test "$have_ndbcluster" = "yes" ])
+ AC_SUBST(ndbcluster_includes)
+ AC_SUBST(ndbcluster_libs)
+ AC_SUBST(ndbcluster_system_libs)
+ AC_SUBST(ndb_mgmclient_libs)
+])
+
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_NDBCLUSTER SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/ha_tina.m4 b/config/ac-macros/ha_tina.m4
new file mode 100644
index 00000000000..fe6e382ce20
--- /dev/null
+++ b/config/ac-macros/ha_tina.m4
@@ -0,0 +1,29 @@
+dnl ---------------------------------------------------------------------------
+dnl Macro: MYSQL_CHECK_CSVDB
+dnl Sets HAVE_CSV_DB if --with-csv-storage-engine is used
+dnl ---------------------------------------------------------------------------
+AC_DEFUN([MYSQL_CHECK_CSVDB], [
+ AC_ARG_WITH([csv-storage-engine],
+ [
+ --with-csv-storage-engine
+ Enable the CSV Storage Engine],
+ [csvdb="$withval"],
+ [csvdb=no])
+ AC_MSG_CHECKING([for csv storage engine])
+
+ case "$csvdb" in
+ yes )
+ AC_DEFINE([HAVE_CSV_DB], [1], [Builds the CSV Storage Engine])
+ AC_MSG_RESULT([yes])
+ [csvdb=yes]
+ ;;
+ * )
+ AC_MSG_RESULT([no])
+ [csvdb=no]
+ ;;
+ esac
+
+])
+dnl ---------------------------------------------------------------------------
+dnl END OF MYSQL_CHECK_CSV SECTION
+dnl ---------------------------------------------------------------------------
diff --git a/config/ac-macros/large_file.m4 b/config/ac-macros/large_file.m4
new file mode 100644
index 00000000000..00c2fdf614e
--- /dev/null
+++ b/config/ac-macros/large_file.m4
@@ -0,0 +1,140 @@
+
+dnl By default, many hosts won't let programs access large files;
+dnl one must use special compiler options to get large-file access to work.
+dnl For more details about this brain damage please see:
+dnl http://www.sas.com/standards/large.file/x_open.20Mar96.html
+
+dnl Written by Paul Eggert <eggert@twinsun.com>.
+
+dnl Internal subroutine of AC_SYS_LARGEFILE.
+dnl AC_SYS_LARGEFILE_FLAGS(FLAGSNAME)
+AC_DEFUN([AC_SYS_LARGEFILE_FLAGS],
+ [AC_CACHE_CHECK([for $1 value to request large file support],
+ ac_cv_sys_largefile_$1,
+ [if ($GETCONF LFS_$1) >conftest.1 2>conftest.2 && test ! -s conftest.2
+ then
+ ac_cv_sys_largefile_$1=`cat conftest.1`
+ else
+ ac_cv_sys_largefile_$1=no
+ ifelse($1, CFLAGS,
+ [case "$host_os" in
+ # HP-UX 10.20 requires -D__STDC_EXT__ with gcc 2.95.1.
+changequote(, )dnl
+ hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
+changequote([, ])dnl
+ if test "$GCC" = yes; then
+ case `$CC --version 2>/dev/null` in
+ 2.95.*) ac_cv_sys_largefile_CFLAGS=-D__STDC_EXT__ ;;
+ esac
+ fi
+ ;;
+ # IRIX 6.2 and later require cc -n32.
+changequote(, )dnl
+ irix6.[2-9]* | irix6.1[0-9]* | irix[7-9].* | irix[1-9][0-9]*)
+changequote([, ])dnl
+ if test "$GCC" != yes; then
+ ac_cv_sys_largefile_CFLAGS=-n32
+ fi
+ esac
+ if test "$ac_cv_sys_largefile_CFLAGS" != no; then
+ ac_save_CC="$CC"
+ CC="$CC $ac_cv_sys_largefile_CFLAGS"
+ AC_TRY_LINK(, , , ac_cv_sys_largefile_CFLAGS=no)
+ CC="$ac_save_CC"
+ fi])
+ fi
+ rm -f conftest*])])
+
+dnl Internal subroutine of AC_SYS_LARGEFILE.
+dnl AC_SYS_LARGEFILE_SPACE_APPEND(VAR, VAL)
+AC_DEFUN([AC_SYS_LARGEFILE_SPACE_APPEND],
+ [case $2 in
+ no) ;;
+ ?*)
+ case "[$]$1" in
+ '') $1=$2 ;;
+ *) $1=[$]$1' '$2 ;;
+ esac ;;
+ esac])
+
+dnl Internal subroutine of AC_SYS_LARGEFILE.
+dnl AC_SYS_LARGEFILE_MACRO_VALUE(C-MACRO, CACHE-VAR, COMMENT, CODE-TO-SET-DEFAULT)
+AC_DEFUN([AC_SYS_LARGEFILE_MACRO_VALUE],
+ [AC_CACHE_CHECK([for $1], $2,
+ [$2=no
+changequote(, )dnl
+ for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
+ case "$ac_flag" in
+ -D$1)
+ $2=1 ;;
+ -D$1=*)
+ $2=`expr " $ac_flag" : '[^=]*=\(.*\)'` ;;
+ esac
+ done
+ $4
+changequote([, ])dnl
+ ])
+ if test "[$]$2" != no; then
+ AC_DEFINE_UNQUOTED([$1], [$]$2, [$3])
+ fi])
+
+AC_DEFUN([MYSQL_SYS_LARGEFILE],
+ [AC_REQUIRE([AC_CANONICAL_HOST])
+ AC_ARG_ENABLE(largefile,
+ [ --disable-largefile Omit support for large files])
+ if test "$enable_largefile" != no; then
+ AC_CHECK_TOOL(GETCONF, getconf)
+ AC_SYS_LARGEFILE_FLAGS(CFLAGS)
+ AC_SYS_LARGEFILE_FLAGS(LDFLAGS)
+ AC_SYS_LARGEFILE_FLAGS(LIBS)
+
+ for ac_flag in $ac_cv_sys_largefile_CFLAGS no; do
+ case "$ac_flag" in
+ no) ;;
+ -D_FILE_OFFSET_BITS=*) ;;
+ -D_LARGEFILE_SOURCE | -D_LARGEFILE_SOURCE=*) ;;
+ -D_LARGE_FILES | -D_LARGE_FILES=*) ;;
+ -D?* | -I?*)
+ AC_SYS_LARGEFILE_SPACE_APPEND(CPPFLAGS, "$ac_flag") ;;
+ *)
+ AC_SYS_LARGEFILE_SPACE_APPEND(CFLAGS, "$ac_flag") ;;
+ esac
+ done
+ AC_SYS_LARGEFILE_SPACE_APPEND(LDFLAGS, "$ac_cv_sys_largefile_LDFLAGS")
+ AC_SYS_LARGEFILE_SPACE_APPEND(LIBS, "$ac_cv_sys_largefile_LIBS")
+
+ AC_SYS_LARGEFILE_MACRO_VALUE(_FILE_OFFSET_BITS,
+ ac_cv_sys_file_offset_bits,
+ [Number of bits in a file offset, on hosts where this is settable.],
+ [case "$host_os" in
+ # HP-UX 10.20 and later
+ hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
+ ac_cv_sys_file_offset_bits=64 ;;
+ # We can't declare _FILE_OFFSET_BITS here as this will cause
+ # compile errors as AC_PROG_CC adds include files in confdefs.h
+ # We solve this (until autoconf is fixed) by instead declaring it
+ # as define instead
+ solaris2.[8,9])
+ CFLAGS="$CFLAGS -D_FILE_OFFSET_BITS=64"
+ CXXFLAGS="$CXXFLAGS -D_FILE_OFFSET_BITS=64"
+ ac_cv_sys_file_offset_bits=no ;;
+ esac])
+ AC_SYS_LARGEFILE_MACRO_VALUE(_LARGEFILE_SOURCE,
+ ac_cv_sys_largefile_source,
+ [makes fseeko etc. visible, on some hosts.],
+ [case "$host_os" in
+ # HP-UX 10.20 and later
+ hpux10.[2-9][0-9]* | hpux1[1-9]* | hpux[2-9][0-9]*)
+ ac_cv_sys_largefile_source=1 ;;
+ esac])
+ AC_SYS_LARGEFILE_MACRO_VALUE(_LARGE_FILES,
+ ac_cv_sys_large_files,
+ [Large files support on AIX-style hosts.],
+ [case "$host_os" in
+ # AIX 4.2 and later
+ aix4.[2-9]* | aix4.1[0-9]* | aix[5-9].* | aix[1-9][0-9]*)
+ ac_cv_sys_large_files=1 ;;
+ esac])
+ fi
+ ])
+
diff --git a/config/ac-macros/misc.m4 b/config/ac-macros/misc.m4
new file mode 100644
index 00000000000..ec0c296a8b2
--- /dev/null
+++ b/config/ac-macros/misc.m4
@@ -0,0 +1,647 @@
+# Local macros for automake & autoconf
+
+# A local version of AC_CHECK_SIZEOF that includes sys/types.h
+dnl MYSQL_CHECK_SIZEOF(TYPE [, CROSS-SIZE])
+AC_DEFUN([MYSQL_CHECK_SIZEOF],
+[changequote(<<, >>)dnl
+dnl The name to #define.
+define(<<AC_TYPE_NAME>>, translit(sizeof_$1, [a-z *], [A-Z_P]))dnl
+dnl The cache variable name.
+define(<<AC_CV_NAME>>, translit(ac_cv_sizeof_$1, [ *], [_p]))dnl
+changequote([, ])dnl
+AC_MSG_CHECKING(size of $1)
+AC_CACHE_VAL(AC_CV_NAME,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+#if STDC_HEADERS
+#include <stdlib.h>
+#include <stddef.h>
+#endif
+main()
+{
+ FILE *f=fopen("conftestval", "w");
+ if (!f) exit(1);
+ fprintf(f, "%d\n", sizeof($1));
+ exit(0);
+}], AC_CV_NAME=`cat conftestval`, AC_CV_NAME=0, ifelse([$2], , , AC_CV_NAME=$2))])dnl
+AC_MSG_RESULT($AC_CV_NAME)
+AC_DEFINE_UNQUOTED(AC_TYPE_NAME, $AC_CV_NAME, [ ])
+undefine([AC_TYPE_NAME])dnl
+undefine([AC_CV_NAME])dnl
+])
+
+#---START: Used in for client configure
+AC_DEFUN([MYSQL_TYPE_ACCEPT],
+[ac_save_CXXFLAGS="$CXXFLAGS"
+AC_CACHE_CHECK([base type of last arg to accept], mysql_cv_btype_last_arg_accept,
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+if test "$ac_cv_prog_gxx" = "yes"
+then
+ CXXFLAGS=`echo $CXXFLAGS -Werror | sed 's/-fbranch-probabilities//'`
+fi
+mysql_cv_btype_last_arg_accept=none
+[AC_TRY_COMPILE([#if defined(inline)
+#undef inline
+#endif
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+],
+[int a = accept(1, (struct sockaddr *) 0, (socklen_t *) 0); return (a != 0);],
+mysql_cv_btype_last_arg_accept=socklen_t)]
+if test "$mysql_cv_btype_last_arg_accept" = "none"; then
+[AC_TRY_COMPILE([#if defined(inline)
+#undef inline
+#endif
+#include <stdlib.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+],
+[int a = accept(1, (struct sockaddr *) 0, (size_t *) 0); return (a != 0);],
+mysql_cv_btype_last_arg_accept=size_t)]
+fi
+if test "$mysql_cv_btype_last_arg_accept" = "none"; then
+mysql_cv_btype_last_arg_accept=int
+fi)
+AC_LANG_RESTORE
+AC_DEFINE_UNQUOTED([SOCKET_SIZE_TYPE], [$mysql_cv_btype_last_arg_accept],
+ [The base type of the last arg to accept])
+CXXFLAGS="$ac_save_CXXFLAGS"
+])
+#---END:
+
+dnl Find type of qsort
+AC_DEFUN([MYSQL_TYPE_QSORT],
+[AC_CACHE_CHECK([return type of qsort], mysql_cv_type_qsort,
+[AC_TRY_COMPILE([#include <stdlib.h>
+#ifdef __cplusplus
+extern "C"
+#endif
+void qsort(void *base, size_t nel, size_t width,
+ int (*compar) (const void *, const void *));
+],
+[int i;], mysql_cv_type_qsort=void, mysql_cv_type_qsort=int)])
+AC_DEFINE_UNQUOTED([RETQSORTTYPE], [$mysql_cv_type_qsort],
+ [The return type of qsort (int or void).])
+if test "$mysql_cv_type_qsort" = "void"
+then
+ AC_DEFINE_UNQUOTED([QSORT_TYPE_IS_VOID], [1], [qsort returns void])
+fi
+])
+
+AC_DEFUN([MYSQL_TIMESPEC_TS],
+[AC_CACHE_CHECK([if struct timespec has a ts_sec member], mysql_cv_timespec_ts,
+[AC_TRY_COMPILE([#include <pthread.h>
+#ifdef __cplusplus
+extern "C"
+#endif
+],
+[struct timespec abstime;
+
+abstime.ts_sec = time(NULL)+1;
+abstime.ts_nsec = 0;
+], mysql_cv_timespec_ts=yes, mysql_cv_timespec_ts=no)])
+if test "$mysql_cv_timespec_ts" = "yes"
+then
+ AC_DEFINE([HAVE_TIMESPEC_TS_SEC], [1],
+ [Timespec has a ts_sec instead of tv_sev])
+fi
+])
+
+AC_DEFUN([MYSQL_TZNAME],
+[AC_CACHE_CHECK([if we have tzname variable], mysql_cv_tzname,
+[AC_TRY_COMPILE([#include <time.h>
+#ifdef __cplusplus
+extern "C"
+#endif
+],
+[ tzset();
+ return tzname[0] != 0;
+], mysql_cv_tzname=yes, mysql_cv_tzname=no)])
+if test "$mysql_cv_tzname" = "yes"
+then
+ AC_DEFINE([HAVE_TZNAME], [1], [Have the tzname variable])
+fi
+])
+
+
+#---START: Used in for client configure
+AC_DEFUN([MYSQL_CHECK_ULONG],
+[AC_MSG_CHECKING(for type ulong)
+AC_CACHE_VAL(ac_cv_ulong,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+main()
+{
+ ulong foo;
+ foo++;
+ exit(0);
+}], ac_cv_ulong=yes, ac_cv_ulong=no, ac_cv_ulong=no)])
+AC_MSG_RESULT($ac_cv_ulong)
+if test "$ac_cv_ulong" = "yes"
+then
+ AC_DEFINE([HAVE_ULONG], [1], [system headers define ulong])
+fi
+])
+
+AC_DEFUN([MYSQL_CHECK_UCHAR],
+[AC_MSG_CHECKING(for type uchar)
+AC_CACHE_VAL(ac_cv_uchar,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+main()
+{
+ uchar foo;
+ foo++;
+ exit(0);
+}], ac_cv_uchar=yes, ac_cv_uchar=no, ac_cv_uchar=no)])
+AC_MSG_RESULT($ac_cv_uchar)
+if test "$ac_cv_uchar" = "yes"
+then
+ AC_DEFINE([HAVE_UCHAR], [1], [system headers define uchar])
+fi
+])
+
+AC_DEFUN([MYSQL_CHECK_UINT],
+[AC_MSG_CHECKING(for type uint)
+AC_CACHE_VAL(ac_cv_uint,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+main()
+{
+ uint foo;
+ foo++;
+ exit(0);
+}], ac_cv_uint=yes, ac_cv_uint=no, ac_cv_uint=no)])
+AC_MSG_RESULT($ac_cv_uint)
+if test "$ac_cv_uint" = "yes"
+then
+ AC_DEFINE([HAVE_UINT], [1], [system headers define uint])
+fi
+])
+
+
+AC_DEFUN([MYSQL_CHECK_IN_ADDR_T],
+[AC_MSG_CHECKING(for type in_addr_t)
+AC_CACHE_VAL(ac_cv_in_addr_t,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+#include <sys/socket.h>
+#include <netinet/in.h>
+#include <arpa/inet.h>
+
+int main(int argc, char **argv)
+{
+ in_addr_t foo;
+ exit(0);
+}], ac_cv_in_addr_t=yes, ac_cv_in_addr_t=no, ac_cv_in_addr_t=no)])
+AC_MSG_RESULT($ac_cv_in_addr_t)
+if test "$ac_cv_in_addr_t" = "yes"
+then
+ AC_DEFINE([HAVE_IN_ADDR_T], [1], [system headers define in_addr_t])
+fi
+])
+
+
+AC_DEFUN([MYSQL_PTHREAD_YIELD],
+[AC_CACHE_CHECK([if pthread_yield takes zero arguments], ac_cv_pthread_yield_zero_arg,
+[AC_TRY_LINK([#define _GNU_SOURCE
+#include <pthread.h>
+#ifdef __cplusplus
+extern "C"
+#endif
+],
+[
+ pthread_yield();
+], ac_cv_pthread_yield_zero_arg=yes, ac_cv_pthread_yield_zero_arg=yeso)])
+if test "$ac_cv_pthread_yield_zero_arg" = "yes"
+then
+ AC_DEFINE([HAVE_PTHREAD_YIELD_ZERO_ARG], [1],
+ [pthread_yield that doesn't take any arguments])
+fi
+]
+[AC_CACHE_CHECK([if pthread_yield takes 1 argument], ac_cv_pthread_yield_one_arg,
+[AC_TRY_LINK([#define _GNU_SOURCE
+#include <pthread.h>
+#ifdef __cplusplus
+extern "C"
+#endif
+],
+[
+ pthread_yield(0);
+], ac_cv_pthread_yield_one_arg=yes, ac_cv_pthread_yield_one_arg=no)])
+if test "$ac_cv_pthread_yield_one_arg" = "yes"
+then
+ AC_DEFINE([HAVE_PTHREAD_YIELD_ONE_ARG], [1],
+ [pthread_yield function with one argument])
+fi
+]
+)
+
+
+
+#---END:
+
+AC_DEFUN([MYSQL_CHECK_FP_EXCEPT],
+[AC_MSG_CHECKING(for type fp_except)
+AC_CACHE_VAL(ac_cv_fp_except,
+[AC_TRY_RUN([#include <stdio.h>
+#include <sys/types.h>
+#include <ieeefp.h>
+main()
+{
+ fp_except foo;
+ foo++;
+ exit(0);
+}], ac_cv_fp_except=yes, ac_cv_fp_except=no, ac_cv_fp_except=no)])
+AC_MSG_RESULT($ac_cv_fp_except)
+if test "$ac_cv_fp_except" = "yes"
+then
+ AC_DEFINE([HAVE_FP_EXCEPT], [1], [fp_except from ieeefp.h])
+fi
+])
+
+# From fileutils-3.14/aclocal.m4
+
+# @defmac AC_PROG_CC_STDC
+# @maindex PROG_CC_STDC
+# @ovindex CC
+# If the C compiler in not in ANSI C mode by default, try to add an option
+# to output variable @code{CC} to make it so. This macro tries various
+# options that select ANSI C on some system or another. It considers the
+# compiler to be in ANSI C mode if it defines @code{__STDC__} to 1 and
+# handles function prototypes correctly.
+#
+# Patched by monty to only check if __STDC__ is defined. With the original
+# check it's impossible to get things to work with the Sunpro compiler from
+# Workshop 4.2
+#
+# If you use this macro, you should check after calling it whether the C
+# compiler has been set to accept ANSI C; if not, the shell variable
+# @code{am_cv_prog_cc_stdc} is set to @samp{no}. If you wrote your source
+# code in ANSI C, you can make an un-ANSIfied copy of it by using the
+# program @code{ansi2knr}, which comes with Ghostscript.
+# @end defmac
+
+AC_DEFUN([AM_PROG_CC_STDC],
+[AC_REQUIRE([AC_PROG_CC])
+AC_MSG_CHECKING(for ${CC-cc} option to accept ANSI C)
+AC_CACHE_VAL(am_cv_prog_cc_stdc,
+[am_cv_prog_cc_stdc=no
+ac_save_CC="$CC"
+# Don't try gcc -ansi; that turns off useful extensions and
+# breaks some systems' header files.
+# AIX -qlanglvl=ansi
+# Ultrix and OSF/1 -std1
+# HP-UX -Aa -D_HPUX_SOURCE
+# SVR4 -Xc -D__EXTENSIONS__
+# removed "-Xc -D__EXTENSIONS__" beacause sun c++ does not like it.
+for ac_arg in "" -qlanglvl=ansi -std1 "-Aa -D_HPUX_SOURCE"
+do
+ CC="$ac_save_CC $ac_arg"
+ AC_TRY_COMPILE(
+[#if !defined(__STDC__)
+choke me
+#endif
+/* DYNIX/ptx V4.1.3 can't compile sys/stat.h with -Xc -D__EXTENSIONS__. */
+#ifdef _SEQUENT_
+# include <sys/types.h>
+# include <sys/stat.h>
+#endif
+], [
+int test (int i, double x);
+struct s1 {int (*f) (int a);};
+struct s2 {int (*f) (double a);};],
+[am_cv_prog_cc_stdc="$ac_arg"; break])
+done
+CC="$ac_save_CC"
+])
+AC_MSG_RESULT($am_cv_prog_cc_stdc)
+case "x$am_cv_prog_cc_stdc" in
+ x|xno) ;;
+ *) CC="$CC $am_cv_prog_cc_stdc" ;;
+esac
+])
+
+# Orginal from bash-2.0 aclocal.m4, Changed to use termcap last by monty.
+
+AC_DEFUN([MYSQL_CHECK_LIB_TERMCAP],
+[
+AC_CACHE_VAL(mysql_cv_termcap_lib,
+[AC_CHECK_LIB(ncurses, tgetent, mysql_cv_termcap_lib=libncurses,
+ [AC_CHECK_LIB(curses, tgetent, mysql_cv_termcap_lib=libcurses,
+ [AC_CHECK_LIB(termcap, tgetent, mysql_cv_termcap_lib=libtermcap,
+ mysql_cv_termcap_lib=NOT_FOUND)])])])
+AC_MSG_CHECKING(for termcap functions library)
+if test "$mysql_cv_termcap_lib" = "NOT_FOUND"; then
+AC_MSG_ERROR([No curses/termcap library found])
+elif test "$mysql_cv_termcap_lib" = "libtermcap"; then
+TERMCAP_LIB=-ltermcap
+elif test "$mysql_cv_termcap_lib" = "libncurses"; then
+TERMCAP_LIB=-lncurses
+else
+TERMCAP_LIB=-lcurses
+fi
+AC_MSG_RESULT($TERMCAP_LIB)
+])
+
+dnl Check type of signal routines (posix, 4.2bsd, 4.1bsd or v7)
+AC_DEFUN([MYSQL_SIGNAL_CHECK],
+[AC_REQUIRE([AC_TYPE_SIGNAL])
+AC_MSG_CHECKING(for type of signal functions)
+AC_CACHE_VAL(mysql_cv_signal_vintage,
+[
+ AC_TRY_LINK([#include <signal.h>],[
+ sigset_t ss;
+ struct sigaction sa;
+ sigemptyset(&ss); sigsuspend(&ss);
+ sigaction(SIGINT, &sa, (struct sigaction *) 0);
+ sigprocmask(SIG_BLOCK, &ss, (sigset_t *) 0);
+ ], mysql_cv_signal_vintage=posix,
+ [
+ AC_TRY_LINK([#include <signal.h>], [
+ int mask = sigmask(SIGINT);
+ sigsetmask(mask); sigblock(mask); sigpause(mask);
+ ], mysql_cv_signal_vintage=4.2bsd,
+ [
+ AC_TRY_LINK([
+ #include <signal.h>
+ RETSIGTYPE foo() { }], [
+ int mask = sigmask(SIGINT);
+ sigset(SIGINT, foo); sigrelse(SIGINT);
+ sighold(SIGINT); sigpause(SIGINT);
+ ], mysql_cv_signal_vintage=svr3, mysql_cv_signal_vintage=v7
+ )]
+ )]
+)
+])
+AC_MSG_RESULT($mysql_cv_signal_vintage)
+if test "$mysql_cv_signal_vintage" = posix; then
+AC_DEFINE(HAVE_POSIX_SIGNALS, [1],
+ [Signal handling is POSIX (sigset/sighold, etc)])
+elif test "$mysql_cv_signal_vintage" = "4.2bsd"; then
+AC_DEFINE([HAVE_BSD_SIGNALS], [1], [BSD style signals])
+elif test "$mysql_cv_signal_vintage" = svr3; then
+AC_DEFINE(HAVE_USG_SIGHOLD, [1], [sighold() is present and usable])
+fi
+])
+
+AC_DEFUN([MYSQL_CHECK_GETPW_FUNCS],
+[AC_MSG_CHECKING(whether programs are able to redeclare getpw functions)
+AC_CACHE_VAL(mysql_cv_can_redecl_getpw,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <pwd.h>
+extern struct passwd *getpwent();], [struct passwd *z; z = getpwent();],
+ mysql_cv_can_redecl_getpw=yes,mysql_cv_can_redecl_getpw=no)])
+AC_MSG_RESULT($mysql_cv_can_redecl_getpw)
+if test "$mysql_cv_can_redecl_getpw" = "no"; then
+AC_DEFINE(HAVE_GETPW_DECLS, [1], [getpwent() declaration present])
+fi
+])
+
+AC_DEFUN([MYSQL_HAVE_TIOCGWINSZ],
+[AC_MSG_CHECKING(for TIOCGWINSZ in sys/ioctl.h)
+AC_CACHE_VAL(mysql_cv_tiocgwinsz_in_ioctl,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/ioctl.h>], [int x = TIOCGWINSZ;],
+ mysql_cv_tiocgwinsz_in_ioctl=yes,mysql_cv_tiocgwinsz_in_ioctl=no)])
+AC_MSG_RESULT($mysql_cv_tiocgwinsz_in_ioctl)
+if test "$mysql_cv_tiocgwinsz_in_ioctl" = "yes"; then
+AC_DEFINE([GWINSZ_IN_SYS_IOCTL], [1],
+ [READLINE: your system defines TIOCGWINSZ in sys/ioctl.h.])
+fi
+])
+
+AC_DEFUN([MYSQL_HAVE_FIONREAD],
+[AC_MSG_CHECKING(for FIONREAD in sys/ioctl.h)
+AC_CACHE_VAL(mysql_cv_fionread_in_ioctl,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/ioctl.h>], [int x = FIONREAD;],
+ mysql_cv_fionread_in_ioctl=yes,mysql_cv_fionread_in_ioctl=no)])
+AC_MSG_RESULT($mysql_cv_fionread_in_ioctl)
+if test "$mysql_cv_fionread_in_ioctl" = "yes"; then
+AC_DEFINE([FIONREAD_IN_SYS_IOCTL], [1], [Do we have FIONREAD])
+fi
+])
+
+AC_DEFUN([MYSQL_HAVE_TIOCSTAT],
+[AC_MSG_CHECKING(for TIOCSTAT in sys/ioctl.h)
+AC_CACHE_VAL(mysql_cv_tiocstat_in_ioctl,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <sys/ioctl.h>], [int x = TIOCSTAT;],
+ mysql_cv_tiocstat_in_ioctl=yes,mysql_cv_tiocstat_in_ioctl=no)])
+AC_MSG_RESULT($mysql_cv_tiocstat_in_ioctl)
+if test "$mysql_cv_tiocstat_in_ioctl" = "yes"; then
+AC_DEFINE(TIOCSTAT_IN_SYS_IOCTL, [1],
+ [declaration of TIOCSTAT in sys/ioctl.h])
+fi
+])
+
+AC_DEFUN([MYSQL_STRUCT_DIRENT_D_INO],
+[AC_REQUIRE([AC_HEADER_DIRENT])
+AC_MSG_CHECKING(if struct dirent has a d_ino member)
+AC_CACHE_VAL(mysql_cv_dirent_has_dino,
+[AC_TRY_COMPILE([
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if defined(HAVE_DIRENT_H)
+# include <dirent.h>
+#else
+# define dirent direct
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif /* SYSNDIR */
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif /* SYSDIR */
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif /* HAVE_DIRENT_H */
+],[
+struct dirent d; int z; z = d.d_ino;
+], mysql_cv_dirent_has_dino=yes, mysql_cv_dirent_has_dino=no)])
+AC_MSG_RESULT($mysql_cv_dirent_has_dino)
+if test "$mysql_cv_dirent_has_dino" = "yes"; then
+AC_DEFINE(STRUCT_DIRENT_HAS_D_INO, [1],
+ [d_ino member present in struct dirent])
+fi
+])
+
+AC_DEFUN([MYSQL_STRUCT_DIRENT_D_NAMLEN],
+[AC_REQUIRE([AC_HEADER_DIRENT])
+AC_MSG_CHECKING(if struct dirent has a d_namlen member)
+AC_CACHE_VAL(mysql_cv_dirent_has_dnamlen,
+[AC_TRY_COMPILE([
+#include <stdio.h>
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+# include <unistd.h>
+#endif /* HAVE_UNISTD_H */
+#if defined(HAVE_DIRENT_H)
+# include <dirent.h>
+#else
+# define dirent direct
+# ifdef HAVE_SYS_NDIR_H
+# include <sys/ndir.h>
+# endif /* SYSNDIR */
+# ifdef HAVE_SYS_DIR_H
+# include <sys/dir.h>
+# endif /* SYSDIR */
+# ifdef HAVE_NDIR_H
+# include <ndir.h>
+# endif
+#endif /* HAVE_DIRENT_H */
+],[
+struct dirent d; int z; z = (int)d.d_namlen;
+], mysql_cv_dirent_has_dnamlen=yes, mysql_cv_dirent_has_dnamlen=no)])
+AC_MSG_RESULT($mysql_cv_dirent_has_dnamlen)
+if test "$mysql_cv_dirent_has_dnamlen" = "yes"; then
+AC_DEFINE(STRUCT_DIRENT_HAS_D_NAMLEN, [1],
+ [d_namlen member present in struct dirent])
+fi
+])
+
+
+AC_DEFUN([MYSQL_TYPE_SIGHANDLER],
+[AC_MSG_CHECKING([whether signal handlers are of type void])
+AC_CACHE_VAL(mysql_cv_void_sighandler,
+[AC_TRY_COMPILE([#include <sys/types.h>
+#include <signal.h>
+#ifdef signal
+#undef signal
+#endif
+#ifdef __cplusplus
+extern "C"
+#endif
+void (*signal ()) ();],
+[int i;], mysql_cv_void_sighandler=yes, mysql_cv_void_sighandler=no)])dnl
+AC_MSG_RESULT($mysql_cv_void_sighandler)
+if test "$mysql_cv_void_sighandler" = "yes"; then
+AC_DEFINE(VOID_SIGHANDLER, [1], [sighandler type is void (*signal ()) ();])
+fi
+])
+
+AC_DEFUN([MYSQL_CXX_BOOL],
+[
+AC_REQUIRE([AC_PROG_CXX])
+AC_MSG_CHECKING(if ${CXX} supports bool types)
+AC_CACHE_VAL(mysql_cv_have_bool,
+[
+AC_LANG_SAVE
+AC_LANG_CPLUSPLUS
+AC_TRY_COMPILE(,[bool b = true;],
+mysql_cv_have_bool=yes,
+mysql_cv_have_bool=no)
+AC_LANG_RESTORE
+])
+AC_MSG_RESULT($mysql_cv_have_bool)
+if test "$mysql_cv_have_bool" = yes; then
+AC_DEFINE([HAVE_BOOL], [1], [bool is not defined by all C++ compilators])
+fi
+])dnl
+
+AC_DEFUN([MYSQL_STACK_DIRECTION],
+ [AC_CACHE_CHECK(stack direction for C alloca, ac_cv_c_stack_direction,
+ [AC_TRY_RUN([#include <stdlib.h>
+ int find_stack_direction ()
+ {
+ static char *addr = 0;
+ auto char dummy;
+ if (addr == 0)
+ {
+ addr = &dummy;
+ return find_stack_direction ();
+ }
+ else
+ return (&dummy > addr) ? 1 : -1;
+ }
+ int main ()
+ {
+ exit (find_stack_direction() < 0);
+ }], ac_cv_c_stack_direction=1, ac_cv_c_stack_direction=-1,
+ ac_cv_c_stack_direction=0)])
+ AC_DEFINE_UNQUOTED(STACK_DIRECTION, $ac_cv_c_stack_direction)
+])dnl
+
+AC_DEFUN([MYSQL_CHECK_LONGLONG_TO_FLOAT],
+[
+AC_MSG_CHECKING(if conversion of longlong to float works)
+AC_CACHE_VAL(ac_cv_conv_longlong_to_float,
+[AC_TRY_RUN([#include <stdio.h>
+typedef long long longlong;
+main()
+{
+ longlong ll=1;
+ float f;
+ FILE *file=fopen("conftestval", "w");
+ f = (float) ll;
+ fprintf(file,"%g\n",f);
+ fclose(file);
+ exit (0);
+}], ac_cv_conv_longlong_to_float=`cat conftestval`, ac_cv_conv_longlong_to_float=0, ifelse([$2], , , ac_cv_conv_longlong_to_float=$2))])dnl
+if test "$ac_cv_conv_longlong_to_float" = "1" -o "$ac_cv_conv_longlong_to_float" = "yes"
+then
+ ac_cv_conv_longlong_to_float=yes
+else
+ ac_cv_conv_longlong_to_float=no
+fi
+AC_MSG_RESULT($ac_cv_conv_longlong_to_float)
+])
+
+AC_DEFUN([MYSQL_CHECK_VIO], [
+ AC_ARG_WITH([vio],
+ [ --with-vio Include the Virtual IO support],
+ [vio="$withval"],
+ [vio=no])
+
+ if test "$vio" = "yes"
+ then
+ vio_dir="vio"
+ vio_libs="../vio/libvio.la"
+ AC_DEFINE(HAVE_VIO, 1)
+ else
+ vio_dir=""
+ vio_libs=""
+ fi
+ AC_SUBST([vio_dir])
+ AC_SUBST([vio_libs])
+])
+
+# Local version of _AC_PROG_CXX_EXIT_DECLARATION that does not
+# include #stdlib.h as default as this breaks things on Solaris
+# (Conflicts with pthreads and big file handling)
+
+m4_define([_AC_PROG_CXX_EXIT_DECLARATION],
+[for ac_declaration in \
+ ''\
+ 'extern "C" void std::exit (int) throw (); using std::exit;' \
+ 'extern "C" void std::exit (int); using std::exit;' \
+ 'extern "C" void exit (int) throw ();' \
+ 'extern "C" void exit (int);' \
+ 'void exit (int);' \
+ '#include <stdlib.h>'
+do
+ _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([@%:@include <stdlib.h>
+$ac_declaration],
+ [exit (42);])],
+ [],
+ [continue])
+ _AC_COMPILE_IFELSE([AC_LANG_PROGRAM([$ac_declaration],
+ [exit (42);])],
+ [break])
+done
+rm -f conftest*
+if test -n "$ac_declaration"; then
+ echo '#ifdef __cplusplus' >>confdefs.h
+ echo $ac_declaration >>confdefs.h
+ echo '#endif' >>confdefs.h
+fi
+])# _AC_PROG_CXX_EXIT_DECLARATION
+
+dnl ---------------------------------------------------------------------------
+
diff --git a/config/ac-macros/mysqlfs.m4 b/config/ac-macros/mysqlfs.m4
new file mode 100644
index 00000000000..eba341937e3
--- /dev/null
+++ b/config/ac-macros/mysqlfs.m4
@@ -0,0 +1,51 @@
+
+AC_DEFUN([MYSQL_CHECK_MYSQLFS], [
+ AC_ARG_WITH([mysqlfs],
+ [
+ --with-mysqlfs Include the corba-based MySQL file system],
+ [mysqlfs="$withval"],
+ [mysqlfs=no])
+
+dnl Call MYSQL_CHECK_ORBIT even if mysqlfs == no, so that @orbit_*@
+dnl get substituted.
+ MYSQL_CHECK_ORBIT
+
+ AC_MSG_CHECKING(if we should build MySQLFS)
+ fs_dirs=""
+ if test "$mysqlfs" = "yes"
+ then
+ if test -n "$orbit_exec_prefix"
+ then
+ fs_dirs=fs
+ AC_MSG_RESULT([yes])
+ else
+ AC_MSG_RESULT(disabled because ORBIT, the CORBA ORB, was not found)
+ fi
+ else
+ AC_MSG_RESULT([no])
+ fi
+ AC_SUBST([fs_dirs])
+])
+
+AC_DEFUN([MYSQL_CHECK_ORBIT], [
+AC_MSG_CHECKING(for ORBit)
+orbit_config_path=`which orbit-config`
+if test -n "$orbit_config_path" -a $? = 0
+then
+ orbit_exec_prefix=`orbit-config --exec-prefix`
+ orbit_includes=`orbit-config --cflags server`
+ orbit_libs=`orbit-config --libs server`
+ orbit_idl="$orbit_exec_prefix/bin/orbit-idl"
+ AC_MSG_RESULT(found!)
+ AC_DEFINE([HAVE_ORBIT], [1], [ORBIT])
+else
+ orbit_exec_prefix=
+ orbit_includes=
+ orbit_libs=
+ orbit_idl=
+ AC_MSG_RESULT(not found)
+fi
+AC_SUBST(orbit_includes)
+AC_SUBST(orbit_libs)
+AC_SUBST(orbit_idl)
+])
diff --git a/config/ac-macros/openssl.m4 b/config/ac-macros/openssl.m4
new file mode 100644
index 00000000000..9da0e38f2ba
--- /dev/null
+++ b/config/ac-macros/openssl.m4
@@ -0,0 +1,136 @@
+AC_DEFUN([MYSQL_FIND_OPENSSL], [
+ incs="$1"
+ libs="$2"
+ case "$incs---$libs" in
+ ---)
+ for d in /usr/ssl/include /usr/local/ssl/include /usr/include \
+/usr/include/ssl /opt/ssl/include /opt/openssl/include \
+/usr/local/ssl/include /usr/local/include /usr/freeware/include ; do
+ if test -f $d/openssl/ssl.h ; then
+ OPENSSL_INCLUDE=-I$d
+ fi
+ done
+
+ for d in /usr/ssl/lib /usr/local/ssl/lib /usr/lib/openssl \
+/usr/lib /usr/lib64 /opt/ssl/lib /opt/openssl/lib \
+/usr/freeware/lib32 /usr/local/lib/ ; do
+ if test -f $d/libssl.a || test -f $d/libssl.so || test -f $d/libssl.dylib ; then
+ OPENSSL_LIB=$d
+ fi
+ done
+ ;;
+ ---* | *---)
+ AC_MSG_ERROR([if either 'includes' or 'libs' is specified, both must be specified])
+ ;;
+ * )
+ if test -f $incs/openssl/ssl.h ; then
+ OPENSSL_INCLUDE=-I$incs
+ fi
+ if test -f $libs/libssl.a || test -f $libs/libssl.so || test -f $libs/libssl.dylib ; then
+ OPENSSL_LIB=$libs
+ fi
+ ;;
+ esac
+
+ # On RedHat 9 we need kerberos to compile openssl
+ for d in /usr/kerberos/include
+ do
+ if test -f $d/krb5.h ; then
+ OPENSSL_KERBEROS_INCLUDE="$d"
+ fi
+ done
+
+
+ if test -z "$OPENSSL_LIB" -o -z "$OPENSSL_INCLUDE" ; then
+ echo "Could not find an installation of OpenSSL"
+ if test -n "$OPENSSL_LIB" ; then
+ if test "$IS_LINUX" = "true"; then
+ echo "Looks like you've forgotten to install OpenSSL development RPM"
+ fi
+ fi
+ exit 1
+ fi
+
+])
+
+AC_DEFUN([MYSQL_CHECK_OPENSSL], [
+AC_MSG_CHECKING(for OpenSSL)
+ AC_ARG_WITH([openssl],
+ [ --with-openssl[=DIR] Include the OpenSSL support],
+ [openssl="$withval"],
+ [openssl=no])
+
+ AC_ARG_WITH([openssl-includes],
+ [
+ --with-openssl-includes=DIR
+ Find OpenSSL headers in DIR],
+ [openssl_includes="$withval"],
+ [openssl_includes=""])
+
+ AC_ARG_WITH([openssl-libs],
+ [
+ --with-openssl-libs=DIR
+ Find OpenSSL libraries in DIR],
+ [openssl_libs="$withval"],
+ [openssl_libs=""])
+
+ if test "$openssl" != "no"
+ then
+ if test "$openssl" != "yes"
+ then
+ if test -z "$openssl_includes"
+ then
+ openssl_includes="$openssl/include"
+ fi
+ if test -z "$openssl_libs"
+ then
+ openssl_libs="$openssl/lib"
+ fi
+ fi
+ MYSQL_FIND_OPENSSL([$openssl_includes], [$openssl_libs])
+ #force VIO use
+ vio_dir="vio"
+ vio_libs="../vio/libvio.la"
+ AC_DEFINE([HAVE_VIO], [1], [Virtual IO])
+ AC_MSG_RESULT(yes)
+ openssl_libs="-L$OPENSSL_LIB -lssl -lcrypto"
+ # Don't set openssl_includes to /usr/include as this gives us a lot of
+ # compiler warnings when using gcc 3.x
+ openssl_includes=""
+ if test "$OPENSSL_INCLUDE" != "-I/usr/include"
+ then
+ openssl_includes="$OPENSSL_INCLUDE"
+ fi
+ if test "$OPENSSL_KERBEROS_INCLUDE"
+ then
+ openssl_includes="$openssl_includes -I$OPENSSL_KERBEROS_INCLUDE"
+ fi
+ AC_DEFINE([HAVE_OPENSSL], [1], [OpenSSL])
+
+ # openssl-devel-0.9.6 requires dlopen() and we can't link staticly
+ # on many platforms (We should actually test this here, but it's quite
+ # hard) to do as we are doing libtool for linking.
+ using_static=""
+ case "$CLIENT_EXTRA_LDFLAGS $MYSQLD_EXTRA_LDFLAGS" in
+ *-all-static*) using_static="yes" ;;
+ esac
+ if test "$using_static" = "yes"
+ then
+ echo "You can't use the --all-static link option when using openssl."
+ exit 1
+ fi
+ NON_THREADED_CLIENT_LIBS="$NON_THREADED_CLIENT_LIBS $openssl_libs"
+ else
+ AC_MSG_RESULT(no)
+ if test ! -z "$openssl_includes"
+ then
+ AC_MSG_ERROR(Can't have --with-openssl-includes without --with-openssl);
+ fi
+ if test ! -z "$openssl_libs"
+ then
+ AC_MSG_ERROR(Can't have --with-openssl-libs without --with-openssl);
+ fi
+ fi
+ AC_SUBST(openssl_libs)
+ AC_SUBST(openssl_includes)
+])
diff --git a/config/ac-macros/readline.m4 b/config/ac-macros/readline.m4
new file mode 100644
index 00000000000..79c6479d15d
--- /dev/null
+++ b/config/ac-macros/readline.m4
@@ -0,0 +1,61 @@
+AC_DEFUN([MYSQL_CHECK_READLINE_DECLARES_HIST_ENTRY], [
+ AC_CACHE_CHECK([HIST_ENTRY is declared in readline/readline.h], mysql_cv_hist_entry_declared,
+ AC_TRY_COMPILE(
+ [
+ #include "stdio.h"
+ #include "readline/readline.h"
+ ],
+ [
+ HIST_ENTRY entry;
+ ],
+ [
+ mysql_cv_hist_entry_declared=yes
+ AC_DEFINE_UNQUOTED(HAVE_HIST_ENTRY, [1],
+ [HIST_ENTRY is defined in the outer libeditreadline])
+ ],
+ [mysql_cv_libedit_interface=no]
+ )
+ )
+])
+
+AC_DEFUN([MYSQL_CHECK_LIBEDIT_INTERFACE], [
+ AC_CACHE_CHECK([libedit variant of rl_completion_entry_function], mysql_cv_libedit_interface,
+ AC_TRY_COMPILE(
+ [
+ #include "stdio.h"
+ #include "readline/readline.h"
+ ],
+ [
+ char res= *(*rl_completion_entry_function)(0,0);
+ completion_matches(0,0);
+ ],
+ [
+ mysql_cv_libedit_interface=yes
+ AC_DEFINE_UNQUOTED([USE_LIBEDIT_INTERFACE], [1],
+ [used libedit interface (can we dereference result of rl_completion_entry_function)])
+ ],
+ [mysql_cv_libedit_interface=no]
+ )
+ )
+])
+
+AC_DEFUN([MYSQL_CHECK_NEW_RL_INTERFACE], [
+ AC_CACHE_CHECK([defined rl_compentry_func_t and rl_completion_func_t], mysql_cv_new_rl_interface,
+ AC_TRY_COMPILE(
+ [
+ #include "stdio.h"
+ #include "readline/readline.h"
+ ],
+ [
+ rl_completion_func_t *func1= (rl_completion_func_t*)0;
+ rl_compentry_func_t *func2= (rl_compentry_func_t*)0;
+ ],
+ [
+ mysql_cv_new_rl_interface=yes
+ AC_DEFINE_UNQUOTED([USE_NEW_READLINE_INTERFACE], [1],
+ [used new readline interface (are rl_completion_func_t and rl_compentry_func_t defined)])
+ ],
+ [mysql_cv_new_rl_interface=no]
+ )
+ )
+])
diff --git a/config/ac-macros/zlib.m4 b/config/ac-macros/zlib.m4
new file mode 100644
index 00000000000..6c92d561e5a
--- /dev/null
+++ b/config/ac-macros/zlib.m4
@@ -0,0 +1,105 @@
+dnl Define zlib paths to point at bundled zlib
+
+AC_DEFUN([MYSQL_USE_BUNDLED_ZLIB], [
+ZLIB_INCLUDES="-I\$(top_srcdir)/zlib"
+ZLIB_LIBS="\$(top_builddir)/zlib/libz.la"
+zlib_dir="zlib"
+AC_SUBST([zlib_dir])
+mysql_cv_compress="yes"
+])
+
+dnl Auxiliary macro to check for zlib at given path
+
+AC_DEFUN([MYSQL_CHECK_ZLIB_DIR], [
+save_INCLUDES="$INCLUDES"
+save_LIBS="$LIBS"
+INCLUDES="$INCLUDES $ZLIB_INCLUDES"
+LIBS="$LIBS $ZLIB_LIBS"
+AC_CACHE_VAL([mysql_cv_compress],
+ [AC_TRY_LINK([#include <zlib.h>],
+ [return compress(0, (unsigned long*) 0, "", 0);],
+ [mysql_cv_compress="yes"
+ AC_MSG_RESULT([ok])],
+ [mysql_cv_compress="no"])
+ ])
+INCLUDES="$save_INCLUDES"
+LIBS="$save_LIBS"
+])
+
+dnl MYSQL_CHECK_ZLIB_WITH_COMPRESS
+dnl ------------------------------------------------------------------------
+dnl @synopsis MYSQL_CHECK_ZLIB_WITH_COMPRESS
+dnl
+dnl Provides the following configure options:
+dnl --with-zlib-dir=DIR
+dnl Possible DIR values are:
+dnl - "no" - the macro will disable use of compression functions
+dnl - "bundled" - means use zlib bundled along with MySQL sources
+dnl - empty, or not specified - the macro will try default system
+dnl library (if present), and in case of error will fall back to
+dnl bundled zlib
+dnl - zlib location prefix - given location prefix, the macro expects
+dnl to find the library headers in $prefix/include, and binaries in
+dnl $prefix/lib. If zlib headers or binaries weren't found at $prefix, the
+dnl macro bails out with error.
+dnl
+dnl If the library was found, this function #defines HAVE_COMPRESS
+dnl and configure variables ZLIB_INCLUDES (i.e. -I/path/to/zlib/include) and
+dnl ZLIB_LIBS (i. e. -L/path/to/zlib/lib -lz).
+
+AC_DEFUN([MYSQL_CHECK_ZLIB_WITH_COMPRESS], [
+AC_MSG_CHECKING([for zlib compression library])
+case $SYSTEM_TYPE in
+*netware* | *modesto*)
+ AC_MSG_RESULT(ok)
+ AC_DEFINE([HAVE_COMPRESS], [1], [Define to enable compression support])
+ ;;
+ *)
+ AC_ARG_WITH([zlib-dir],
+ AC_HELP_STRING([--with-zlib-dir=DIR],
+ [Provide MySQL with a custom location of
+ compression library. Given DIR, zlib binary is
+ assumed to be in $DIR/lib and header files
+ in $DIR/include.]),
+ [mysql_zlib_dir=${withval}],
+ [mysql_zlib_dir=""])
+ case "$mysql_zlib_dir" in
+ "no")
+ mysql_cv_compress="no"
+ AC_MSG_RESULT([disabled])
+ ;;
+ "bundled")
+ MYSQL_USE_BUNDLED_ZLIB
+ AC_MSG_RESULT([using bundled zlib])
+ ;;
+ "")
+ ZLIB_INCLUDES=""
+ ZLIB_LIBS="-lz"
+ MYSQL_CHECK_ZLIB_DIR
+ if test "$mysql_cv_compress" = "no"; then
+ MYSQL_USE_BUNDLED_ZLIB
+ AC_MSG_RESULT([system-wide zlib not found, using one bundled with MySQL])
+ fi
+ ;;
+ *)
+ if test -f "$mysql_zlib_dir/lib/libz.a" -a \
+ -f "$mysql_zlib_dir/include/zlib.h"; then
+ ZLIB_INCLUDES="-I$mysql_zlib_dir/include"
+ ZLIB_LIBS="-L$mysql_zlib_dir/lib -lz"
+ MYSQL_CHECK_ZLIB_DIR
+ fi
+ if test "x$mysql_cv_compress" != "xyes"; then
+ AC_MSG_ERROR([headers or binaries were not found in $mysql_zlib_dir/{include,lib}])
+ fi
+ ;;
+ esac
+ if test "$mysql_cv_compress" = "yes"; then
+ AC_SUBST([ZLIB_LIBS])
+ AC_SUBST([ZLIB_INCLUDES])
+ AC_DEFINE([HAVE_COMPRESS], [1], [Define to enable compression support])
+ fi
+ ;;
+esac
+])
+
+dnl ------------------------------------------------------------------------
diff --git a/configure.in b/configure.in
index 754494f7d70..7a334dee7c1 100644
--- a/configure.in
+++ b/configure.in
@@ -1,11 +1,12 @@
dnl -*- ksh -*-
dnl Process this file with autoconf to produce a configure script.
+AC_PREREQ(2.50)dnl Minimum Autoconf version required.
+
AC_INIT(sql/mysqld.cc)
AC_CANONICAL_SYSTEM
-# The Docs Makefile.am parses this line!
-# remember to also change ndb version below and update version.c in ndb
-AM_INIT_AUTOMAKE(mysql, 5.0.2-alpha)
+# Don't forget to also update the NDB lines below.
+AM_INIT_AUTOMAKE(mysql, 5.0.3-alpha)
AM_CONFIG_HEADER(config.h)
PROTOCOL_VERSION=10
@@ -29,12 +30,32 @@ MYSQL_VERSION_ID=`echo $MYSQL_NO_DASH_VERSION. | sed -e 's/\./ /g; s/ \([[0-9]]
MYSQL_TCP_PORT_DEFAULT=3306
MYSQL_UNIX_ADDR_DEFAULT="/tmp/mysql.sock"
+dnl Include m4
+sinclude(config/ac-macros/alloca.m4)
+sinclude(config/ac-macros/check_cpu.m4)
+sinclude(config/ac-macros/character_sets.m4)
+sinclude(config/ac-macros/compiler_flag.m4)
+sinclude(config/ac-macros/ha_archive.m4)
+sinclude(config/ac-macros/ha_berkeley.m4)
+sinclude(config/ac-macros/ha_example.m4)
+sinclude(config/ac-macros/ha_innodb.m4)
+sinclude(config/ac-macros/ha_isam.m4)
+sinclude(config/ac-macros/ha_ndbcluster.m4)
+sinclude(config/ac-macros/ha_tina.m4)
+sinclude(config/ac-macros/large_file.m4)
+sinclude(config/ac-macros/misc.m4)
+sinclude(config/ac-macros/mysqlfs.m4)
+sinclude(config/ac-macros/openssl.m4)
+sinclude(config/ac-macros/readline.m4)
+sinclude(config/ac-macros/zlib.m4)
+
# Remember to add a directory sql/share/LANGUAGE
AVAILABLE_LANGUAGES="\
czech danish dutch english estonian french german greek hungarian \
italian japanese korean norwegian norwegian-ny polish portuguese \
romanian russian serbian slovak spanish swedish ukrainian"
+
# Generate make rules for all error messages
AVAILABLE_LANGUAGES_ERRORS=
AVAILABLE_LANGUAGES_ERRORS_RULES=$srcdir/ac_available_languages_fragment
@@ -118,14 +139,12 @@ AC_SUBST(SAVE_LDFLAGS)
AC_SUBST(SAVE_CXXLDFLAGS)
AC_SUBST(CXXLDFLAGS)
-AC_PREREQ(2.12)dnl Minimum Autoconf version required.
#AC_ARG_PROGRAM # Automaticly invoked by AM_INIT_AUTOMAKE
+
AM_SANITY_CHECK
# This is needed is SUBDIRS is set
AC_PROG_MAKE_SET
-# This generates rules for webpage generation for the MySQL homepage.
-AM_CONDITIONAL(LOCAL, test -d ../web/SitePages)
# This is need before AC_PROG_CC
#
@@ -272,48 +291,6 @@ AC_TRY_RUN([
;;
esac
-
-# option, cache_name, variable,
-# code to execute if yes, code to exectute if fail
-AC_DEFUN([AC_SYS_COMPILER_FLAG],
-[
- AC_MSG_CHECKING($1)
- OLD_CFLAGS="[$]CFLAGS"
- AC_CACHE_VAL(mysql_cv_option_$2,
- [
- CFLAGS="[$]OLD_CFLAGS $1"
- AC_TRY_RUN([int main(){exit(0);}],mysql_cv_option_$2=yes,mysql_cv_option_$2=no,mysql_cv_option_$2=no)
- ])
-
- CFLAGS="[$]OLD_CFLAGS"
-
- if test x"[$]mysql_cv_option_$2" = "xyes" ; then
- $3="[$]$3 $1"
- AC_MSG_RESULT(yes)
- $5
- else
- AC_MSG_RESULT(no)
- $4
- fi
-])
-
-# arch, option, cache_name, variable
-AC_DEFUN([AC_SYS_CPU_COMPILER_FLAG],
-[
- if test "`uname -m 2>/dev/null`" = "$1" ; then
- AC_SYS_COMPILER_FLAG($2,$3,$4)
- fi
-])
-
-# os, option, cache_name, variable
-AC_DEFUN([AC_SYS_OS_COMPILER_FLAG],
-[
- if test "x$mysql_cv_sys_os" = "x$1" ; then
- AC_SYS_COMPILER_FLAG($2,$3,$4)
- fi
-])
-
-# We need some special hacks when running slowaris
AC_PATH_PROG(uname_prog, uname, no)
# We should go through this and put all the explictly system dependent
@@ -480,7 +457,7 @@ if $PS p $$ 2> /dev/null | grep $0 > /dev/null
then
FIND_PROC="$PS p \$\$PID | grep mysqld > /dev/null"
# Solaris
-elif $PS -p $$ 2> /dev/null | grep $0 > /dev/null
+elif $PS -fp $$ 2> /dev/null | grep $0 > /dev/null
then
FIND_PROC="$PS -p \$\$PID | grep mysqld > /dev/null"
# BSD style
@@ -974,8 +951,11 @@ case $SYSTEM_TYPE-$MACHINE_TYPE-$ac_cv_prog_gcc in
CFLAGS="$CFLAGS -DBIG_TABLES"
CXXFLAGS="$CXXFLAGS -DBIG_TABLES"
;;
+ *) ;;
+esac
+case $SYSTEM_TYPE-$ac_cv_prog_gcc in
# workaround for Sun Forte compile problem for ndb
- *solaris2.10*-sparc-no)
+ *solaris*-no)
ndb_cxxflags_fix="$ndb_cxxflags_fix -instances=static"
;;
*) ;;
@@ -1036,8 +1016,8 @@ case $SYSTEM_TYPE in
;;
*hpux11.*)
echo "Enabling workarounds for hpux 11"
- CFLAGS="$CFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
- CXXFLAGS="$CXXFLAGS -DHPUX11 -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
+ CFLAGS="$CFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -DHAVE_BROKEN_GETPASS -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
+ CXXFLAGS="$CXXFLAGS -DHPUX11 -DSNPRINTF_RETURN_TRUNC -DHAVE_BROKEN_PREAD -DDONT_USE_FINITE -D_INCLUDE_LONGLONG -DNO_FCNTL_NONBLOCK -DDO_NOT_REMOVE_THREAD_WRAPPERS -DHAVE_BROKEN_PTHREAD_COND_TIMEDWAIT"
if test "$with_named_thread" = "no"
then
echo "Using --with-named-thread=-lpthread"
@@ -1143,9 +1123,10 @@ dnl Is this the right match for DEC OSF on alpha?
fi
echo "Adding defines for OSF1"
# gethostbyname_r is deprecated and doesn't work ok on OSF1
- CFLAGS="$CFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R"
- CXXFLAGS="$CXXFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R"
- ndb_cxxflags_fix="$ndb_cxxflags_fix -I/usr/include.dtk"
+ CFLAGS="$CFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC"
+ CXXFLAGS="$CXXFLAGS -DUNDEF_HAVE_GETHOSTBYNAME_R -DSNPRINTF_RETURN_TRUNC"
+ # fix to handle include of <stdint.h> correctly on OSF1 with cxx compiler
+ CXXFLAGS="$CXXFLAGS -I/usr/include/cxx -I/usr/include/cxx_cname -I/usr/include -I/usr/include.dtk"
;;
*netware*)
# No need for curses library so set it to null
@@ -1905,7 +1886,7 @@ if test "$GCC" != "yes"; then
AC_SYS_COMPILER_FLAG(-nolib_inline,nolib_inline,CFLAGS,[],[])
fi
-AC_FUNC_MMAP
+#AC_FUNC_MMAP
AC_TYPE_SIGNAL
MYSQL_TYPE_QSORT
AC_FUNC_UTIME_NULL
@@ -1916,7 +1897,7 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
getcwd gethostbyaddr_r gethostbyname_r getpass getpassphrase getpwnam \
getpwuid getrlimit getrusage getwd gmtime_r index initgroups isnan \
localtime_r locking longjmp lrand48 madvise mallinfo memcpy memmove \
- mkstemp mlockall perror poll pread pthread_attr_create clock_gettime \
+ mkstemp mlockall perror poll pread pthread_attr_create mmap \
pthread_attr_getstacksize pthread_attr_setprio pthread_attr_setschedparam \
pthread_attr_setstacksize pthread_condattr_create pthread_getsequence_np \
pthread_key_delete pthread_rwlock_rdlock pthread_setprio \
@@ -1925,6 +1906,20 @@ AC_CHECK_FUNCS(alarm bcmp bfill bmove bzero chsize cuserid fchmod fcntl \
snprintf socket stpcpy strcasecmp strerror strnlen strpbrk strstr strtol \
strtoll strtoul strtoull tell tempnam thr_setconcurrency vidattr)
+#
+#
+#
+case "$target" in
+ *-*-aix4* | *-*-sco*)
+ # (grr) aix 4.3 has a stub for clock_gettime, (returning ENOSYS)
+ # and using AC_TRY_RUN is hard when cross-compiling
+ # We also disable for SCO for the time being, the headers for the
+ # thread library we use conflicts with other headers.
+ ;;
+ *) AC_CHECK_FUNCS(clock_gettime)
+ ;;
+esac
+
# isinf() could be a function or a macro (HPUX)
AC_MSG_CHECKING(for isinf with <math.h>)
AC_TRY_LINK([#include <math.h>], [float f = 0.0; isinf(f)],
@@ -2419,398 +2414,6 @@ AC_SUBST(readline_basedir)
AC_SUBST(readline_link)
AC_SUBST(readline_h_ln_cmd)
-
-dnl In order to add new charset, you must add charset name to
-dnl this CHARSETS_AVAILABLE list and sql/share/charsets/Index.xml.
-dnl If the character set uses strcoll or other special handling,
-dnl you must also create strings/ctype-$charset_name.c
-
-AC_DIVERT_PUSH(0)
-
-define(CHARSETS_AVAILABLE0,binary)
-define(CHARSETS_AVAILABLE1,armscii8 ascii big5 cp1250 cp1251 cp1256 cp1257)
-define(CHARSETS_AVAILABLE2,cp850 cp852 cp866 dec8 euckr gb2312 gbk geostd8)
-define(CHARSETS_AVAILABLE3,greek hebrew hp8 keybcs2 koi8r koi8u)
-define(CHARSETS_AVAILABLE4,latin1 latin2 latin5 latin7 macce macroman)
-define(CHARSETS_AVAILABLE5,sjis swe7 tis620 ucs2 ujis utf8)
-
-DEFAULT_CHARSET=latin1
-CHARSETS_AVAILABLE="CHARSETS_AVAILABLE0 CHARSETS_AVAILABLE1 CHARSETS_AVAILABLE2 CHARSETS_AVAILABLE3 CHARSETS_AVAILABLE4 CHARSETS_AVAILABLE5"
-CHARSETS_COMPLEX="big5 cp1250 euckr gb2312 gbk latin1 latin2 sjis tis620 ucs2 ujis utf8"
-
-AC_DIVERT_POP
-
-AC_ARG_WITH(charset,
- [ --with-charset=CHARSET
- Default character set, use one of:
- CHARSETS_AVAILABLE0
- CHARSETS_AVAILABLE1
- CHARSETS_AVAILABLE2
- CHARSETS_AVAILABLE3
- CHARSETS_AVAILABLE4
- CHARSETS_AVAILABLE5],
- [default_charset="$withval"],
- [default_charset="$DEFAULT_CHARSET"])
-
-AC_ARG_WITH(collation,
- [ --with-collation=COLLATION
- Default collation],
- [default_collation="$withval"],
- [default_collation="default"])
-
-
-AC_ARG_WITH(extra-charsets,
- [ --with-extra-charsets=CHARSET[,CHARSET,...]
- Use charsets in addition to default (none, complex,
- all, or a list selected from the above sets)],
- [extra_charsets="$withval"],
- [extra_charsets="none"])
-
-
-AC_MSG_CHECKING("character sets")
-
-CHARSETS="$default_charset latin1 utf8"
-
-if test "$extra_charsets" = no; then
- CHARSETS="$CHARSETS"
-elif test "$extra_charsets" = none; then
- CHARSETS="$CHARSETS"
-elif test "$extra_charsets" = complex; then
- CHARSETS="$CHARSETS $CHARSETS_COMPLEX"
- AC_DEFINE([DEFINE_ALL_CHARACTER_SETS],1,[all charsets are available])
-elif test "$extra_charsets" = all; then
- CHARSETS="$CHARSETS $CHARSETS_AVAILABLE"
- AC_DEFINE([DEFINE_ALL_CHARACTER_SETS],1,[all charsets are available])
-else
- EXTRA_CHARSETS=`echo $extra_charsets | sed -e 's/,/ /g'`
- CHARSETS="$CHARSETS $EXTRA_CHARSETS"
-fi
-
-for cs in $CHARSETS
-do
- case $cs in
- armscii8)
- AC_DEFINE(HAVE_CHARSET_armscii8, 1,
- [Define to enable charset armscii8])
- ;;
- ascii)
- AC_DEFINE(HAVE_CHARSET_ascii, 1,
- [Define to enable ascii character set])
- ;;
- big5)
- AC_DEFINE(HAVE_CHARSET_big5, 1, [Define to enable charset big5])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, [1], [ ])
- ;;
- binary)
- ;;
- cp1250)
- AC_DEFINE(HAVE_CHARSET_cp1250, 1, [Define to enable cp1250])
- ;;
- cp1251)
- AC_DEFINE(HAVE_CHARSET_cp1251, 1, [Define to enable charset cp1251])
- ;;
- cp1256)
- AC_DEFINE(HAVE_CHARSET_cp1256, 1, [Define to enable charset cp1256])
- ;;
- cp1257)
- AC_DEFINE(HAVE_CHARSET_cp1257, 1, [Define to enable charset cp1257])
- ;;
- cp850)
- AC_DEFINE(HAVE_CHARSET_cp850, 1, [Define to enable charset cp850])
- ;;
- cp852)
- AC_DEFINE(HAVE_CHARSET_cp852, 1, [Define to enable charset cp852])
- ;;
- cp866)
- AC_DEFINE(HAVE_CHARSET_cp866, 1, [Define to enable charset cp866])
- ;;
- dec8)
- AC_DEFINE(HAVE_CHARSET_dec8, 1, [Define to enable charset dec8])
- ;;
- euckr)
- AC_DEFINE(HAVE_CHARSET_euckr, 1, [Define to enable charset euckr])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- gb2312)
- AC_DEFINE(HAVE_CHARSET_gb2312, 1, [Define to enable charset gb2312])
- AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- gbk)
- AC_DEFINE(HAVE_CHARSET_gbk, 1, [Define to enable charset gbk])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- geostd8)
- AC_DEFINE(HAVE_CHARSET_geostd8, 1, [Define to enable charset geostd8])
- ;;
- greek)
- AC_DEFINE(HAVE_CHARSET_greek, 1, [Define to enable charset greek])
- ;;
- hebrew)
- AC_DEFINE(HAVE_CHARSET_hebrew, 1, [Define to enable charset hebrew])
- ;;
- hp8)
- AC_DEFINE(HAVE_CHARSET_hp8, 1, [Define to enable charset hp8])
- ;;
- keybcs2)
- AC_DEFINE(HAVE_CHARSET_keybcs2, 1, [Define to enable charset keybcs2])
- ;;
- koi8r)
- AC_DEFINE(HAVE_CHARSET_koi8r, 1, [Define to enable charset koi8r])
- ;;
- koi8u)
- AC_DEFINE(HAVE_CHARSET_koi8u, 1, [Define to enable charset koi8u])
- ;;
- latin1)
- AC_DEFINE(HAVE_CHARSET_latin1, 1, [Define to enable charset latin1])
- ;;
- latin2)
- AC_DEFINE(HAVE_CHARSET_latin2, 1, [Define to enable charset latin2])
- ;;
- latin5)
- AC_DEFINE(HAVE_CHARSET_latin5, 1, [Define to enable charset latin5])
- ;;
- latin7)
- AC_DEFINE(HAVE_CHARSET_latin7, 1, [Define to enable charset latin7])
- ;;
- macce)
- AC_DEFINE(HAVE_CHARSET_macce, 1, [Define to enable charset macce])
- ;;
- macroman)
- AC_DEFINE(HAVE_CHARSET_macroman, 1,
- [Define to enable charset macroman])
- ;;
- sjis)
- AC_DEFINE(HAVE_CHARSET_sjis, 1, [Define to enable charset sjis])
- AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- swe7)
- AC_DEFINE(HAVE_CHARSET_swe7, 1, [Define to enable charset swe7])
- ;;
- tis620)
- AC_DEFINE(HAVE_CHARSET_tis620, 1, [Define to enable charset tis620])
- ;;
- ucs2)
- AC_DEFINE(HAVE_CHARSET_ucs2, 1, [Define to enable charset ucs2])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- ujis)
- AC_DEFINE(HAVE_CHARSET_ujis, 1, [Define to enable charset ujis])
- AC_DEFINE([USE_MB], [1], [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- utf8)
- AC_DEFINE(HAVE_CHARSET_utf8, 1, [Define to enable ut8])
- AC_DEFINE([USE_MB], 1, [Use multi-byte character routines])
- AC_DEFINE(USE_MB_IDENT, 1)
- ;;
- *)
- AC_MSG_ERROR([Charset '$cs' not available. (Available are: $CHARSETS_AVAILABLE).
- See the Installation chapter in the Reference Manual.]);
- esac
-done
-
-
- default_charset_collations=""
-
-case $default_charset in
- armscii8)
- default_charset_default_collation="armscii8_general_ci"
- default_charset_collations="armscii8_general_ci armscii8_bin"
- ;;
- ascii)
- default_charset_default_collation="ascii_general_ci"
- default_charset_collations="ascii_general_ci ascii_bin"
- ;;
- big5)
- default_charset_default_collation="big5_chinese_ci"
- default_charset_collations="big5_chinese_ci big5_bin"
- ;;
- binary)
- default_charset_default_collation="binary"
- default_charset_collations="binary"
- ;;
- cp1250)
- default_charset_default_collation="cp1250_general_ci"
- default_charset_collations="cp1250_general_ci cp1250_czech_cs cp1250_bin"
- ;;
- cp1251)
- default_charset_default_collation="cp1251_general_ci"
- default_charset_collations="cp1251_general_ci cp1251_general_cs cp1251_bin cp1251_bulgarian_ci cp1251_ukrainian_ci"
- ;;
- cp1256)
- default_charset_default_collation="cp1256_general_ci"
- default_charset_collations="cp1256_general_ci cp1256_bin"
- ;;
- cp1257)
- default_charset_default_collation="cp1257_general_ci"
- default_charset_collations="cp1257_general_ci cp1257_lithuanian_ci cp1257_bin"
- ;;
- cp850)
- default_charset_default_collation="cp850_general_ci"
- default_charset_collations="cp850_general_ci cp850_bin"
- ;;
- cp852)
- default_charset_default_collation="cp852_general_ci"
- default_charset_collations="cp852_general_ci cp852_bin"
- ;;
- cp866)
- default_charset_default_collation="cp866_general_ci"
- default_charset_collations="cp866_general_ci cp866_bin"
- ;;
- dec8)
- default_charset_default_collation="dec8_swedish_ci"
- default_charset_collations="dec8_swedish_ci dec8_bin"
- ;;
- euckr)
- default_charset_default_collation="euckr_korean_ci"
- default_charset_collations="euckr_korean_ci euckr_bin"
- ;;
- gb2312)
- default_charset_default_collation="gb2312_chinese_ci"
- default_charset_collations="gb2312_chinese_ci gb2312_bin"
- ;;
- gbk)
- default_charset_default_collation="gbk_chinese_ci"
- default_charset_collations="gbk_chinese_ci gbk_bin"
- ;;
- geostd8)
- default_charset_default_collation="geostd8_general_ci"
- default_charset_collations="geostd8_general_ci geostd8_bin"
- ;;
- greek)
- default_charset_default_collation="greek_general_ci"
- default_charset_collations="greek_general_ci greek_bin"
- ;;
- hebrew)
- default_charset_default_collation="hebrew_general_ci"
- default_charset_collations="hebrew_general_ci hebrew_bin"
- ;;
- hp8)
- default_charset_default_collation="hp8_english_ci"
- default_charset_collations="hp8_english_ci hp8_bin"
- ;;
- keybcs2)
- default_charset_default_collation="keybcs2_general_ci"
- default_charset_collations="keybcs2_general_ci keybcs2_bin"
- ;;
- koi8r)
- default_charset_default_collation="koi8r_general_ci"
- default_charset_collations="koi8r_general_ci koi8r_bin"
- ;;
- koi8u)
- default_charset_default_collation="koi8u_general_ci"
- default_charset_collations="koi8u_general_ci koi8u_bin"
- ;;
- latin1)
- default_charset_default_collation="latin1_swedish_ci"
- default_charset_collations="latin1_general_ci latin1_general_cs latin1_bin latin1_german1_ci latin1_german2_ci latin1_danish_ci latin1_swedish_ci"
- ;;
- latin2)
- default_charset_default_collation="latin2_general_ci"
- default_charset_collations="latin2_general_ci latin2_bin latin2_czech_cs latin2_hungarian_ci latin2_croatian_ci"
- ;;
- latin5)
- default_charset_default_collation="latin5_turkish_ci"
- default_charset_collations="latin5_turkish_ci latin5_bin"
- ;;
- latin7)
- default_charset_default_collation="latin7_general_ci"
- default_charset_collations="latin7_general_ci latin7_general_cs latin7_bin latin7_estonian_cs"
- ;;
- macce)
- default_charset_default_collation="macce_general_ci"
- default_charset_collations="macce_general_ci macce_bin"
- ;;
- macroman)
- default_charset_default_collation="macroman_general_ci"
- default_charset_collations="macroman_general_ci macroman_bin"
- ;;
- sjis)
- default_charset_default_collation="sjis_japanese_ci"
- default_charset_collations="sjis_japanese_ci sjis_bin"
- ;;
- swe7)
- default_charset_default_collation="swe7_swedish_ci"
- default_charset_collations="swe7_swedish_ci swe7_bin"
- ;;
- tis620)
- default_charset_default_collation="tis620_thai_ci"
- default_charset_collations="tis620_thai_ci tis620_bin"
- ;;
- ucs2)
- default_charset_default_collation="ucs2_general_ci"
- define(UCSC1, ucs2_general_ci ucs2_bin)
- define(UCSC2, ucs2_czech_ci ucs2_danish_ci)
- define(UCSC3, ucs2_estonian_ci ucs2_icelandic_ci)
- define(UCSC4, ucs2_latvian_ci ucs2_lithuanian_ci)
- define(UCSC5, ucs2_persian_ci ucs2_polish_ci ucs2_romanian_ci)
- define(UCSC6, ucs2_slovak_ci ucs2_slovenian_ci)
- define(UCSC7, ucs2_spanish2_ci ucs2_spanish_ci)
- define(UCSC8, ucs2_swedish_ci ucs2_turkish_ci)
- define(UCSC9, ucs2_unicode_ci)
- UCSC="UCSC1 UCSC2 UCSC3 UCSC4 UCSC5 UCSC6 UCSC7 UCSC8 UCSC9"
- default_charset_collations="$UCSC"
- ;;
- ujis)
- default_charset_default_collation="ujis_japanese_ci"
- default_charset_collations="ujis_japanese_ci ujis_bin"
- ;;
- utf8)
- default_charset_default_collation="utf8_general_ci"
- define(UTFC1, utf8_general_ci utf8_bin)
- define(UTFC2, utf8_czech_ci utf8_danish_ci)
- define(UTFC3, utf8_estonian_ci utf8_icelandic_ci)
- define(UTFC4, utf8_latvian_ci utf8_lithuanian_ci)
- define(UTFC5, utf8_persian_ci utf8_polish_ci utf8_romanian_ci)
- define(UTFC6, utf8_slovak_ci utf8_slovenian_ci)
- define(UTFC7, utf8_spanish2_ci utf8_spanish_ci)
- define(UTFC8, utf8_swedish_ci utf8_turkish_ci)
- define(UTFC9, utf8_unicode_ci)
- UTFC="UTFC1 UTFC2 UTFC3 UTFC4 UTFC5 UTFC6 UTFC7 UTFC8 UTFC9"
- default_charset_collations="$UTFC"
- ;;
- *)
- AC_MSG_ERROR([Charset $cs not available. (Available are: $CHARSETS_AVAILABLE).
- See the Installation chapter in the Reference Manual.]);
-esac
-
-if test "$default_collation" = default; then
- default_collation=$default_charset_default_collation
-fi
-
-valid_default_collation=no
-for cl in $default_charset_collations
-do
- if test x"$cl" = x"$default_collation"
- then
- valid_default_collation=yes
- break
- fi
-done
-
-if test x$valid_default_collation = xyes
-then
- AC_MSG_RESULT([default: $default_charset, collation: $default_collation; compiled in: $CHARSETS])
-else
- AC_MSG_ERROR([
- Collation $default_collation is not valid for character set $default_charset.
- Valid collations are: $default_charset_collations.
- See the Installation chapter in the Reference Manual.
- ]);
-fi
-
-AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_CHARSET_NAME], ["$default_charset"],
- [Define the default charset name])
-AC_DEFINE_UNQUOTED([MYSQL_DEFAULT_COLLATION_NAME], ["$default_collation"],
- [Define the default charset name])
-
-MYSQL_CHECK_ISAM
MYSQL_CHECK_BDB
MYSQL_CHECK_INNODB
MYSQL_CHECK_EXAMPLEDB
@@ -2825,7 +2428,7 @@ thread_dirs=
dnl This probably should be cleaned up more - for now the threaded
dnl client is just using plain-old libs.
-sql_client_dirs="libmysql strings regex client"
+sql_client_dirs="libmysql client"
linked_client_targets="linked_libmysql_sources"
CLIENT_LIBS=$NON_THREADED_CLIENT_LIBS
if test "$THREAD_SAFE_CLIENT" != "no"
@@ -2861,24 +2464,16 @@ then
AC_DEFINE([THREAD], [1],
[Define if you want to have threaded code. This may be undef on client code])
# Avoid _PROGRAMS names
- THREAD_LPROGRAMS="test_thr_alarm\$(EXEEXT) test_thr_lock\$(EXEEXT)"
- AC_SUBST(THREAD_LPROGRAMS)
THREAD_LOBJECTS="thr_alarm.o thr_lock.o thr_mutex.o thr_rwlock.o my_pthread.o my_thr_init.o"
AC_SUBST(THREAD_LOBJECTS)
server_scripts="mysqld_safe mysql_install_db"
- sql_server_dirs="strings dbug mysys extra regex"
+ sql_server_dirs="strings mysys dbug extra regex"
#
# Configuration for optional table handlers
#
- if test X"$have_isam" != Xno
- then
- sql_server_dirs="$sql_server_dirs isam merge"
- AC_CONFIG_FILES(isam/Makefile merge/Makefile)
- fi
-
if test X"$have_berkeley_db" != Xno; then
if test X"$have_berkeley_db" != Xyes; then
# we must build berkeley db from source
@@ -3029,6 +2624,7 @@ case $SYSTEM_TYPE in
;;
esac
+
if test X"$have_ndbcluster" = Xyes
then
MAKE_BINARY_DISTRIBUTION_OPTIONS="$MAKE_BINARY_DISTRIBUTION_OPTIONS --with-ndbcluster"
@@ -3049,9 +2645,15 @@ AC_SUBST([NDB_DEFS])
AC_SUBST([ndb_cxxflags_fix])
+if test X"$ndb_port" = Xdefault
+then
+ ndb_port="1186"
+fi
+AC_SUBST([ndb_port])
+
if test X"$ndb_port_base" = Xdefault
then
- ndb_port_base="2200"
+ ndb_port_base="2202"
fi
AC_SUBST([ndb_port_base])
@@ -3090,7 +2692,6 @@ AC_CONFIG_FILES(ndb/Makefile ndb/include/Makefile dnl
ndb/src/common/logger/Makefile dnl
ndb/src/common/transporter/Makefile dnl
ndb/src/common/mgmcommon/Makefile dnl
- ndb/src/common/editline/Makefile dnl
ndb/src/kernel/Makefile dnl
ndb/src/kernel/error/Makefile dnl
ndb/src/kernel/blocks/Makefile dnl
@@ -3106,7 +2707,6 @@ AC_CONFIG_FILES(ndb/Makefile ndb/include/Makefile dnl
ndb/src/kernel/blocks/qmgr/Makefile dnl
ndb/src/kernel/blocks/trix/Makefile dnl
ndb/src/kernel/blocks/backup/Makefile dnl
- ndb/src/kernel/blocks/backup/restore/Makefile dnl
ndb/src/kernel/blocks/dbutil/Makefile dnl
ndb/src/kernel/blocks/suma/Makefile dnl
ndb/src/kernel/blocks/grep/Makefile dnl
@@ -3142,7 +2742,7 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
dbug/Makefile scripts/Makefile dnl
include/Makefile sql-bench/Makefile tools/Makefile dnl
server-tools/Makefile server-tools/instance-manager/Makefile dnl
- tests/Makefile Docs/Makefile support-files/Makefile dnl
+ tests/Makefile Docs/Makefile Docs/Images/Makefile support-files/Makefile dnl
support-files/MacOSX/Makefile mysql-test/Makefile dnl
netware/Makefile dnl
include/mysql_version.h dnl
@@ -3153,7 +2753,6 @@ AC_CONFIG_FILES(Makefile extra/Makefile mysys/Makefile dnl
AC_CONFIG_COMMANDS([default], , test -z "$CONFIG_HEADERS" || echo timestamp > stamp-h)
AC_OUTPUT
-rm -f $AVAILABLE_LANGUAGES_ERRORS_RULES
echo
echo "MySQL has a Web site at http://www.mysql.com/ which carries details on the"
echo "latest release, upcoming features, and other information to make your"
diff --git a/dbug/Makefile.am b/dbug/Makefile.am
index bd512ee1d1d..f8ddf0e6567 100644
--- a/dbug/Makefile.am
+++ b/dbug/Makefile.am
@@ -15,43 +15,52 @@
# Software Foundation, Inc., 59 Temple Place - Suite 330, Boston,
# MA 02111-1307, USA
-INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
-LDADD = libdbug.a ../strings/libmystrings.a
-pkglib_LIBRARIES = libdbug.a
-noinst_HEADERS = dbug_long.h
-libdbug_a_SOURCES = dbug.c sanity.c
-EXTRA_DIST = example1.c example2.c example3.c \
- user.r monty.doc readme.prof \
- main.c factorial.c dbug_analyze.c
+INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
+LDADD = libdbug.a ../mysys/libmysys.a ../strings/libmystrings.a
+pkglib_LIBRARIES = libdbug.a
+noinst_HEADERS = dbug_long.h
+libdbug_a_SOURCES = dbug.c sanity.c
+EXTRA_DIST = example1.c example2.c example3.c \
+ user.r monty.doc readme.prof dbug_add_tags.pl \
+ my_main.c main.c factorial.c dbug_analyze.c
+NROFF_INC = example1.r example2.r example3.r main.r \
+ factorial.r output1.r output2.r output3.r \
+ output4.r output5.r
+
# Must be linked with libs that are not compiled yet
-extra_progs: factorial dbug_analyze
+noinst_PROGRAMS = factorial dbug_analyze
+factorial_SOURCES = my_main.c factorial.c
+dbug_analyze_SOURCES = dbug_analyze.c
+
+all: user.t user.ps
-factorial: main.o factorial.o
- @rm -f factorial
- $(LINK) main.o factorial.o -lmysys
+user.t: user.r $(NROFF_INC)
+ -nroff -mm user.r > $@
-dbug_analyze: dbug_analyze.o
- @rm -f dbug_analyze
- $(LINK) dbug_analyze.o -lmysys
+user.ps: user.r $(NROFF_INC)
+ -groff -mm user.r > $@
-user.t: user.r $(NROFF_INC)
- nroff -cm user.r > $@
+output1.r: factorial
+ ./factorial 1 2 3 4 5 | cat > $@
-output1.r: $(PROGRAM)
- factorial 1 2 3 4 5 | cat > $@
+output2.r: factorial
+ ./factorial -\#t:o 2 3 | cat >$@
-output2.r: $(PROGRAM)
- factorial -\#t:o 2 3 | cat >$@
+output3.r: factorial
+ ./factorial -\#d:t:o 3 | cat >$@
-output3.r: $(PROGRAM)
- factorial -\#d:t:o 3 | cat >$@
+output4.r: factorial
+ ./factorial -\#d,result:o 4 | cat >$@
-output4.r: $(PROGRAM)
- factorial -\#d,result:o 4 | cat >$@
+output5.r: factorial
+ ./factorial -\#d:f,factorial:F:L:o 3 | cat >$@
+.c.r:
+ @RM@ -f $@
+ @SED@ -e 's!\\!\\\\!g' $< > $@
-output5.r: $(PROGRAM)
- factorial -\#d:f,factorial:F:L:o 3 | cat >$@
+clean:
+ @RM@ -f $(NROFF_INC) user.t user.ps
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/dbug/dbug.c b/dbug/dbug.c
index 1796d883c5e..d21b4e7801a 100644
--- a/dbug/dbug.c
+++ b/dbug/dbug.c
@@ -21,8 +21,7 @@
* all copies and derivative works. Thank you. *
* *
* The author makes no warranty of any kind with respect to this *
- * product and explicitly disclaims any implied warranties of mer- *ct_lex.table_list.first=0;
- thd->lex.selec
+ * product and explicitly disclaims any implied warranties of mer- *
* chantability or fitness for any particular purpose. *
* *
******************************************************************************
@@ -60,8 +59,8 @@
*
* Michael Widenius:
* DBUG_DUMP - To dump a block of memory.
- * PUSH_FLAG "O" - To be used insted of "o" if we don't
- * want flushing (for slow systems)
+ * PUSH_FLAG "O" - To be used insted of "o" if we
+ * want flushing after each write
* PUSH_FLAG "A" - as 'O', but we will append to the out file instead
* of creating a new one.
* Check of malloc on entry/exit (option "S")
@@ -227,14 +226,15 @@ static my_bool init_done = FALSE; /* Set to TRUE when initialization done */
static struct state *stack=0;
typedef struct st_code_state {
- int lineno; /* Current debugger output line number */
- int level; /* Current function nesting level */
const char *func; /* Name of current user function */
const char *file; /* Name of current user file */
char **framep; /* Pointer to current frame */
- int jmplevel; /* Remember nesting level at setjmp () */
const char *jmpfunc; /* Remember current function for setjmp */
const char *jmpfile; /* Remember current file for setjmp */
+ int lineno; /* Current debugger output line number */
+ int level; /* Current function nesting level */
+ int disable_output; /* Set to it if output is disabled */
+ int jmplevel; /* Remember nesting level at setjmp () */
/*
* The following variables are used to hold the state information
@@ -247,8 +247,8 @@ typedef struct st_code_state {
*/
uint u_line; /* User source code line number */
- const char *u_keyword; /* Keyword for current macro */
int locked; /* If locked with _db_lock_file */
+ const char *u_keyword; /* Keyword for current macro */
} CODE_STATE;
/* Parse a debug command string */
@@ -370,8 +370,10 @@ static CODE_STATE *code_state(void)
#define code_state() (&static_code_state)
#define pthread_mutex_lock(A) {}
#define pthread_mutex_unlock(A) {}
-static CODE_STATE static_code_state = { 0,0,"?func","?file",NULL,0,NULL,
- NULL,0,"?",0};
+static CODE_STATE static_code_state=
+{
+ "?func", "?file", NULL, NullS, NullS, 0,0,0,0,0,0, NullS
+};
#endif
@@ -728,9 +730,12 @@ char ***_sframep_ __attribute__((unused)))
if (DoProfile ())
{
long stackused;
- if (*state->framep == NULL) {
+ if (*state->framep == NULL)
+ {
stackused = 0;
- } else {
+ }
+ else
+ {
stackused = ((long)(*state->framep)) - ((long)(state->framep));
stackused = stackused > 0 ? stackused : -stackused;
}
@@ -744,7 +749,7 @@ char ***_sframep_ __attribute__((unused)))
(void) fflush (_db_pfp_);
}
#endif
- if (DoTrace (state))
+ if (DoTrace(state))
{
if (!state->locked)
pthread_mutex_lock(&THR_LOCK_dbug);
@@ -754,7 +759,7 @@ char ***_sframep_ __attribute__((unused)))
dbug_flush (state); /* This does a unlock */
}
#ifdef SAFEMALLOC
- if (stack -> flags & SANITY_CHECK_ON)
+ if (stack->flags & SANITY_CHECK_ON && !state->disable_output)
if (_sanity(_file_,_line_)) /* Check of safemalloc */
stack -> flags &= ~SANITY_CHECK_ON;
#endif
@@ -809,9 +814,11 @@ uint *_slevel_)
else
{
#ifdef SAFEMALLOC
- if (stack -> flags & SANITY_CHECK_ON)
+ if (stack->flags & SANITY_CHECK_ON && !state->disable_output)
+ {
if (_sanity(*_sfile_,_line_))
stack->flags &= ~SANITY_CHECK_ON;
+ }
#endif
#ifndef THREAD
if (DoProfile ())
@@ -930,7 +937,7 @@ void _db_doprnt_ (const char *format,...)
/*
* FUNCTION
*
- * _db_dump_ dump a string until '\0' is found
+ * _db_dump_ dump a string in hex
*
* SYNOPSIS
*
@@ -954,7 +961,6 @@ uint length)
int pos;
char dbuff[90];
CODE_STATE *state;
- /* Sasha: pre-my_thread_init() safety */
if (!(state=code_state()))
return;
@@ -994,6 +1000,25 @@ uint length)
}
}
+
+/*
+ Enable/Disable output for this thread
+
+ SYNOPSIS
+ _db_output_()
+ flag 1 = enable output, 0 = disable_output
+
+*/
+
+void _db_output_(uint flag)
+{
+ CODE_STATE *state;
+ if (!(state=code_state()))
+ return;
+ state->disable_output= !flag;
+}
+
+
/*
* FUNCTION
*
@@ -1159,7 +1184,7 @@ static BOOLEAN DoTrace (CODE_STATE *state)
{
reg2 BOOLEAN trace=FALSE;
- if (TRACING &&
+ if (TRACING && !state->disable_output &&
state->level <= stack -> maxdepth &&
InList (stack -> functions, state->func) &&
InList (stack -> processes, _db_process_))
@@ -1195,7 +1220,7 @@ static BOOLEAN DoProfile ()
state=code_state();
profile = FALSE;
- if (PROFILING &&
+ if (PROFILING && !state->disable_output &&
state->level <= stack -> maxdepth &&
InList (stack -> p_functions, state->func) &&
InList (stack -> processes, _db_process_))
@@ -1204,6 +1229,33 @@ static BOOLEAN DoProfile ()
}
#endif
+/*
+ * FUNCTION
+ *
+ * _db_strict_keyword_ test keyword for member of keyword list
+ *
+ * SYNOPSIS
+ *
+ * BOOLEAN _db_strict_keyword_ (keyword)
+ * char *keyword;
+ *
+ * DESCRIPTION
+ *
+ * Similar to _db_keyword_, but keyword is NOT accepted if keyword list
+ * is empty. Used in DBUG_EXECUTE_IF() - for actions that must not be
+ * executed by default.
+ *
+ * Returns TRUE if keyword accepted, FALSE otherwise.
+ *
+ */
+
+BOOLEAN _db_strict_keyword_ (
+const char *keyword)
+{
+ if (stack -> keywords == NULL)
+ return FALSE;
+ return _db_keyword_ (keyword);
+}
/*
* FUNCTION
@@ -1242,7 +1294,7 @@ const char *keyword)
if (!(state=code_state()))
return FALSE;
result = FALSE;
- if (DEBUGGING &&
+ if (DEBUGGING && !state->disable_output &&
state->level <= stack -> maxdepth &&
InList (stack -> functions, state->func) &&
InList (stack -> keywords, keyword) &&
diff --git a/dbug/dbug_analyze.c b/dbug/dbug_analyze.c
index de228c64aa5..0841e8e0b70 100644
--- a/dbug/dbug_analyze.c
+++ b/dbug/dbug_analyze.c
@@ -572,6 +572,11 @@ int main (int argc, char **argv)
FILE *infile;
FILE *outfile = {stdout};
+#if defined(HAVE_PTHREAD_INIT) && defined(THREAD)
+ pthread_init(); /* Must be called before DBUG_ENTER */
+#endif
+ my_thread_global_init();
+ {
DBUG_ENTER ("main");
DBUG_PROCESS (argv[0]);
my_name = argv[0];
@@ -601,6 +606,7 @@ int main (int argc, char **argv)
output (outfile);
DBUG_RETURN (EX_OK);
}
+}
#ifdef MSDOS
diff --git a/dbug/dbug_long.h b/dbug/dbug_long.h
index 07266b51553..829df181ef1 100644
--- a/dbug/dbug_long.h
+++ b/dbug/dbug_long.h
@@ -1,3 +1,4 @@
+#error This file is not used in MySQL - see ../include/my_dbug.h instead
/******************************************************************************
* *
* N O T I C E *
diff --git a/dbug/example1.c b/dbug/example1.c
index e468f065796..7b3c3fcd63d 100644
--- a/dbug/example1.c
+++ b/dbug/example1.c
@@ -1,6 +1,3 @@
-
-#include <my_global.h>
-
main (argc, argv)
int argc;
char *argv[];
diff --git a/dbug/example2.c b/dbug/example2.c
index 5e5f14f0e7e..75fc1321b13 100644
--- a/dbug/example2.c
+++ b/dbug/example2.c
@@ -1,6 +1,3 @@
-
-#include <my_global.h>
-
int debug = 0;
main (argc, argv)
diff --git a/dbug/example3.c b/dbug/example3.c
index f177c07425d..c035cdfffa0 100644
--- a/dbug/example3.c
+++ b/dbug/example3.c
@@ -1,6 +1,3 @@
-
-#include <my_global.h>
-
main (argc, argv)
int argc;
char *argv[];
diff --git a/dbug/main.c b/dbug/main.c
index da56c00feb3..00e80c8ba31 100644
--- a/dbug/main.c
+++ b/dbug/main.c
@@ -1,33 +1,24 @@
-#ifdef DBUG_OFF /* We are testing dbug */
-#undef DBUG_OFF
-#endif
-
-#include <my_global.h> /* This includes dbug.h */
+#include <dbug.h>
int main (argc, argv)
int argc;
char *argv[];
{
- register int result, ix;
+ int result, ix;
extern int factorial(int);
-#if defined(HAVE_PTHREAD_INIT) && defined(THREAD)
- pthread_init(); /* Must be called before DBUG_ENTER */
-#endif
- {
- DBUG_ENTER ("main");
- DBUG_PROCESS (argv[0]);
- for (ix = 1; ix < argc && argv[ix][0] == '-'; ix++) {
- switch (argv[ix][1]) {
- case '#':
- DBUG_PUSH (&(argv[ix][2]));
- break;
- }
- }
- for (; ix < argc; ix++) {
- DBUG_PRINT ("args", ("argv[%d] = %s", ix, argv[ix]));
- result = factorial (atoi(argv[ix]));
- printf ("%d\n", result);
+ DBUG_ENTER ("main");
+ DBUG_PROCESS (argv[0]);
+ for (ix = 1; ix < argc && argv[ix][0] == '-'; ix++) {
+ switch (argv[ix][1]) {
+ case '#':
+ DBUG_PUSH (&(argv[ix][2]));
+ break;
}
- DBUG_RETURN (0);
}
+ for (; ix < argc; ix++) {
+ DBUG_PRINT ("args", ("argv[%d] = %s", ix, argv[ix]));
+ result = factorial (atoi(argv[ix]));
+ printf ("%d\n", result);
+ }
+ DBUG_RETURN (0);
}
diff --git a/dbug/monty.doc b/dbug/monty.doc
index 1c102e1c31e..bd4096951d2 100644
--- a/dbug/monty.doc
+++ b/dbug/monty.doc
@@ -15,6 +15,6 @@ All changes that I or other people at MySQL AB have done to all files
in the dbug library (Mainly in dbug.c, dbug_analyze.c, dbug_long.h,
dbug.h) are put in public domain, as the rest of the dbug.c library)
-To my knowledge, all code in dbug library are in public domain.
+To my knowledge, all code in dbug library is in public domain.
Michael Widenius
diff --git a/dbug/my_main.c b/dbug/my_main.c
new file mode 100644
index 00000000000..90af23b42b9
--- /dev/null
+++ b/dbug/my_main.c
@@ -0,0 +1,39 @@
+/*
+ this is modified version of the original example main.c
+ fixed so that it could compile and run in MySQL source tree
+*/
+
+#ifdef DBUG_OFF /* We are testing dbug */
+#undef DBUG_OFF
+#endif
+
+#include <my_global.h> /* This includes dbug.h */
+
+int main (argc, argv)
+int argc;
+char *argv[];
+{
+ register int result, ix;
+ extern int factorial(int);
+#if defined(HAVE_PTHREAD_INIT) && defined(THREAD)
+ pthread_init(); /* Must be called before DBUG_ENTER */
+#endif
+ my_thread_global_init();
+ {
+ DBUG_ENTER ("main");
+ DBUG_PROCESS (argv[0]);
+ for (ix = 1; ix < argc && argv[ix][0] == '-'; ix++) {
+ switch (argv[ix][1]) {
+ case '#':
+ DBUG_PUSH (&(argv[ix][2]));
+ break;
+ }
+ }
+ for (; ix < argc; ix++) {
+ DBUG_PRINT ("args", ("argv[%d] = %s", ix, argv[ix]));
+ result = factorial (atoi(argv[ix]));
+ printf ("%d\n", result);
+ }
+ DBUG_RETURN (0);
+ }
+}
diff --git a/dbug/user.r b/dbug/user.r
index e8321243962..198f88cf272 100644
--- a/dbug/user.r
+++ b/dbug/user.r
@@ -1,8 +1,13 @@
.\" @(#)user.r 1.13 10/29/86
.\"
+.\" 2004-10-29: documented features implemented since 10/29/86
+.\" formatting cleanup
+.\" - Sergei Golubchik
+.\"
.\" DBUG (Macro Debugger Package) nroff source
.\"
.\" nroff -mm user.r >user.t
+.\" groff -mm user.r >user.ps
.\"
.\" ===================================================
.\"
@@ -196,7 +201,9 @@ Figure 1 is an example of this type of primitive debugging
technique.
.DS I N
.SP 2
+\fC
.so example1.r
+\fR
.SP 2
.ll -5
.ce
@@ -222,7 +229,9 @@ C preprocessor.
Figure 2 is an example of all three techniques.
.DS I N
.SP 2
+\fC
.so example2.r
+\fR
.SP 2
.ll -5
.ce
@@ -255,7 +264,9 @@ like an arbitrary and unreasonable restriction.
Figure 3 is an example of this usage.
.DS I N
.SP 2
+\fC
.so example3.r
+\fR
.SP 2
.ll -5
.ce
@@ -281,7 +292,9 @@ program is implemented recursively.
Figure 4 is the main function for this factorial program.
.DS I N
.SP 2
+\fC
.so main.r
+\fR
.SP 2
.ll -5
.ce
@@ -346,7 +359,7 @@ All of these macros will be fully explained in subsequent sections.
To use the debugger, the factorial program is invoked with a command
line of the form:
.DS CB N
-factorial -#d:t 1 2 3
+\fCfactorial -#d:t 1 2 3
.DE
The
.B main
@@ -364,7 +377,7 @@ The factorial function is then called three times, with the arguments
Note that the DBUG_PRINT takes exactly
.B two
arguments, with the second argument (a format string and list
-of printable values) enclosed in parenthesis.
+of printable values) enclosed in parentheses.
.P
Debug control strings consist of a header, the "-#", followed
by a colon separated list of debugger arguments.
@@ -373,6 +386,7 @@ by an optional comma separated list of arguments specific
to the given flag.
Some examples are:
.DS CB N
+\fC
-#d:t:o
-#d,in,out:f,main:F:L
.DE
@@ -391,7 +405,9 @@ Note that this is not necessarily the best way to do factorials
and error conditions are ignored completely.
.DS I N
.SP 2
+\fC
.so factorial.r
+\fR
.SP 2
.ll -5
.ce
@@ -421,7 +437,7 @@ To build the factorial program on a
system, compile and
link with the command:
.DS CB N
-cc -o factorial main.c factorial.c -ldbug
+\fCcc -o factorial main.c factorial.c -ldbug
.DE
The "-ldbug" argument tells the loader to link in the
runtime support modules for the
@@ -429,18 +445,20 @@ runtime support modules for the
package.
Executing the factorial program with a command of the form:
.DS CB N
-factorial 1 2 3 4 5
+\fCfactorial 1 2 3 4 5
.DE
generates the output shown in figure 6.
.DS I N
.SP 2
+\fC
.so output1.r
+\fR
.SP 2
.ll -5
.ce
Figure 6
.ce
-factorial 1 2 3 4 5
+\fCfactorial 1 2 3 4 5
.ll +5
.SP 2
.DE
@@ -449,16 +467,18 @@ factorial 1 2 3 4 5
Function level tracing is enabled by passing the debugger
the 't' flag in the debug control string.
Figure 7 is the output resulting from the command
-"factorial\ -#t:o\ 3\ 2".
+"factorial\ -#t:o\ 2\ 3".
.DS I N
.SP 2
+\fC
.so output2.r
+\fR
.SP 2
.ll -5
.ce
Figure 7
.ce
-factorial -#t:o 3 2
+\fCfactorial -#t:o 2 3
.ll +5
.SP 2
.DE
@@ -510,7 +530,7 @@ output instead, via the 'o' flag character.
Note that no 'o' implies the default (standard error), a 'o'
with no arguments means standard output, and a 'o'
with an argument means used the named file.
-I.E, "factorial\ -#t:o,logfile\ 3\ 2" would write the trace
+i.e, "factorial\ -#t:o,logfile\ 3\ 2" would write the trace
output in "logfile".
Because of
.B UNIX
@@ -555,7 +575,7 @@ The second argument to a
.B DBUG_PRINT
macro is a standard printf style
format string and one or more arguments to print, all
-enclosed in parenthesis so that they collectively become a single macro
+enclosed in parentheses so that they collectively become a single macro
argument.
This is how variable numbers of printf arguments are supported.
Also note that no explicit newline is required at the end of the format string.
@@ -566,13 +586,15 @@ to a single macro with a huge format string.
Figure 8 shows the output for default tracing and debug.
.DS I N
.SP 2
+\fC
.so output3.r
+\fR
.SP 2
.ll -5
.ce
Figure 8
.ce
-factorial -#d:t:o 3
+\fCfactorial -#d:t:o 3
.ll +5
.SP 2
.DE
@@ -591,13 +613,15 @@ To demonstrate selection of specific macros for output, figure
the debug control string "-#d,result:o".
.DS I N
.SP 2
+\fC
.so output4.r
+\fR
.SP 2
.ll -5
.ce
Figure 9
.ce
-factorial -#d,result:o 4
+\fCfactorial -#d,result:o 4
.ll +5
.SP 2
.DE
@@ -613,13 +637,15 @@ The 'F' flag enables printing of the source file name and the 'L'
flag enables printing of the source file line number.
.DS I N
.SP 2
+\fC
.so output5.r
+\fR
.SP 2
.ll -5
.ce
Figure 10
.ce
-factorial -#d:f,factorial:F:L:o 3
+\fCfactorial -#d:f,factorial:F:L:o 3
.ll +5
.SP 2
.DE
@@ -671,7 +697,7 @@ will cause warning messages from the
.I dbug
package runtime support module.
.SP 1
-EX:\ DBUG_ENTER\ ("main");
+EX:\ \fCDBUG_ENTER\ ("main");\fR
.SP 1
.LI DBUG_RETURN\
Used at each exit point of a function containing a
@@ -693,16 +719,16 @@ DBUG_ENTER
macro, and the compiler will complain
if the macros are actually used (expanded).
.SP 1
-EX:\ DBUG_RETURN\ (value);
+EX:\ \fCDBUG_RETURN\ (value);\fR
.br
-EX:\ DBUG_VOID_RETURN;
+EX:\ \fCDBUG_VOID_RETURN;\fR
.SP 1
.LI DBUG_PROCESS\
Used to name the current process being executed.
A typical argument for this macro is "argv[0]", though
it will be perfectly happy with any other string.
.SP 1
-EX:\ DBUG_PROCESS\ (argv[0]);
+EX:\ \fCDBUG_PROCESS\ (argv[0]);\fR
.SP 1
.LI DBUG_PUSH\
Sets a new debugger state by pushing the current
@@ -720,11 +746,11 @@ The proper usage is to pass a pointer to the first character
.B after
the "-#" string.
.SP 1
-EX:\ DBUG_PUSH\ (\&(argv[i][2]));
+EX:\ \fCDBUG_PUSH\ (\&(argv[i][2]));\fR
.br
-EX:\ DBUG_PUSH\ ("d:t");
+EX:\ \fCDBUG_PUSH\ ("d:t");\fR
.br
-EX:\ DBUG_PUSH\ ("");
+EX:\ \fCDBUG_PUSH\ ("");\fR
.SP 1
.LI DBUG_POP\
Restores the previous debugger state by popping the state stack.
@@ -734,7 +760,7 @@ The
DBUG_POP
macro has no arguments.
.SP 1
-EX:\ DBUG_POP\ ();
+EX:\ \fCDBUG_POP\ ();\fR
.SP 1
.LI DBUG_FILE\
The
@@ -744,7 +770,7 @@ stream.
It is used in the same manner as the symbols "stdout" and "stderr"
in the standard I/O package.
.SP 1
-EX:\ fprintf\ (DBUG_FILE,\ "Doing my own I/O!\n");
+EX:\ \fCfprintf\ (DBUG_FILE,\ "Doing\ my\ own\ I/O!\\n");\fR
.SP 1
.LI DBUG_EXECUTE\
The DBUG_EXECUTE macro is used to execute any arbitrary C code.
@@ -754,9 +780,19 @@ This macro must be used cautiously because, like the
DBUG_PRINT
macro,
it is automatically selected by default whenever the 'd' flag has
-no argument list (I.E., a "-#d:t" control string).
+no argument list (i.e., a "-#d:t" control string).
+.SP 1
+EX:\ \fCDBUG_EXECUTE\ ("status",\ print_status\ ());\fR
+.SP 1
+.LI DBUG_EXECUTE_IF\
+Works like DBUG_EXECUTE macro, but the code is
+.B not
+executed "by default", if the keyword is not explicitly listed in
+the 'd' flag. Used to conditionally execute "dangerous" actions, e.g
+to crash the program testing how recovery works, or to introduce an
+artificial delay checking for race conditions.
.SP 1
-EX:\ DBUG_EXECUTE\ ("abort",\ abort\ ());
+EX:\ \fCDBUG_EXECUTE_IF\ ("crashme",\ abort\ ());\fR
.SP 1
.LI DBUG_N\
These macros, where N is in the range 2-5, are currently obsolete
@@ -771,22 +807,32 @@ and the corresponding argument list.
Note that the format string and argument list are all one macro argument
and
.B must
-be enclosed in parenthesis.
+be enclosed in parentheses.
.SP 1
-EX:\ DBUG_PRINT\ ("eof",\ ("end\ of\ file\ found"));
+EX:\ \fCDBUG_PRINT\ ("eof",\ ("end\ of\ file\ found"));\fR
.br
-EX:\ DBUG_PRINT\ ("type",\ ("type\ is\ %x", type));
+EX:\ \fCDBUG_PRINT\ ("type",\ ("type\ is\ %x", type));\fR
.br
-EX:\ DBUG_PRINT\ ("stp",\ ("%x\ ->\ %s", stp, stp\ ->\ name));
+EX:\ \fCDBUG_PRINT\ ("stp",\ ("%x\ ->\ %s", stp, stp\ ->\ name));\fR
+.SP 1
+.LI DBUG_DUMP\
+Used to dump a memory block in hex via the "fprintf" library function on the
+current debug stream, DBUG_FILE.
+The first argument is a debug keyword, the second is a pointer to
+a memory to dump, the third is a number of bytes to dump.
+.SP 1
+EX: \fCDBUG_DBUG\ ("net",\ packet,\ len);\fR
+.SP 1
.LI DBUG_SETJMP\
Used in place of the setjmp() function to first save the current
debugger state and then execute the standard setjmp call.
-This allows to the debugger to restore it's state when the
+This allows to the debugger to restore its state when the
DBUG_LONGJMP macro is used to invoke the standard longjmp() call.
Currently all instances of DBUG_SETJMP must occur within the
same function and at the same function nesting level.
.SP 1
-EX:\ DBUG_SETJMP\ (env);
+EX: \fCDBUG_SETJMP\ (env);\fR
+.SP 1
.LI DBUG_LONGJMP\
Used in place of the longjmp() function to first restore the
previous debugger state at the time of the last DBUG_SETJMP
@@ -797,7 +843,45 @@ It would be possible to maintain separate DBUG_SETJMP and DBUG_LONGJMP
pairs by having the debugger runtime support module use the first
argument to differentiate the pairs.
.SP 1
-EX:\ DBUG_LONGJMP\ (env,val);
+EX: \fCDBUG_LONGJMP\ (env,val);\fR
+.SP 1
+.LI DBUG_LOCK_FILE\
+Used in multi-threaded environment to lock DBUG_FILE stream.
+It can be used, for example, in functions that need to write something to a
+debug stream more than in one fprintf() call and want to ensure that no other
+thread will write something in between.
+.SP 1
+EX:\fC
+.br
+ DBUG_LOCK_FILE;
+.br
+ fprintf (DBUG_FILE, "a=[");
+.br
+ for (int i=0; i < a_length; i++)
+.br
+ fprintf (DBUG_FILE, "0x%03x ", a[i]);
+.br
+ fprintf (DBUG_FILE, "]");
+.br
+ DBUG_UNLOCK_FILE;\fR
+.SP 1
+.LI DBUG_UNLOCK_FILE\
+Unlocks DBUG_FILE stream, that was locked with a DBUG_LOCK_FILE.
+.LI DBUG_ASSERT\
+This macro just does a regular assert(). The difference is that it will be
+disabled by DBUG_OFF togeher with the
+.I dbug
+library. So there will be no need to disable asserts separately with NDEBUG.
+.SP 1
+EX:\ \fCDBUG_ASSERT(\ a\ >\ 0\ );\fR
+.SP 1
+.LI DBUG_OUTPUT\
+In multi-threaded environment disables (or enables) any
+.I dbug
+output from the current thread.
+.SP 1
+EX:\ \fCDBUG_OUTPUT(\ 0\ );\fR
+.SP 1
.LE
.SK
@@ -815,6 +899,18 @@ and the flag characters which enable or disable them.
Argument lists enclosed in '[' and ']' are optional.
.SP 2
.BL 22
+.LI a[,file]
+Redirect the debugger output stream and append it to the specified file.
+The default output stream is stderr.
+A null argument list causes output to be redirected to stdout.
+Double the colon, if you want it in the path
+.SP 1
+EX: \fCa,C::\\tmp\\log\fR
+.LI A[,file]
+Like 'a[,file]' but ensure that data are written after each write
+(this typically implies flush or close/reopen). It helps to get
+a complete log file in case of crashes. This mode is implied in
+multi-threaded environment.
.LI d[,keywords]
Enable output from macros with specified keywords.
A null list of keywords implies that all keywords are selected.
@@ -828,6 +924,14 @@ A null list of functions implies that all functions are selected.
.LI F
Mark each debugger output line with the name of the source file
containing the macro causing the output.
+.LI i
+Mark each debugger output line with the PID of the current process.
+.LI g,[functions]
+Enable profiling for the specified list of functions.
+By default profiling is enabled for all functions.
+See
+.B PROFILING\ WITH\ DBUG
+below.
.LI L
Mark each debugger output line with the source file line number of
the macro causing the output.
@@ -838,9 +942,9 @@ Sequentially number each debugger output line starting at 1.
This is useful for reference purposes when debugger output is
interspersed with program output.
.LI o[,file]
-Redirect the debugger output stream to the specified file.
-The default output stream is stderr.
-A null argument list causes output to be redirected to stdout.
+Like 'a[,file]' but overwrite old file, do not append.
+.LI O[,file]
+Like 'A[,file]' but overwrite old file, do not append.
.LI p[,processes]
Limit debugger actions to the specified processes.
A null list implies all processes.
@@ -865,6 +969,14 @@ Most useful with
.B DBUG_PUSH
macros used to temporarily alter the
debugger state.
+.LI S
+When compiled with
+.I safemalloc
+this flag forces "sanity" memory checks (for overwrites/underwrites)
+on each
+.B DBUG_ENTER
+and
+.B DBUG_RETURN.
.LI t[,N]
Enable function control flow tracing.
The maximum nesting depth is specified by N, and defaults to
@@ -872,6 +984,76 @@ The maximum nesting depth is specified by N, and defaults to
.LE
.SK
.B
+PROFILING WITH DBUG
+.R
+
+.P
+With
+.I dbug
+one can do profiling in a machine independent fashion,
+without a need for profiled version of system libraries.
+For this,
+.I dbug
+can write out a file
+called
+.B dbugmon.out
+(by default). This is an ascii file containing lines of the form:
+.DS CB N
+\fC<function-name> E <time-entered>
+<function-name> X <time-exited>
+.DE
+
+.P
+A second program (\fBanalyze\fR) reads this file, and produces a report on
+standard output.
+
+.P
+Profiling is enabled through the
+.B g
+flag. It can take a list of
+function names for which profiling is enabled. By default, it
+profiles all functions.
+
+.P
+The profile file is opened for appending. This
+is in order that one can run a program several times, and get the
+sum total of all the times, etc.
+
+.P
+An example of the report generated follows:
+.DS CB N
+\fC
+ Profile of Execution
+ Execution times are in milliseconds
+
+ Calls Time
+ ----- ----
+ Times Percentage Time Spent Percentage
+Function Called of total in Function of total Importance
+======== ====== ========== =========== ========== ==========
+factorial 5 83.33 30 100.00 8333
+main 1 16.67 0 0.00 0
+======== ====== ========== =========== ==========
+Totals 6 100.00 30 100.00
+.DE
+.P
+As you can see, it's quite self-evident. The
+.B Importance
+column is a
+metric obtained by multiplying the percentage of the calls and the percentage
+of the time. Functions with higher 'importance' benefit the most from
+being sped up.
+
+.P
+As a limitation - setjmp/longjmp, or child processes, are ignored
+for the time being. Also, profiling does not work
+in a multi-threaded environment.
+
+.P
+Profiling code is (c) Binayak Banerjee.
+
+.SK
+.B
HINTS AND MISCELLANEOUS
.R
@@ -934,4 +1116,4 @@ The most common problem is multiply allocated memory.
.\" .DE nroff dident like this. davida 900108
.CS
-
+.\" vim:filetype=nroff
diff --git a/extra/Makefile.am b/extra/Makefile.am
index aec7ad7dda5..08f3985c34c 100644
--- a/extra/Makefile.am
+++ b/extra/Makefile.am
@@ -20,6 +20,7 @@ LDADD = @CLIENT_EXTRA_LDFLAGS@ ../mysys/libmysys.a \
../dbug/libdbug.a ../strings/libmystrings.a
bin_PROGRAMS = replace comp_err perror resolveip my_print_defaults \
resolve_stack_dump mysql_waitpid
+noinst_PROGRAMS = charset2html
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/mysys/charset2html.c b/extra/charset2html.c
index 96862ff16a1..96862ff16a1 100644
--- a/mysys/charset2html.c
+++ b/extra/charset2html.c
diff --git a/extra/perror.c b/extra/perror.c
index a28626fd873..1bd4b203120 100644
--- a/extra/perror.c
+++ b/extra/perror.c
@@ -69,7 +69,7 @@ static HA_ERRORS ha_errlist[]=
{
{ 120,"Didn't find key on read or update" },
{ 121,"Duplicate key on write or update" },
- { 123,"Someone has changed the row since it was read; Update with is recoverable" },
+ { 123,"Someone has changed the row since it was read (while the table was locked to prevent it)" },
{ 124,"Wrong index given to function" },
{ 126,"Index file is crashed" },
{ 127,"Record-file is crashed" },
diff --git a/heap/_check.c b/heap/_check.c
index 233cb8cb0c5..a745aee48bf 100644
--- a/heap/_check.c
+++ b/heap/_check.c
@@ -102,9 +102,11 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
int error;
uint i,found,max_links,seek,links;
uint rec_link; /* Only used with debugging */
+ uint hash_buckets_found;
HASH_INFO *hash_info;
error=0;
+ hash_buckets_found= 0;
for (i=found=max_links=seek=0 ; i < records ; i++)
{
hash_info=hp_find_hash(&keydef->block,i);
@@ -128,21 +130,32 @@ static int check_one_key(HP_KEYDEF *keydef, uint keynr, ulong records,
found++;
}
if (links > max_links) max_links=links;
+ hash_buckets_found++;
}
}
if (found != records)
{
- DBUG_PRINT("error",("Found %ld of %ld records"));
+ DBUG_PRINT("error",("Found %ld of %ld records", found, records));
+ error=1;
+ }
+ if (keydef->hash_buckets != hash_buckets_found)
+ {
+ DBUG_PRINT("error",("Found %ld buckets, stats shows %ld buckets",
+ hash_buckets_found, keydef->hash_buckets));
error=1;
}
DBUG_PRINT("info",
- ("records: %ld seeks: %d max links: %d hitrate: %.2f",
+ ("records: %ld seeks: %d max links: %d hitrate: %.2f "
+ "buckets: %d",
records,seek,max_links,
- (float) seek / (float) (records ? records : 1)));
+ (float) seek / (float) (records ? records : 1),
+ hash_buckets_found));
if (print_status)
- printf("Key: %d records: %ld seeks: %d max links: %d hitrate: %.2f\n",
+ printf("Key: %d records: %ld seeks: %d max links: %d "
+ "hitrate: %.2f buckets: %d\n",
keynr, records, seek, max_links,
- (float) seek / (float) (records ? records : 1));
+ (float) seek / (float) (records ? records : 1),
+ hash_buckets_found);
return error;
}
diff --git a/heap/heapdef.h b/heap/heapdef.h
index 083765334ab..68d9405138f 100644
--- a/heap/heapdef.h
+++ b/heap/heapdef.h
@@ -86,7 +86,8 @@ extern ulong hp_mask(ulong hashnr,ulong buffmax,ulong maxlength);
extern void hp_movelink(HASH_INFO *pos,HASH_INFO *next_link,
HASH_INFO *newlink);
extern int hp_rec_key_cmp(HP_KEYDEF *keydef,const byte *rec1,
- const byte *rec2);
+ const byte *rec2,
+ my_bool diff_if_only_endspace_difference);
extern int hp_key_cmp(HP_KEYDEF *keydef,const byte *rec,
const byte *key);
extern void hp_make_key(HP_KEYDEF *keydef,byte *key,const byte *rec);
@@ -94,6 +95,7 @@ extern uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos);
extern uint hp_rb_key_length(HP_KEYDEF *keydef, const byte *key);
extern uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key);
+extern uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key);
extern my_bool hp_if_null_in_key(HP_KEYDEF *keyinfo, const byte *record);
extern int hp_close(register HP_INFO *info);
extern void hp_clear(HP_SHARE *info);
diff --git a/heap/hp_block.c b/heap/hp_block.c
index 6a022fb3084..f26b208b521 100644
--- a/heap/hp_block.c
+++ b/heap/hp_block.c
@@ -18,12 +18,19 @@
#include "heapdef.h"
- /* Find record according to record-position */
+/*
+ Find record according to record-position.
+
+ The record is located by factoring position number pos into (p_0, p_1, ...)
+ such that
+ pos = SUM_i(block->level_info[i].records_under_level * p_i)
+ {p_0, p_1, ...} serve as indexes to descend the blocks tree.
+*/
byte *hp_find_block(HP_BLOCK *block, ulong pos)
{
reg1 int i;
- reg3 HP_PTRS *ptr;
+ reg3 HP_PTRS *ptr; /* block base ptr */
for (i=block->levels-1, ptr=block->root ; i > 0 ; i--)
{
@@ -34,8 +41,18 @@ byte *hp_find_block(HP_BLOCK *block, ulong pos)
}
- /* get one new block-of-records. Alloc ptr to block if neaded */
- /* Interrupts are stopped to allow ha_panic in interrupts */
+/*
+ Get one new block-of-records. Alloc ptr to block if needed
+ SYNOPSIS
+ hp_get_new_block()
+ block HP_BLOCK tree-like block
+ alloc_length OUT Amount of memory allocated from the heap
+
+ Interrupts are stopped to allow ha_panic in interrupts
+ RETURN
+ 0 OK
+ 1 Out of memory
+*/
int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
{
@@ -46,6 +63,18 @@ int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
if (block->level_info[i].free_ptrs_in_block)
break;
+ /*
+ Allocate space for leaf block plus space for upper level blocks up to
+ first level that has a free slot to put the pointer.
+ In some cases we actually allocate more then we need:
+ Consider e.g. a situation where we have one level 1 block and one level 0
+ block, the level 0 block is full and this function is called. We only
+ need a leaf block in this case. Nevertheless, we will get here with i=1
+ and will also allocate sizeof(HP_PTRS) for non-leaf block and will never
+ use this space.
+ This doesn't add much overhead - with current values of sizeof(HP_PTRS)
+ and my_default_record_cache_size we get about 1/128 unused memory.
+ */
*alloc_length=sizeof(HP_PTRS)*i+block->records_in_block* block->recbuffer;
if (!(root=(HP_PTRS*) my_malloc(*alloc_length,MYF(0))))
return 1;
@@ -60,21 +89,33 @@ int hp_get_new_block(HP_BLOCK *block, ulong *alloc_length)
dont_break(); /* Dont allow SIGHUP or SIGINT */
if ((uint) i == block->levels)
{
+ /* Adding a new level on top of the existing ones. */
block->levels=i+1;
+ /*
+ Use first allocated HP_PTRS as a top-level block. Put the current
+ block tree into the first slot of a new top-level block.
+ */
block->level_info[i].free_ptrs_in_block=HP_PTRS_IN_NOD-1;
((HP_PTRS**) root)[0]= block->root;
block->root=block->level_info[i].last_blocks= root++;
}
+ /* Occupy the free slot we've found at level i */
block->level_info[i].last_blocks->
blocks[HP_PTRS_IN_NOD - block->level_info[i].free_ptrs_in_block--]=
(byte*) root;
-
+
+ /* Add a block subtree with each node having one left-most child */
for (j=i-1 ; j >0 ; j--)
{
block->level_info[j].last_blocks= root++;
block->level_info[j].last_blocks->blocks[0]=(byte*) root;
block->level_info[j].free_ptrs_in_block=HP_PTRS_IN_NOD-1;
}
+
+ /*
+ root now points to last (block->records_in_block* block->recbuffer)
+ allocated bytes. Use it as a leaf block.
+ */
block->level_info[0].last_blocks= root;
allow_break(); /* Allow SIGHUP & SIGINT */
}
diff --git a/heap/hp_clear.c b/heap/hp_clear.c
index 4440344f990..596d71ebe9c 100644
--- a/heap/hp_clear.c
+++ b/heap/hp_clear.c
@@ -97,6 +97,7 @@ void hp_clear_keys(HP_SHARE *info)
VOID(hp_free_level(block,block->levels,block->root,(byte*) 0));
block->levels=0;
block->last_allocated=0;
+ keyinfo->hash_buckets= 0;
}
}
info->index_length=0;
diff --git a/heap/hp_create.c b/heap/hp_create.c
index 02725576c8f..d296c9db28b 100644
--- a/heap/hp_create.c
+++ b/heap/hp_create.c
@@ -41,6 +41,13 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
{
HP_KEYDEF *keyinfo;
DBUG_PRINT("info",("Initializing new table"));
+
+ /*
+ We have to store sometimes byte* del_link in records,
+ so the record length should be at least sizeof(byte*)
+ */
+ set_if_bigger(reclength, sizeof (byte*));
+
for (i= key_segs= max_length= 0, keyinfo= keydef; i < keys; i++, keyinfo++)
{
bzero((char*) &keyinfo->block,sizeof(keyinfo->block));
@@ -69,9 +76,21 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
case HA_KEYTYPE_UINT24:
case HA_KEYTYPE_INT8:
keyinfo->seg[j].flag|= HA_SWAP_KEY;
+ break;
+ case HA_KEYTYPE_VARBINARY:
+ /* Case-insensitiveness is handled in coll->hash_sort */
+ keyinfo->seg[j].type= HA_KEYTYPE_VARTEXT;
+ /* fall_through */
+ case HA_KEYTYPE_VARTEXT:
+ if (!my_binary_compare(keyinfo->seg[j].charset))
+ keyinfo->flag|= HA_END_SPACE_KEY;
+ keyinfo->flag|= HA_VAR_LENGTH_KEY;
+ break;
default:
break;
}
+ if (keyinfo->seg[j].flag & HA_END_SPACE_ARE_EQUAL)
+ keyinfo->flag|= HA_END_SPACE_KEY;
}
keyinfo->length= length;
length+= keyinfo->rb_tree.size_of_element +
@@ -82,7 +101,9 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
if (keyinfo->algorithm == HA_KEY_ALG_BTREE)
{
key_segs++; /* additional HA_KEYTYPE_END segment */
- if (keyinfo->flag & HA_NULL_PART_KEY)
+ if (keyinfo->flag & HA_VAR_LENGTH_KEY)
+ keyinfo->get_key_length= hp_rb_var_key_length;
+ else if (keyinfo->flag & HA_NULL_PART_KEY)
keyinfo->get_key_length= hp_rb_null_key_length;
else
keyinfo->get_key_length= hp_rb_key_length;
@@ -128,6 +149,7 @@ int heap_create(const char *name, uint keys, HP_KEYDEF *keydef,
max_records);
keyinfo->delete_key= hp_delete_key;
keyinfo->write_key= hp_write_key;
+ keyinfo->hash_buckets= 0;
}
}
share->min_records= min_records;
diff --git a/heap/hp_delete.c b/heap/hp_delete.c
index c918cf37f05..4adefde1fe9 100644
--- a/heap/hp_delete.c
+++ b/heap/hp_delete.c
@@ -97,8 +97,8 @@ int hp_rb_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
flag Is set if we want's to correct info->current_ptr
RETURN
- 0 ok
- # error number
+ 0 Ok
+ other Error code
*/
int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
@@ -123,7 +123,7 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
while (pos->ptr_to_rec != recpos)
{
- if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
+ if (flag && !hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 0))
last_ptr=pos; /* Previous same key */
gpos=pos;
if (!(pos=pos->next_key))
@@ -151,6 +151,8 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
pos->ptr_to_rec=empty->ptr_to_rec;
pos->next_key=empty->next_key;
}
+ else
+ keyinfo->hash_buckets--;
if (empty == lastpos) /* deleted last hash key */
DBUG_RETURN (0);
@@ -187,7 +189,11 @@ int hp_delete_key(HP_INFO *info, register HP_KEYDEF *keyinfo,
}
pos3= pos; /* Link pos->next after lastpos */
}
- else pos3= 0; /* Different positions merge */
+ else
+ {
+ pos3= 0; /* Different positions merge */
+ keyinfo->hash_buckets--;
+ }
empty[0]=lastpos[0];
hp_movelink(pos3, empty, pos->next_key);
diff --git a/heap/hp_hash.c b/heap/hp_hash.c
index b54e76d79fe..7e5f92bc7b8 100644
--- a/heap/hp_hash.c
+++ b/heap/hp_hash.c
@@ -196,7 +196,18 @@ byte *hp_search_next(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *key,
}
- /* Calculate pos according to keys */
+/*
+ Calculate position number for hash value.
+ SYNOPSIS
+ hp_mask()
+ hashnr Hash value
+ buffmax Value such that
+ 2^(n-1) < maxlength <= 2^n = buffmax
+ maxlength
+
+ RETURN
+ Array index, in [0..maxlength)
+*/
ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
{
@@ -205,7 +216,12 @@ ulong hp_mask(ulong hashnr, ulong buffmax, ulong maxlength)
}
- /* Change link from pos to new_link */
+/*
+ Change
+ next_link -> ... -> X -> pos
+ to
+ next_link -> ... -> X -> newlink
+*/
void hp_movelink(HASH_INFO *pos, HASH_INFO *next_link, HASH_INFO *newlink)
{
@@ -246,14 +262,27 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
if (seg->type == HA_KEYTYPE_TEXT)
{
CHARSET_INFO *cs= seg->charset;
- uint char_length= (uint) ((uchar*) key - pos);
+ uint length= seg->length;
if (cs->mbmaxlen > 1)
{
- uint length= char_length;
+ uint char_length;
char_length= my_charpos(cs, pos, pos + length, length/cs->mbmaxlen);
- set_if_smaller(char_length, length); /* QQ: ok to remove? */
+ set_if_smaller(length, char_length);
}
- cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
+ cs->coll->hash_sort(cs, pos, length, &nr, &nr2);
+ }
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ CHARSET_INFO *cs= seg->charset;
+ uint length= uint2korr(pos);
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length;
+ char_length= my_charpos(cs, pos +2, pos +2 + length,
+ seg->length/cs->mbmaxlen);
+ set_if_smaller(length, char_length);
+ }
+ cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
}
else
{
@@ -298,6 +327,19 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
}
cs->coll->hash_sort(cs, pos, char_length, &nr, &nr2);
}
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ CHARSET_INFO *cs= seg->charset;
+ uint length= uint2korr(pos);
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length;
+ char_length= my_charpos(cs, pos + 2 , pos + 2 + length,
+ seg->length/cs->mbmaxlen);
+ set_if_smaller(length, char_length);
+ }
+ cs->coll->hash_sort(cs, pos+2, length, &nr, &nr2);
+ }
else
{
for (; pos < end ; pos++)
@@ -350,6 +392,11 @@ ulong hp_hashnr(register HP_KEYDEF *keydef, register const byte *key)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ uint length= uint2korr(pos);
+ seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
+ }
else
{
for ( ; pos < (uchar*) key ; pos++)
@@ -384,6 +431,11 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
{
seg->charset->hash_sort(seg->charset,pos,((uchar*)key)-pos,&nr,NULL);
}
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ uint length= uint2korr(pos);
+ seg->charset->hash_sort(seg->charset, pos+2, length, &nr, NULL);
+ }
else
{
for ( ; pos < end ; pos++)
@@ -399,9 +451,28 @@ ulong hp_rec_hashnr(register HP_KEYDEF *keydef, register const byte *rec)
#endif
- /* Compare keys for two records. Returns 0 if they are identical */
+/*
+ Compare keys for two records. Returns 0 if they are identical
+
+ SYNOPSIS
+ hp_rec_key_cmp()
+ keydef Key definition
+ rec1 Record to compare
+ rec2 Other record to compare
+ diff_if_only_endspace_difference
+ Different number of end space is significant
-int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
+ NOTES
+ diff_if_only_endspace_difference is used to allow us to insert
+ 'a' and 'a ' when there is an an unique key.
+
+ RETURN
+ 0 Key is identical
+ <> 0 Key differes
+*/
+
+int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2,
+ my_bool diff_if_only_endspace_difference)
{
HA_KEYSEG *seg,*endseg;
@@ -426,9 +497,9 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
{
uint char_length= seg->length / cs->mbmaxlen;
char_length1= my_charpos(cs, pos1, pos1 + seg->length, char_length);
- set_if_smaller(char_length1, seg->length); /* QQ: ok to remove? */
+ set_if_smaller(char_length1, seg->length);
char_length2= my_charpos(cs, pos2, pos2 + seg->length, char_length);
- set_if_smaller(char_length2, seg->length); /* QQ: ok to remove? */
+ set_if_smaller(char_length2, seg->length);
}
else
{
@@ -436,7 +507,30 @@ int hp_rec_key_cmp(HP_KEYDEF *keydef, const byte *rec1, const byte *rec2)
}
if (seg->charset->coll->strnncollsp(seg->charset,
pos1,char_length1,
- pos2,char_length2))
+ pos2,char_length2, 0))
+ return 1;
+ }
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ uchar *pos1= (uchar*)rec1 + seg->start;
+ uchar *pos2= (uchar*)rec2 + seg->start;
+ uint char_length1= uint2korr(pos1);
+ uint char_length2= uint2korr(pos2);
+ CHARSET_INFO *cs= seg->charset;
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length= seg->length / cs->mbmaxlen;
+ char_length1= my_charpos(cs, pos1, pos1 + char_length1, char_length);
+ set_if_smaller(char_length1, seg->length);
+ char_length2= my_charpos(cs, pos2, pos2 + char_length2, char_length);
+ set_if_smaller(char_length2, seg->length);
+ }
+
+ if (cs->coll->strnncollsp(seg->charset,
+ pos1+2, char_length1,
+ pos2+2, char_length2,
+ seg->flag & HA_END_SPACE_ARE_EQUAL ?
+ 0 : diff_if_only_endspace_difference))
return 1;
}
else
@@ -488,7 +582,31 @@ int hp_key_cmp(HP_KEYDEF *keydef, const byte *rec, const byte *key)
if (seg->charset->coll->strnncollsp(seg->charset,
(uchar*) pos, char_length_rec,
- (uchar*) key, char_length_key))
+ (uchar*) key, char_length_key, 0))
+ return 1;
+ }
+ else if (seg->type == HA_KEYTYPE_VARTEXT)
+ {
+ uchar *pos= (uchar*) rec + seg->start;
+ CHARSET_INFO *cs= seg->charset;
+ uint char_length_rec= uint2korr(pos);
+ uint char_length_key= uint2korr(key);
+
+ if (cs->mbmaxlen > 1)
+ {
+ uint char_length= seg->length / cs->mbmaxlen;
+ char_length_key= my_charpos(cs, key+2, key +2 + char_length_key,
+ char_length);
+ set_if_smaller(char_length_key, seg->length);
+ char_length_rec= my_charpos(cs, pos +2 , pos + 2 + char_length_rec,
+ char_length);
+ set_if_smaller(char_length_rec, seg->length);
+ }
+
+
+ if (cs->coll->strnncollsp(seg->charset,
+ (uchar*) pos+2, char_length_rec,
+ (uchar*) key+2, char_length_key, 0))
return 1;
}
else
@@ -525,6 +643,13 @@ void hp_make_key(HP_KEYDEF *keydef, byte *key, const byte *rec)
}
}
+#define FIX_LENGTH(cs, pos, length, char_length) \
+ do { \
+ if (length > char_length) \
+ char_length= my_charpos(cs, pos, pos+length, char_length); \
+ set_if_smaller(char_length,length); \
+ } while(0)
+
uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
const byte *rec, byte *recpos)
@@ -577,6 +702,24 @@ uint hp_rb_make_key(HP_KEYDEF *keydef, byte *key,
}
continue;
}
+
+ if (seg->flag & HA_VAR_LENGTH_PART)
+ {
+ uchar *pos= (uchar*) rec + seg->start;
+ uint length= seg->length;
+ uint tmp_length= uint2korr(pos);
+ CHARSET_INFO *cs= seg->charset;
+ char_length= length/cs->mbmaxlen;
+
+ pos+=2; /* Skip VARCHAR length */
+ set_if_smaller(length,tmp_length);
+ FIX_LENGTH(cs, pos, length, char_length);
+ store_key_length_inc(key,char_length);
+ memcpy((byte*) key,(byte*) pos,(size_t) char_length);
+ key+= char_length;
+ continue;
+ }
+
char_length= seg->length;
if (seg->charset->mbmaxlen > 1)
{
@@ -627,6 +770,23 @@ uint hp_rb_pack_key(HP_KEYDEF *keydef, uchar *key, const uchar *old,
}
continue;
}
+ if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
+ {
+ /* Length of key-part used with heap_rkey() always 2 */
+ uint tmp_length=uint2korr(old);
+ uint length= seg->length;
+ CHARSET_INFO *cs= seg->charset;
+ char_length= length/cs->mbmaxlen;
+
+ k_len-= 2+length;
+ old+= 2;
+ set_if_smaller(length,tmp_length); /* Safety */
+ FIX_LENGTH(cs, old, length, char_length);
+ store_key_length_inc(key,char_length);
+ memcpy((byte*) key, old,(size_t) char_length);
+ key+= char_length;
+ continue;
+ }
char_length= seg->length;
if (seg->charset->mbmaxlen > 1)
{
@@ -666,6 +826,27 @@ uint hp_rb_null_key_length(HP_KEYDEF *keydef, const byte *key)
return key - start_key;
}
+
+uint hp_rb_var_key_length(HP_KEYDEF *keydef, const byte *key)
+{
+ const byte *start_key= key;
+ HA_KEYSEG *seg, *endseg;
+
+ for (seg= keydef->seg, endseg= seg + keydef->keysegs; seg < endseg; seg++)
+ {
+ uint length= seg->length;
+ if (seg->null_bit && !*key++)
+ continue;
+ if (seg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
+ {
+ get_key_length(length, key);
+ }
+ key+= length;
+ }
+ return key - start_key;
+}
+
+
/*
Test if any of the key parts are NULL.
Return:
diff --git a/heap/hp_rfirst.c b/heap/hp_rfirst.c
index 1668376ed1c..85548fea212 100644
--- a/heap/hp_rfirst.c
+++ b/heap/hp_rfirst.c
@@ -52,6 +52,7 @@ int heap_rfirst(HP_INFO *info, byte *record, int inx)
my_errno=HA_ERR_END_OF_FILE;
DBUG_RETURN(my_errno);
}
+ DBUG_ASSERT(0); /* TODO fix it */
info->current_record=0;
info->current_hash_ptr=0;
info->update=HA_STATE_PREV_FOUND;
diff --git a/heap/hp_rkey.c b/heap/hp_rkey.c
index 2c23d9d721e..a88139bbdee 100644
--- a/heap/hp_rkey.c
+++ b/heap/hp_rkey.c
@@ -64,7 +64,7 @@ int heap_rkey(HP_INFO *info, byte *record, int inx, const byte *key,
info->update= 0;
DBUG_RETURN(my_errno);
}
- if (!(keyinfo->flag & HA_NOSAME))
+ if (!(keyinfo->flag & HA_NOSAME) || (keyinfo->flag & HA_END_SPACE_KEY))
memcpy(info->lastkey, key, (size_t) keyinfo->length);
}
memcpy(record, pos, (size_t) share->reclength);
diff --git a/heap/hp_update.c b/heap/hp_update.c
index 2ed0edf08de..2f4ea75f9aa 100644
--- a/heap/hp_update.c
+++ b/heap/hp_update.c
@@ -37,7 +37,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
p_lastinx= share->keydef + info->lastinx;
for (keydef= share->keydef, end= keydef + share->keys; keydef < end; keydef++)
{
- if (hp_rec_key_cmp(keydef, old, heap_new))
+ if (hp_rec_key_cmp(keydef, old, heap_new, 0))
{
if ((*keydef->delete_key)(info, keydef, old, pos, keydef == p_lastinx) ||
(*keydef->write_key)(info, keydef, heap_new, pos))
@@ -74,7 +74,7 @@ int heap_update(HP_INFO *info, const byte *old, const byte *heap_new)
}
while (keydef >= share->keydef)
{
- if (hp_rec_key_cmp(keydef, old, heap_new))
+ if (hp_rec_key_cmp(keydef, old, heap_new, 0))
{
if ((*keydef->delete_key)(info, keydef, heap_new, pos, 0) ||
(*keydef->write_key)(info, keydef, old, pos))
diff --git a/heap/hp_write.c b/heap/hp_write.c
index 3b0ec76d616..577c52a007d 100644
--- a/heap/hp_write.c
+++ b/heap/hp_write.c
@@ -36,7 +36,6 @@ int heap_write(HP_INFO *info, const byte *record)
byte *pos;
HP_SHARE *share=info->s;
DBUG_ENTER("heap_write");
-
#ifndef DBUG_OFF
if (info->mode & O_RDONLY)
{
@@ -106,7 +105,7 @@ int hp_rb_write_key(HP_INFO *info, HP_KEYDEF *keyinfo, const byte *record,
custom_arg.key_length= hp_rb_make_key(keyinfo, info->recbuf, record, recpos);
if (keyinfo->flag & HA_NOSAME)
{
- custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME;
+ custom_arg.search_flag= SEARCH_FIND | SEARCH_SAME | SEARCH_UPDATE;
keyinfo->rb_tree.flag= TREE_NO_DUPS;
}
else
@@ -160,7 +159,31 @@ static byte *next_free_record_pos(HP_SHARE *info)
block_pos*info->block.recbuffer);
}
- /* Write a hash-key to the hash-index */
+
+/*
+ Write a hash-key to the hash-index
+ SYNOPSIS
+ info Heap table info
+ keyinfo Key info
+ record Table record to added
+ recpos Memory buffer where the table record will be stored if added
+ successfully
+ NOTE
+ Hash index uses HP_BLOCK structure as a 'growable array' of HASH_INFO
+ structs. Array size == number of entries in hash index.
+ hp_mask(hp_rec_hashnr()) maps hash entries values to hash array positions.
+ If there are several hash entries with the same hash array position P,
+ they are connected in a linked list via HASH_INFO::next_key. The first
+ list element is located at position P, next elements are located at
+ positions for which there is no record that should be located at that
+ position. The order of elements in the list is arbitrary.
+
+ RETURN
+ 0 - OK
+ -1 - Out of memory
+ HA_ERR_FOUND_DUPP_KEY - Duplicate record on unique key. The record was
+ still added and the caller must call hp_delete_key for it.
+*/
int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
const byte *record, byte *recpos)
@@ -180,19 +203,54 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
DBUG_RETURN(-1); /* No more memory */
halfbuff= (long) share->blength >> 1;
pos= hp_find_hash(&keyinfo->block,(first_index=share->records-halfbuff));
-
+
+ /*
+ We're about to add one more hash array position, with hash_mask=#records.
+ The number of hash positions will change and some entries might need to
+ be relocated to the newly added position. Those entries are currently
+ members of the list that starts at #first_index position (this is
+ guaranteed by properties of hp_mask(hp_rec_hashnr(X)) mapping function)
+ At #first_index position currently there may be either:
+ a) An entry with hashnr != first_index. We don't need to move it.
+ or
+ b) A list of items with hash_mask=first_index. The list contains entries
+ of 2 types:
+ 1) entries that should be relocated to the list that starts at new
+ position we're adding ('uppper' list)
+ 2) entries that should be left in the list starting at #first_index
+ position ('lower' list)
+ */
if (pos != empty) /* If some records */
{
do
{
hashnr = hp_rec_hashnr(keyinfo, pos->ptr_to_rec);
- if (flag == 0) /* First loop; Check if ok */
+ if (flag == 0)
+ {
+ /*
+ First loop, bail out if we're dealing with case a) from above
+ comment
+ */
if (hp_mask(hashnr, share->blength, share->records) != first_index)
break;
+ }
+ /*
+ flag & LOWFIND - found a record that should be put into lower position
+ flag & LOWUSED - lower position occupied by the record
+ Same for HIGHFIND and HIGHUSED and 'upper' position
+
+ gpos - ptr to last element in lower position's list
+ gpos2 - ptr to last element in upper position's list
+
+ ptr_to_rec - ptr to last entry that should go into lower list.
+ ptr_to_rec2 - same for upper list.
+ */
if (!(hashnr & halfbuff))
- { /* Key will not move */
+ {
+ /* Key should be put into 'lower' list */
if (!(flag & LOWFIND))
{
+ /* key is the first element to go into lower position */
if (flag & HIGHFIND)
{
flag=LOWFIND | HIGHFIND;
@@ -203,16 +261,21 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
}
else
{
- flag=LOWFIND | LOWUSED; /* key isn't changed */
+ /*
+ We can only get here at first iteration: key is at 'lower'
+ position pos and should be left here.
+ */
+ flag=LOWFIND | LOWUSED;
gpos=pos;
ptr_to_rec=pos->ptr_to_rec;
}
}
else
- {
+ {
+ /* Already have another key for lower position */
if (!(flag & LOWUSED))
{
- /* Change link of previous LOW-key */
+ /* Change link of previous lower-list key */
gpos->ptr_to_rec=ptr_to_rec;
gpos->next_key=pos;
flag= (flag & HIGHFIND) | (LOWFIND | LOWUSED);
@@ -222,19 +285,21 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
}
}
else
- { /* key will be moved */
+ {
+ /* key will be put into 'higher' list */
if (!(flag & HIGHFIND))
{
flag= (flag & LOWFIND) | HIGHFIND;
/* key shall be moved to the last (empty) position */
- gpos2 = empty; empty=pos;
+ gpos2= empty;
+ empty= pos;
ptr_to_rec2=pos->ptr_to_rec;
}
else
{
if (!(flag & HIGHUSED))
{
- /* Change link of previous hash-key and save */
+ /* Change link of previous upper-list key and save */
gpos2->ptr_to_rec=ptr_to_rec2;
gpos2->next_key=pos;
flag= (flag & LOWFIND) | (HIGHFIND | HIGHUSED);
@@ -245,6 +310,15 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
}
}
while ((pos=pos->next_key));
+
+ if ((flag & (LOWFIND | HIGHFIND)) == (LOWFIND | HIGHFIND))
+ {
+ /*
+ If both 'higher' and 'lower' list have at least one element, now
+ there are two hash buckets instead of one.
+ */
+ keyinfo->hash_buckets++;
+ }
if ((flag & (LOWFIND | LOWUSED)) == LOWFIND)
{
@@ -265,6 +339,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
{
pos->ptr_to_rec=recpos;
pos->next_key=0;
+ keyinfo->hash_buckets++;
}
else
{
@@ -280,6 +355,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
}
else
{
+ keyinfo->hash_buckets++;
pos->ptr_to_rec=recpos;
pos->next_key=0;
hp_movelink(pos, gpos, empty);
@@ -293,7 +369,7 @@ int hp_write_key(HP_INFO *info, HP_KEYDEF *keyinfo,
pos=empty;
do
{
- if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec))
+ if (! hp_rec_key_cmp(keyinfo, record, pos->ptr_to_rec, 1))
{
DBUG_RETURN(my_errno=HA_ERR_FOUND_DUPP_KEY);
}
diff --git a/include/config-win.h b/include/config-win.h
index d28bb25cd09..1d54a4bf9ec 100644
--- a/include/config-win.h
+++ b/include/config-win.h
@@ -175,6 +175,8 @@ typedef uint rf_SetTimer;
#define sigset(A,B) signal((A),(B))
#define finite(A) _finite(A)
#define sleep(A) Sleep((A)*1000)
+#define popen(A) popen(A,B) _popen((A),(B))
+#define pclose(A) _pclose(A)
#ifndef __BORLANDC__
#define access(A,B) _access(A,B)
@@ -301,6 +303,9 @@ inline double ulonglong2double(ulonglong value)
#define HAVE_SETFILEPOINTER
#define HAVE_VIO
+#define HAME_MMAP /* in mysys/my_mmap.c */
+#define HAVE_GETPAGESIZE /* in mysys/my_mmap.c */
+
#ifdef NOT_USED
#define HAVE_SNPRINTF /* Gave link error */
#define _snprintf snprintf
diff --git a/include/decimal.h b/include/decimal.h
index 5b5b8c0b460..4d1fbfddc01 100644
--- a/include/decimal.h
+++ b/include/decimal.h
@@ -17,8 +17,6 @@
#ifndef _decimal_h
#define _decimal_h
-#include <my_global.h>
-
typedef enum {TRUNCATE=0, HALF_EVEN, HALF_UP, CEILING, FLOOR} decimal_round_mode;
typedef int32 decimal_digit;
@@ -51,13 +49,7 @@ int decimal_mul(decimal *from1, decimal *from2, decimal *to);
int decimal_div(decimal *from1, decimal *from2, decimal *to, int scale_incr);
int decimal_mod(decimal *from1, decimal *from2, decimal *to);
int decimal_round(decimal *from, decimal *to, int new_scale, decimal_round_mode mode);
-
-/*
- the following works only on special "zero" decimal, not on any
- decimal that happen to evaluate to zero
-*/
-
-#define decimal_is_zero(dec) ((dec)->intg1==1 && (dec)->frac1==0 && (dec)->buf[0]==0)
+int decimal_is_zero(decimal *from);
/* set a decimal to zero */
diff --git a/include/heap.h b/include/heap.h
index 63f2abbabc7..5e83a6e2cb5 100644
--- a/include/heap.h
+++ b/include/heap.h
@@ -63,18 +63,48 @@ typedef struct st_heap_ptrs
struct st_level_info
{
- uint free_ptrs_in_block,records_under_level;
- HP_PTRS *last_blocks; /* pointers to HP_PTRS or records */
+ /* Number of unused slots in *last_blocks HP_PTRS block (0 for 0th level) */
+ uint free_ptrs_in_block;
+
+ /*
+ Maximum number of records that can be 'contained' inside of each element
+ of last_blocks array. For level 0 - 1, for level 1 - HP_PTRS_IN_NOD, for
+ level 2 - HP_PTRS_IN_NOD^2 and so forth.
+ */
+ uint records_under_level;
+
+ /*
+ Ptr to last allocated HP_PTRS (or records buffer for level 0) on this
+ level.
+ */
+ HP_PTRS *last_blocks;
};
-typedef struct st_heap_block /* The data is saved in blocks */
+
+/*
+ Heap table records and hash index entries are stored in HP_BLOCKs.
+ HP_BLOCK is used as a 'growable array' of fixed-size records. Size of record
+ is recbuffer bytes.
+ The internal representation is as follows:
+ HP_BLOCK is a hierarchical structure of 'blocks'.
+ A block at level 0 is an array records_in_block records.
+ A block at higher level is an HP_PTRS structure with pointers to blocks at
+ lower levels.
+ At the highest level there is one top block. It is stored in HP_BLOCK::root.
+
+ See hp_find_block for a description of how record pointer is obtained from
+ its index.
+ See hp_get_new_block
+*/
+
+typedef struct st_heap_block
{
- HP_PTRS *root;
+ HP_PTRS *root; /* Top-level block */
struct st_level_info level_info[HP_MAX_LEVELS+1];
- uint levels;
- uint records_in_block; /* Records in a heap-block */
+ uint levels; /* number of used levels */
+ uint records_in_block; /* Records in one heap-block */
uint recbuffer; /* Length of one saved record */
- ulong last_allocated; /* Blocks allocated, used by keys */
+ ulong last_allocated; /* number of records there is allocated space for */
} HP_BLOCK;
struct st_heap_info; /* For referense */
@@ -87,6 +117,11 @@ typedef struct st_hp_keydef /* Key definition with open */
uint8 algorithm; /* HASH / BTREE */
HA_KEYSEG *seg;
HP_BLOCK block; /* Where keys are saved */
+ /*
+ Number of buckets used in hash table. Used only to provide
+ #records estimates for heap key scans.
+ */
+ ha_rows hash_buckets;
TREE rb_tree;
int (*write_key)(struct st_heap_info *info, struct st_hp_keydef *keyinfo,
const byte *record, byte *recpos);
@@ -102,7 +137,7 @@ typedef struct st_heap_share
ulong min_records,max_records; /* Params to open */
ulong data_length,index_length;
uint records; /* records */
- uint blength;
+ uint blength; /* records rounded up to 2^n */
uint deleted; /* Deleted records in database */
uint reclength; /* Length of one record */
uint changed;
diff --git a/include/m_ctype.h b/include/m_ctype.h
index ddc21070547..d7a4af08b0f 100644
--- a/include/m_ctype.h
+++ b/include/m_ctype.h
@@ -63,7 +63,7 @@ typedef struct unicase_info_st
#define MY_CS_UNICODE 128 /* is a charset is full unicode */
#define MY_CS_READY 256 /* if a charset is initialized */
#define MY_CS_AVAILABLE 512 /* If either compiled-in or loaded*/
-
+#define MY_CS_CSSORT 1024 /* if case sensitive sort order */
#define MY_CHARSET_UNDEFINED 0
@@ -106,7 +106,8 @@ typedef struct my_collation_handler_st
int (*strnncoll)(struct charset_info_st *,
const uchar *, uint, const uchar *, uint, my_bool);
int (*strnncollsp)(struct charset_info_st *,
- const uchar *, uint, const uchar *, uint);
+ const uchar *, uint, const uchar *, uint,
+ my_bool diff_if_only_endspace_difference);
int (*strnxfrm)(struct charset_info_st *,
uchar *, uint, const uchar *, uint);
my_bool (*like_range)(struct charset_info_st *,
@@ -259,7 +260,8 @@ extern int my_strnncoll_simple(CHARSET_INFO *, const uchar *, uint,
const uchar *, uint, my_bool);
extern int my_strnncollsp_simple(CHARSET_INFO *, const uchar *, uint,
- const uchar *, uint);
+ const uchar *, uint,
+ my_bool diff_if_only_endspace_difference);
extern void my_hash_sort_simple(CHARSET_INFO *cs,
const uchar *key, uint len,
diff --git a/include/my_base.h b/include/my_base.h
index 815a1c76c0e..88d3ec0b270 100644
--- a/include/my_base.h
+++ b/include/my_base.h
@@ -213,7 +213,7 @@ enum ha_base_keytype {
/*
Key has a part that can have end space. If this is an unique key
we have to handle it differently from other unique keys as we can find
- many matching rows for one key (becaue end space are not compared)
+ many matching rows for one key (because end space are not compared)
*/
#define HA_END_SPACE_KEY 4096
@@ -221,12 +221,17 @@ enum ha_base_keytype {
#define HA_SPACE_PACK 1 /* Pack space in key-seg */
#define HA_PART_KEY_SEG 4 /* Used by MySQL for part-key-cols */
-#define HA_VAR_LENGTH 8
+#define HA_VAR_LENGTH_PART 8
#define HA_NULL_PART 16
#define HA_BLOB_PART 32
#define HA_SWAP_KEY 64
#define HA_REVERSE_SORT 128 /* Sort key in reverse order */
#define HA_NO_SORT 256 /* do not bother sorting on this keyseg */
+/*
+ End space in unique/varchar are considered equal. (Like 'a' and 'a ')
+ Only needed for internal temporary tables.
+*/
+#define HA_END_SPACE_ARE_EQUAL 512
/* optionbits for database */
#define HA_OPTION_PACK_RECORD 1
@@ -345,6 +350,7 @@ enum ha_base_keytype {
#define HA_STATE_BUFF_SAVED 512 /* If current keybuff is info->buff */
#define HA_STATE_ROW_CHANGED 1024 /* To invalide ROW cache */
#define HA_STATE_EXTEND_BLOCK 2048
+#define HA_STATE_RNEXT_SAME 4096 /* rnext_same was called */
enum en_fieldtype {
FIELD_LAST=-1,FIELD_NORMAL,FIELD_SKIP_ENDSPACE,FIELD_SKIP_PRESPACE,
diff --git a/include/my_dbug.h b/include/my_dbug.h
index 9174a8b1ef9..cf32102b34b 100644
--- a/include/my_dbug.h
+++ b/include/my_dbug.h
@@ -25,6 +25,7 @@ extern int _db_on_,_no_db_;
extern FILE *_db_fp_;
extern char *_db_process_;
extern int _db_keyword_(const char *keyword);
+extern int _db_strict_keyword_(const char *keyword);
extern void _db_setjmp_(void);
extern void _db_longjmp_(void);
extern void _db_push_(const char *control);
@@ -38,6 +39,7 @@ extern void _db_pargs_(uint _line_,const char *keyword);
extern void _db_doprnt_ _VARARGS((const char *format,...));
extern void _db_dump_(uint _line_,const char *keyword,const char *memory,
uint length);
+extern void _db_output_();
extern void _db_lock_file();
extern void _db_unlock_file();
@@ -66,13 +68,17 @@ extern void _db_unlock_file();
#define DEBUGGER_ON _no_db_=0
#define DBUG_LOCK_FILE { _db_lock_file(); }
#define DBUG_UNLOCK_FILE { _db_unlock_file(); }
+#define DBUG_OUTPUT(A) { _db_output_(A); }
#define DBUG_ASSERT(A) assert(A)
+#define DBUG_EXECUTE_IF(keyword,a1) \
+ {if (_db_on_) {if (_db_strict_keyword_ (keyword)) { a1 }}}
#else /* No debugger */
#define DBUG_ENTER(a1)
#define DBUG_RETURN(a1) return(a1)
#define DBUG_VOID_RETURN return
#define DBUG_EXECUTE(keyword,a1) {}
+#define DBUG_EXECUTE_IF(keyword,a1) {}
#define DBUG_PRINT(keyword,arglist) {}
#define DBUG_PUSH(a1) {}
#define DBUG_POP() {}
@@ -86,6 +92,7 @@ extern void _db_unlock_file();
#define DEBUGGER_ON
#define DBUG_LOCK_FILE
#define DBUG_UNLOCK_FILE
+#define DBUG_OUTPUT(A)
#define DBUG_ASSERT(A) {}
#endif
#ifdef __cplusplus
diff --git a/include/my_global.h b/include/my_global.h
index 0ace3123fae..3c0266d2e71 100644
--- a/include/my_global.h
+++ b/include/my_global.h
@@ -194,10 +194,10 @@ C_MODE_END
/* Fix problem when linking c++ programs with gcc 3.x */
#ifdef DEFINE_CXA_PURE_VIRTUAL
#define FIX_GCC_LINKING_PROBLEM \
-extern "C" { int __cxa_pure_virtual() {\
+C_MODE_START int __cxa_pure_virtual() {\
DBUG_ASSERT("Pure virtual method called." == "Aborted");\
return 0;\
-} }
+} C_MODE_END
#else
#define FIX_GCC_LINKING_PROBLEM
#endif
@@ -370,6 +370,12 @@ int __void__;
#define LINT_INIT(var)
#endif
+#if defined(_lint) || defined(FORCE_INIT_OF_VARS) || defined(HAVE_purify)
+#define PURIFY_OR_LINT_INIT(var) var=0
+#else
+#define PURIFY_OR_LINT_INIT(var)
+#endif
+
/* Define some useful general macros */
#if defined(__cplusplus) && defined(__GNUC__)
#define max(a, b) ((a) >? (b))
diff --git a/include/my_handler.h b/include/my_handler.h
index 18a6234d3f6..d81c4590f8e 100644
--- a/include/my_handler.h
+++ b/include/my_handler.h
@@ -57,6 +57,13 @@ typedef struct st_HA_KEYSEG /* Key-portion */
{ length=mi_uint2korr((key)+1); (key)+=3; length_pack=3; } \
}
+#define store_key_length_inc(key,length) \
+{ if ((length) < 255) \
+ { *(key)++=(length); } \
+ else \
+ { *(key)=255; mi_int2store((key)+1,(length)); (key)+=3; } \
+}
+
extern int mi_compare_text(CHARSET_INFO *, uchar *, uint, uchar *, uint ,
my_bool, my_bool);
extern int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
diff --git a/include/my_list.h b/include/my_list.h
index 789bbb50f97..f786621e311 100644
--- a/include/my_list.h
+++ b/include/my_list.h
@@ -33,8 +33,8 @@ extern LIST *list_delete(LIST *root,LIST *element);
extern LIST *list_cons(void *data,LIST *root);
extern LIST *list_reverse(LIST *root);
extern void list_free(LIST *root,unsigned int free_data);
-extern unsigned int list_length(LIST *list);
-extern int list_walk(LIST *list,list_walk_action action,gptr argument);
+extern unsigned int list_length(LIST *);
+extern int list_walk(LIST *,list_walk_action action,gptr argument);
#define rest(a) ((a)->next)
#define list_push(a,b) (a)=list_cons((b),(a))
diff --git a/include/my_pthread.h b/include/my_pthread.h
index cd0cf49a891..b483b68d5cb 100644
--- a/include/my_pthread.h
+++ b/include/my_pthread.h
@@ -674,21 +674,42 @@ extern pthread_t shutdown_th, main_th, signal_th;
#ifndef thread_safe_increment
#ifdef HAVE_ATOMIC_ADD
-#define thread_safe_increment(V,L) atomic_add(1,(atomic_t*) &V);
-#define thread_safe_add(V,C,L) atomic_add((C),(atomic_t*) &V);
-#define thread_safe_sub(V,C,L) atomic_sub((C),(atomic_t*) &V);
+#define thread_safe_increment(V,L) atomic_inc((atomic_t*) &V)
+#define thread_safe_decrement(V,L) atomic_dec((atomic_t*) &V)
+#define thread_safe_dec_and_test(V, L) atomic_dec_and_test((atomic_t*) &V)
+#define thread_safe_add(V,C,L) atomic_add((C),(atomic_t*) &V)
+#define thread_safe_sub(V,C,L) atomic_sub((C),(atomic_t*) &V)
#else
#define thread_safe_increment(V,L) \
- pthread_mutex_lock((L)); (V)++; pthread_mutex_unlock((L));
-#define thread_safe_add(V,C,L) \
- pthread_mutex_lock((L)); (V)+=(C); pthread_mutex_unlock((L));
+ (pthread_mutex_lock((L)), (V)++, pthread_mutex_unlock((L)))
+#define thread_safe_decrement(V,L) \
+ (pthread_mutex_lock((L)), (V)--, pthread_mutex_unlock((L)))
+#define thread_safe_add(V,C,L) (pthread_mutex_lock((L)), (V)+=(C), pthread_mutex_unlock((L)))
#define thread_safe_sub(V,C,L) \
- pthread_mutex_lock((L)); (V)-=(C); pthread_mutex_unlock((L));
+ (pthread_mutex_lock((L)), (V)-=(C), pthread_mutex_unlock((L)))
+#if defined (__GNUC__) || defined (__cplusplus)
+static inline bool thread_safe_dec_and_test(ulong V, pthread_mutex_t *L)
+{
+ ulong res;
+ pthread_mutex_lock(L);
+ res=V--;
+ pthread_mutex_unlock(L);
+ return res==0;
+}
+#else
+/*
+ what should we do ? define it as static ?
+ a regular function somewhere in mysys/ ?
+ for now it's only used in c++ code, so there's no need to bother
+*/
+#endif
#endif /* HAVE_ATOMIC_ADD */
#ifdef SAFE_STATISTICS
#define statistic_increment(V,L) thread_safe_increment((V),(L))
+#define statistic_decrement(V,L) thread_safe_decrement((V),(L))
#define statistic_add(V,C,L) thread_safe_add((V),(C),(L))
#else
+#define statistic_decrement(V,L) (V)--
#define statistic_increment(V,L) (V)++
#define statistic_add(V,C,L) (V)+=(C)
#endif /* SAFE_STATISTICS */
diff --git a/include/my_sys.h b/include/my_sys.h
index e99b2d343ff..3de3ec9687c 100644
--- a/include/my_sys.h
+++ b/include/my_sys.h
@@ -138,6 +138,7 @@ extern int NEAR my_errno; /* Last error in mysys */
#define my_memdup(A,B,C) _my_memdup((A),(B), __FILE__,__LINE__,C)
#define my_strdup(A,C) _my_strdup((A), __FILE__,__LINE__,C)
#define my_strdup_with_length(A,B,C) _my_strdup_with_length((A),(B),__FILE__,__LINE__,C)
+#define TRASH(A,B) bfill(A, B, 0x8F)
#define QUICK_SAFEMALLOC sf_malloc_quick=1
#define NORMAL_SAFEMALLOC sf_malloc_quick=0
extern uint sf_malloc_prehunc,sf_malloc_endhunc,sf_malloc_quick;
@@ -164,6 +165,7 @@ extern char *my_strdup_with_length(const byte *from, uint length,
#define CALLER_INFO_PROTO /* nothing */
#define CALLER_INFO /* nothing */
#define ORIG_CALLER_INFO /* nothing */
+#define TRASH(A,B) /* nothing */
#endif
#ifdef HAVE_ALLOCA
@@ -221,6 +223,7 @@ extern ulong my_cache_w_requests, my_cache_write, my_cache_r_requests,
my_cache_read;
extern ulong my_blocks_used, my_blocks_changed;
extern ulong my_file_opened,my_stream_opened, my_tmp_file_created;
+extern uint mysys_usage_id;
extern my_bool my_init_done;
/* Point to current my_message() */
@@ -663,6 +666,8 @@ extern void radixsort_for_str_ptr(uchar* base[], uint number_of_elements,
extern qsort_t qsort2(void *base_ptr, size_t total_elems, size_t size,
qsort2_cmp cmp, void *cmp_argument);
extern qsort2_cmp get_ptr_compare(uint);
+void my_store_ptr(byte *buff, uint pack_length, my_off_t pos);
+my_off_t my_get_ptr(byte *ptr, uint pack_length);
extern int init_io_cache(IO_CACHE *info,File file,uint cachesize,
enum cache_type type,my_off_t seek_offset,
pbool use_async_io, myf cache_myflags);
@@ -772,6 +777,32 @@ void my_free_open_file_info(void);
ulonglong my_getsystime(void);
my_bool my_gethwaddr(uchar *to);
+#ifdef HAVE_MMAP
+#include <sys/mman.h>
+
+#ifndef MAP_NOSYNC
+#define MAP_NOSYNC 0
+#endif
+
+#define my_mmap(a,b,c,d,e,f) mmap(a,b,c,d,e,f)
+#define my_getpagesize() getpagesize()
+#define my_munmap(a,b) munmap(a,b)
+
+#else
+/* not a complete set of mmap() flags, but only those that nesessary */
+#define PROT_READ 1
+#define PROT_WRITE 2
+#define MAP_NOSYNC 0x800
+#define MAP_FAILED ((void *)-1)
+#define MS_SYNC 0x0000
+
+int my_getpagesize(void);
+void *my_mmap(void *, size_t, int, int, int, my_off_t);
+int my_munmap(void *, size_t);
+#endif
+
+int my_msync(int, void *, size_t, int);
+
/* character sets */
extern uint get_charset_number(const char *cs_name, uint cs_flags);
extern uint get_collation_number(const char *name);
diff --git a/include/my_time.h b/include/my_time.h
index c55eb051a1a..1635c55fdc9 100644
--- a/include/my_time.h
+++ b/include/my_time.h
@@ -64,14 +64,15 @@ void init_time(void);
my_time_t
my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap);
-void set_zero_time(MYSQL_TIME *tm);
+void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type);
/*
Required buffer length for my_time_to_str, my_date_to_str,
my_datetime_to_str and TIME_to_string functions. Note, that the
caller is still responsible to check that given TIME structure
has values in valid ranges, otherwise size of the buffer could
- be not enough.
+ be not enough. We also rely on the fact that even wrong values
+ sent using binary protocol fit in this buffer.
*/
#define MAX_DATE_STRING_REP_LENGTH 30
diff --git a/include/mysql.h b/include/mysql.h
index 87c01c9903f..0edd3873192 100644
--- a/include/mysql.h
+++ b/include/mysql.h
@@ -490,6 +490,8 @@ MYSQL_RES * STDCALL mysql_list_fields(MYSQL *mysql, const char *table,
const char *wild);
unsigned long STDCALL mysql_escape_string(char *to,const char *from,
unsigned long from_length);
+unsigned long STDCALL mysql_hex_string(char *to,const char *from,
+ unsigned long from_length);
unsigned long STDCALL mysql_real_escape_string(MYSQL *mysql,
char *to,const char *from,
unsigned long length);
@@ -653,23 +655,6 @@ typedef struct st_mysql_methods
#endif
} MYSQL_METHODS;
-#ifdef HAVE_DEPRECATED_411_API
-/* Deprecated calls (since MySQL 4.1.2) */
-
-/* Use mysql_stmt_init + mysql_stmt_prepare instead */
-MYSQL_STMT * STDCALL mysql_prepare(MYSQL * mysql, const char *query,
- unsigned long length);
-#define mysql_execute mysql_stmt_execute
-#define mysql_fetch mysql_stmt_fetch
-#define mysql_fetch_column mysql_stmt_fetch_column
-#define mysql_bind_param mysql_stmt_bind_param
-#define mysql_bind_result mysql_stmt_bind_result
-#define mysql_param_count mysql_stmt_param_count
-#define mysql_param_result mysql_stmt_param_metadata
-#define mysql_get_metadata mysql_stmt_result_metadata
-#define mysql_send_long_data mysql_stmt_send_long_data
-
-#endif /* HAVE_DEPRECATED_411_API */
MYSQL_STMT * STDCALL mysql_stmt_init(MYSQL *mysql);
int STDCALL mysql_stmt_prepare(MYSQL_STMT *stmt, const char *query,
diff --git a/include/mysql_com.h b/include/mysql_com.h
index 09ee5b22286..6a03fe90eb5 100644
--- a/include/mysql_com.h
+++ b/include/mysql_com.h
@@ -209,7 +209,7 @@ enum enum_field_types { MYSQL_TYPE_DECIMAL, MYSQL_TYPE_TINY,
MYSQL_TYPE_LONGLONG,MYSQL_TYPE_INT24,
MYSQL_TYPE_DATE, MYSQL_TYPE_TIME,
MYSQL_TYPE_DATETIME, MYSQL_TYPE_YEAR,
- MYSQL_TYPE_NEWDATE,
+ MYSQL_TYPE_NEWDATE, MYSQL_TYPE_VARCHAR,
MYSQL_TYPE_ENUM=247,
MYSQL_TYPE_SET=248,
MYSQL_TYPE_TINY_BLOB=249,
@@ -312,13 +312,7 @@ void my_net_local_init(NET *net);
void net_end(NET *net);
void net_clear(NET *net);
my_bool net_realloc(NET *net, unsigned long length);
-
-#ifndef EMBEDDED_LIBRARY /* To be removed by HF */
my_bool net_flush(NET *net);
-#else
-#define net_flush(A)
-#endif
-
my_bool my_net_write(NET *net,const char *packet,unsigned long len);
my_bool net_write_command(NET *net,unsigned char command,
const char *header, unsigned long head_len,
diff --git a/include/mysql_time.h b/include/mysql_time.h
index ec67d60dea5..5f4fc12c005 100644
--- a/include/mysql_time.h
+++ b/include/mysql_time.h
@@ -33,6 +33,18 @@ enum enum_mysql_timestamp_type
};
+/*
+ Structure which is used to represent datetime values inside MySQL.
+
+ We assume that values in this structure are normalized, i.e. year <= 9999,
+ month <= 12, day <= 31, hour <= 23, hour <= 59, hour <= 59. Many functions
+ in server such as my_system_gmt_sec() or make_time() family of functions
+ rely on this (actually now usage of make_*() family relies on a bit weaker
+ restriction). Also functions that produce MYSQL_TIME as result ensure this.
+ There is one exception to this rule though if this structure holds time
+ value (time_type == MYSQL_TIMESTAMP_TIME) days and hour member can hold
+ bigger values.
+*/
typedef struct st_mysql_time
{
unsigned int year, month, day, hour, minute, second;
diff --git a/include/mysqld_error.h b/include/mysqld_error.h
index 1e190496fde..99f126cc23d 100644
--- a/include/mysqld_error.h
+++ b/include/mysqld_error.h
@@ -12,7 +12,7 @@
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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+ Foundation, Inc., 59 Temple Placeo Suite 330, Boston, MA 02111-1307 USA */
/* Definefile for error messagenumbers */
@@ -387,4 +387,30 @@
#define ER_VIEW_NONUPD_CHECK 1368
#define ER_VIEW_CHECK_FAILED 1369
#define ER_SP_ACCESS_DENIED_ERROR 1370
-#define ER_ERROR_MESSAGES 371
+#define ER_RELAY_LOG_FAIL 1371
+#define ER_PASSWD_LENGTH 1372
+#define ER_UNKNOWN_TARGET_BINLOG 1373
+#define ER_IO_ERR_LOG_INDEX_READ 1374
+#define ER_BINLOG_PURGE_PROHIBITED 1375
+#define ER_FSEEK_FAIL 1376
+#define ER_BINLOG_PURGE_FATAL_ERR 1377
+#define ER_LOG_IN_USE 1378
+#define ER_LOG_PURGE_UNKNOWN_ERR 1379
+#define ER_RELAY_LOG_INIT 1380
+#define ER_NO_BINARY_LOGGING 1381
+#define ER_RESERVED_SYNTAX 1382
+#define ER_WSAS_FAILED 1383
+#define ER_DIFF_GROUPS_PROC 1384
+#define ER_NO_GROUP_FOR_PROC 1385
+#define ER_ORDER_WITH_PROC 1386
+#define ER_LOGING_PROHIBIT_CHANGING_OF 1387
+#define ER_NO_FILE_MAPPING 1388
+#define ER_WRONG_MAGIC 1389
+#define ER_PS_MANY_PARAM 1390
+#define ER_KEY_PART_0 1391
+#define ER_VIEW_CHECKSUM 1392
+#define ER_VIEW_MULTIUPDATE 1393
+#define ER_VIEW_NO_INSERT_FIELD_LIST 1394
+#define ER_VIEW_DELETE_MERGE_VIEW 1395
+#define ER_CANNOT_USER 1396
+#define ER_ERROR_MESSAGES 397
diff --git a/innobase/btr/btr0btr.c b/innobase/btr/btr0btr.c
index ae967e0525e..c911124e705 100644
--- a/innobase/btr/btr0btr.c
+++ b/innobase/btr/btr0btr.c
@@ -86,15 +86,6 @@ btr_page_create(
page_t* page, /* in: page to be created */
dict_tree_t* tree, /* in: index tree */
mtr_t* mtr); /* in: mtr */
-/******************************************************************
-Sets the child node file address in a node pointer. */
-UNIV_INLINE
-void
-btr_node_ptr_set_child_page_no(
-/*===========================*/
- rec_t* rec, /* in: node pointer record */
- ulint page_no, /* in: child node address */
- mtr_t* mtr); /* in: mtr */
/****************************************************************
Returns the upper level node pointer to a page. It is assumed that
mtr holds an x-latch on the tree. */
@@ -128,7 +119,10 @@ btr_page_insert_fits(
rec_t* split_rec, /* in: suggestion for first record
on upper half-page, or NULL if
tuple should be first */
- dtuple_t* tuple); /* in: tuple to insert */
+ const ulint* offsets, /* in: rec_get_offsets(
+ split_rec, cursor->index) */
+ dtuple_t* tuple, /* in: tuple to insert */
+ mem_heap_t* heap); /* in: temporary memory heap */
/******************************************************************
Gets the root node of a tree and x-latches it. */
@@ -143,11 +137,13 @@ btr_root_get(
ulint space;
ulint root_page_no;
page_t* root;
+ ibool comp = UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp;
space = dict_tree_get_space(tree);
root_page_no = dict_tree_get_page(tree);
root = btr_page_get(space, root_page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(root) == comp);
return(root);
}
@@ -194,6 +190,7 @@ btr_get_prev_user_rec(
MTR_MEMO_PAGE_S_FIX))
|| (mtr_memo_contains(mtr, buf_block_align(prev_page),
MTR_MEMO_PAGE_X_FIX)));
+ ut_a(page_is_comp(prev_page) == page_is_comp(page));
prev_rec = page_rec_get_prev(page_get_supremum_rec(prev_page));
@@ -246,6 +243,7 @@ btr_get_next_user_rec(
|| (mtr_memo_contains(mtr, buf_block_align(next_page),
MTR_MEMO_PAGE_X_FIX)));
+ ut_a(page_is_comp(next_page) == page_is_comp(page));
next_rec = page_rec_get_next(page_get_infimum_rec(next_page));
return(next_rec);
@@ -267,7 +265,8 @@ btr_page_create(
{
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
- page_create(page, mtr);
+ page_create(page, mtr,
+ UT_LIST_GET_FIRST(tree->tree_indexes)->table->comp);
buf_block_align(page)->check_index_page_at_flush = TRUE;
btr_page_set_index_id(page, tree->id, mtr);
@@ -503,20 +502,21 @@ UNIV_INLINE
void
btr_node_ptr_set_child_page_no(
/*===========================*/
- rec_t* rec, /* in: node pointer record */
- ulint page_no, /* in: child node address */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: node pointer record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint page_no,/* in: child node address */
+ mtr_t* mtr) /* in: mtr */
{
- ulint n_fields;
byte* field;
ulint len;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(0 < btr_page_get_level(buf_frame_align(rec), mtr));
-
- n_fields = rec_get_n_fields(rec);
+ ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
/* The child address is in the last field */
- field = rec_get_nth_field(rec, n_fields - 1, &len);
+ field = rec_get_nth_field(rec, offsets,
+ rec_offs_n_fields(offsets) - 1, &len);
ut_ad(len == 4);
@@ -529,16 +529,18 @@ static
page_t*
btr_node_ptr_get_child(
/*===================*/
- /* out: child page, x-latched */
- rec_t* node_ptr, /* in: node pointer */
- mtr_t* mtr) /* in: mtr */
+ /* out: child page, x-latched */
+ rec_t* node_ptr,/* in: node pointer */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ mtr_t* mtr) /* in: mtr */
{
ulint page_no;
ulint space;
page_t* page;
-
+
+ ut_ad(rec_offs_validate(node_ptr, NULL, offsets));
space = buf_frame_get_space_id(node_ptr);
- page_no = btr_node_ptr_get_child_page_no(node_ptr);
+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
@@ -564,6 +566,8 @@ btr_page_get_father_for_rec(
dtuple_t* tuple;
btr_cur_t cursor;
rec_t* node_ptr;
+ dict_index_t* index;
+ ulint* offsets;
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
@@ -576,18 +580,20 @@ btr_page_get_father_for_rec(
tuple = dict_tree_build_node_ptr(tree, user_rec, 0, heap,
btr_page_get_level(page, mtr));
+ index = UT_LIST_GET_FIRST(tree->tree_indexes);
/* In the following, we choose just any index from the tree as the
first parameter for btr_cur_search_to_nth_level. */
-
- btr_cur_search_to_nth_level(UT_LIST_GET_FIRST(tree->tree_indexes),
+
+ btr_cur_search_to_nth_level(index,
btr_page_get_level(page, mtr) + 1,
tuple, PAGE_CUR_LE,
BTR_CONT_MODIFY_TREE, &cursor, 0, mtr);
node_ptr = btr_cur_get_rec(&cursor);
+ offsets = rec_get_offsets(node_ptr, index, ULINT_UNDEFINED, heap);
- if (btr_node_ptr_get_child_page_no(node_ptr) !=
+ if (btr_node_ptr_get_child_page_no(node_ptr, offsets) !=
buf_frame_get_page_no(page)) {
fputs("InnoDB: Dump of the child page:\n", stderr);
buf_page_print(buf_frame_align(page));
@@ -595,17 +601,22 @@ btr_page_get_father_for_rec(
buf_page_print(buf_frame_align(node_ptr));
fputs("InnoDB: Corruption of an index tree: table ", stderr);
- ut_print_name(stderr, NULL,
- UT_LIST_GET_FIRST(tree->tree_indexes)->table_name);
+ ut_print_name(stderr, NULL, index->table_name);
fputs(", index ", stderr);
- ut_print_name(stderr, NULL,
- UT_LIST_GET_FIRST(tree->tree_indexes)->name);
+ ut_print_name(stderr, NULL, index->name);
fprintf(stderr, ",\n"
"InnoDB: father ptr page no %lu, child page no %lu\n",
- (ulong) btr_node_ptr_get_child_page_no(node_ptr),
+ (ulong)
+ btr_node_ptr_get_child_page_no(node_ptr, offsets),
(ulong) buf_frame_get_page_no(page));
- page_rec_print(page_rec_get_next(page_get_infimum_rec(page)));
- page_rec_print(node_ptr);
+ offsets = rec_reget_offsets(page_rec_get_next(
+ page_get_infimum_rec(page)), index,
+ offsets, ULINT_UNDEFINED, heap);
+ page_rec_print(page_rec_get_next(page_get_infimum_rec(page)),
+ offsets);
+ offsets = rec_reget_offsets(node_ptr, index, offsets,
+ ULINT_UNDEFINED, heap);
+ page_rec_print(node_ptr, offsets);
fputs(
"InnoDB: You should dump + drop + reimport the table to fix the\n"
@@ -614,7 +625,7 @@ btr_page_get_father_for_rec(
"InnoDB: forcing recovery. Then dump + drop + reimport.\n", stderr);
}
- ut_a(btr_node_ptr_get_child_page_no(node_ptr) ==
+ ut_a(btr_node_ptr_get_child_page_no(node_ptr, offsets) ==
buf_frame_get_page_no(page));
mem_heap_free(heap);
@@ -649,6 +660,7 @@ btr_create(
ulint type, /* in: type of the index */
ulint space, /* in: space where created */
dulint index_id,/* in: index id */
+ ibool comp, /* in: TRUE=compact page format */
mtr_t* mtr) /* in: mini-transaction handle */
{
ulint page_no;
@@ -716,7 +728,7 @@ btr_create(
}
/* Create a new index page on the the allocated segment page */
- page = page_create(frame, mtr);
+ page = page_create(frame, mtr, comp);
buf_block_align(page)->check_index_page_at_flush = TRUE;
/* Set the index id of the page */
@@ -821,12 +833,14 @@ static
void
btr_page_reorganize_low(
/*====================*/
- ibool recovery,/* in: TRUE if called in recovery: locks should not
- be updated, i.e., there cannot exist locks on the
- page, and a hash index should not be dropped: it
- cannot exist */
- page_t* page, /* in: page to be reorganized */
- mtr_t* mtr) /* in: mtr */
+ ibool recovery,/* in: TRUE if called in recovery:
+ locks should not be updated, i.e.,
+ there cannot exist locks on the
+ page, and a hash index should not be
+ dropped: it cannot exist */
+ page_t* page, /* in: page to be reorganized */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_t* new_page;
ulint log_mode;
@@ -841,7 +855,9 @@ btr_page_reorganize_low(
max_ins_size1 = page_get_max_insert_size_after_reorganize(page, 1);
/* Write the log record */
- mlog_write_initial_log_record(page, MLOG_PAGE_REORGANIZE, mtr);
+ mlog_open_and_write_index(mtr, page, index, index->table->comp
+ ? MLOG_COMP_PAGE_REORGANIZE
+ : MLOG_PAGE_REORGANIZE, 0);
/* Turn logging off */
log_mode = mtr_set_log_mode(mtr, MTR_LOG_NONE);
@@ -858,14 +874,14 @@ btr_page_reorganize_low(
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
- page_create(page, mtr);
+ page_create(page, mtr, index->table->comp);
buf_block_align(page)->check_index_page_at_flush = TRUE;
/* Copy the records from the temporary space to the recreated page;
do not copy the lock bits yet */
page_copy_rec_list_end_no_locks(page, new_page,
- page_get_infimum_rec(new_page), mtr);
+ page_get_infimum_rec(new_page), index, mtr);
/* Copy max trx id to recreated page */
page_set_max_trx_id(page, page_get_max_trx_id(new_page));
@@ -901,10 +917,11 @@ Reorganizes an index page. */
void
btr_page_reorganize(
/*================*/
- page_t* page, /* in: page to be reorganized */
- mtr_t* mtr) /* in: mtr */
+ page_t* page, /* in: page to be reorganized */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
- btr_page_reorganize_low(FALSE, page, mtr);
+ btr_page_reorganize_low(FALSE, page, index, mtr);
}
/***************************************************************
@@ -913,18 +930,20 @@ Parses a redo log record of reorganizing a page. */
byte*
btr_parse_page_reorganize(
/*======================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr __attribute__((unused)), /* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr __attribute__((unused)),
+ /* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
ut_ad(ptr && end_ptr);
/* The record is empty, except for the record initial part */
if (page) {
- btr_page_reorganize_low(TRUE, page, mtr);
+ btr_page_reorganize_low(TRUE, page, index, mtr);
}
return(ptr);
@@ -946,7 +965,7 @@ btr_page_empty(
/* Recreate the page: note that global data on page (possible
segment headers, next page-field, etc.) is preserved intact */
- page_create(page, mtr);
+ page_create(page, mtr, page_is_comp(page));
buf_block_align(page)->check_index_page_at_flush = TRUE;
}
@@ -1011,7 +1030,7 @@ btr_root_raise_and_insert(
/* Move the records from root to the new page */
page_move_rec_list_end(new_page, root, page_get_infimum_rec(root),
- mtr);
+ cursor->index, mtr);
/* If this is a pessimistic insert which is actually done to
perform a pessimistic update then we have stored the lock
information of the record to be inserted on the infimum of the
@@ -1031,7 +1050,7 @@ btr_root_raise_and_insert(
node_ptr = dict_tree_build_node_ptr(tree, rec, new_page_no, heap,
level);
/* Reorganize the root to get free space */
- btr_page_reorganize(root, mtr);
+ btr_page_reorganize(root, cursor->index, mtr);
page_cursor = btr_cur_get_page_cur(cursor);
@@ -1039,7 +1058,8 @@ btr_root_raise_and_insert(
page_cur_set_before_first(root, page_cursor);
- node_ptr_rec = page_cur_tuple_insert(page_cursor, node_ptr, mtr);
+ node_ptr_rec = page_cur_tuple_insert(page_cursor, node_ptr,
+ cursor->index, mtr);
ut_ad(node_ptr_rec);
@@ -1047,7 +1067,7 @@ btr_root_raise_and_insert(
as there is no lower alphabetical limit to records in the leftmost
node of a level: */
- btr_set_min_rec_mark(node_ptr_rec, mtr);
+ btr_set_min_rec_mark(node_ptr_rec, cursor->index->table->comp, mtr);
/* Free the memory heap */
mem_heap_free(heap);
@@ -1060,7 +1080,8 @@ btr_root_raise_and_insert(
ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
new_page);
/* Reposition the cursor to the child node */
- page_cur_search(new_page, tuple, PAGE_CUR_LE, page_cursor);
+ page_cur_search(new_page, cursor->index, tuple,
+ PAGE_CUR_LE, page_cursor);
/* Split the child and insert tuple */
return(btr_page_split_and_insert(cursor, tuple, mtr));
@@ -1190,11 +1211,13 @@ btr_page_get_sure_split_rec(
rec_t* rec;
rec_t* next_rec;
ulint n;
-
+ mem_heap_t* heap;
+ ulint* offsets;
+
page = btr_cur_get_page(cursor);
- insert_size = rec_get_converted_size(tuple);
- free_space = page_get_free_space_of_empty();
+ insert_size = rec_get_converted_size(cursor->index, tuple);
+ free_space = page_get_free_space_of_empty(cursor->index->table->comp);
/* free_space is now the free space of a created new page */
@@ -1208,6 +1231,9 @@ btr_page_get_sure_split_rec(
ins_rec = btr_cur_get_rec(cursor);
rec = page_get_infimum_rec(page);
+ heap = mem_heap_create(100);
+ offsets = NULL;
+
/* We start to include records to the left half, and when the
space reserved by them exceeds half of total_space, then if
the included records fit on the left page, they will be put there
@@ -1230,7 +1256,9 @@ btr_page_get_sure_split_rec(
/* Include tuple */
incl_data += insert_size;
} else {
- incl_data += rec_get_size(rec);
+ offsets = rec_reget_offsets(rec, cursor->index,
+ offsets, ULINT_UNDEFINED, heap);
+ incl_data += rec_offs_size(offsets);
}
n++;
@@ -1252,11 +1280,12 @@ btr_page_get_sure_split_rec(
next_rec = page_rec_get_next(rec);
}
if (next_rec != page_get_supremum_rec(page)) {
-
+ mem_heap_free(heap);
return(next_rec);
}
}
+ mem_heap_free(heap);
return(rec);
}
}
@@ -1275,7 +1304,10 @@ btr_page_insert_fits(
rec_t* split_rec, /* in: suggestion for first record
on upper half-page, or NULL if
tuple to be inserted should be first */
- dtuple_t* tuple) /* in: tuple to insert */
+ const ulint* offsets, /* in: rec_get_offsets(
+ split_rec, cursor->index) */
+ dtuple_t* tuple, /* in: tuple to insert */
+ mem_heap_t* heap) /* in: temporary memory heap */
{
page_t* page;
ulint insert_size;
@@ -1284,11 +1316,19 @@ btr_page_insert_fits(
ulint total_n_recs;
rec_t* rec;
rec_t* end_rec;
+ ulint* offs;
page = btr_cur_get_page(cursor);
-
- insert_size = rec_get_converted_size(tuple);
- free_space = page_get_free_space_of_empty();
+
+ ut_ad(!split_rec == !offsets);
+ ut_ad(!offsets
+ || cursor->index->table->comp == rec_offs_comp(offsets));
+ ut_ad(!offsets
+ || rec_offs_validate(split_rec, cursor->index, offsets));
+ ut_ad(page_is_comp(page) == cursor->index->table->comp);
+
+ insert_size = rec_get_converted_size(cursor->index, tuple);
+ free_space = page_get_free_space_of_empty(cursor->index->table->comp);
/* free_space is now the free space of a created new page */
@@ -1303,7 +1343,7 @@ btr_page_insert_fits(
rec = page_rec_get_next(page_get_infimum_rec(page));
end_rec = page_rec_get_next(btr_cur_get_rec(cursor));
- } else if (cmp_dtuple_rec(tuple, split_rec) >= 0) {
+ } else if (cmp_dtuple_rec(tuple, split_rec, offsets) >= 0) {
rec = page_rec_get_next(page_get_infimum_rec(page));
end_rec = split_rec;
@@ -1321,11 +1361,16 @@ btr_page_insert_fits(
return(TRUE);
}
+ offs = NULL;
+
while (rec != end_rec) {
/* In this loop we calculate the amount of reserved
space after rec is removed from page. */
- total_data -= rec_get_size(rec);
+ offs = rec_reget_offsets(rec, cursor->index, offs,
+ ULINT_UNDEFINED, heap);
+
+ total_data -= rec_offs_size(offs);
total_n_recs--;
if (total_data + page_dir_calc_reserved_space(total_n_recs)
@@ -1411,6 +1456,10 @@ btr_attach_half_pages(
MTR_MEMO_PAGE_X_FIX));
ut_ad(mtr_memo_contains(mtr, buf_block_align(new_page),
MTR_MEMO_PAGE_X_FIX));
+ ut_a(page_is_comp(page) == page_is_comp(new_page));
+
+ /* Create a memory heap where the data tuple is stored */
+ heap = mem_heap_create(100);
/* Based on split direction, decide upper and lower pages */
if (direction == FSP_DOWN) {
@@ -1426,7 +1475,12 @@ btr_attach_half_pages(
/* Replace the address of the old child node (= page) with the
address of the new lower half */
- btr_node_ptr_set_child_page_no(node_ptr, lower_page_no, mtr);
+ btr_node_ptr_set_child_page_no(node_ptr,
+ rec_get_offsets(node_ptr,
+ UT_LIST_GET_FIRST(tree->tree_indexes),
+ ULINT_UNDEFINED, heap),
+ lower_page_no, mtr);
+ mem_heap_empty(heap);
} else {
lower_page_no = buf_frame_get_page_no(page);
upper_page_no = buf_frame_get_page_no(new_page);
@@ -1434,9 +1488,6 @@ btr_attach_half_pages(
upper_page = new_page;
}
- /* Create a memory heap where the data tuple is stored */
- heap = mem_heap_create(100);
-
/* Get the level of the split pages */
level = btr_page_get_level(page, mtr);
@@ -1465,6 +1516,7 @@ btr_attach_half_pages(
if (prev_page_no != FIL_NULL) {
prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(prev_page) == page_is_comp(page));
btr_page_set_next(prev_page, lower_page_no, mtr);
}
@@ -1472,6 +1524,7 @@ btr_attach_half_pages(
if (next_page_no != FIL_NULL) {
next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(next_page) == page_is_comp(page));
btr_page_set_prev(next_page, upper_page_no, mtr);
}
@@ -1522,7 +1575,15 @@ btr_page_split_and_insert(
ibool insert_will_fit;
ulint n_iterations = 0;
rec_t* rec;
+ mem_heap_t* heap;
+ ulint n_uniq;
+ ulint* offsets;
+
+ heap = mem_heap_create(1024);
+ n_uniq = dict_index_get_n_unique_in_tree(cursor->index);
func_start:
+ mem_heap_empty(heap);
+ offsets = NULL;
tree = btr_cur_get_tree(cursor);
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
@@ -1574,9 +1635,10 @@ func_start:
first_rec = split_rec;
move_limit = split_rec;
} else {
- buf = mem_alloc(rec_get_converted_size(tuple));
+ buf = mem_alloc(rec_get_converted_size(cursor->index, tuple));
- first_rec = rec_convert_dtuple_to_rec(buf, tuple);
+ first_rec = rec_convert_dtuple_to_rec(buf,
+ cursor->index, tuple);
move_limit = page_rec_get_next(btr_cur_get_rec(cursor));
}
@@ -1593,7 +1655,16 @@ func_start:
We can then move the records after releasing the tree latch,
thus reducing the tree latch contention. */
- insert_will_fit = btr_page_insert_fits(cursor, split_rec, tuple);
+ if (split_rec) {
+ offsets = rec_reget_offsets(split_rec, cursor->index,
+ offsets, n_uniq, heap);
+
+ insert_will_fit = btr_page_insert_fits(cursor,
+ split_rec, offsets, tuple, heap);
+ } else {
+ insert_will_fit = btr_page_insert_fits(cursor,
+ NULL, NULL, tuple, heap);
+ }
if (insert_will_fit && (btr_page_get_level(page, mtr) == 0)) {
@@ -1605,7 +1676,8 @@ func_start:
if (direction == FSP_DOWN) {
/* fputs("Split left\n", stderr); */
- page_move_rec_list_start(new_page, page, move_limit, mtr);
+ page_move_rec_list_start(new_page, page, move_limit,
+ cursor->index, mtr);
left_page = new_page;
right_page = page;
@@ -1613,7 +1685,8 @@ func_start:
} else {
/* fputs("Split right\n", stderr); */
- page_move_rec_list_end(new_page, page, move_limit, mtr);
+ page_move_rec_list_end(new_page, page, move_limit,
+ cursor->index, mtr);
left_page = page;
right_page = new_page;
@@ -1626,19 +1699,25 @@ func_start:
if (split_rec == NULL) {
insert_page = right_page;
- } else if (cmp_dtuple_rec(tuple, first_rec) >= 0) {
-
- insert_page = right_page;
} else {
- insert_page = left_page;
+ offsets = rec_reget_offsets(first_rec, cursor->index,
+ offsets, n_uniq, heap);
+
+ if (cmp_dtuple_rec(tuple, first_rec, offsets) >= 0) {
+
+ insert_page = right_page;
+ } else {
+ insert_page = left_page;
+ }
}
/* 7. Reposition the cursor for insert and try insertion */
page_cursor = btr_cur_get_page_cur(cursor);
- page_cur_search(insert_page, tuple, PAGE_CUR_LE, page_cursor);
+ page_cur_search(insert_page, cursor->index, tuple,
+ PAGE_CUR_LE, page_cursor);
- rec = page_cur_tuple_insert(page_cursor, tuple, mtr);
+ rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr);
if (rec != NULL) {
/* Insert fit on the page: update the free bits for the
@@ -1650,15 +1729,17 @@ func_start:
/* fprintf(stderr, "Split and insert done %lu %lu\n",
buf_frame_get_page_no(left_page),
buf_frame_get_page_no(right_page)); */
+ mem_heap_free(heap);
return(rec);
}
/* 8. If insert did not fit, try page reorganization */
- btr_page_reorganize(insert_page, mtr);
+ btr_page_reorganize(insert_page, cursor->index, mtr);
- page_cur_search(insert_page, tuple, PAGE_CUR_LE, page_cursor);
- rec = page_cur_tuple_insert(page_cursor, tuple, mtr);
+ page_cur_search(insert_page, cursor->index, tuple,
+ PAGE_CUR_LE, page_cursor);
+ rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr);
if (rec == NULL) {
/* The insert did not fit on the page: loop back to the
@@ -1688,6 +1769,7 @@ func_start:
ut_ad(page_validate(left_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
ut_ad(page_validate(right_page, UT_LIST_GET_FIRST(tree->tree_indexes)));
+ mem_heap_free(heap);
return(rec);
}
@@ -1721,6 +1803,7 @@ btr_level_list_remove(
if (prev_page_no != FIL_NULL) {
prev_page = btr_page_get(space, prev_page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(prev_page) == page_is_comp(page));
btr_page_set_next(prev_page, next_page_no, mtr);
}
@@ -1728,6 +1811,7 @@ btr_level_list_remove(
if (next_page_no != FIL_NULL) {
next_page = btr_page_get(space, next_page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(next_page) == page_is_comp(page));
btr_page_set_prev(next_page, prev_page_no, mtr);
}
@@ -1741,9 +1825,11 @@ void
btr_set_min_rec_mark_log(
/*=====================*/
rec_t* rec, /* in: record */
+ ibool comp, /* TRUE=compact record format */
mtr_t* mtr) /* in: mtr */
{
- mlog_write_initial_log_record(rec, MLOG_REC_MIN_MARK, mtr);
+ mlog_write_initial_log_record(rec,
+ comp ? MLOG_COMP_REC_MIN_MARK : MLOG_REC_MIN_MARK, mtr);
/* Write rec offset as a 2-byte ulint */
mlog_catenate_ulint(mtr, rec - buf_frame_align(rec), MLOG_2BYTES);
@@ -1759,6 +1845,7 @@ btr_parse_set_min_rec_mark(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
+ ibool comp, /* in: TRUE=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -1772,7 +1859,7 @@ btr_parse_set_min_rec_mark(
if (page) {
rec = page + mach_read_from_2(ptr);
- btr_set_min_rec_mark(rec, mtr);
+ btr_set_min_rec_mark(rec, comp, mtr);
}
return(ptr + 2);
@@ -1785,15 +1872,16 @@ void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
+ ibool comp, /* in: TRUE=compact page format */
mtr_t* mtr) /* in: mtr */
{
ulint info_bits;
- info_bits = rec_get_info_bits(rec);
+ info_bits = rec_get_info_bits(rec, comp);
- rec_set_info_bits(rec, info_bits | REC_INFO_MIN_REC_FLAG);
+ rec_set_info_bits(rec, comp, info_bits | REC_INFO_MIN_REC_FLAG);
- btr_set_min_rec_mark_log(rec, mtr);
+ btr_set_min_rec_mark_log(rec, comp, mtr);
}
/*****************************************************************
@@ -1842,18 +1930,19 @@ btr_lift_page_up(
record from the page should be removed */
mtr_t* mtr) /* in: mtr */
{
- rec_t* node_ptr;
- page_t* father_page;
- ulint page_level;
-
+ page_t* father_page;
+ ulint page_level;
+ dict_index_t* index;
+
ut_ad(btr_page_get_prev(page, mtr) == FIL_NULL);
ut_ad(btr_page_get_next(page, mtr) == FIL_NULL);
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
- node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
- father_page = buf_frame_align(node_ptr);
+ father_page = buf_frame_align(
+ btr_page_get_father_node_ptr(tree, page, mtr));
page_level = btr_page_get_level(page, mtr);
+ index = UT_LIST_GET_FIRST(tree->tree_indexes);
btr_search_drop_page_hash_index(page);
@@ -1862,7 +1951,7 @@ btr_lift_page_up(
/* Move records to the father */
page_copy_rec_list_end(father_page, page, page_get_infimum_rec(page),
- mtr);
+ index, mtr);
lock_update_copy_and_discard(father_page, page);
btr_page_set_level(father_page, page_level, mtr);
@@ -1871,10 +1960,8 @@ btr_lift_page_up(
btr_page_free(tree, page, mtr);
/* We play safe and reset the free bits for the father */
- ibuf_reset_free_bits(UT_LIST_GET_FIRST(tree->tree_indexes),
- father_page);
- ut_ad(page_validate(father_page,
- UT_LIST_GET_FIRST(tree->tree_indexes)));
+ ibuf_reset_free_bits(index, father_page);
+ ut_ad(page_validate(father_page, index));
ut_ad(btr_check_node_ptr(tree, father_page, mtr));
}
@@ -1914,9 +2001,11 @@ btr_compress(
ulint max_ins_size;
ulint max_ins_size_reorg;
ulint level;
-
+ ibool comp = cursor->index->table->comp;
+
page = btr_cur_get_page(cursor);
tree = btr_cur_get_tree(cursor);
+ ut_a(comp == page_is_comp(page));
ut_ad(mtr_memo_contains(mtr, dict_tree_get_lock(tree),
MTR_MEMO_X_LOCK));
@@ -1932,7 +2021,9 @@ btr_compress(
right_page_no); */
node_ptr = btr_page_get_father_node_ptr(tree, page, mtr);
+ ut_ad(!comp || rec_get_status(node_ptr) == REC_STATUS_NODE_PTR);
father_page = buf_frame_align(node_ptr);
+ ut_a(comp == page_is_comp(father_page));
/* Decide the page to which we try to merge and which will inherit
the locks */
@@ -1957,6 +2048,7 @@ btr_compress(
n_recs = page_get_n_recs(page);
data_size = page_get_data_size(page);
+ ut_a(page_is_comp(merge_page) == page_is_comp(page));
max_ins_size_reorg = page_get_max_insert_size_after_reorganize(
merge_page, n_recs);
@@ -1975,7 +2067,7 @@ btr_compress(
/* We have to reorganize merge_page */
- btr_page_reorganize(merge_page, mtr);
+ btr_page_reorganize(merge_page, cursor->index, mtr);
max_ins_size = page_get_max_insert_size(merge_page, n_recs);
@@ -1999,11 +2091,14 @@ btr_compress(
if (is_left) {
btr_node_ptr_delete(tree, page, mtr);
} else {
+ mem_heap_t* heap = mem_heap_create(100);
/* Replace the address of the old child node (= page) with the
address of the merge page to the right */
- btr_node_ptr_set_child_page_no(node_ptr, right_page_no, mtr);
-
+ btr_node_ptr_set_child_page_no(node_ptr,
+ rec_get_offsets(node_ptr, cursor->index,
+ ULINT_UNDEFINED, heap), right_page_no, mtr);
+ mem_heap_free(heap);
btr_node_ptr_delete(tree, merge_page, mtr);
}
@@ -2012,14 +2107,14 @@ btr_compress(
orig_pred = page_rec_get_prev(
page_get_supremum_rec(merge_page));
page_copy_rec_list_start(merge_page, page,
- page_get_supremum_rec(page), mtr);
+ page_get_supremum_rec(page), cursor->index, mtr);
lock_update_merge_left(merge_page, orig_pred, page);
} else {
orig_succ = page_rec_get_next(
page_get_infimum_rec(merge_page));
page_copy_rec_list_end(merge_page, page,
- page_get_infimum_rec(page), mtr);
+ page_get_infimum_rec(page), cursor->index, mtr);
lock_update_merge_right(orig_succ, page);
}
@@ -2133,6 +2228,7 @@ btr_discard_page(
return;
}
+ ut_a(page_is_comp(merge_page) == page_is_comp(page));
btr_search_drop_page_hash_index(page);
if (left_page_no == FIL_NULL && btr_page_get_level(page, mtr) > 0) {
@@ -2144,7 +2240,8 @@ btr_discard_page(
ut_ad(node_ptr != page_get_supremum_rec(merge_page));
- btr_set_min_rec_mark(node_ptr, mtr);
+ btr_set_min_rec_mark(node_ptr,
+ cursor->index->table->comp, mtr);
}
btr_node_ptr_delete(tree, page, mtr);
@@ -2215,6 +2312,8 @@ btr_print_recursive(
page_t* page, /* in: index page */
ulint width, /* in: print this many entries from start
and end */
+ mem_heap_t* heap, /* in: heap for rec_reget_offsets() */
+ ulint** offsets,/* in/out: buffer for rec_reget_offsets() */
mtr_t* mtr) /* in: mtr */
{
page_cur_t cursor;
@@ -2223,14 +2322,16 @@ btr_print_recursive(
mtr_t mtr2;
rec_t* node_ptr;
page_t* child;
-
+ dict_index_t* index;
+
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
fprintf(stderr, "NODE ON LEVEL %lu page number %lu\n",
(ulong) btr_page_get_level(page, mtr),
(ulong) buf_frame_get_page_no(page));
- page_print(page, width, width);
+ index = UT_LIST_GET_FIRST(tree->tree_indexes);
+ page_print(page, index, width, width);
n_recs = page_get_n_recs(page);
@@ -2249,15 +2350,20 @@ btr_print_recursive(
node_ptr = page_cur_get_rec(&cursor);
- child = btr_node_ptr_get_child(node_ptr, &mtr2);
-
- btr_print_recursive(tree, child, width, &mtr2);
+ *offsets = rec_reget_offsets(node_ptr, index,
+ *offsets, ULINT_UNDEFINED, heap);
+ child = btr_node_ptr_get_child(node_ptr,
+ *offsets, &mtr2);
+ btr_print_recursive(tree, child, width,
+ heap, offsets, &mtr2);
mtr_commit(&mtr2);
}
page_cur_move_to_next(&cursor);
i++;
}
+
+ mem_heap_free(heap);
}
/******************************************************************
@@ -2270,8 +2376,10 @@ btr_print_tree(
ulint width) /* in: print this many entries from start
and end */
{
- mtr_t mtr;
- page_t* root;
+ mtr_t mtr;
+ page_t* root;
+ mem_heap_t* heap = mem_heap_create(100);
+ ulint* offsets = NULL;
fputs("--------------------------\n"
"INDEX TREE PRINT\n", stderr);
@@ -2280,7 +2388,8 @@ btr_print_tree(
root = btr_root_get(tree, &mtr);
- btr_print_recursive(tree, root, width, &mtr);
+ btr_print_recursive(tree, root, width, heap, &offsets, &mtr);
+ mem_heap_free(heap);
mtr_commit(&mtr);
@@ -2323,7 +2432,10 @@ btr_check_node_ptr(
page_rec_get_next(page_get_infimum_rec(page)),
0, heap, btr_page_get_level(page, mtr));
- ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr) == 0);
+ ut_a(cmp_dtuple_rec(node_ptr_tuple, node_ptr,
+ rec_get_offsets(node_ptr,
+ dict_tree_find_index(tree, node_ptr),
+ ULINT_UNDEFINED, heap)) == 0);
mem_heap_free(heap);
@@ -2360,10 +2472,12 @@ btr_index_rec_validate(
should print hex dump of record
and page on error */
{
- ulint len;
- ulint n;
- ulint i;
- page_t* page;
+ ulint len;
+ ulint n;
+ ulint i;
+ page_t* page;
+ mem_heap_t* heap;
+ ulint* offsets;
page = buf_frame_align(rec);
@@ -2377,10 +2491,10 @@ btr_index_rec_validate(
n = dict_index_get_n_fields(index);
- if (rec_get_n_fields(rec) != n) {
+ if (!index->table->comp && rec_get_n_fields_old(rec) != n) {
btr_index_rec_validate_report(page, rec, index);
fprintf(stderr, "InnoDB: has %lu fields, should have %lu\n",
- (ulong) rec_get_n_fields(rec), (ulong) n);
+ (ulong) rec_get_n_fields_old(rec), (ulong) n);
if (!dump_on_error) {
@@ -2390,23 +2504,27 @@ btr_index_rec_validate(
buf_page_print(page);
fputs("InnoDB: corrupt record ", stderr);
- rec_print(stderr, rec);
+ rec_print_old(stderr, rec);
putc('\n', stderr);
return(FALSE);
}
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
for (i = 0; i < n; i++) {
dtype_t* type = dict_index_get_nth_type(index, i);
+ ulint fixed_size = dtype_get_fixed_size(type);
- rec_get_nth_field(rec, i, &len);
+ rec_get_nth_field(rec, offsets, i, &len);
/* Note that prefix indexes are not fixed size even when
their type is CHAR. */
if ((dict_index_get_nth_field(index, i)->prefix_len == 0
- && len != UNIV_SQL_NULL && dtype_is_fixed_size(type)
- && len != dtype_get_fixed_size(type))
+ && len != UNIV_SQL_NULL && fixed_size
+ && len != fixed_size)
||
(dict_index_get_nth_field(index, i)->prefix_len > 0
&& len != UNIV_SQL_NULL
@@ -2419,20 +2537,22 @@ btr_index_rec_validate(
(ulong) i, (ulong) len, (ulong) dtype_get_fixed_size(type));
if (!dump_on_error) {
-
+ mem_heap_free(heap);
return(FALSE);
}
buf_page_print(page);
fputs("InnoDB: corrupt record ", stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, offsets);
putc('\n', stderr);
+ mem_heap_free(heap);
return(FALSE);
}
}
+ mem_heap_free(heap);
return(TRUE);
}
@@ -2527,15 +2647,18 @@ btr_validate_level(
page_t* right_father_page;
rec_t* node_ptr;
rec_t* right_node_ptr;
+ rec_t* rec;
ulint right_page_no;
ulint left_page_no;
page_cur_t cursor;
- mem_heap_t* heap;
dtuple_t* node_ptr_tuple;
ibool ret = TRUE;
dict_index_t* index;
mtr_t mtr;
-
+ mem_heap_t* heap = mem_heap_create(256);
+ ulint* offsets = NULL;
+ ulint* offsets2= NULL;
+
mtr_start(&mtr);
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
@@ -2544,6 +2667,8 @@ btr_validate_level(
space = buf_frame_get_space_id(page);
+ index = UT_LIST_GET_FIRST(tree->tree_indexes);
+
while (level != btr_page_get_level(page, &mtr)) {
ut_a(btr_page_get_level(page, &mtr) > 0);
@@ -2552,14 +2677,16 @@ btr_validate_level(
page_cur_move_to_next(&cursor);
node_ptr = page_cur_get_rec(&cursor);
- page = btr_node_ptr_get_child(node_ptr, &mtr);
+ offsets = rec_reget_offsets(node_ptr, index,
+ offsets, ULINT_UNDEFINED, heap);
+ page = btr_node_ptr_get_child(node_ptr, offsets, &mtr);
}
- index = UT_LIST_GET_FIRST(tree->tree_indexes);
-
/* Now we are on the desired level. Loop through the pages on that
level. */
loop:
+ mem_heap_empty(heap);
+ offsets = offsets2 = NULL;
mtr_x_lock(dict_tree_get_lock(tree), &mtr);
/* Check ordering etc. of records */
@@ -2588,12 +2715,20 @@ loop:
(buf_frame_get_page_no(page) == dict_tree_get_page(tree))));
if (right_page_no != FIL_NULL) {
-
+ rec_t* right_rec;
right_page = btr_page_get(space, right_page_no, RW_X_LATCH,
&mtr);
- if (cmp_rec_rec(page_rec_get_prev(page_get_supremum_rec(page)),
- page_rec_get_next(page_get_infimum_rec(right_page)),
- UT_LIST_GET_FIRST(tree->tree_indexes)) >= 0) {
+ ut_a(page_is_comp(right_page) == page_is_comp(page));
+ rec = page_rec_get_prev(page_get_supremum_rec(page));
+ right_rec = page_rec_get_next(
+ page_get_infimum_rec(right_page));
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ offsets2 = rec_reget_offsets(right_rec, index,
+ offsets2, ULINT_UNDEFINED, heap);
+ if (cmp_rec_rec(rec, right_rec, offsets, offsets2,
+ dict_index_get_n_fields(index),
+ index) >= 0) {
btr_validate_report2(index, level, page, right_page);
@@ -2604,12 +2739,17 @@ loop:
buf_page_print(right_page);
fputs("InnoDB: record ", stderr);
- rec_print(stderr, page_rec_get_prev(
- page_get_supremum_rec(page)));
+ rec = page_rec_get_prev(page_get_supremum_rec(page));
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ rec_print(stderr, rec, offsets);
putc('\n', stderr);
fputs("InnoDB: record ", stderr);
- rec_print(stderr, page_rec_get_next(
- page_get_infimum_rec(right_page)));
+ rec = page_rec_get_next(page_get_infimum_rec(
+ right_page));
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ rec_print(stderr, rec, offsets);
putc('\n', stderr);
ret = FALSE;
@@ -2618,7 +2758,8 @@ loop:
if (level > 0 && left_page_no == FIL_NULL) {
ut_a(REC_INFO_MIN_REC_FLAG & rec_get_info_bits(
- page_rec_get_next(page_get_infimum_rec(page))));
+ page_rec_get_next(page_get_infimum_rec(page)),
+ index->table->comp));
}
if (buf_frame_get_page_no(page) != dict_tree_get_page(tree)) {
@@ -2627,12 +2768,14 @@ loop:
node_ptr = btr_page_get_father_node_ptr(tree, page, &mtr);
father_page = buf_frame_align(node_ptr);
+ offsets = rec_reget_offsets(node_ptr, index,
+ offsets, ULINT_UNDEFINED, heap);
- if (btr_node_ptr_get_child_page_no(node_ptr) !=
+ if (btr_node_ptr_get_child_page_no(node_ptr, offsets) !=
buf_frame_get_page_no(page)
|| node_ptr != btr_page_get_father_for_rec(tree, page,
- page_rec_get_prev(page_get_supremum_rec(page)),
- &mtr)) {
+ page_rec_get_prev(page_get_supremum_rec(page)),
+ &mtr)) {
btr_validate_report1(index, level, page);
fputs("InnoDB: node pointer to the page is wrong\n",
@@ -2642,17 +2785,20 @@ loop:
buf_page_print(page);
fputs("InnoDB: node ptr ", stderr);
- rec_print(stderr, node_ptr);
+ rec_print(stderr, node_ptr, offsets);
fprintf(stderr, "\n"
"InnoDB: node ptr child page n:o %lu\n",
- (unsigned long) btr_node_ptr_get_child_page_no(node_ptr));
+ (unsigned long) btr_node_ptr_get_child_page_no(
+ node_ptr, offsets));
fputs("InnoDB: record on page ", stderr);
- rec_print(stderr,
- btr_page_get_father_for_rec(tree, page,
- page_rec_get_prev(page_get_supremum_rec(page)),
- &mtr));
+ rec = btr_page_get_father_for_rec(tree, page,
+ page_rec_get_prev(page_get_supremum_rec(page)),
+ &mtr);
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ rec_print(stderr, rec, offsets);
putc('\n', stderr);
ret = FALSE;
@@ -2660,7 +2806,8 @@ loop:
}
if (btr_page_get_level(page, &mtr) > 0) {
- heap = mem_heap_create(256);
+ offsets = rec_reget_offsets(node_ptr, index,
+ offsets, ULINT_UNDEFINED, heap);
node_ptr_tuple = dict_tree_build_node_ptr(
tree,
@@ -2669,7 +2816,10 @@ loop:
0, heap,
btr_page_get_level(page, &mtr));
- if (cmp_dtuple_rec(node_ptr_tuple, node_ptr) != 0) {
+ if (cmp_dtuple_rec(node_ptr_tuple, node_ptr,
+ offsets)) {
+ rec_t* first_rec = page_rec_get_next(
+ page_get_infimum_rec(page));
btr_validate_report1(index, level, page);
@@ -2679,18 +2829,16 @@ loop:
fputs("InnoDB: Error: node ptrs differ"
" on levels > 0\n"
"InnoDB: node ptr ", stderr);
- rec_print(stderr, node_ptr);
+ rec_print(stderr, node_ptr, offsets);
fputs("InnoDB: first rec ", stderr);
- rec_print(stderr, page_rec_get_next(
- page_get_infimum_rec(page)));
+ offsets = rec_reget_offsets(first_rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ rec_print(stderr, first_rec, offsets);
putc('\n', stderr);
ret = FALSE;
- mem_heap_free(heap);
goto node_ptr_fails;
}
-
- mem_heap_free(heap);
}
if (left_page_no == FIL_NULL) {
@@ -2701,7 +2849,7 @@ loop:
if (right_page_no == FIL_NULL) {
ut_a(node_ptr == page_rec_get_prev(
- page_get_supremum_rec(father_page)));
+ page_get_supremum_rec(father_page)));
ut_a(btr_page_get_next(father_page, &mtr) == FIL_NULL);
}
@@ -2771,13 +2919,16 @@ node_ptr_fails:
mtr_commit(&mtr);
if (right_page_no != FIL_NULL) {
+ ibool comp = page_is_comp(page);
mtr_start(&mtr);
page = btr_page_get(space, right_page_no, RW_X_LATCH, &mtr);
+ ut_a(page_is_comp(page) == comp);
goto loop;
}
+ mem_heap_free(heap);
return(ret);
}
diff --git a/innobase/btr/btr0cur.c b/innobase/btr/btr0cur.c
index 48de5644908..f5e146172ed 100644
--- a/innobase/btr/btr0cur.c
+++ b/innobase/btr/btr0cur.c
@@ -73,8 +73,9 @@ static
void
btr_cur_unmark_extern_fields(
/*=========================*/
- rec_t* rec, /* in: record in a clustered index */
- mtr_t* mtr); /* in: mtr */
+ rec_t* rec, /* in: record in a clustered index */
+ mtr_t* mtr, /* in: mtr */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/***********************************************************************
Adds path information to the cursor for the current page, for which
the binary search has been performed. */
@@ -96,6 +97,7 @@ btr_rec_free_updated_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree MUST be
X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update, /* in: update vector */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
@@ -108,9 +110,10 @@ static
ulint
btr_rec_get_externally_stored_len(
/*==============================*/
- /* out: externally stored part, in units of a
- database page */
- rec_t* rec); /* in: record */
+ /* out: externally stored part,
+ in units of a database page */
+ rec_t* rec, /* in: record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*==================== B-TREE SEARCH =========================*/
@@ -137,11 +140,13 @@ btr_cur_latch_leaves(
if (latch_mode == BTR_SEARCH_LEAF) {
get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else if (latch_mode == BTR_MODIFY_LEAF) {
get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else if (latch_mode == BTR_MODIFY_TREE) {
@@ -152,11 +157,13 @@ btr_cur_latch_leaves(
if (left_page_no != FIL_NULL) {
get_page = btr_page_get(space, left_page_no,
RW_X_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush =
TRUE;
}
get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
right_page_no = btr_page_get_next(page, mtr);
@@ -176,11 +183,14 @@ btr_cur_latch_leaves(
if (left_page_no != FIL_NULL) {
cursor->left_page = btr_page_get(space, left_page_no,
RW_S_LATCH, mtr);
+ ut_a(page_is_comp(cursor->left_page) ==
+ page_is_comp(page));
buf_block_align(
cursor->left_page)->check_index_page_at_flush = TRUE;
}
get_page = btr_page_get(space, page_no, RW_S_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else if (latch_mode == BTR_MODIFY_PREV) {
@@ -191,11 +201,14 @@ btr_cur_latch_leaves(
if (left_page_no != FIL_NULL) {
cursor->left_page = btr_page_get(space, left_page_no,
RW_X_LATCH, mtr);
+ ut_a(page_is_comp(cursor->left_page) ==
+ page_is_comp(page));
buf_block_align(
cursor->left_page)->check_index_page_at_flush = TRUE;
}
get_page = btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(get_page) == page_is_comp(page));
buf_block_align(get_page)->check_index_page_at_flush = TRUE;
} else {
ut_error;
@@ -261,6 +274,8 @@ btr_cur_search_to_nth_level(
#ifdef BTR_CUR_ADAPT
btr_search_t* info;
#endif
+ mem_heap_t* heap;
+ ulint* offsets;
/* Currently, PAGE_CUR_LE is the only search mode used for searches
ending to upper levels */
@@ -379,7 +394,9 @@ btr_cur_search_to_nth_level(
page_mode = mode;
break;
}
-
+
+ heap = mem_heap_create(100);
+ offsets = NULL;
/* Loop and search until we arrive at the desired level */
for (;;) {
@@ -414,7 +431,7 @@ retry_page_get:
cursor->thr)) {
/* Insertion to the insert buffer succeeded */
cursor->flag = BTR_CUR_INSERT_TO_IBUF;
-
+ mem_heap_free(heap);
return;
}
@@ -470,9 +487,9 @@ retry_page_get:
page_mode = mode;
}
- page_cur_search_with_match(page, tuple, page_mode, &up_match,
- &up_bytes, &low_match, &low_bytes,
- page_cursor);
+ page_cur_search_with_match(page, index, tuple, page_mode,
+ &up_match, &up_bytes,
+ &low_match, &low_bytes, page_cursor);
if (estimate) {
btr_cur_add_path_info(cursor, height, root_height);
}
@@ -486,7 +503,9 @@ retry_page_get:
if (level > 0) {
/* x-latch the page */
- btr_page_get(space, page_no, RW_X_LATCH, mtr);
+ ut_a(page_is_comp(btr_page_get(space,
+ page_no, RW_X_LATCH, mtr))
+ == index->table->comp);
}
break;
@@ -498,11 +517,14 @@ retry_page_get:
guess = NULL;
node_ptr = page_cur_get_rec(page_cursor);
-
+ offsets = rec_reget_offsets(node_ptr, cursor->index,
+ offsets, ULINT_UNDEFINED, heap);
/* Go to the child node */
- page_no = btr_node_ptr_get_child_page_no(node_ptr);
+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
}
+ mem_heap_free(heap);
+
if (level == 0) {
cursor->low_match = low_match;
cursor->low_bytes = low_bytes;
@@ -552,6 +574,8 @@ btr_cur_open_at_index_side(
rec_t* node_ptr;
ulint estimate;
ulint savepoint;
+ mem_heap_t* heap;
+ ulint* offsets = NULL;
estimate = latch_mode & BTR_ESTIMATE;
latch_mode = latch_mode & ~BTR_ESTIMATE;
@@ -576,7 +600,8 @@ btr_cur_open_at_index_side(
page_no = dict_tree_get_page(tree);
height = ULINT_UNDEFINED;
-
+ heap = mem_heap_create(100);
+
for (;;) {
page = buf_page_get_gen(space, page_no, RW_NO_LATCH, NULL,
BUF_GET,
@@ -645,10 +670,13 @@ btr_cur_open_at_index_side(
height--;
node_ptr = page_cur_get_rec(page_cursor);
-
+ offsets = rec_reget_offsets(node_ptr, cursor->index,
+ offsets, ULINT_UNDEFINED, heap);
/* Go to the child node */
- page_no = btr_node_ptr_get_child_page_no(node_ptr);
+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
}
+
+ mem_heap_free(heap);
}
/**************************************************************************
@@ -669,6 +697,8 @@ btr_cur_open_at_rnd_pos(
ulint space;
ulint height;
rec_t* node_ptr;
+ mem_heap_t* heap = mem_heap_create(100);
+ ulint* offsets = NULL;
tree = index->tree;
@@ -717,10 +747,13 @@ btr_cur_open_at_rnd_pos(
height--;
node_ptr = page_cur_get_rec(page_cursor);
-
+ offsets = rec_reget_offsets(node_ptr, cursor->index,
+ offsets, ULINT_UNDEFINED, heap);
/* Go to the child node */
- page_no = btr_node_ptr_get_child_page_no(node_ptr);
+ page_no = btr_node_ptr_get_child_page_no(node_ptr, offsets);
}
+
+ mem_heap_free(heap);
}
/*==================== B-TREE INSERT =========================*/
@@ -758,18 +791,20 @@ btr_cur_insert_if_possible(
page_cursor = btr_cur_get_page_cur(cursor);
/* Now, try the insert */
- rec = page_cur_tuple_insert(page_cursor, tuple, mtr);
+ rec = page_cur_tuple_insert(page_cursor, tuple, cursor->index, mtr);
if (!rec) {
/* If record did not fit, reorganize */
- btr_page_reorganize(page, mtr);
+ btr_page_reorganize(page, cursor->index, mtr);
*reorg = TRUE;
- page_cur_search(page, tuple, PAGE_CUR_LE, page_cursor);
+ page_cur_search(page, cursor->index, tuple,
+ PAGE_CUR_LE, page_cursor);
- rec = page_cur_tuple_insert(page_cursor, tuple, mtr);
+ rec = page_cur_tuple_insert(page_cursor, tuple,
+ cursor->index, mtr);
}
return(rec);
@@ -887,8 +922,6 @@ btr_cur_optimistic_insert(
ibool reorg;
ibool inherit;
ulint rec_size;
- ulint data_size;
- ulint extra_size;
ulint type;
ulint err;
@@ -914,13 +947,11 @@ btr_cur_optimistic_insert(
calculate_sizes_again:
/* Calculate the record size when entry is converted to a record */
- data_size = dtuple_get_data_size(entry);
- extra_size = rec_get_converted_extra_size(data_size,
- dtuple_get_n_fields(entry));
- rec_size = data_size + extra_size;
+ rec_size = rec_get_converted_size(index, entry);
- if ((rec_size >= page_get_free_space_of_empty() / 2)
- || (rec_size >= REC_MAX_DATA_SIZE)) {
+ if (rec_size >=
+ ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
+ REC_MAX_DATA_SIZE)) {
/* The record is so big that we have to store some fields
externally on separate database pages */
@@ -983,19 +1014,18 @@ calculate_sizes_again:
/* Now, try the insert */
- *rec = page_cur_insert_rec_low(page_cursor, entry, data_size,
- NULL, mtr);
+ *rec = page_cur_insert_rec_low(page_cursor, entry, index, NULL, mtr);
if (!(*rec)) {
/* If the record did not fit, reorganize */
- btr_page_reorganize(page, mtr);
+ btr_page_reorganize(page, index, mtr);
ut_ad(page_get_max_insert_size(page, 1) == max_size);
reorg = TRUE;
- page_cur_search(page, entry, PAGE_CUR_LE, page_cursor);
+ page_cur_search(page, index, entry, PAGE_CUR_LE, page_cursor);
- *rec = page_cur_tuple_insert(page_cursor, entry, mtr);
+ *rec = page_cur_tuple_insert(page_cursor, entry, index, mtr);
if (!*rec) {
fputs("InnoDB: Error: cannot insert tuple ", stderr);
@@ -1123,9 +1153,9 @@ btr_cur_pessimistic_insert(
}
}
- if ((rec_get_converted_size(entry)
- >= page_get_free_space_of_empty() / 2)
- || (rec_get_converted_size(entry) >= REC_MAX_DATA_SIZE)) {
+ if (rec_get_converted_size(index, entry) >=
+ ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
+ REC_MAX_DATA_SIZE)) {
/* The record is so big that we have to store some fields
externally on separate database pages */
@@ -1212,8 +1242,11 @@ btr_cur_upd_lock_and_undo(
err = DB_SUCCESS;
if (!(flags & BTR_NO_LOCKING_FLAG)) {
+ mem_heap_t* heap = mem_heap_create(100);
err = lock_clust_rec_modify_check_and_lock(flags, rec, index,
- thr);
+ rec_get_offsets(rec, index, ULINT_UNDEFINED, heap),
+ thr);
+ mem_heap_free(heap);
if (err != DB_SUCCESS) {
return(err);
@@ -1243,14 +1276,17 @@ btr_cur_update_in_place_log(
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
+ ut_ad(flags < 256);
- log_ptr = mlog_open(mtr, 30 + MLOG_BUF_MARGIN);
-
- log_ptr = mlog_write_initial_log_record_fast(rec,
- MLOG_REC_UPDATE_IN_PLACE, log_ptr, mtr);
+ log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
+ ? MLOG_COMP_REC_UPDATE_IN_PLACE
+ : MLOG_REC_UPDATE_IN_PLACE,
+ 1 + DATA_ROLL_PTR_LEN + 14 + 2 + MLOG_BUF_MARGIN);
- mach_write_to_1(log_ptr, flags);
- log_ptr++;
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery */
+ return;
+ }
/* The code below assumes index is a clustered index: change index to
the clustered index if we are updating a secondary index record (or we
@@ -1259,6 +1295,9 @@ btr_cur_update_in_place_log(
index = dict_table_get_first_index(index->table);
+ mach_write_to_1(log_ptr, flags);
+ log_ptr++;
+
log_ptr = row_upd_write_sys_vals_to_log(index, trx, roll_ptr, log_ptr,
mtr);
mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
@@ -1273,10 +1312,11 @@ Parses a redo log record of updating a record in-place. */
byte*
btr_cur_parse_update_in_place(
/*==========================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page) /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ page_t* page, /* in: page or NULL */
+ dict_index_t* index) /* in: index corresponding to page */
{
ulint flags;
rec_t* rec;
@@ -1286,6 +1326,7 @@ btr_cur_parse_update_in_place(
dulint roll_ptr;
ulint rec_offset;
mem_heap_t* heap;
+ ulint* offsets;
if (end_ptr < ptr + 1) {
@@ -1333,11 +1374,14 @@ btr_cur_parse_update_in_place(
/* We do not need to reserve btr_search_latch, as the page is only
being recovered, and there cannot be a hash index to it. */
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields_in_recovery(rec, pos, trx_id, roll_ptr);
+ row_upd_rec_sys_fields_in_recovery(rec, offsets,
+ pos, trx_id, roll_ptr);
}
- row_upd_rec_in_place(rec, update);
+ row_upd_rec_in_place(rec, offsets, update);
mem_heap_free(heap);
@@ -1369,14 +1413,18 @@ btr_cur_update_in_place(
dulint roll_ptr = ut_dulint_zero;
trx_t* trx;
ibool was_delete_marked;
+ mem_heap_t* heap;
+ const ulint* offsets;
rec = btr_cur_get_rec(cursor);
index = cursor->index;
trx = thr_get_trx(thr);
-
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(trx, index, "update ");
- rec_print(stderr, rec);
+ rec_print(stderr, rec, offsets);
}
/* Do lock checking and undo logging */
@@ -1384,6 +1432,7 @@ btr_cur_update_in_place(
thr, &roll_ptr);
if (err != DB_SUCCESS) {
+ mem_heap_free(heap);
return(err);
}
@@ -1405,15 +1454,15 @@ btr_cur_update_in_place(
}
if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields(rec, index, trx, roll_ptr);
+ row_upd_rec_sys_fields(rec, index, offsets, trx, roll_ptr);
}
/* FIXME: in a mixed tree, all records may not have enough ordering
fields for btr search: */
- was_delete_marked = rec_get_deleted_flag(rec);
-
- row_upd_rec_in_place(rec, update);
+ was_delete_marked = rec_get_deleted_flag(rec, index->table->comp);
+
+ row_upd_rec_in_place(rec, offsets, update);
if (block->is_hashed) {
rw_lock_x_unlock(&btr_search_latch);
@@ -1421,13 +1470,14 @@ btr_cur_update_in_place(
btr_cur_update_in_place_log(flags, rec, index, update, trx, roll_ptr,
mtr);
- if (was_delete_marked && !rec_get_deleted_flag(rec)) {
+ if (was_delete_marked && !rec_get_deleted_flag(rec, index->table->comp)) {
/* The new updated record owns its possible externally
stored fields */
- btr_cur_unmark_extern_fields(rec, mtr);
+ btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
+ mem_heap_free(heap);
return(DB_SUCCESS);
}
@@ -1469,24 +1519,28 @@ btr_cur_optimistic_update(
mem_heap_t* heap;
ibool reorganized = FALSE;
ulint i;
-
+ ulint* offsets;
+
page = btr_cur_get_page(cursor);
rec = btr_cur_get_rec(cursor);
index = cursor->index;
+ heap = mem_heap_create(1024);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "update ");
- rec_print(stderr, rec);
+ rec_print(stderr, rec, offsets);
}
ut_ad(mtr_memo_contains(mtr, buf_block_align(page),
MTR_MEMO_PAGE_X_FIX));
- if (!row_upd_changes_field_size_or_external(rec, index, update)) {
+ if (!row_upd_changes_field_size_or_external(index, offsets, update)) {
/* The simplest and the most common case: the update does not
change the size of any field and none of the updated fields is
externally stored in rec or update */
-
+ mem_heap_free(heap);
return(btr_cur_update_in_place(flags, cursor, update,
cmpl_info, thr, mtr));
}
@@ -1497,29 +1551,30 @@ btr_cur_optimistic_update(
/* Externally stored fields are treated in pessimistic
update */
+ mem_heap_free(heap);
return(DB_OVERFLOW);
}
}
- if (rec_contains_externally_stored_field(btr_cur_get_rec(cursor))) {
+ if (rec_offs_any_extern(offsets)) {
/* Externally stored fields are treated in pessimistic
update */
+ mem_heap_free(heap);
return(DB_OVERFLOW);
}
page_cursor = btr_cur_get_page_cur(cursor);
- heap = mem_heap_create(1024);
-
new_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
row_upd_index_replace_new_col_vals_index_pos(new_entry, index, update,
NULL);
- old_rec_size = rec_get_size(rec);
- new_rec_size = rec_get_converted_size(new_entry);
+ old_rec_size = rec_offs_size(offsets);
+ new_rec_size = rec_get_converted_size(index, new_entry);
- if (new_rec_size >= page_get_free_space_of_empty() / 2) {
+ if (new_rec_size >=
+ page_get_free_space_of_empty(index->table->comp) / 2) {
mem_heap_free(heap);
@@ -1570,7 +1625,7 @@ btr_cur_optimistic_update(
btr_search_update_hash_on_delete(cursor);
- page_cur_delete_rec(page_cursor, mtr);
+ page_cur_delete_rec(page_cursor, index, mtr);
page_cur_move_to_prev(page_cursor);
@@ -1587,11 +1642,13 @@ btr_cur_optimistic_update(
ut_a(rec); /* <- We calculated above the insert would fit */
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, index->table->comp)) {
/* The new inserted record owns its possible externally
stored fields */
- btr_cur_unmark_extern_fields(rec, mtr);
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
/* Restore the old explicit lock state on the record */
@@ -1690,6 +1747,7 @@ btr_cur_pessimistic_update(
ulint* ext_vect;
ulint n_ext_vect;
ulint reserve_flag;
+ ulint* offsets = NULL;
*big_rec = NULL;
@@ -1743,6 +1801,7 @@ btr_cur_pessimistic_update(
}
heap = mem_heap_create(1024);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
trx = thr_get_trx(thr);
@@ -1767,28 +1826,29 @@ btr_cur_pessimistic_update(
ut_a(big_rec_vec == NULL);
- btr_rec_free_updated_extern_fields(index, rec, update,
- TRUE, mtr);
+ btr_rec_free_updated_extern_fields(index, rec, offsets,
+ update, TRUE, mtr);
}
/* We have to set appropriate extern storage bits in the new
record to be inserted: we have to remember which fields were such */
- ext_vect = mem_heap_alloc(heap, sizeof(ulint) * rec_get_n_fields(rec));
- n_ext_vect = btr_push_update_extern_fields(ext_vect, rec, update);
-
- if ((rec_get_converted_size(new_entry) >=
- page_get_free_space_of_empty() / 2)
- || (rec_get_converted_size(new_entry) >= REC_MAX_DATA_SIZE)) {
+ ext_vect = mem_heap_alloc(heap, sizeof(ulint)
+ * dict_index_get_n_fields(index));
+ ut_ad(!cursor->index->table->comp || !rec_get_node_ptr_flag(rec));
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets, update);
+
+ if (rec_get_converted_size(index, new_entry) >=
+ ut_min(page_get_free_space_of_empty(index->table->comp) / 2,
+ REC_MAX_DATA_SIZE)) {
big_rec_vec = dtuple_convert_big_rec(index, new_entry,
ext_vect, n_ext_vect);
if (big_rec_vec == NULL) {
- mem_heap_free(heap);
-
err = DB_TOO_BIG_RECORD;
-
goto return_after_reservations;
}
}
@@ -1808,7 +1868,7 @@ btr_cur_pessimistic_update(
btr_search_update_hash_on_delete(cursor);
- page_cur_delete_rec(page_cursor, mtr);
+ page_cur_delete_rec(page_cursor, index, mtr);
page_cur_move_to_prev(page_cursor);
@@ -1817,21 +1877,22 @@ btr_cur_pessimistic_update(
ut_a(rec || optim_err != DB_UNDERFLOW);
if (rec) {
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+
lock_rec_restore_from_page_infimum(rec, page);
- rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);
+ rec_set_field_extern_bits(rec, index,
+ ext_vect, n_ext_vect, mtr);
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) {
/* The new inserted record owns its possible externally
stored fields */
-
- btr_cur_unmark_extern_fields(rec, mtr);
+ btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
btr_cur_compress_if_useful(cursor, mtr);
err = DB_SUCCESS;
- mem_heap_free(heap);
-
goto return_after_reservations;
}
@@ -1856,13 +1917,15 @@ btr_cur_pessimistic_update(
ut_a(err == DB_SUCCESS);
ut_a(dummy_big_rec == NULL);
- rec_set_field_extern_bits(rec, ext_vect, n_ext_vect, mtr);
+ rec_set_field_extern_bits(rec, index, ext_vect, n_ext_vect, mtr);
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, rec_offs_comp(offsets))) {
/* The new inserted record owns its possible externally
stored fields */
- btr_cur_unmark_extern_fields(rec, mtr);
+ btr_cur_unmark_extern_fields(rec, mtr, offsets);
}
lock_rec_restore_from_page_infimum(rec, page);
@@ -1876,9 +1939,8 @@ btr_cur_pessimistic_update(
btr_cur_pess_upd_restore_supremum(rec, mtr);
}
- mem_heap_free(heap);
-
return_after_reservations:
+ mem_heap_free(heap);
if (n_extents > 0) {
fil_space_release_free_extents(cursor->index->space,
@@ -1908,11 +1970,18 @@ btr_cur_del_mark_set_clust_rec_log(
mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
+ ut_ad(flags < 256);
+ ut_ad(val <= 1);
- log_ptr = mlog_open(mtr, 30);
+ log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
+ ? MLOG_COMP_REC_CLUST_DELETE_MARK
+ : MLOG_REC_CLUST_DELETE_MARK,
+ 1 + 1 + DATA_ROLL_PTR_LEN + 14 + 2);
- log_ptr = mlog_write_initial_log_record_fast(rec,
- MLOG_REC_CLUST_DELETE_MARK, log_ptr, mtr);
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery */
+ return;
+ }
mach_write_to_1(log_ptr, flags);
log_ptr++;
@@ -1934,10 +2003,11 @@ index record. */
byte*
btr_cur_parse_del_mark_set_clust_rec(
/*=================================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page) /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: index corresponding to page */
+ page_t* page) /* in: page or NULL */
{
ulint flags;
ibool val;
@@ -1978,15 +2048,19 @@ btr_cur_parse_del_mark_set_clust_rec(
rec = page + offset;
if (!(flags & BTR_KEEP_SYS_FLAG)) {
- row_upd_rec_sys_fields_in_recovery(rec, pos, trx_id,
- roll_ptr);
+ mem_heap_t* heap = mem_heap_create(100);
+ row_upd_rec_sys_fields_in_recovery(rec,
+ rec_get_offsets(rec, index,
+ ULINT_UNDEFINED, heap),
+ pos, trx_id, roll_ptr);
+ mem_heap_free(heap);
}
/* We do not need to reserve btr_search_latch, as the page
is only being recovered, and there cannot be a hash index to
it. */
- rec_set_deleted_flag(rec, val);
+ rec_set_deleted_flag(rec, index->table->comp, val);
}
return(ptr);
@@ -2015,22 +2089,28 @@ btr_cur_del_mark_set_clust_rec(
ulint err;
rec_t* rec;
trx_t* trx;
+ mem_heap_t* heap;
+ const ulint* offsets;
rec = btr_cur_get_rec(cursor);
index = cursor->index;
-
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
if (btr_cur_print_record_ops && thr) {
btr_cur_trx_report(thr_get_trx(thr), index, "del mark ");
- rec_print(stderr, rec);
+ rec_print(stderr, rec, offsets);
}
ut_ad(index->type & DICT_CLUSTERED);
- ut_ad(rec_get_deleted_flag(rec) == FALSE);
+ ut_ad(rec_get_deleted_flag(rec, index->table->comp) == FALSE);
- err = lock_clust_rec_modify_check_and_lock(flags, rec, index, thr);
+ err = lock_clust_rec_modify_check_and_lock(flags,
+ rec, index, offsets, thr);
if (err != DB_SUCCESS) {
+ mem_heap_free(heap);
return(err);
}
@@ -2039,6 +2119,7 @@ btr_cur_del_mark_set_clust_rec(
&roll_ptr);
if (err != DB_SUCCESS) {
+ mem_heap_free(heap);
return(err);
}
@@ -2048,13 +2129,12 @@ btr_cur_del_mark_set_clust_rec(
rw_lock_x_lock(&btr_search_latch);
}
- rec_set_deleted_flag(rec, val);
+ rec_set_deleted_flag(rec, index->table->comp, val);
trx = thr_get_trx(thr);
if (!(flags & BTR_KEEP_SYS_FLAG)) {
-
- row_upd_rec_sys_fields(rec, index, trx, roll_ptr);
+ row_upd_rec_sys_fields(rec, index, offsets, trx, roll_ptr);
}
if (block->is_hashed) {
@@ -2063,6 +2143,7 @@ btr_cur_del_mark_set_clust_rec(
btr_cur_del_mark_set_clust_rec_log(flags, rec, index, val, trx,
roll_ptr, mtr);
+ mem_heap_free(heap);
return(DB_SUCCESS);
}
@@ -2073,16 +2154,24 @@ UNIV_INLINE
void
btr_cur_del_mark_set_sec_rec_log(
/*=============================*/
- rec_t* rec, /* in: record */
- ibool val, /* in: value to set */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ibool val, /* in: value to set */
+ mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
+ ut_ad(val <= 1);
- log_ptr = mlog_open(mtr, 30);
+ log_ptr = mlog_open_and_write_index(mtr, rec, index, index->table->comp
+ ? MLOG_COMP_REC_SEC_DELETE_MARK
+ : MLOG_REC_SEC_DELETE_MARK,
+ 1 + 2);
- log_ptr = mlog_write_initial_log_record_fast(rec,
- MLOG_REC_SEC_DELETE_MARK, log_ptr, mtr);
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery:
+ in that case mlog_open returns NULL */
+ return;
+ }
mach_write_to_1(log_ptr, val);
log_ptr++;
@@ -2100,10 +2189,11 @@ index record. */
byte*
btr_cur_parse_del_mark_set_sec_rec(
/*===============================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page) /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page) /* in: page or NULL */
{
ibool val;
ulint offset;
@@ -2129,7 +2219,7 @@ btr_cur_parse_del_mark_set_sec_rec(
is only being recovered, and there cannot be a hash index to
it. */
- rec_set_deleted_flag(rec, val);
+ rec_set_deleted_flag(rec, index->table->comp, val);
}
return(ptr);
@@ -2156,9 +2246,12 @@ btr_cur_del_mark_set_sec_rec(
rec = btr_cur_get_rec(cursor);
if (btr_cur_print_record_ops && thr) {
+ mem_heap_t* heap = mem_heap_create(100);
btr_cur_trx_report(thr_get_trx(thr), cursor->index,
"del mark ");
- rec_print(stderr, rec);
+ rec_print(stderr, rec, rec_get_offsets(rec, cursor->index,
+ ULINT_UNDEFINED, heap));
+ mem_heap_free(heap);
}
err = lock_sec_rec_modify_check_and_lock(flags, rec, cursor->index,
@@ -2174,13 +2267,13 @@ btr_cur_del_mark_set_sec_rec(
rw_lock_x_lock(&btr_search_latch);
}
- rec_set_deleted_flag(rec, val);
+ rec_set_deleted_flag(rec, cursor->index->table->comp, val);
if (block->is_hashed) {
rw_lock_x_unlock(&btr_search_latch);
}
- btr_cur_del_mark_set_sec_rec_log(rec, val, mtr);
+ btr_cur_del_mark_set_sec_rec_log(rec, cursor->index, val, mtr);
return(DB_SUCCESS);
}
@@ -2192,15 +2285,16 @@ used by the insert buffer insert merge mechanism. */
void
btr_cur_del_unmark_for_ibuf(
/*========================*/
- rec_t* rec, /* in: record to delete unmark */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: record to delete unmark */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
/* We do not need to reserve btr_search_latch, as the page has just
been read to the buffer pool and there cannot be a hash index to it. */
- rec_set_deleted_flag(rec, FALSE);
+ rec_set_deleted_flag(rec, index->table->comp, FALSE);
- btr_cur_del_mark_set_sec_rec_log(rec, FALSE, mtr);
+ btr_cur_del_mark_set_sec_rec_log(rec, index, FALSE, mtr);
}
/*==================== B-TREE RECORD REMOVE =========================*/
@@ -2279,8 +2373,11 @@ btr_cur_optimistic_delete(
successor of the deleted record */
mtr_t* mtr) /* in: mtr */
{
- page_t* page;
- ulint max_ins_size;
+ page_t* page;
+ ulint max_ins_size;
+ mem_heap_t* heap;
+ rec_t* rec;
+ const ulint* offsets;
ut_ad(mtr_memo_contains(mtr, buf_block_align(btr_cur_get_page(cursor)),
MTR_MEMO_PAGE_X_FIX));
@@ -2290,26 +2387,30 @@ btr_cur_optimistic_delete(
ut_ad(btr_page_get_level(page, mtr) == 0);
- if (rec_contains_externally_stored_field(btr_cur_get_rec(cursor))) {
-
- return(FALSE);
- }
+ heap = mem_heap_create(100);
+ rec = btr_cur_get_rec(cursor);
+ offsets = rec_get_offsets(rec, cursor->index, ULINT_UNDEFINED, heap);
- if (btr_cur_can_delete_without_compress(cursor, mtr)) {
+ if (!rec_offs_any_extern(offsets)
+ && btr_cur_can_delete_without_compress(
+ cursor, rec_offs_size(offsets), mtr)) {
- lock_update_delete(btr_cur_get_rec(cursor));
+ lock_update_delete(rec);
btr_search_update_hash_on_delete(cursor);
max_ins_size = page_get_max_insert_size_after_reorganize(page,
1);
- page_cur_delete_rec(btr_cur_get_page_cur(cursor), mtr);
+ page_cur_delete_rec(btr_cur_get_page_cur(cursor),
+ cursor->index, mtr);
ibuf_update_free_bits_low(cursor->index, page, max_ins_size,
mtr);
+ mem_heap_free(heap);
return(TRUE);
}
+ mem_heap_free(heap);
return(FALSE);
}
@@ -2375,8 +2476,20 @@ btr_cur_pessimistic_delete(
}
}
- btr_rec_free_externally_stored_fields(cursor->index,
- btr_cur_get_rec(cursor), in_rollback, mtr);
+ heap = mem_heap_create(256);
+ rec = btr_cur_get_rec(cursor);
+
+ /* Free externally stored fields if the record is neither
+ a node pointer nor in two-byte format.
+ This avoids unnecessary calls to rec_get_offsets(). */
+ if (cursor->index->table->comp
+ ? !rec_get_node_ptr_flag(rec)
+ : !rec_get_1byte_offs_flag(rec)) {
+ btr_rec_free_externally_stored_fields(cursor->index,
+ rec, rec_get_offsets(rec, cursor->index,
+ ULINT_UNDEFINED, heap),
+ in_rollback, mtr);
+ }
if ((page_get_n_recs(page) < 2)
&& (dict_tree_get_page(btr_cur_get_tree(cursor))
@@ -2393,8 +2506,6 @@ btr_cur_pessimistic_delete(
goto return_after_reservations;
}
- rec = btr_cur_get_rec(cursor);
-
lock_update_delete(rec);
if ((btr_page_get_level(page, mtr) > 0)
@@ -2406,7 +2517,8 @@ btr_cur_pessimistic_delete(
non-leaf level, we must mark the new leftmost node
pointer as the predefined minimum record */
- btr_set_min_rec_mark(page_rec_get_next(rec), mtr);
+ btr_set_min_rec_mark(page_rec_get_next(rec),
+ cursor->index->table->comp, mtr);
} else {
/* Otherwise, if we delete the leftmost node pointer
on a page, we have to change the father node pointer
@@ -2415,8 +2527,6 @@ btr_cur_pessimistic_delete(
btr_node_ptr_delete(tree, page, mtr);
- heap = mem_heap_create(256);
-
node_ptr = dict_tree_build_node_ptr(
tree, page_rec_get_next(rec),
buf_frame_get_page_no(page),
@@ -2425,20 +2535,19 @@ btr_cur_pessimistic_delete(
btr_insert_on_non_leaf_level(tree,
btr_page_get_level(page, mtr) + 1,
node_ptr, mtr);
-
- mem_heap_free(heap);
}
}
btr_search_update_hash_on_delete(cursor);
- page_cur_delete_rec(btr_cur_get_page_cur(cursor), mtr);
+ page_cur_delete_rec(btr_cur_get_page_cur(cursor), cursor->index, mtr);
ut_ad(btr_check_node_ptr(tree, page, mtr));
*err = DB_SUCCESS;
return_after_reservations:
+ mem_heap_free(heap);
if (ret == FALSE) {
ret = btr_cur_compress_if_useful(cursor, mtr);
@@ -2663,9 +2772,13 @@ btr_estimate_number_of_different_key_vals(
ulint j;
ulint add_on;
mtr_t mtr;
+ mem_heap_t* heap;
+ ulint* offsets1 = 0;
+ ulint* offsets2 = 0;
n_cols = dict_index_get_n_unique(index);
+ heap = mem_heap_create(100);
n_diff = mem_alloc((n_cols + 1) * sizeof(ib_longlong));
for (j = 0; j <= n_cols; j++) {
@@ -2697,11 +2810,17 @@ btr_estimate_number_of_different_key_vals(
while (rec != page_get_supremum_rec(page)
&& page_rec_get_next(rec)
!= page_get_supremum_rec(page)) {
+ rec_t* next_rec = page_rec_get_next(rec);
matched_fields = 0;
matched_bytes = 0;
-
- cmp_rec_rec_with_match(rec, page_rec_get_next(rec),
- index, &matched_fields,
+ offsets1 = rec_reget_offsets(rec, index,
+ offsets1, ULINT_UNDEFINED, heap);
+ offsets2 = rec_reget_offsets(next_rec, index,
+ offsets2, n_cols, heap);
+
+ cmp_rec_rec_with_match(rec, next_rec,
+ offsets1, offsets2,
+ index, n_cols, &matched_fields,
&matched_bytes);
for (j = matched_fields + 1; j <= n_cols; j++) {
@@ -2712,7 +2831,8 @@ btr_estimate_number_of_different_key_vals(
}
total_external_size +=
- btr_rec_get_externally_stored_len(rec);
+ btr_rec_get_externally_stored_len(
+ rec, offsets1);
rec = page_rec_get_next(rec);
}
@@ -2736,8 +2856,11 @@ btr_estimate_number_of_different_key_vals(
}
}
+ offsets1 = rec_reget_offsets(rec, index,
+ offsets1, ULINT_UNDEFINED, heap);
total_external_size +=
- btr_rec_get_externally_stored_len(rec);
+ btr_rec_get_externally_stored_len(rec,
+ offsets1);
mtr_commit(&mtr);
}
@@ -2778,6 +2901,7 @@ btr_estimate_number_of_different_key_vals(
}
mem_free(n_diff);
+ mem_heap_free(heap);
}
/*================== EXTERNAL STORAGE OF BIG FIELDS ===================*/
@@ -2788,9 +2912,10 @@ static
ulint
btr_rec_get_externally_stored_len(
/*==============================*/
- /* out: externally stored part, in units of a
- database page */
- rec_t* rec) /* in: record */
+ /* out: externally stored part,
+ in units of a database page */
+ rec_t* rec, /* in: record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_fields;
byte* data;
@@ -2799,17 +2924,13 @@ btr_rec_get_externally_stored_len(
ulint total_extern_len = 0;
ulint i;
- if (rec_get_data_size(rec) <= REC_1BYTE_OFFS_LIMIT) {
-
- return(0);
- }
-
- n_fields = rec_get_n_fields(rec);
+ ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+ n_fields = rec_offs_n_fields(offsets);
for (i = 0; i < n_fields; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+ if (rec_offs_nth_extern(offsets, i)) {
- data = rec_get_nth_field(rec, i, &local_len);
+ data = rec_get_nth_field(rec, offsets, i, &local_len);
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
@@ -2830,16 +2951,17 @@ static
void
btr_cur_set_ownership_of_extern_field(
/*==================================*/
- rec_t* rec, /* in: clustered index record */
- ulint i, /* in: field number */
- ibool val, /* in: value to set */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: clustered index record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint i, /* in: field number */
+ ibool val, /* in: value to set */
+ mtr_t* mtr) /* in: mtr */
{
byte* data;
ulint local_len;
ulint byte_val;
- data = rec_get_nth_field(rec, i, &local_len);
+ data = rec_get_nth_field(rec, offsets, i, &local_len);
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
@@ -2866,19 +2988,22 @@ to free the field. */
void
btr_cur_mark_extern_inherited_fields(
/*=================================*/
- rec_t* rec, /* in: record in a clustered index */
- upd_t* update, /* in: update vector */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: record in a clustered index */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update, /* in: update vector */
+ mtr_t* mtr) /* in: mtr */
{
ibool is_updated;
ulint n;
ulint j;
ulint i;
-
- n = rec_get_n_fields(rec);
+
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+ n = rec_offs_n_fields(offsets);
for (i = 0; i < n; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+ if (rec_offs_nth_extern(offsets, i)) {
/* Check it is not in updated fields */
is_updated = FALSE;
@@ -2894,8 +3019,8 @@ btr_cur_mark_extern_inherited_fields(
}
if (!is_updated) {
- btr_cur_set_ownership_of_extern_field(rec, i,
- FALSE, mtr);
+ btr_cur_set_ownership_of_extern_field(rec,
+ offsets, i, FALSE, mtr);
}
}
}
@@ -2967,18 +3092,20 @@ static
void
btr_cur_unmark_extern_fields(
/*=========================*/
- rec_t* rec, /* in: record in a clustered index */
- mtr_t* mtr) /* in: mtr */
+ rec_t* rec, /* in: record in a clustered index */
+ mtr_t* mtr, /* in: mtr */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n;
ulint i;
- n = rec_get_n_fields(rec);
+ ut_ad(!rec_offs_comp(offsets) || !rec_get_node_ptr_flag(rec));
+ n = rec_offs_n_fields(offsets);
for (i = 0; i < n; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
-
- btr_cur_set_ownership_of_extern_field(rec, i,
+ if (rec_offs_nth_extern(offsets, i)) {
+
+ btr_cur_set_ownership_of_extern_field(rec, offsets, i,
TRUE, mtr);
}
}
@@ -3028,10 +3155,10 @@ ulint
btr_push_update_extern_fields(
/*==========================*/
/* out: number of values stored in ext_vect */
- ulint* ext_vect, /* in: array of ulints, must be preallocated
+ ulint* ext_vect,/* in: array of ulints, must be preallocated
to have space for all fields in rec */
- rec_t* rec, /* in: record */
- upd_t* update) /* in: update vector or NULL */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update) /* in: update vector or NULL */
{
ulint n_pushed = 0;
ibool is_updated;
@@ -3054,10 +3181,10 @@ btr_push_update_extern_fields(
}
}
- n = rec_get_n_fields(rec);
+ n = rec_offs_n_fields(offsets);
for (i = 0; i < n; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+ if (rec_offs_nth_extern(offsets, i)) {
/* Check it is not in updated fields */
is_updated = FALSE;
@@ -3119,6 +3246,7 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */
mtr_t* local_mtr __attribute__((unused))) /* in: mtr
@@ -3139,6 +3267,7 @@ btr_store_big_rec_extern_fields(
ulint i;
mtr_t mtr;
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mtr_memo_contains(local_mtr, dict_tree_get_lock(index->tree),
MTR_MEMO_X_LOCK));
ut_ad(mtr_memo_contains(local_mtr, buf_block_align(rec),
@@ -3152,8 +3281,8 @@ btr_store_big_rec_extern_fields(
for (i = 0; i < big_rec_vec->n_fields; i++) {
- data = rec_get_nth_field(rec, big_rec_vec->fields[i].field_no,
- &local_len);
+ data = rec_get_nth_field(rec, offsets,
+ big_rec_vec->fields[i].field_no, &local_len);
ut_a(local_len >= BTR_EXTERN_FIELD_REF_SIZE);
local_len -= BTR_EXTERN_FIELD_REF_SIZE;
extern_len = big_rec_vec->fields[i].len;
@@ -3254,7 +3383,7 @@ btr_store_big_rec_extern_fields(
/* Set the bit denoting that this field
in rec is stored externally */
- rec_set_nth_field_extern_bit(rec,
+ rec_set_nth_field_extern_bit(rec, index,
big_rec_vec->fields[i].field_no,
TRUE, &mtr);
}
@@ -3407,6 +3536,7 @@ btr_rec_free_externally_stored_fields(
dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
inherited fields */
@@ -3419,21 +3549,18 @@ btr_rec_free_externally_stored_fields(
ulint len;
ulint i;
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec),
MTR_MEMO_PAGE_X_FIX));
- if (rec_get_data_size(rec) <= REC_1BYTE_OFFS_LIMIT) {
-
- return;
- }
-
/* Free possible externally stored fields in the record */
- n_fields = rec_get_n_fields(rec);
+ ut_ad(index->table->comp == rec_offs_comp(offsets));
+ n_fields = rec_offs_n_fields(offsets);
for (i = 0; i < n_fields; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+ if (rec_offs_nth_extern(offsets, i)) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
btr_free_externally_stored_field(index, data, len,
do_not_free_inherited, mtr);
}
@@ -3450,6 +3577,7 @@ btr_rec_free_updated_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree MUST be
X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update, /* in: update vector */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
@@ -3463,13 +3591,10 @@ btr_rec_free_updated_extern_fields(
ulint len;
ulint i;
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec),
MTR_MEMO_PAGE_X_FIX));
- if (rec_get_data_size(rec) <= REC_1BYTE_OFFS_LIMIT) {
- return;
- }
-
/* Free possible externally stored fields in the record */
n_fields = upd_get_n_fields(update);
@@ -3477,9 +3602,10 @@ btr_rec_free_updated_extern_fields(
for (i = 0; i < n_fields; i++) {
ufield = upd_get_nth_field(update, i);
- if (rec_get_nth_field_extern_bit(rec, ufield->field_no)) {
+ if (rec_offs_nth_extern(offsets, ufield->field_no)) {
- data = rec_get_nth_field(rec, ufield->field_no, &len);
+ data = rec_get_nth_field(rec, offsets,
+ ufield->field_no, &len);
btr_free_externally_stored_field(index, data, len,
do_not_free_inherited, mtr);
}
@@ -3583,7 +3709,8 @@ byte*
btr_rec_copy_externally_stored_field(
/*=================================*/
/* out: the field copied to heap */
- rec_t* rec, /* in: record */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint no, /* in: field number */
ulint* len, /* out: length of the field */
mem_heap_t* heap) /* in: mem heap */
@@ -3591,7 +3718,8 @@ btr_rec_copy_externally_stored_field(
ulint local_len;
byte* data;
- ut_a(rec_get_nth_field_extern_bit(rec, no));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_a(rec_offs_nth_extern(offsets, no));
/* An externally stored field can contain some initial
data from the field, and in the last 20 bytes it has the
@@ -3602,7 +3730,7 @@ btr_rec_copy_externally_stored_field(
limit so that field offsets are stored in two bytes, and
the extern bit is available in those two bytes. */
- data = rec_get_nth_field(rec, no, &local_len);
+ data = rec_get_nth_field(rec, offsets, no, &local_len);
return(btr_copy_externally_stored_field(len, data, local_len, heap));
}
diff --git a/innobase/btr/btr0pcur.c b/innobase/btr/btr0pcur.c
index cf8a612ef28..7df8e53cd07 100644
--- a/innobase/btr/btr0pcur.c
+++ b/innobase/btr/btr0pcur.c
@@ -45,12 +45,12 @@ btr_pcur_free_for_mysql(
mem_free(cursor->old_rec_buf);
- cursor->old_rec = NULL;
cursor->old_rec_buf = NULL;
}
cursor->btr_cur.page_cur.rec = NULL;
cursor->old_rec = NULL;
+ cursor->old_n_fields = 0;
cursor->old_stored = BTR_PCUR_OLD_NOT_STORED;
cursor->latch_mode = BTR_NO_LATCHES;
@@ -133,9 +133,10 @@ btr_pcur_store_position(
cursor->old_stored = BTR_PCUR_OLD_STORED;
cursor->old_rec = dict_tree_copy_rec_order_prefix(tree, rec,
- &(cursor->old_rec_buf),
- &(cursor->buf_size));
-
+ &cursor->old_n_fields,
+ &cursor->old_rec_buf,
+ &cursor->buf_size);
+
cursor->block_when_stored = buf_block_align(page);
cursor->modify_clock = buf_frame_get_modify_clock(page);
}
@@ -166,6 +167,8 @@ btr_pcur_copy_stored_position(
pcur_receive->old_rec = pcur_receive->old_rec_buf
+ (pcur_donate->old_rec - pcur_donate->old_rec_buf);
}
+
+ pcur_receive->old_n_fields = pcur_donate->old_n_fields;
}
/******************************************************************
@@ -228,6 +231,7 @@ btr_pcur_restore_position(
}
ut_a(cursor->old_rec);
+ ut_a(cursor->old_n_fields);
page = btr_cur_get_page(btr_pcur_get_btr_cur(cursor));
@@ -242,17 +246,32 @@ btr_pcur_restore_position(
buf_page_dbg_add_level(page, SYNC_TREE_NODE);
#endif /* UNIV_SYNC_DEBUG */
if (cursor->rel_pos == BTR_PCUR_ON) {
-
+#ifdef UNIV_DEBUG
+ rec_t* rec;
+ ulint* offsets1;
+ ulint* offsets2;
+ dict_index_t* index;
+#endif /* UNIV_DEBUG */
cursor->latch_mode = latch_mode;
-
- ut_ad(cmp_rec_rec(cursor->old_rec,
- btr_pcur_get_rec(cursor),
- dict_tree_find_index(
- btr_cur_get_tree(
+#ifdef UNIV_DEBUG
+ rec = btr_pcur_get_rec(cursor);
+ index = dict_tree_find_index(
+ btr_cur_get_tree(
btr_pcur_get_btr_cur(cursor)),
- btr_pcur_get_rec(cursor)))
- == 0);
+ rec);
+
+ heap = mem_heap_create(256);
+ offsets1 = rec_get_offsets(cursor->old_rec,
+ index, ULINT_UNDEFINED, heap);
+ offsets2 = rec_get_offsets(rec,
+ index, ULINT_UNDEFINED, heap);
+ ut_ad(cmp_rec_rec(cursor->old_rec,
+ rec, offsets1, offsets2,
+ cursor->old_n_fields,
+ index) == 0);
+ mem_heap_free(heap);
+#endif /* UNIV_DEBUG */
return(TRUE);
}
@@ -265,7 +284,8 @@ btr_pcur_restore_position(
heap = mem_heap_create(256);
tree = btr_cur_get_tree(btr_pcur_get_btr_cur(cursor));
- tuple = dict_tree_build_data_tuple(tree, cursor->old_rec, heap);
+ tuple = dict_tree_build_data_tuple(tree, cursor->old_rec,
+ cursor->old_n_fields, heap);
/* Save the old search mode of the cursor */
old_mode = cursor->search_mode;
@@ -287,7 +307,10 @@ btr_pcur_restore_position(
if (cursor->rel_pos == BTR_PCUR_ON
&& btr_pcur_is_on_user_rec(cursor, mtr)
- && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor))) {
+ && 0 == cmp_dtuple_rec(tuple, btr_pcur_get_rec(cursor),
+ rec_get_offsets(btr_pcur_get_rec(cursor),
+ btr_pcur_get_btr_cur(cursor)->index,
+ ULINT_UNDEFINED, heap))) {
/* We have to store the NEW value for the modify clock, since
the cursor can now be on a different page! But we can retain
@@ -376,6 +399,7 @@ btr_pcur_move_to_next_page(
ut_ad(next_page_no != FIL_NULL);
next_page = btr_page_get(space, next_page_no, cursor->latch_mode, mtr);
+ ut_a(page_is_comp(next_page) == page_is_comp(page));
buf_block_align(next_page)->check_index_page_at_flush = TRUE;
btr_leaf_page_release(page, cursor->latch_mode, mtr);
diff --git a/innobase/btr/btr0sea.c b/innobase/btr/btr0sea.c
index ad74f9704da..40ccf56492f 100644
--- a/innobase/btr/btr0sea.c
+++ b/innobase/btr/btr0sea.c
@@ -416,7 +416,7 @@ btr_search_update_hash_ref(
&& (block->curr_n_fields == info->n_fields)
&& (block->curr_n_bytes == info->n_bytes)
&& (block->curr_side == info->side)) {
-
+ mem_heap_t* heap;
rec = btr_cur_get_rec(cursor);
if (!page_rec_is_user_rec(rec)) {
@@ -425,10 +425,11 @@ btr_search_update_hash_ref(
}
tree_id = ((cursor->index)->tree)->id;
-
- fold = rec_fold(rec, block->curr_n_fields,
- block->curr_n_bytes, tree_id);
-
+ heap = mem_heap_create(100);
+ fold = rec_fold(rec, rec_get_offsets(rec, cursor->index,
+ ULINT_UNDEFINED, heap), block->curr_n_fields,
+ block->curr_n_bytes, tree_id);
+ mem_heap_free(heap);
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
@@ -535,15 +536,17 @@ btr_search_check_guess(
or PAGE_CUR_GE */
mtr_t* mtr) /* in: mtr */
{
- page_t* page;
- rec_t* rec;
- rec_t* prev_rec;
- rec_t* next_rec;
- ulint n_unique;
- ulint match;
- ulint bytes;
- int cmp;
-
+ page_t* page;
+ rec_t* rec;
+ rec_t* prev_rec;
+ rec_t* next_rec;
+ ulint n_unique;
+ ulint match;
+ ulint bytes;
+ int cmp;
+ mem_heap_t* heap = mem_heap_create(100);
+ ulint* offsets = NULL;
+
n_unique = dict_index_get_n_unique_in_tree(cursor->index);
rec = btr_cur_get_rec(cursor);
@@ -554,23 +557,25 @@ btr_search_check_guess(
match = 0;
bytes = 0;
- cmp = page_cmp_dtuple_rec_with_match(tuple, rec, &match, &bytes);
+ offsets = rec_get_offsets(rec, cursor->index, n_unique, heap);
+ cmp = page_cmp_dtuple_rec_with_match(tuple, rec,
+ offsets, &match, &bytes);
if (mode == PAGE_CUR_GE) {
if (cmp == 1) {
-
+ mem_heap_free(heap);
return(FALSE);
}
cursor->up_match = match;
if (match >= n_unique) {
-
+ mem_heap_free(heap);
return(TRUE);
}
} else if (mode == PAGE_CUR_LE) {
if (cmp == -1) {
-
+ mem_heap_free(heap);
return(FALSE);
}
@@ -578,12 +583,12 @@ btr_search_check_guess(
} else if (mode == PAGE_CUR_G) {
if (cmp != -1) {
-
+ mem_heap_free(heap);
return(FALSE);
}
} else if (mode == PAGE_CUR_L) {
if (cmp != 1) {
-
+ mem_heap_free(heap);
return(FALSE);
}
}
@@ -591,7 +596,7 @@ btr_search_check_guess(
if (can_only_compare_to_cursor_rec) {
/* Since we could not determine if our guess is right just by
looking at the record under the cursor, return FALSE */
-
+ mem_heap_free(heap);
return(FALSE);
}
@@ -605,17 +610,15 @@ btr_search_check_guess(
prev_rec = page_rec_get_prev(rec);
if (prev_rec == page_get_infimum_rec(page)) {
-
- if (btr_page_get_prev(page, mtr) != FIL_NULL) {
-
- return(FALSE);
- }
-
- return(TRUE);
+ mem_heap_free(heap);
+ return(btr_page_get_prev(page, mtr) == FIL_NULL);
}
+ offsets = rec_reget_offsets(prev_rec, cursor->index,
+ offsets, n_unique, heap);
cmp = page_cmp_dtuple_rec_with_match(tuple, prev_rec,
- &match, &bytes);
+ offsets, &match, &bytes);
+ mem_heap_free(heap);
if (mode == PAGE_CUR_GE) {
if (cmp != 1) {
@@ -636,6 +639,7 @@ btr_search_check_guess(
next_rec = page_rec_get_next(rec);
if (next_rec == page_get_supremum_rec(page)) {
+ mem_heap_free(heap);
if (btr_page_get_next(page, mtr) == FIL_NULL) {
@@ -647,8 +651,12 @@ btr_search_check_guess(
return(FALSE);
}
- cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, &match, &bytes);
-
+ offsets = rec_reget_offsets(next_rec, cursor->index,
+ offsets, n_unique, heap);
+ cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec,
+ offsets, &match, &bytes);
+ mem_heap_free(heap);
+
if (mode == PAGE_CUR_LE) {
if (cmp != -1) {
@@ -1003,8 +1011,7 @@ static
void
btr_search_build_page_hash_index(
/*=============================*/
- dict_index_t* index, /* in: index for which to build, or NULL if
- not known */
+ dict_index_t* index, /* in: index for which to build */
page_t* page, /* in: index page, s- or x-latched */
ulint n_fields,/* in: hash this many full fields */
ulint n_bytes,/* in: hash this many bytes from the next
@@ -1024,7 +1031,11 @@ btr_search_build_page_hash_index(
ulint* folds;
rec_t** recs;
ulint i;
-
+ mem_heap_t* heap;
+ ulint* offsets;
+
+ ut_ad(index);
+
block = buf_block_align(page);
table = btr_search_sys->hash_index;
@@ -1061,9 +1072,9 @@ btr_search_build_page_hash_index(
return;
}
- if (index && (dict_index_get_n_unique_in_tree(index) < n_fields
+ if (dict_index_get_n_unique_in_tree(index) < n_fields
|| (dict_index_get_n_unique_in_tree(index) == n_fields
- && n_bytes > 0))) {
+ && n_bytes > 0)) {
return;
}
@@ -1072,6 +1083,7 @@ btr_search_build_page_hash_index(
folds = mem_alloc(n_recs * sizeof(ulint));
recs = mem_alloc(n_recs * sizeof(rec_t*));
+ heap = mem_heap_create(100);
n_cached = 0;
@@ -1082,18 +1094,19 @@ btr_search_build_page_hash_index(
rec = page_get_infimum_rec(page);
rec = page_rec_get_next(rec);
+ offsets = rec_get_offsets(rec, index, n_fields + (n_bytes > 0), heap);
+
if (rec != sup) {
- ut_a(n_fields <= rec_get_n_fields(rec));
+ ut_a(n_fields <= rec_offs_n_fields(offsets));
if (n_bytes > 0) {
- ut_a(n_fields < rec_get_n_fields(rec));
+ ut_a(n_fields < rec_offs_n_fields(offsets));
}
}
/* FIXME: in a mixed tree, all records may not have enough ordering
fields: */
-
- fold = rec_fold(rec, n_fields, n_bytes, tree_id);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
if (side == BTR_SEARCH_LEFT_SIDE) {
@@ -1117,7 +1130,10 @@ btr_search_build_page_hash_index(
break;
}
- next_fold = rec_fold(next_rec, n_fields, n_bytes, tree_id);
+ offsets = rec_reget_offsets(next_rec, index,
+ offsets, n_fields + (n_bytes > 0), heap);
+ next_fold = rec_fold(next_rec, offsets, n_fields,
+ n_bytes, tree_id);
if (fold != next_fold) {
/* Insert an entry into the hash index */
@@ -1145,13 +1161,7 @@ btr_search_build_page_hash_index(
if (block->is_hashed && ((block->curr_n_fields != n_fields)
|| (block->curr_n_bytes != n_bytes)
|| (block->curr_side != side))) {
-
- rw_lock_x_unlock(&btr_search_latch);
-
- mem_free(folds);
- mem_free(recs);
-
- return;
+ goto exit_func;
}
block->is_hashed = TRUE;
@@ -1166,10 +1176,12 @@ btr_search_build_page_hash_index(
ha_insert_for_fold(table, folds[i], recs[i]);
}
+exit_func:
rw_lock_x_unlock(&btr_search_latch);
mem_free(folds);
mem_free(recs);
+ mem_heap_free(heap);
}
/************************************************************************
@@ -1181,10 +1193,13 @@ parameters as page (this often happens when a page is split). */
void
btr_search_move_or_delete_hash_entries(
/*===================================*/
- page_t* new_page, /* in: records are copied to this page */
- page_t* page) /* in: index page from which records were
- copied, and the copied records will be deleted
- from this page */
+ page_t* new_page, /* in: records are copied
+ to this page */
+ page_t* page, /* in: index page from which
+ records were copied, and the
+ copied records will be deleted
+ from this page */
+ dict_index_t* index) /* in: record descriptor */
{
buf_block_t* block;
buf_block_t* new_block;
@@ -1194,6 +1209,7 @@ btr_search_move_or_delete_hash_entries(
block = buf_block_align(page);
new_block = buf_block_align(new_page);
+ ut_a(page_is_comp(page) == page_is_comp(new_page));
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(block->lock), RW_LOCK_EX));
@@ -1224,8 +1240,8 @@ btr_search_move_or_delete_hash_entries(
rw_lock_s_unlock(&btr_search_latch);
ut_a(n_fields + n_bytes > 0);
-
- btr_search_build_page_hash_index(NULL, new_page, n_fields,
+
+ btr_search_build_page_hash_index(index, new_page, n_fields,
n_bytes, side);
ut_a(n_fields == block->curr_n_fields);
ut_a(n_bytes == block->curr_n_bytes);
@@ -1253,6 +1269,7 @@ btr_search_update_hash_on_delete(
ulint fold;
dulint tree_id;
ibool found;
+ mem_heap_t* heap;
rec = btr_cur_get_rec(cursor);
@@ -1272,9 +1289,11 @@ btr_search_update_hash_on_delete(
table = btr_search_sys->hash_index;
tree_id = cursor->index->tree->id;
-
- fold = rec_fold(rec, block->curr_n_fields, block->curr_n_bytes,
- tree_id);
+ heap = mem_heap_create(100);
+ fold = rec_fold(rec, rec_get_offsets(rec, cursor->index,
+ ULINT_UNDEFINED, heap), block->curr_n_fields,
+ block->curr_n_bytes, tree_id);
+ mem_heap_free(heap);
rw_lock_x_lock(&btr_search_latch);
found = ha_search_and_delete_if_found(table, fold, rec);
@@ -1355,6 +1374,8 @@ btr_search_update_hash_on_insert(
ulint n_bytes;
ulint side;
ibool locked = FALSE;
+ mem_heap_t* heap;
+ ulint* offsets;
table = btr_search_sys->hash_index;
@@ -1383,15 +1404,22 @@ btr_search_update_hash_on_insert(
next_rec = page_rec_get_next(ins_rec);
page = buf_frame_align(rec);
-
- ins_fold = rec_fold(ins_rec, n_fields, n_bytes, tree_id);
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(ins_rec, cursor->index,
+ ULINT_UNDEFINED, heap);
+ ins_fold = rec_fold(ins_rec, offsets, n_fields, n_bytes, tree_id);
if (next_rec != page_get_supremum_rec(page)) {
- next_fold = rec_fold(next_rec, n_fields, n_bytes, tree_id);
+ offsets = rec_reget_offsets(next_rec, cursor->index,
+ offsets, n_fields + (n_bytes > 0), heap);
+ next_fold = rec_fold(next_rec, offsets, n_fields,
+ n_bytes, tree_id);
}
if (rec != page_get_infimum_rec(page)) {
- fold = rec_fold(rec, n_fields, n_bytes, tree_id);
+ offsets = rec_reget_offsets(rec, cursor->index,
+ offsets, n_fields + (n_bytes > 0), heap);
+ fold = rec_fold(rec, offsets, n_fields, n_bytes, tree_id);
} else {
if (side == BTR_SEARCH_LEFT_SIDE) {
@@ -1461,6 +1489,7 @@ check_next_rec:
}
function_exit:
+ mem_heap_free(heap);
if (locked) {
rw_lock_x_unlock(&btr_search_latch);
}
@@ -1470,9 +1499,10 @@ function_exit:
Validates the search system. */
ibool
-btr_search_validate(void)
-/*=====================*/
+btr_search_validate(
+/*================*/
/* out: TRUE if ok */
+ dict_index_t* index) /* in: record descriptor */
{
buf_block_t* block;
page_t* page;
@@ -1480,6 +1510,8 @@ btr_search_validate(void)
ulint n_page_dumps = 0;
ibool ok = TRUE;
ulint i;
+ mem_heap_t* heap = mem_heap_create(100);
+ ulint* offsets = NULL;
rw_lock_x_lock(&btr_search_latch);
@@ -1489,9 +1521,13 @@ btr_search_validate(void)
while (node != NULL) {
block = buf_block_align(node->data);
page = buf_frame_align(node->data);
+ offsets = rec_reget_offsets((rec_t*) node->data, index,
+ offsets, block->curr_n_fields
+ + (block->curr_n_bytes > 0), heap);
if (!block->is_hashed
|| node->fold != rec_fold((rec_t*)(node->data),
+ offsets,
block->curr_n_fields,
block->curr_n_bytes,
btr_page_get_index_id(page))) {
@@ -1507,12 +1543,13 @@ btr_search_validate(void)
(ulong) ut_dulint_get_low(btr_page_get_index_id(page)),
(ulong) node->fold,
(ulong) rec_fold((rec_t*)(node->data),
+ offsets,
block->curr_n_fields,
block->curr_n_bytes,
btr_page_get_index_id(page)));
fputs("InnoDB: Record ", stderr);
- rec_print(stderr, (rec_t*)(node->data));
+ rec_print(stderr, (rec_t*)node->data, offsets);
fprintf(stderr, "\nInnoDB: on that page."
"Page mem address %p, is hashed %lu, n fields %lu, n bytes %lu\n"
"side %lu\n",
@@ -1536,6 +1573,7 @@ btr_search_validate(void)
}
rw_lock_x_unlock(&btr_search_latch);
+ mem_heap_free(heap);
return(ok);
}
diff --git a/innobase/buf/buf0buf.c b/innobase/buf/buf0buf.c
index 4b1f2d0ab99..2f8ce7507ba 100644
--- a/innobase/buf/buf0buf.c
+++ b/innobase/buf/buf0buf.c
@@ -548,8 +548,9 @@ buf_pool_init(
}
/*----------------------------------------*/
} else {
- buf_pool->frame_mem = ut_malloc(
- UNIV_PAGE_SIZE * (n_frames + 1));
+ buf_pool->frame_mem = ut_malloc_low(
+ UNIV_PAGE_SIZE * (n_frames + 1),
+ TRUE, FALSE);
}
if (buf_pool->frame_mem == NULL) {
@@ -2137,6 +2138,31 @@ buf_print(void)
}
/*************************************************************************
+Returns the number of latched pages in the buffer pool. */
+
+ulint
+buf_get_latched_pages_number(void)
+{
+ buf_block_t* block;
+ ulint i;
+ ulint fixed_pages_number = 0;
+
+ mutex_enter(&(buf_pool->mutex));
+
+ for (i = 0; i < buf_pool->curr_size; i++) {
+
+ block = buf_pool_get_nth_block(buf_pool, i);
+
+ if (((block->buf_fix_count != 0) || (block->io_fix != 0)) &&
+ block->magic_n == BUF_BLOCK_MAGIC_N )
+ fixed_pages_number++;
+ }
+
+ mutex_exit(&(buf_pool->mutex));
+ return fixed_pages_number;
+}
+
+/*************************************************************************
Returns the number of pending buf pool ios. */
ulint
diff --git a/innobase/buf/buf0flu.c b/innobase/buf/buf0flu.c
index 964c396dd08..aff4fe92a71 100644
--- a/innobase/buf/buf0flu.c
+++ b/innobase/buf/buf0flu.c
@@ -273,6 +273,10 @@ buf_flush_buffered_writes(void)
}
}
+ /* increment the doublewrite flushed pages counter */
+ srv_dblwr_pages_written+= trx_doublewrite->first_free;
+ srv_dblwr_writes++;
+
if (trx_doublewrite->first_free > TRX_SYS_DOUBLEWRITE_BLOCK_SIZE) {
len = TRX_SYS_DOUBLEWRITE_BLOCK_SIZE * UNIV_PAGE_SIZE;
} else {
@@ -901,6 +905,9 @@ buf_flush_batch(
(ulong) page_count);
}
+ if (page_count != ULINT_UNDEFINED)
+ srv_buf_pool_flushed+= page_count;
+
return(page_count);
}
diff --git a/innobase/buf/buf0lru.c b/innobase/buf/buf0lru.c
index 21dd0e304eb..985426a9e2b 100644
--- a/innobase/buf/buf0lru.c
+++ b/innobase/buf/buf0lru.c
@@ -42,6 +42,10 @@ initial segment in buf_LRU_get_recent_limit */
#define BUF_LRU_INITIAL_RATIO 8
+/* If we switch on the InnoDB monitor because there are too few available
+frames in the buffer pool, we set this to TRUE */
+ibool buf_lru_switched_on_innodb_mon = FALSE;
+
/**********************************************************************
Takes a block out of the LRU list and page hash table and sets the block
state to BUF_BLOCK_REMOVE_HASH. */
@@ -288,6 +292,32 @@ buf_LRU_try_free_flushed_blocks(void)
}
/**********************************************************************
+Returns TRUE if less than 15 % of the buffer pool is available. This can be
+used in heuristics to prevent huge transactions eating up the whole buffer
+pool for their locks. */
+
+ibool
+buf_LRU_buf_pool_running_out(void)
+/*==============================*/
+ /* out: TRUE if less than 15 % of buffer pool
+ left */
+{
+ ibool ret = FALSE;
+
+ mutex_enter(&(buf_pool->mutex));
+
+ if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 7) {
+
+ ret = TRUE;
+ }
+
+ mutex_exit(&(buf_pool->mutex));
+
+ return(ret);
+}
+
+/**********************************************************************
Returns a free block from buf_pool. The block is taken off the free list.
If it is empty, blocks are moved from the end of the LRU list to the free
list. */
@@ -325,7 +355,8 @@ loop:
} else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
+ UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 5) {
- if (!srv_print_innodb_monitor) {
+
+ if (!buf_lru_switched_on_innodb_mon) {
/* Over 80 % of the buffer pool is occupied by lock
heaps or the adaptive hash index. This may be a memory
@@ -342,16 +373,18 @@ loop:
"InnoDB: lock heap and hash index sizes.\n",
(ulong) (buf_pool->curr_size / (1024 * 1024 / UNIV_PAGE_SIZE)));
+ buf_lru_switched_on_innodb_mon = TRUE;
srv_print_innodb_monitor = TRUE;
os_event_set(srv_lock_timeout_thread_event);
}
- } else if (!recv_recovery_on && UT_LIST_GET_LEN(buf_pool->free)
- + UT_LIST_GET_LEN(buf_pool->LRU) < buf_pool->max_size / 4) {
+ } else if (buf_lru_switched_on_innodb_mon) {
/* Switch off the InnoDB Monitor; this is a simple way
to stop the monitor if the situation becomes less urgent,
- but may also surprise users! */
+ but may also surprise users if the user also switched on the
+ monitor! */
+ buf_lru_switched_on_innodb_mon = FALSE;
srv_print_innodb_monitor = FALSE;
}
@@ -432,6 +465,7 @@ loop:
/* No free block was found: try to flush the LRU list */
buf_flush_free_margin();
+ ++srv_buf_pool_wait_free;
os_aio_simulated_wake_handler_threads();
diff --git a/innobase/buf/buf0rea.c b/innobase/buf/buf0rea.c
index 11107d777c8..f34920549fe 100644
--- a/innobase/buf/buf0rea.c
+++ b/innobase/buf/buf0rea.c
@@ -20,6 +20,10 @@ Created 11/5/1995 Heikki Tuuri
#include "os0file.h"
#include "srv0start.h"
+extern ulint srv_read_ahead_rnd;
+extern ulint srv_read_ahead_seq;
+extern ulint srv_buf_pool_reads;
+
/* The size in blocks of the area where the random read-ahead algorithm counts
the accessed pages when deciding whether to read-ahead */
#define BUF_READ_AHEAD_RANDOM_AREA BUF_READ_AHEAD_AREA
@@ -291,6 +295,7 @@ buf_read_ahead_random(
(ulong) count);
}
+ ++srv_read_ahead_rnd;
return(count);
}
@@ -323,6 +328,7 @@ buf_read_page(
count2 = buf_read_page_low(&err, TRUE, BUF_READ_ANY_PAGE, space,
tablespace_version, offset);
+ srv_buf_pool_reads+= count2;
if (err == DB_TABLESPACE_DELETED) {
ut_print_timestamp(stderr);
fprintf(stderr,
@@ -575,6 +581,7 @@ buf_read_ahead_linear(
(ulong) space, (ulong) offset, (ulong) count);
}
+ ++srv_read_ahead_seq;
return(count);
}
diff --git a/innobase/configure.in b/innobase/configure.in
index 652291f1f38..baf11272ab9 100644
--- a/innobase/configure.in
+++ b/innobase/configure.in
@@ -41,7 +41,9 @@ AC_CHECK_SIZEOF(long, 4)
AC_CHECK_SIZEOF(void*, 4)
AC_CHECK_FUNCS(sched_yield)
AC_CHECK_FUNCS(fdatasync)
-#AC_CHECK_FUNCS(localtime_r) # Already checked by MySQL
+AC_CHECK_FUNCS(localtime_r)
+#AC_CHECK_FUNCS(readdir_r) MySQL checks that it has also the right args.
+# Some versions of Unix only take 2 arguments.
#AC_C_INLINE Already checked in MySQL
AC_C_BIGENDIAN
@@ -110,6 +112,9 @@ esac
case "$target" in
i[[4567]]86-*-*)
CFLAGS="$CFLAGS -DUNIV_INTEL_X86";;
+ # The compiler on Linux/S390 does not seem to have inlining
+ s390-*-*)
+ CFLAGS="$CFLAGS -DUNIV_MUST_NOT_INLINE";;
esac
AC_OUTPUT(Makefile os/Makefile ut/Makefile btr/Makefile dnl
diff --git a/innobase/data/data0data.c b/innobase/data/data0data.c
index 97ec1a1acd9..25ba19d0296 100644
--- a/innobase/data/data0data.c
+++ b/innobase/data/data0data.c
@@ -500,7 +500,7 @@ dtuple_convert_big_rec(
ut_a(dtuple_check_typed_no_assert(entry));
- size = rec_get_converted_size(entry);
+ size = rec_get_converted_size(index, entry);
if (size > 1000000000) {
fprintf(stderr,
@@ -524,9 +524,10 @@ dtuple_convert_big_rec(
n_fields = 0;
- while ((rec_get_converted_size(entry)
- >= page_get_free_space_of_empty() / 2)
- || rec_get_converted_size(entry) >= REC_MAX_DATA_SIZE) {
+ while (rec_get_converted_size(index, entry)
+ >= ut_min(page_get_free_space_of_empty(
+ index->table->comp) / 2,
+ REC_MAX_DATA_SIZE)) {
longest = 0;
for (i = dict_index_get_n_unique_in_tree(index);
diff --git a/innobase/data/data0type.c b/innobase/data/data0type.c
index 714cf92bc65..9b8fb084e33 100644
--- a/innobase/data/data0type.c
+++ b/innobase/data/data0type.c
@@ -195,7 +195,7 @@ dtype_validate(
ut_a((type->mtype >= DATA_VARCHAR) && (type->mtype <= DATA_MYSQL));
if (type->mtype == DATA_SYS) {
- ut_a(type->prtype <= DATA_MIX_ID);
+ ut_a((type->prtype & DATA_MYSQL_TYPE_MASK) < DATA_N_SYS_COLS);
}
return(TRUE);
diff --git a/innobase/dict/dict0boot.c b/innobase/dict/dict0boot.c
index f156cf67a18..e500b92252f 100644
--- a/innobase/dict/dict0boot.c
+++ b/innobase/dict/dict0boot.c
@@ -158,7 +158,7 @@ dict_hdr_create(
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_TABLES_ID, mtr);
+ DICT_HDR_SPACE, DICT_TABLES_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -168,7 +168,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_UNIQUE, DICT_HDR_SPACE,
- DICT_TABLE_IDS_ID, mtr);
+ DICT_TABLE_IDS_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -178,7 +178,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_COLUMNS_ID, mtr);
+ DICT_HDR_SPACE, DICT_COLUMNS_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -188,7 +188,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_INDEXES_ID, mtr);
+ DICT_HDR_SPACE, DICT_INDEXES_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -198,7 +198,7 @@ dict_hdr_create(
MLOG_4BYTES, mtr);
/*--------------------------*/
root_page_no = btr_create(DICT_CLUSTERED | DICT_UNIQUE,
- DICT_HDR_SPACE, DICT_FIELDS_ID, mtr);
+ DICT_HDR_SPACE, DICT_FIELDS_ID, FALSE, mtr);
if (root_page_no == FIL_NULL) {
return(FALSE);
@@ -254,7 +254,7 @@ dict_boot(void)
/* Insert into the dictionary cache the descriptions of the basic
system tables */
/*-------------------------*/
- table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE,8);
+ table = dict_mem_table_create("SYS_TABLES", DICT_HDR_SPACE, 8, FALSE);
dict_mem_table_add_col(table, "NAME", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
@@ -290,7 +290,7 @@ dict_boot(void)
index->id = DICT_TABLE_IDS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- table = dict_mem_table_create("SYS_COLUMNS",DICT_HDR_SPACE,7);
+ table = dict_mem_table_create("SYS_COLUMNS", DICT_HDR_SPACE, 7, FALSE);
dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY,0,0,0);
dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
@@ -316,7 +316,7 @@ dict_boot(void)
index->id = DICT_COLUMNS_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- table = dict_mem_table_create("SYS_INDEXES",DICT_HDR_SPACE,7);
+ table = dict_mem_table_create("SYS_INDEXES", DICT_HDR_SPACE, 7, FALSE);
dict_mem_table_add_col(table, "TABLE_ID", DATA_BINARY, 0,0,0);
dict_mem_table_add_col(table, "ID", DATA_BINARY, 0, 0, 0);
@@ -349,7 +349,7 @@ dict_boot(void)
index->id = DICT_INDEXES_ID;
ut_a(dict_index_add_to_cache(table, index));
/*-------------------------*/
- table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE,3);
+ table = dict_mem_table_create("SYS_FIELDS", DICT_HDR_SPACE, 3, FALSE);
dict_mem_table_add_col(table, "INDEX_ID", DATA_BINARY, 0,0,0);
dict_mem_table_add_col(table, "POS", DATA_INT, 0, 4, 0);
diff --git a/innobase/dict/dict0crea.c b/innobase/dict/dict0crea.c
index 137964b26c1..747a99ebdc9 100644
--- a/innobase/dict/dict0crea.c
+++ b/innobase/dict/dict0crea.c
@@ -84,7 +84,8 @@ dict_create_sys_tables_tuple(
dfield = dtuple_get_nth_field(entry, 5);
ptr = mem_heap_alloc(heap, 4);
- mach_write_to_4(ptr, table->mix_len);
+ mach_write_to_4(ptr, (table->mix_len & 0x7fffffff) |
+ ((ulint) table->comp << 31));
dfield_set_data(dfield, ptr, 4);
/* 8: CLUSTER_NAME ---------------------*/
@@ -624,7 +625,7 @@ dict_create_index_tree_step(
btr_pcur_move_to_next_user_rec(&pcur, &mtr);
index->page_no = btr_create(index->type, index->space, index->id,
- &mtr);
+ table->comp, &mtr);
/* printf("Created a new index tree in space %lu root page %lu\n",
index->space, index->page_no); */
@@ -660,8 +661,9 @@ dict_drop_index_tree(
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&(dict_sys->mutex)));
#endif /* UNIV_SYNC_DEBUG */
-
- ptr = rec_get_nth_field(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
+
+ ut_a(!dict_sys->sys_indexes->comp);
+ ptr = rec_get_nth_field_old(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD, &len);
ut_ad(len == 4);
@@ -673,8 +675,9 @@ dict_drop_index_tree(
return;
}
- ptr = rec_get_nth_field(rec, DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
-
+ ptr = rec_get_nth_field_old(rec,
+ DICT_SYS_INDEXES_SPACE_NO_FIELD, &len);
+
ut_ad(len == 4);
space = mtr_read_ulint(ptr, MLOG_4BYTES, mtr);
@@ -699,8 +702,8 @@ dict_drop_index_tree(
root_page_no); */
btr_free_root(space, root_page_no, mtr);
- page_rec_write_index_page_no(rec, DICT_SYS_INDEXES_PAGE_NO_FIELD,
- FIL_NULL, mtr);
+ page_rec_write_index_page_no(rec,
+ DICT_SYS_INDEXES_PAGE_NO_FIELD, FIL_NULL, mtr);
}
/*************************************************************************
@@ -1067,6 +1070,12 @@ dict_create_or_check_foreign_constraint_tables(void)
there are 2 secondary indexes on SYS_FOREIGN, and they
are defined just like below */
+ /* NOTE: when designing InnoDB's foreign key support in 2001, we made
+ an error and made the table names and the foreign key id of type
+ 'CHAR' (internally, really a VARCHAR). We should have made the type
+ VARBINARY, like in other InnoDB system tables, to get a clean
+ design. */
+
str =
"PROCEDURE CREATE_FOREIGN_SYS_TABLES_PROC () IS\n"
"BEGIN\n"
@@ -1284,9 +1293,17 @@ loop:
fputs(".\nA foreign key constraint of name ", ef);
ut_print_name(ef, trx, foreign->id);
fputs("\nalready exists."
- " (Note that internally InnoDB adds 'databasename/'\n"
+ " (Note that internally InnoDB adds 'databasename/'\n"
"in front of the user-defined constraint name).\n",
ef);
+ fputs("Note that InnoDB's FOREIGN KEY system tables store\n"
+ "constraint names as case-insensitive, with the\n"
+ "MySQL standard latin1_swedish_ci collation. If you\n"
+ "create tables or databases whose names differ only in\n"
+ "the character case, then collisions in constraint\n"
+ "names can occur. Workaround: name your constraints\n"
+ "explicitly with unique names.\n",
+ ef);
mutex_exit(&dict_foreign_err_mutex);
diff --git a/innobase/dict/dict0dict.c b/innobase/dict/dict0dict.c
index c3d0d8d9ac1..0aaa3a9a721 100644
--- a/innobase/dict/dict0dict.c
+++ b/innobase/dict/dict0dict.c
@@ -156,7 +156,7 @@ dict_index_build_internal_non_clust(
dict_index_t* index); /* in: user representation of a non-clustered
index */
/**************************************************************************
-Removes a foreign constraint struct from the dictionet cache. */
+Removes a foreign constraint struct from the dictionary cache. */
static
void
dict_foreign_remove_from_cache(
@@ -606,7 +606,7 @@ dict_table_get_on_id(
dict_table_t* table;
if (ut_dulint_cmp(table_id, DICT_FIELDS_ID) <= 0
- || trx->dict_operation) {
+ || trx->dict_operation_lock_mode == RW_X_LATCH) {
/* It is a system table which will always exist in the table
cache: we avoid acquiring the dictionary mutex, because
if we are doing a rollback to handle an error in TABLE
@@ -814,23 +814,22 @@ dict_table_add_to_cache(
system columns. */
dict_mem_table_add_col(table, "DB_ROW_ID", DATA_SYS,
- DATA_ROW_ID, 0, 0);
+ DATA_ROW_ID | DATA_NOT_NULL, DATA_ROW_ID_LEN, 0);
#if DATA_ROW_ID != 0
#error "DATA_ROW_ID != 0"
#endif
dict_mem_table_add_col(table, "DB_TRX_ID", DATA_SYS,
- DATA_TRX_ID, 0, 0);
+ DATA_TRX_ID | DATA_NOT_NULL, DATA_TRX_ID_LEN, 0);
#if DATA_TRX_ID != 1
#error "DATA_TRX_ID != 1"
#endif
dict_mem_table_add_col(table, "DB_ROLL_PTR", DATA_SYS,
- DATA_ROLL_PTR, 0, 0);
+ DATA_ROLL_PTR | DATA_NOT_NULL, DATA_ROLL_PTR_LEN, 0);
#if DATA_ROLL_PTR != 2
#error "DATA_ROLL_PTR != 2"
#endif
-
dict_mem_table_add_col(table, "DB_MIX_ID", DATA_SYS,
- DATA_MIX_ID, 0, 0);
+ DATA_MIX_ID | DATA_NOT_NULL, DATA_MIX_ID_LEN, 0);
#if DATA_MIX_ID != 3
#error "DATA_MIX_ID != 3"
#endif
@@ -1588,7 +1587,7 @@ dict_index_find_cols(
/***********************************************************************
Adds a column to index. */
-UNIV_INLINE
+
void
dict_index_add_col(
/*===============*/
@@ -1604,6 +1603,34 @@ dict_index_add_col(
field = dict_index_get_nth_field(index, index->n_def - 1);
field->col = col;
+ field->fixed_len = dtype_get_fixed_size(&col->type);
+
+ if (prefix_len && field->fixed_len > prefix_len) {
+ field->fixed_len = prefix_len;
+ }
+
+ /* Long fixed-length fields that need external storage are treated as
+ variable-length fields, so that the extern flag can be embedded in
+ the length word. */
+
+ if (field->fixed_len > DICT_MAX_COL_PREFIX_LEN) {
+ field->fixed_len = 0;
+ }
+
+ if (!(dtype_get_prtype(&col->type) & DATA_NOT_NULL)) {
+ index->n_nullable++;
+ }
+
+ if (index->n_def > 1) {
+ const dict_field_t* field2 =
+ dict_index_get_nth_field(index, index->n_def - 2);
+ field->fixed_offs = (!field2->fixed_len ||
+ field2->fixed_offs == ULINT_UNDEFINED)
+ ? ULINT_UNDEFINED
+ : field2->fixed_len + field2->fixed_offs;
+ } else {
+ field->fixed_offs = 0;
+ }
}
/***********************************************************************
@@ -2266,8 +2293,8 @@ dict_foreign_add_to_cache(
/*************************************************************************
Scans from pointer onwards. Stops if is at the start of a copy of
-'string' where characters are compared without case sensitivity. Stops
-also at '\0'. */
+'string' where characters are compared without case sensitivity, and
+only outside `` or "" quotes. Stops also at '\0'. */
const char*
dict_scan_to(
@@ -2276,31 +2303,34 @@ dict_scan_to(
const char* ptr, /* in: scan from */
const char* string) /* in: look for this */
{
- ibool success;
- ulint i;
-loop:
- if (*ptr == '\0') {
- return(ptr);
- }
-
- success = TRUE;
-
- for (i = 0; i < ut_strlen(string); i++) {
- if (toupper((ulint)(ptr[i])) != toupper((ulint)(string[i]))) {
- success = FALSE;
+ char quote = '\0';
+ for (; *ptr; ptr++) {
+ if (*ptr == quote) {
+ /* Closing quote character: do not look for
+ starting quote or the keyword. */
+ quote = '\0';
+ } else if (quote) {
+ /* Within quotes: do nothing. */
+ } else if (*ptr == '`' || *ptr == '"') {
+ /* Starting quote: remember the quote character. */
+ quote = *ptr;
+ } else {
+ /* Outside quotes: look for the keyword. */
+ ulint i;
+ for (i = 0; string[i]; i++) {
+ if (toupper((ulint)(ptr[i]))
+ != toupper((ulint)(string[i]))) {
+ goto nomatch;
+ }
+ }
break;
+ nomatch:
+ ;
}
}
- if (success) {
-
- return(ptr);
- }
-
- ptr++;
-
- goto loop;
+ return(ptr);
}
/*************************************************************************
@@ -2877,13 +2907,13 @@ loop:
ut_a(success);
- if (!isspace(*ptr)) {
+ if (!isspace(*ptr) && *ptr != '"' && *ptr != '`') {
goto loop;
}
- do {
+ while (isspace(*ptr)) {
ptr++;
- } while (isspace(*ptr));
+ }
/* read constraint name unless got "CONSTRAINT FOREIGN" */
if (ptr != ptr2) {
@@ -3577,9 +3607,10 @@ dict_tree_find_index_low(
&& (table->type != DICT_TABLE_ORDINARY)) {
/* Get the mix id of the record */
+ ut_a(!table->comp);
mix_id = mach_dulint_read_compressed(
- rec_get_nth_field(rec, table->mix_len, &len));
+ rec_get_nth_field_old(rec, table->mix_len, &len));
while (ut_dulint_cmp(table->mix_id, mix_id) != 0) {
@@ -3712,7 +3743,8 @@ dict_tree_build_node_ptr(
on non-leaf levels we remove the last field, which
contains the page number of the child page */
- n_unique = rec_get_n_fields(rec);
+ ut_a(!ind->table->comp);
+ n_unique = rec_get_n_fields_old(rec);
if (level > 0) {
ut_a(n_unique > 1);
@@ -3741,9 +3773,11 @@ dict_tree_build_node_ptr(
field = dtuple_get_nth_field(tuple, n_unique);
dfield_set_data(field, buf, 4);
- dtype_set(dfield_get_type(field), DATA_SYS_CHILD, 0, 0, 0);
+ dtype_set(dfield_get_type(field), DATA_SYS_CHILD, DATA_NOT_NULL, 4, 0);
- rec_copy_prefix_to_dtuple(tuple, rec, n_unique, heap);
+ rec_copy_prefix_to_dtuple(tuple, rec, ind, n_unique, heap);
+ dtuple_set_info_bits(tuple, dtuple_get_info_bits(tuple) |
+ REC_STATUS_NODE_PTR);
ut_ad(dtuple_check_typed(tuple));
@@ -3760,27 +3794,26 @@ dict_tree_copy_rec_order_prefix(
/* out: pointer to the prefix record */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to copy prefix */
+ ulint* n_fields,/* out: number of fields copied */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size)/* in/out: buffer size */
{
- dict_index_t* ind;
- rec_t* order_rec;
- ulint n_fields;
-
- ind = dict_tree_find_index_low(tree, rec);
+ dict_index_t* index;
+ ulint n;
- n_fields = dict_index_get_n_unique_in_tree(ind);
-
- if (tree->type & DICT_UNIVERSAL) {
+ index = dict_tree_find_index_low(tree, rec);
- n_fields = rec_get_n_fields(rec);
+ if (tree->type & DICT_UNIVERSAL) {
+ ut_a(!index->table->comp);
+ n = rec_get_n_fields_old(rec);
+ } else {
+ n = dict_index_get_n_unique_in_tree(index);
}
- order_rec = rec_copy_prefix_to_buf(rec, n_fields, buf, buf_size);
-
- return(order_rec);
-}
+ *n_fields = n;
+ return(rec_copy_prefix_to_buf(rec, index, n, buf, buf_size));
+}
/**************************************************************************
Builds a typed data tuple out of a physical record. */
@@ -3791,21 +3824,21 @@ dict_tree_build_data_tuple(
/* out, own: data tuple */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build data tuple */
+ ulint n_fields,/* in: number of data fields */
mem_heap_t* heap) /* in: memory heap where tuple created */
{
dtuple_t* tuple;
dict_index_t* ind;
- ulint n_fields;
ind = dict_tree_find_index_low(tree, rec);
- n_fields = rec_get_n_fields(rec);
+ ut_ad(ind->table->comp || n_fields <= rec_get_n_fields_old(rec));
tuple = dtuple_create(heap, n_fields);
dict_index_copy_types(tuple, ind, n_fields);
- rec_copy_prefix_to_dtuple(tuple, rec, n_fields, heap);
+ rec_copy_prefix_to_dtuple(tuple, rec, ind, n_fields, heap);
ut_ad(dtuple_check_typed(tuple));
@@ -3823,6 +3856,27 @@ dict_index_calc_min_rec_len(
ulint sum = 0;
ulint i;
+ if (index->table->comp) {
+ ulint nullable = 0;
+ sum = REC_N_NEW_EXTRA_BYTES;
+ for (i = 0; i < dict_index_get_n_fields(index); i++) {
+ dtype_t*t = dict_index_get_nth_type(index, i);
+ ulint size = dtype_get_fixed_size(t);
+ sum += size;
+ if (!size) {
+ size = dtype_get_len(t);
+ sum += size < 128 ? 1 : 2;
+ }
+ if (!(dtype_get_prtype(t) & DATA_NOT_NULL))
+ nullable++;
+ }
+
+ /* round the NULL flags up to full bytes */
+ sum += (nullable + 7) / 8;
+
+ return(sum);
+ }
+
for (i = 0; i < dict_index_get_n_fields(index); i++) {
sum += dtype_get_fixed_size(dict_index_get_nth_type(index, i));
}
@@ -3833,7 +3887,7 @@ dict_index_calc_min_rec_len(
sum += dict_index_get_n_fields(index);
}
- sum += REC_N_EXTRA_BYTES;
+ sum += REC_N_OLD_EXTRA_BYTES;
return(sum);
}
diff --git a/innobase/dict/dict0load.c b/innobase/dict/dict0load.c
index d430eadc97b..c80f8346abf 100644
--- a/innobase/dict/dict0load.c
+++ b/innobase/dict/dict0load.c
@@ -19,7 +19,9 @@ Created 4/24/1996 Heikki Tuuri
#include "mach0data.h"
#include "dict0dict.h"
#include "dict0boot.h"
+#include "rem0cmp.h"
#include "srv0start.h"
+#include "srv0srv.h"
/************************************************************************
Finds the first table name in the given database. */
@@ -53,6 +55,7 @@ dict_get_first_table_name_in_db(
sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
+ ut_a(!sys_tables->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -75,7 +78,7 @@ loop:
return(NULL);
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
if (len < strlen(name)
|| ut_memcmp(name, field, strlen(name)) != 0) {
@@ -88,7 +91,7 @@ loop:
return(NULL);
}
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
/* We found one */
@@ -123,6 +126,13 @@ dict_print(void)
ulint len;
mtr_t mtr;
+ /* Enlarge the fatal semaphore wait timeout during the InnoDB table
+ monitor printout */
+
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold += 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
mutex_enter(&(dict_sys->mutex));
mtr_start(&mtr);
@@ -145,12 +155,18 @@ loop:
mutex_exit(&(dict_sys->mutex));
+ /* Restore the fatal semaphore wait timeout */
+
+ mutex_enter(&kernel_mutex);
+ srv_fatal_semaphore_wait_threshold -= 7200; /* 2 hours */
+ mutex_exit(&kernel_mutex);
+
return;
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
/* We found one */
@@ -214,6 +230,7 @@ dict_check_tablespaces_or_store_max_id(
sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
+ ut_a(!sys_tables->comp);
btr_pcur_open_at_index_side(TRUE, sys_index, BTR_SEARCH_LEAF, &pcur,
TRUE, &mtr);
@@ -240,15 +257,15 @@ loop:
return;
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, sys_tables->comp)) {
/* We found one */
char* name = mem_strdupl((char*) field, len);
- field = rec_get_nth_field(rec, 9, &len);
+ field = rec_get_nth_field_old(rec, 9, &len);
ut_a(len == 4);
space_id = mach_read_from_4(field);
@@ -313,6 +330,7 @@ dict_load_columns(
sys_columns = dict_table_get_low("SYS_COLUMNS");
sys_index = UT_LIST_GET_FIRST(sys_columns->indexes);
+ ut_a(!sys_columns->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -331,28 +349,27 @@ dict_load_columns(
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
- ut_a(!rec_get_deleted_flag(rec));
-
- field = rec_get_nth_field(rec, 0, &len);
+ ut_a(!rec_get_deleted_flag(rec, sys_columns->comp));
+
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
ut_a(ut_dulint_cmp(table->id, mach_read_from_8(field)) == 0);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
ut_ad(len == 4);
ut_a(i == mach_read_from_4(field));
ut_a(0 == ut_strcmp("NAME",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_columns), 4))->name));
+ dict_index_get_nth_field(sys_index, 4))->name));
- field = rec_get_nth_field(rec, 4, &len);
+ field = rec_get_nth_field_old(rec, 4, &len);
name = mem_heap_strdupl(heap, (char*) field, len);
- field = rec_get_nth_field(rec, 5, &len);
+ field = rec_get_nth_field_old(rec, 5, &len);
mtype = mach_read_from_4(field);
- field = rec_get_nth_field(rec, 6, &len);
+ field = rec_get_nth_field_old(rec, 6, &len);
prtype = mach_read_from_4(field);
if (dtype_is_non_binary_string_type(mtype, prtype)
@@ -364,15 +381,14 @@ dict_load_columns(
data_mysql_default_charset_coll);
}
- field = rec_get_nth_field(rec, 7, &len);
+ field = rec_get_nth_field_old(rec, 7, &len);
col_len = mach_read_from_4(field);
ut_a(0 == ut_strcmp("PREC",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_columns), 8))->name));
+ dict_index_get_nth_field(sys_index, 8))->name));
- field = rec_get_nth_field(rec, 8, &len);
+ field = rec_get_nth_field_old(rec, 8, &len);
prec = mach_read_from_4(field);
dict_mem_table_add_col(table, name, mtype, prtype, col_len,
@@ -437,6 +453,7 @@ dict_load_fields(
sys_fields = dict_table_get_low("SYS_FIELDS");
sys_index = UT_LIST_GET_FIRST(sys_fields->indexes);
+ ut_a(!sys_fields->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -454,15 +471,15 @@ dict_load_fields(
rec = btr_pcur_get_rec(&pcur);
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, sys_fields->comp)) {
dict_load_report_deleted_index(table->name, i);
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
ut_a(ut_memcmp(buf, field, len) == 0);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
ut_a(len == 4);
/* The next field stores the field position in the index
@@ -488,10 +505,9 @@ dict_load_fields(
ut_a(0 == ut_strcmp("COL_NAME",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_fields), 4))->name));
+ dict_index_get_nth_field(sys_index, 4))->name));
- field = rec_get_nth_field(rec, 4, &len);
+ field = rec_get_nth_field_old(rec, 4, &len);
dict_mem_index_add_field(index,
mem_heap_strdupl(heap, (char*) field, len), 0, prefix_len);
@@ -550,6 +566,7 @@ dict_load_indexes(
sys_indexes = dict_table_get_low("SYS_INDEXES");
sys_index = UT_LIST_GET_FIRST(sys_indexes->indexes);
+ ut_a(!sys_indexes->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -570,14 +587,14 @@ dict_load_indexes(
rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
if (ut_memcmp(buf, field, len) != 0) {
break;
}
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, table->comp)) {
dict_load_report_deleted_index(table->name,
ULINT_UNDEFINED);
@@ -587,33 +604,31 @@ dict_load_indexes(
return(FALSE);
}
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
ut_ad(len == 8);
id = mach_read_from_8(field);
ut_a(0 == ut_strcmp("NAME",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_indexes), 4))->name));
-
- field = rec_get_nth_field(rec, 4, &name_len);
+ dict_index_get_nth_field(sys_index, 4))->name));
+
+ field = rec_get_nth_field_old(rec, 4, &name_len);
name_buf = mem_heap_strdupl(heap, (char*) field, name_len);
- field = rec_get_nth_field(rec, 5, &len);
+ field = rec_get_nth_field_old(rec, 5, &len);
n_fields = mach_read_from_4(field);
- field = rec_get_nth_field(rec, 6, &len);
+ field = rec_get_nth_field_old(rec, 6, &len);
type = mach_read_from_4(field);
- field = rec_get_nth_field(rec, 7, &len);
+ field = rec_get_nth_field_old(rec, 7, &len);
space = mach_read_from_4(field);
ut_a(0 == ut_strcmp("PAGE_NO",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_indexes), 8))->name));
+ dict_index_get_nth_field(sys_index, 8))->name));
- field = rec_get_nth_field(rec, 8, &len);
+ field = rec_get_nth_field_old(rec, 8, &len);
page_no = mach_read_from_4(field);
if (page_no == FIL_NULL) {
@@ -716,6 +731,7 @@ dict_load_table(
sys_tables = dict_table_get_low("SYS_TABLES");
sys_index = UT_LIST_GET_FIRST(sys_tables->indexes);
+ ut_a(!sys_tables->comp);
tuple = dtuple_create(heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -728,7 +744,7 @@ dict_load_table(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
- || rec_get_deleted_flag(rec)) {
+ || rec_get_deleted_flag(rec, sys_tables->comp)) {
/* Not found */
btr_pcur_close(&pcur);
@@ -738,7 +754,7 @@ dict_load_table(
return(NULL);
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the table name in record is the searched one */
if (len != ut_strlen(name) || ut_memcmp(name, field, len) != 0) {
@@ -752,10 +768,9 @@ dict_load_table(
ut_a(0 == ut_strcmp("SPACE",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_tables), 9))->name));
+ dict_index_get_nth_field(sys_index, 9))->name));
- field = rec_get_nth_field(rec, 9, &len);
+ field = rec_get_nth_field_old(rec, 9, &len);
space = mach_read_from_4(field);
/* Check if the tablespace exists and has the right name */
@@ -777,43 +792,45 @@ dict_load_table(
ut_a(0 == ut_strcmp("N_COLS",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_tables), 4))->name));
+ dict_index_get_nth_field(sys_index, 4))->name));
- field = rec_get_nth_field(rec, 4, &len);
+ field = rec_get_nth_field_old(rec, 4, &len);
n_cols = mach_read_from_4(field);
- table = dict_mem_table_create(name, space, n_cols);
+ /* table->comp will be initialized later, in this function */
+ table = dict_mem_table_create(name, space, n_cols, FALSE);
table->ibd_file_missing = ibd_file_missing;
ut_a(0 == ut_strcmp("ID",
dict_field_get_col(
- dict_index_get_nth_field(
- dict_table_get_first_index(sys_tables), 3))->name));
+ dict_index_get_nth_field(sys_index, 3))->name));
- field = rec_get_nth_field(rec, 3, &len);
+ field = rec_get_nth_field_old(rec, 3, &len);
table->id = mach_read_from_8(field);
- field = rec_get_nth_field(rec, 5, &len);
+ field = rec_get_nth_field_old(rec, 5, &len);
table->type = mach_read_from_4(field);
if (table->type == DICT_TABLE_CLUSTER_MEMBER) {
ut_error;
#if 0 /* clustered tables have not been implemented yet */
- field = rec_get_nth_field(rec, 6, &len);
+ field = rec_get_nth_field_old(rec, 6, &len);
table->mix_id = mach_read_from_8(field);
- field = rec_get_nth_field(rec, 8, &len);
+ field = rec_get_nth_field_old(rec, 8, &len);
table->cluster_name = mem_heap_strdupl(heap, (char*) field, len);
#endif
}
+ /* The high-order bit of MIX_LEN is the "compact format" flag */
+ field = rec_get_nth_field_old(rec, 7, &len);
+ table->comp = !!(mach_read_from_1(field) & 0x80);
+
if ((table->type == DICT_TABLE_CLUSTER)
|| (table->type == DICT_TABLE_CLUSTER_MEMBER)) {
-
- field = rec_get_nth_field(rec, 7, &len);
- table->mix_len = mach_read_from_4(field);
+
+ table->mix_len = mach_read_from_4(field) & 0x7fffffff;
}
btr_pcur_close(&pcur);
@@ -891,6 +908,7 @@ dict_load_table_on_id(
sys_tables = dict_sys->sys_tables;
sys_table_ids = dict_table_get_next_index(
dict_table_get_first_index(sys_tables));
+ ut_a(!sys_tables->comp);
heap = mem_heap_create(256);
tuple = dtuple_create(heap, 1);
@@ -907,7 +925,7 @@ dict_load_table_on_id(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
- || rec_get_deleted_flag(rec)) {
+ || rec_get_deleted_flag(rec, sys_tables->comp)) {
/* Not found */
btr_pcur_close(&pcur);
@@ -922,7 +940,7 @@ dict_load_table_on_id(
table ID and NAME */
rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_ad(len == 8);
/* Check if the table id in record is the one searched for */
@@ -936,7 +954,7 @@ dict_load_table_on_id(
}
/* Now we get the table name from the record */
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
/* Load the table definition to memory */
table = dict_load_table(mem_heap_strdupl(heap, (char*) field, len));
@@ -1004,6 +1022,7 @@ dict_load_foreign_cols(
sys_foreign_cols = dict_table_get_low("SYS_FOREIGN_COLS");
sys_index = UT_LIST_GET_FIRST(sys_foreign_cols->indexes);
+ ut_a(!sys_foreign_cols->comp);
tuple = dtuple_create(foreign->heap, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -1018,21 +1037,21 @@ dict_load_foreign_cols(
rec = btr_pcur_get_rec(&pcur);
ut_a(btr_pcur_is_on_user_rec(&pcur, &mtr));
- ut_a(!rec_get_deleted_flag(rec));
-
- field = rec_get_nth_field(rec, 0, &len);
+ ut_a(!rec_get_deleted_flag(rec, sys_foreign_cols->comp));
+
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == ut_strlen(id));
ut_a(ut_memcmp(id, field, len) == 0);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
ut_a(len == 4);
ut_a(i == mach_read_from_4(field));
- field = rec_get_nth_field(rec, 4, &len);
+ field = rec_get_nth_field_old(rec, 4, &len);
foreign->foreign_col_names[i] =
mem_heap_strdupl(foreign->heap, (char*) field, len);
- field = rec_get_nth_field(rec, 5, &len);
+ field = rec_get_nth_field_old(rec, 5, &len);
foreign->referenced_col_names[i] =
mem_heap_strdupl(foreign->heap, (char*) field, len);
@@ -1076,6 +1095,7 @@ dict_load_foreign(
sys_foreign = dict_table_get_low("SYS_FOREIGN");
sys_index = UT_LIST_GET_FIRST(sys_foreign->indexes);
+ ut_a(!sys_foreign->comp);
tuple = dtuple_create(heap2, 1);
dfield = dtuple_get_nth_field(tuple, 0);
@@ -1088,7 +1108,7 @@ dict_load_foreign(
rec = btr_pcur_get_rec(&pcur);
if (!btr_pcur_is_on_user_rec(&pcur, &mtr)
- || rec_get_deleted_flag(rec)) {
+ || rec_get_deleted_flag(rec, sys_foreign->comp)) {
/* Not found */
fprintf(stderr,
@@ -1102,7 +1122,7 @@ dict_load_foreign(
return(DB_ERROR);
}
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
/* Check if the id in record is the searched one */
if (len != ut_strlen(id) || ut_memcmp(id, field, len) != 0) {
@@ -1125,7 +1145,8 @@ dict_load_foreign(
foreign = dict_mem_foreign_create();
- foreign->n_fields = mach_read_from_4(rec_get_nth_field(rec, 5, &len));
+ foreign->n_fields =
+ mach_read_from_4(rec_get_nth_field_old(rec, 5, &len));
ut_a(len == 4);
@@ -1136,11 +1157,11 @@ dict_load_foreign(
foreign->id = mem_heap_strdup(foreign->heap, id);
- field = rec_get_nth_field(rec, 3, &len);
+ field = rec_get_nth_field_old(rec, 3, &len);
foreign->foreign_table_name =
mem_heap_strdupl(foreign->heap, (char*) field, len);
-
- field = rec_get_nth_field(rec, 4, &len);
+
+ field = rec_get_nth_field_old(rec, 4, &len);
foreign->referenced_table_name =
mem_heap_strdupl(foreign->heap, (char*) field, len);
@@ -1209,6 +1230,7 @@ dict_load_foreigns(
return(DB_ERROR);
}
+ ut_a(!sys_foreign->comp);
mtr_start(&mtr);
/* Get the secondary index based on FOR_NAME from table
@@ -1240,22 +1262,36 @@ loop:
name and a foreign constraint ID */
rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
- /* Check if the table name in record is the one searched for */
- if (len != ut_strlen(table_name)
- || 0 != ut_memcmp(field, table_name, len)) {
+ /* Check if the table name in the record is the one searched for; the
+ following call does the comparison in the latin1_swedish_ci
+ charset-collation, in a case-insensitive way. */
+ if (0 != cmp_data_data(dfield_get_type(dfield),
+ dfield_get_data(dfield), dfield_get_len(dfield),
+ field, len)) {
+
goto load_next_index;
}
+
+ /* Since table names in SYS_FOREIGN are stored in a case-insensitive
+ order, we have to check that the table name matches also in a binary
+ string comparison. On Unix, MySQL allows table names that only differ
+ in character case. */
+
+ if (0 != ut_memcmp(field, table_name, len)) {
+
+ goto next_rec;
+ }
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, sys_foreign->comp)) {
goto next_rec;
}
/* Now we get a foreign key constraint id */
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
id = mem_heap_strdupl(heap, (char*) field, len);
btr_pcur_store_position(&pcur, &mtr);
diff --git a/innobase/dict/dict0mem.c b/innobase/dict/dict0mem.c
index 1d45585aac1..48b9f28d292 100644
--- a/innobase/dict/dict0mem.c
+++ b/innobase/dict/dict0mem.c
@@ -35,7 +35,8 @@ dict_mem_table_create(
the table is placed; this parameter is
ignored if the table is made a member of
a cluster */
- ulint n_cols) /* in: number of columns */
+ ulint n_cols, /* in: number of columns */
+ ibool comp) /* in: TRUE=compact page format */
{
dict_table_t* table;
mem_heap_t* heap;
@@ -54,6 +55,7 @@ dict_mem_table_create(
table->space = space;
table->ibd_file_missing = FALSE;
table->tablespace_discarded = FALSE;
+ table->comp = comp;
table->n_def = 0;
table->n_cols = n_cols + DATA_N_SYS_COLS;
table->mem_fix = 0;
@@ -110,7 +112,8 @@ dict_mem_cluster_create(
{
dict_table_t* cluster;
- cluster = dict_mem_table_create(name, space, n_cols);
+ /* Clustered tables cannot work with the compact record format. */
+ cluster = dict_mem_table_create(name, space, n_cols, FALSE);
cluster->type = DICT_TABLE_CLUSTER;
cluster->mix_len = mix_len;
@@ -197,7 +200,7 @@ dict_mem_index_create(
index->name = mem_heap_strdup(heap, index_name);
index->table_name = table_name;
index->table = NULL;
- index->n_def = 0;
+ index->n_def = index->n_nullable = 0;
index->n_fields = n_fields;
index->fields = mem_heap_alloc(heap, 1 + n_fields
* sizeof(dict_field_t));
diff --git a/innobase/eval/eval0eval.c b/innobase/eval/eval0eval.c
index ebb6cb1b7d9..5b2d1f857b1 100644
--- a/innobase/eval/eval0eval.c
+++ b/innobase/eval/eval0eval.c
@@ -627,7 +627,11 @@ eval_concat(
}
/*********************************************************************
-Evaluates a predefined function node. */
+Evaluates a predefined function node. If the first argument is an integer,
+this function looks at the second argument which is the integer length in
+bytes, and converts the integer to a VARCHAR.
+If the first argument is of some other type, this function converts it to
+BINARY. */
UNIV_INLINE
void
eval_to_binary(
@@ -638,12 +642,24 @@ eval_to_binary(
que_node_t* arg2;
dfield_t* dfield;
byte* str1;
+ ulint len;
ulint len1;
arg1 = func_node->args;
str1 = dfield_get_data(que_node_get_val(arg1));
+ if (dtype_get_mtype(que_node_get_data_type(arg1)) != DATA_INT) {
+
+ len = dfield_get_len(que_node_get_val(arg1));
+
+ dfield = que_node_get_val(func_node);
+
+ dfield_set_data(dfield, str1, len);
+
+ return;
+ }
+
arg2 = que_node_get_next(arg1);
len1 = (ulint)eval_node_get_int_val(arg2);
diff --git a/innobase/fil/fil0fil.c b/innobase/fil/fil0fil.c
index 7d57468f632..dea48117e00 100644
--- a/innobase/fil/fil0fil.c
+++ b/innobase/fil/fil0fil.c
@@ -88,6 +88,9 @@ but in the MySQL Embedded Server Library and ibbackup it is not the default
directory, and we must set the base file path explicitly */
const char* fil_path_to_mysql_datadir = ".";
+/* The number of fsyncs done to the log */
+ulint fil_n_log_flushes = 0;
+
ulint fil_n_pending_log_flushes = 0;
ulint fil_n_pending_tablespace_flushes = 0;
@@ -106,7 +109,7 @@ struct fil_node_struct {
device or a raw disk partition */
ulint size; /* size of the file in database pages, 0 if
not known yet; the possible last incomplete
- megabyte is ignored if space == 0 */
+ megabyte may be ignored if space == 0 */
ulint n_pending;
/* count of pending i/o's on this file;
closing of the file is not allowed if
@@ -160,7 +163,9 @@ struct fil_space_struct {
UT_LIST_BASE_NODE_T(fil_node_t) chain;
/* base node for the file chain */
ulint size; /* space size in pages; 0 if a single-table
- tablespace whose size we do not know yet */
+ tablespace whose size we do not know yet;
+ last incomplete megabytes in data files may be
+ ignored if space == 0 */
ulint n_reserved_extents;
/* number of reserved free extents for
ongoing operations like B-tree page split */
@@ -1574,30 +1579,38 @@ fil_op_write_log(
mtr_t* mtr) /* in: mini-transaction handle */
{
byte* log_ptr;
+ ulint len;
+
+ log_ptr = mlog_open(mtr, 11 + 2);
+
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery:
+ in that case mlog_open returns NULL */
+ return;
+ }
- log_ptr = mlog_open(mtr, 30);
-
log_ptr = mlog_write_initial_log_record_for_file_op(type, space_id, 0,
log_ptr, mtr);
/* Let us store the strings as null-terminated for easier readability
and handling */
- mach_write_to_2(log_ptr, ut_strlen(name) + 1);
+ len = strlen(name) + 1;
+
+ mach_write_to_2(log_ptr, len);
log_ptr += 2;
-
mlog_close(mtr, log_ptr);
- mlog_catenate_string(mtr, (byte*) name, ut_strlen(name) + 1);
+ mlog_catenate_string(mtr, (byte*) name, len);
if (type == MLOG_FILE_RENAME) {
- log_ptr = mlog_open(mtr, 30);
- mach_write_to_2(log_ptr, ut_strlen(new_name) + 1);
+ ulint len = strlen(new_name) + 1;
+ log_ptr = mlog_open(mtr, 2 + len);
+ ut_a(log_ptr);
+ mach_write_to_2(log_ptr, len);
log_ptr += 2;
-
mlog_close(mtr, log_ptr);
- mlog_catenate_string(mtr, (byte*) new_name,
- ut_strlen(new_name) + 1);
+ mlog_catenate_string(mtr, (byte*) new_name, len);
}
}
#endif
@@ -3255,7 +3268,7 @@ fil_extend_space_to_desired_size(
ulint* actual_size, /* out: size of the space after extension;
if we ran out of disk space this may be lower
than the desired size */
- ulint space_id, /* in: space id, must be != 0 */
+ ulint space_id, /* in: space id */
ulint size_after_extend)/* in: desired size in pages after the
extension; if the current space size is bigger
than this already, the function does nothing */
@@ -3352,6 +3365,17 @@ fil_extend_space_to_desired_size(
fil_node_complete_io(node, system, OS_FILE_WRITE);
*actual_size = space->size;
+
+ if (space_id == 0) {
+ ulint pages_per_mb = (1024 * 1024) / UNIV_PAGE_SIZE;
+
+ /* Keep the last data file size info up to date, rounded to
+ full megabytes */
+
+ srv_data_file_sizes[srv_n_data_files - 1] =
+ (node->size / pages_per_mb) * pages_per_mb;
+ }
+
/*
printf("Extended %s to %lu, actual size %lu pages\n", space->name,
size_after_extend, *actual_size); */
@@ -3671,6 +3695,12 @@ fil_io(
mode = OS_AIO_NORMAL;
}
+ if (type == OS_FILE_READ) {
+ srv_data_read+= len;
+ } else if (type == OS_FILE_WRITE) {
+ srv_data_written+= len;
+ }
+
/* Reserve the fil_system mutex and make sure that we can open at
least one file while holding it, if the file is not already open */
@@ -3956,6 +3986,7 @@ fil_flush(
fil_n_pending_tablespace_flushes++;
} else {
fil_n_pending_log_flushes++;
+ fil_n_log_flushes++;
}
#ifdef __WIN__
if (node->is_raw_disk) {
diff --git a/innobase/fsp/fsp0fsp.c b/innobase/fsp/fsp0fsp.c
index e1621cc2765..ef8e70646c6 100644
--- a/innobase/fsp/fsp0fsp.c
+++ b/innobase/fsp/fsp0fsp.c
@@ -910,7 +910,7 @@ fsp_header_init(
if (space == 0) {
fsp_fill_free_list(FALSE, space, header, mtr);
btr_create(DICT_CLUSTERED | DICT_UNIVERSAL | DICT_IBUF, space,
- ut_dulint_add(DICT_IBUF_ID_MIN, space), mtr);
+ ut_dulint_add(DICT_IBUF_ID_MIN, space), FALSE, mtr);
} else {
fsp_fill_free_list(TRUE, space, header, mtr);
}
diff --git a/innobase/ibuf/ibuf0ibuf.c b/innobase/ibuf/ibuf0ibuf.c
index b3c8ade2414..c7ca03f9901 100644
--- a/innobase/ibuf/ibuf0ibuf.c
+++ b/innobase/ibuf/ibuf0ibuf.c
@@ -46,7 +46,7 @@ Note that contary to what we planned in the 1990's, there will only be one
insert buffer tree, and that is in the system tablespace of InnoDB.
1. The first field is the space id.
-2. The second field is a one-byte marker which differentiates records from
+2. The second field is a one-byte marker (0) which differentiates records from
the < 4.1.x storage format.
3. The third field is the page number.
4. The fourth field contains the type info, where we have also added 2 bytes to
@@ -55,7 +55,14 @@ insert buffer tree, and that is in the system tablespace of InnoDB.
can use in the binary search on the index page in the ibuf merge phase.
5. The rest of the fields contain the fields of the actual index record.
-*/
+In versions >= 5.0.3:
+
+The first byte of the fourth field is an additional marker (0) if the record
+is in the compact format. The presence of this marker can be detected by
+looking at the length of the field modulo DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE.
+
+The high-order bit of the character set field in the type info is the
+"nullable" flag for the field. */
/* PREVENTING DEADLOCKS IN THE INSERT BUFFER SYSTEM
@@ -525,8 +532,8 @@ ibuf_data_init_for_space(
ibuf_exit();
sprintf(buf, "SYS_IBUF_TABLE_%lu", (ulong) space);
-
- table = dict_mem_table_create(buf, space, 2);
+ /* use old-style record format for the insert buffer */
+ table = dict_mem_table_create(buf, space, 2, FALSE);
dict_mem_table_add_col(table, "PAGE_NO", DATA_BINARY, 0, 0, 0);
dict_mem_table_add_col(table, "TYPES", DATA_BINARY, 0, 0, 0);
@@ -1049,20 +1056,20 @@ ibuf_rec_get_page_no(
ulint len;
ut_ad(ibuf_inside());
- ut_ad(rec_get_n_fields(rec) > 2);
+ ut_ad(rec_get_n_fields_old(rec) > 2);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
- field = rec_get_nth_field(rec, 2, &len);
+ field = rec_get_nth_field_old(rec, 2, &len);
} else {
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
}
ut_a(len == 4);
@@ -1084,15 +1091,15 @@ ibuf_rec_get_space(
ulint len;
ut_ad(ibuf_inside());
- ut_ad(rec_get_n_fields(rec) > 2);
+ ut_ad(rec_get_n_fields_old(rec) > 2);
- field = rec_get_nth_field(rec, 1, &len);
+ field = rec_get_nth_field_old(rec, 1, &len);
if (len == 1) {
/* This is of the >= 4.1.x record format */
ut_a(trx_sys_multiple_tablespace_format);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == 4);
return(mach_read_from_4(field));
@@ -1105,6 +1112,161 @@ ibuf_rec_get_space(
}
/************************************************************************
+Creates a dummy index for inserting a record to a non-clustered index.
+*/
+static
+dict_index_t*
+ibuf_dummy_index_create(
+/*====================*/
+ /* out: dummy index */
+ ulint n, /* in: number of fields */
+ ibool comp) /* in: TRUE=use compact record format */
+{
+ dict_table_t* table;
+ dict_index_t* index;
+ table = dict_mem_table_create("IBUF_DUMMY",
+ DICT_HDR_SPACE, n, comp);
+ index = dict_mem_index_create("IBUF_DUMMY", "IBUF_DUMMY",
+ DICT_HDR_SPACE, 0, n);
+ index->table = table;
+ /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
+ index->cached = TRUE;
+ return(index);
+}
+/************************************************************************
+Add a column to the dummy index */
+static
+void
+ibuf_dummy_index_add_col(
+/*====================*/
+ dict_index_t* index, /* in: dummy index */
+ dtype_t* type) /* in: the data type of the column */
+{
+ ulint i = index->table->n_def;
+ dict_mem_table_add_col(index->table, "DUMMY",
+ dtype_get_mtype(type),
+ dtype_get_prtype(type),
+ dtype_get_len(type),
+ dtype_get_prec(type));
+ dict_index_add_col(index,
+ dict_table_get_nth_col(index->table, i), 0, 0);
+}
+/************************************************************************
+Deallocates a dummy index for inserting a record to a non-clustered index.
+*/
+static
+void
+ibuf_dummy_index_free(
+/*====================*/
+ dict_index_t* index) /* in: dummy index */
+{
+ dict_table_t* table = index->table;
+ mem_heap_free(index->heap);
+ mutex_free(&(table->autoinc_mutex));
+ mem_heap_free(table->heap);
+}
+
+/*************************************************************************
+Builds the entry to insert into a non-clustered index when we have the
+corresponding record in an ibuf index. */
+static
+dtuple_t*
+ibuf_build_entry_from_ibuf_rec(
+/*===========================*/
+ /* out, own: entry to insert to
+ a non-clustered index; NOTE that
+ as we copy pointers to fields in
+ ibuf_rec, the caller must hold a
+ latch to the ibuf_rec page as long
+ as the entry is used! */
+ rec_t* ibuf_rec, /* in: record in an insert buffer */
+ mem_heap_t* heap, /* in: heap where built */
+ dict_index_t** pindex) /* out, own: dummy index that
+ describes the entry */
+{
+ dtuple_t* tuple;
+ dfield_t* field;
+ ulint n_fields;
+ byte* types;
+ const byte* data;
+ ulint len;
+ ulint i;
+ dict_index_t* index;
+
+ data = rec_get_nth_field_old(ibuf_rec, 1, &len);
+
+ if (len > 1) {
+ /* This a < 4.1.x format record */
+
+ ut_a(trx_doublewrite_must_reset_space_ids);
+ ut_a(!trx_sys_multiple_tablespace_format);
+
+ n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
+ tuple = dtuple_create(heap, n_fields);
+ types = rec_get_nth_field_old(ibuf_rec, 1, &len);
+
+ ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
+
+ for (i = 0; i < n_fields; i++) {
+ field = dtuple_get_nth_field(tuple, i);
+
+ data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
+
+ dfield_set_data(field, data, len);
+
+ dtype_read_for_order_and_null_size(
+ dfield_get_type(field),
+ types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
+ }
+
+ *pindex = ibuf_dummy_index_create(n_fields, FALSE);
+ return(tuple);
+ }
+
+ /* This a >= 4.1.x format record */
+
+ ut_a(trx_sys_multiple_tablespace_format);
+ ut_a(*data == 0);
+ ut_a(rec_get_n_fields_old(ibuf_rec) > 4);
+
+ n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
+
+ tuple = dtuple_create(heap, n_fields);
+
+ types = rec_get_nth_field_old(ibuf_rec, 3, &len);
+
+ ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1);
+ index = ibuf_dummy_index_create(n_fields,
+ len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+
+ if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
+ /* compact record format */
+ len--;
+ ut_a(*types == 0);
+ types++;
+ }
+
+ ut_a(len == n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+
+ for (i = 0; i < n_fields; i++) {
+ field = dtuple_get_nth_field(tuple, i);
+
+ data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
+
+ dfield_set_data(field, data, len);
+
+ dtype_new_read_for_order_and_null_size(
+ dfield_get_type(field),
+ types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+
+ ibuf_dummy_index_add_col(index, dfield_get_type(field));
+ }
+
+ *pindex = index;
+ return(tuple);
+}
+
+/************************************************************************
Returns the space taken by a stored non-clustered index entry if converted to
an index record. */
static
@@ -1125,43 +1287,60 @@ ibuf_rec_get_volume(
ulint i;
ut_ad(ibuf_inside());
- ut_ad(rec_get_n_fields(ibuf_rec) > 2);
-
- data = rec_get_nth_field(ibuf_rec, 1, &len);
+ ut_ad(rec_get_n_fields_old(ibuf_rec) > 2);
+
+ data = rec_get_nth_field_old(ibuf_rec, 1, &len);
if (len > 1) {
- /* < 4.1.x format record */
+ /* < 4.1.x format record */
ut_a(trx_doublewrite_must_reset_space_ids);
ut_a(!trx_sys_multiple_tablespace_format);
- n_fields = rec_get_n_fields(ibuf_rec) - 2;
+ n_fields = rec_get_n_fields_old(ibuf_rec) - 2;
- types = rec_get_nth_field(ibuf_rec, 1, &len);
+ types = rec_get_nth_field_old(ibuf_rec, 1, &len);
ut_ad(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
} else {
- /* >= 4.1.x format record */
+ /* >= 4.1.x format record */
ut_a(trx_sys_multiple_tablespace_format);
- new_format = TRUE;
+ ut_a(*data == 0);
+
+ types = rec_get_nth_field_old(ibuf_rec, 3, &len);
+
+ ut_a(len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE <= 1);
+ if (len % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE) {
+ /* compact record format */
+ ulint volume;
+ dict_index_t* dummy_index;
+ mem_heap_t* heap = mem_heap_create(500);
+ dtuple_t* entry =
+ ibuf_build_entry_from_ibuf_rec(
+ ibuf_rec, heap, &dummy_index);
+ volume = rec_get_converted_size(dummy_index, entry);
+ ibuf_dummy_index_free(dummy_index);
+ mem_heap_free(heap);
+ return(volume + page_dir_calc_reserved_space(1));
+ }
- n_fields = rec_get_n_fields(ibuf_rec) - 4;
+ n_fields = rec_get_n_fields_old(ibuf_rec) - 4;
- types = rec_get_nth_field(ibuf_rec, 3, &len);
+ new_format = TRUE;
}
for (i = 0; i < n_fields; i++) {
if (new_format) {
- data = rec_get_nth_field(ibuf_rec, i + 4, &len);
+ data = rec_get_nth_field_old(ibuf_rec, i + 4, &len);
dtype_new_read_for_order_and_null_size(&dtype,
- types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+ types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
} else {
- data = rec_get_nth_field(ibuf_rec, i + 2, &len);
+ data = rec_get_nth_field_old(ibuf_rec, i + 2, &len);
dtype_read_for_order_and_null_size(&dtype,
- types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
+ types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
}
if (len == UNIV_SQL_NULL) {
@@ -1187,6 +1366,7 @@ ibuf_entry_build(
must be kept because we copy pointers to its
fields */
dtuple_t* entry, /* in: entry for a non-clustered index */
+ ibool comp, /* in: flag: TRUE=compact record format */
ulint space, /* in: space id */
ulint page_no,/* in: index page number where entry should
be inserted */
@@ -1202,11 +1382,14 @@ ibuf_entry_build(
/* Starting from 4.1.x, we have to build a tuple whose
(1) first field is the space id,
- (2) the second field a single marker byte to tell that this
+ (2) the second field a single marker byte (0) to tell that this
is a new format record,
(3) the third contains the page number, and
(4) the fourth contains the relevent type information of each data
- field,
+ field; the length of this field % DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE is
+ (a) 0 for b-trees in the old format, and
+ (b) 1 for b-trees in the compact format, the first byte of the field
+ being the marker (0);
(5) and the rest of the fields are copied from entry. All fields
in the tuple are ordered like the type binary in our insert buffer
tree. */
@@ -1247,10 +1430,15 @@ ibuf_entry_build(
dfield_set_data(field, buf, 4);
+ ut_ad(comp == 0 || comp == 1);
/* Store the type info in buf2, and add the fields from entry to
tuple */
buf2 = mem_heap_alloc(heap, n_fields
- * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+ * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+ + comp);
+ if (comp) {
+ *buf2++ = 0; /* write the compact format indicator */
+ }
for (i = 0; i < n_fields; i++) {
/* We add 4 below because we have the 4 extra fields at the
start of an ibuf record */
@@ -1268,8 +1456,13 @@ ibuf_entry_build(
field = dtuple_get_nth_field(tuple, 3);
+ if (comp) {
+ buf2--;
+ }
+
dfield_set_data(field, buf2, n_fields
- * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+ * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+ + comp);
/* Set all the types in the new tuple binary */
dtuple_set_types_binary(tuple, n_fields + 4);
@@ -1278,88 +1471,6 @@ ibuf_entry_build(
}
/*************************************************************************
-Builds the entry to insert into a non-clustered index when we have the
-corresponding record in an ibuf index. */
-static
-dtuple_t*
-ibuf_build_entry_from_ibuf_rec(
-/*===========================*/
- /* out, own: entry to insert to
- a non-clustered index; NOTE that
- as we copy pointers to fields in
- ibuf_rec, the caller must hold a
- latch to the ibuf_rec page as long
- as the entry is used! */
- rec_t* ibuf_rec, /* in: record in an insert buffer */
- mem_heap_t* heap) /* in: heap where built */
-{
- dtuple_t* tuple;
- dfield_t* field;
- ulint n_fields;
- byte* types;
- byte* data;
- ulint len;
- ulint i;
-
- data = rec_get_nth_field(ibuf_rec, 1, &len);
-
- if (len > 1) {
- /* This a < 4.1.x format record */
-
- ut_a(trx_doublewrite_must_reset_space_ids);
- ut_a(!trx_sys_multiple_tablespace_format);
-
- n_fields = rec_get_n_fields(ibuf_rec) - 2;
- tuple = dtuple_create(heap, n_fields);
- types = rec_get_nth_field(ibuf_rec, 1, &len);
-
- ut_a(len == n_fields * DATA_ORDER_NULL_TYPE_BUF_SIZE);
-
- for (i = 0; i < n_fields; i++) {
- field = dtuple_get_nth_field(tuple, i);
-
- data = rec_get_nth_field(ibuf_rec, i + 2, &len);
-
- dfield_set_data(field, data, len);
-
- dtype_read_for_order_and_null_size(
- dfield_get_type(field),
- types + i * DATA_ORDER_NULL_TYPE_BUF_SIZE);
- }
-
- return(tuple);
- }
-
- /* This a >= 4.1.x format record */
-
- ut_a(trx_sys_multiple_tablespace_format);
-
- ut_a(rec_get_n_fields(ibuf_rec) > 4);
-
- n_fields = rec_get_n_fields(ibuf_rec) - 4;
-
- tuple = dtuple_create(heap, n_fields);
-
- types = rec_get_nth_field(ibuf_rec, 3, &len);
-
- ut_a(len == n_fields * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
-
- for (i = 0; i < n_fields; i++) {
- field = dtuple_get_nth_field(tuple, i);
-
- data = rec_get_nth_field(ibuf_rec, i + 4, &len);
-
- dfield_set_data(field, data, len);
-
- dtype_new_read_for_order_and_null_size(
- dfield_get_type(field),
- types + i * DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
- }
-
- return(tuple);
-}
-
-/*************************************************************************
Builds a search tuple used to search buffered inserts for an index page.
This is for < 4.1.x format records */
static
@@ -2047,8 +2158,7 @@ loop:
mutex_exit(&ibuf_mutex);
sum_sizes = ibuf_get_merge_page_nos(TRUE, btr_pcur_get_rec(&pcur),
- space_ids, space_versions, page_nos,
- &n_stored);
+ space_ids, space_versions, page_nos, &n_stored);
#ifdef UNIV_IBUF_DEBUG
/* fprintf(stderr, "Ibuf contract sync %lu pages %lu volume %lu\n",
sync, n_stored, sum_sizes); */
@@ -2344,6 +2454,7 @@ ibuf_update_max_tablespace_id(void)
ibuf_data = fil_space_get_ibuf_data(0);
ibuf_index = ibuf_data->index;
+ ut_a(!ibuf_index->table->comp);
ibuf_enter();
@@ -2360,7 +2471,7 @@ ibuf_update_max_tablespace_id(void)
} else {
rec = btr_pcur_get_rec(&pcur);
- field = rec_get_nth_field(rec, 0, &len);
+ field = rec_get_nth_field_old(rec, 0, &len);
ut_a(len == 4);
@@ -2479,7 +2590,7 @@ ibuf_insert_low(
ibuf_enter();
}
- entry_size = rec_get_converted_size(entry);
+ entry_size = rec_get_converted_size(index, entry);
heap = mem_heap_create(512);
@@ -2487,7 +2598,8 @@ ibuf_insert_low(
the first fields and the type information for other fields, and which
will be inserted to the insert buffer. */
- ibuf_entry = ibuf_entry_build(entry, space, page_no, heap);
+ ibuf_entry = ibuf_entry_build(entry, index->table->comp,
+ space, page_no, heap);
/* Open a cursor to the insert buffer tree to calculate if we can add
the new entry to it without exceeding the free space limit for the
@@ -2532,8 +2644,8 @@ ibuf_insert_low(
do_merge = TRUE;
ibuf_get_merge_page_nos(FALSE, btr_pcur_get_rec(&pcur),
- space_ids, space_versions, page_nos,
- &n_stored);
+ space_ids, space_versions,
+ page_nos, &n_stored);
goto function_exit;
}
@@ -2656,8 +2768,8 @@ ibuf_insert(
ut_a(!(index->type & DICT_CLUSTERED));
- if (rec_get_converted_size(entry)
- >= page_get_free_space_of_empty() / 2) {
+ if (rec_get_converted_size(index, entry)
+ >= page_get_free_space_of_empty(index->table->comp) / 2) {
return(FALSE);
}
@@ -2692,6 +2804,7 @@ ibuf_insert_to_index_page(
dtuple_t* entry, /* in: buffered entry to insert */
page_t* page, /* in: index page where the buffered entry
should be placed */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mtr */
{
page_cur_t page_cur;
@@ -2699,17 +2812,28 @@ ibuf_insert_to_index_page(
rec_t* rec;
page_t* bitmap_page;
ulint old_bits;
+ mem_heap_t* heap;
ut_ad(ibuf_inside());
ut_ad(dtuple_check_typed(entry));
- if (rec_get_n_fields(page_rec_get_next(page_get_infimum_rec(page)))
- != dtuple_get_n_fields(entry)) {
-
- fprintf(stderr,
+ if (index->table->comp != page_is_comp(page)) {
+ fputs(
"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
-"InnoDB: but the number of fields does not match!\n");
+"InnoDB: but the 'compact' flag does not match!\n", stderr);
+ goto dump;
+ }
+
+ heap = mem_heap_create(100);
+ rec = page_rec_get_next(page_get_infimum_rec(page));
+ if (rec_offs_n_fields(rec_get_offsets(rec, index, ULINT_UNDEFINED,
+ heap)) != dtuple_get_n_fields(entry)) {
+ mem_heap_free(heap);
+ fputs(
+"InnoDB: Trying to insert a record from the insert buffer to an index page\n"
+"InnoDB: but the number of fields does not match!\n", stderr);
+ dump:
buf_page_print(page);
dtuple_print(stderr, entry);
@@ -2723,31 +2847,35 @@ ibuf_insert_to_index_page(
return;
}
- low_match = page_cur_search(page, entry, PAGE_CUR_LE, &page_cur);
+ mem_heap_free(heap);
+ low_match = page_cur_search(page, index, entry,
+ PAGE_CUR_LE, &page_cur);
if (low_match == dtuple_get_n_fields(entry)) {
rec = page_cur_get_rec(&page_cur);
- btr_cur_del_unmark_for_ibuf(rec, mtr);
+ btr_cur_del_unmark_for_ibuf(rec, index, mtr);
} else {
- rec = page_cur_tuple_insert(&page_cur, entry, mtr);
+ rec = page_cur_tuple_insert(&page_cur, entry, index, mtr);
if (rec == NULL) {
/* If the record did not fit, reorganize */
- btr_page_reorganize(page, mtr);
+ btr_page_reorganize(page, index, mtr);
- page_cur_search(page, entry, PAGE_CUR_LE, &page_cur);
+ page_cur_search(page, index, entry,
+ PAGE_CUR_LE, &page_cur);
/* This time the record must fit */
- if (!page_cur_tuple_insert(&page_cur, entry, mtr)) {
+ if (!page_cur_tuple_insert(&page_cur, entry,
+ index, mtr)) {
ut_print_timestamp(stderr);
fprintf(stderr,
"InnoDB: Error: Insert buffer insert fails; page free %lu, dtuple size %lu\n",
(ulong) page_get_max_insert_size(page, 1),
- (ulong) rec_get_converted_size(entry));
+ (ulong) rec_get_converted_size(index, entry));
fputs("InnoDB: Cannot insert index record ",
stderr);
dtuple_print(stderr, entry);
@@ -2836,11 +2964,12 @@ ibuf_delete_rec(
"InnoDB: ibuf record inserted to page %lu\n", (ulong) page_no);
fflush(stderr);
- rec_print(stderr, btr_pcur_get_rec(pcur));
- rec_print(stderr, pcur->old_rec);
+ rec_print_old(stderr, btr_pcur_get_rec(pcur));
+ rec_print_old(stderr, pcur->old_rec);
dtuple_print(stderr, search_tuple);
- rec_print(stderr, page_rec_get_next(btr_pcur_get_rec(pcur)));
+ rec_print_old(stderr,
+ page_rec_get_next(btr_pcur_get_rec(pcur)));
fflush(stderr);
btr_pcur_commit_specify_mtr(pcur, mtr);
@@ -2866,6 +2995,8 @@ ibuf_delete_rec(
#ifdef UNIV_IBUF_DEBUG
ibuf_count_set(space, page_no, ibuf_count_get(space, page_no) - 1);
+#else
+ UT_NOT_USED(space);
#endif
ibuf_data_sizes_update(ibuf_data, root, mtr);
@@ -3073,7 +3204,7 @@ loop:
if (corruption_noticed) {
fputs("InnoDB: Discarding record\n ", stderr);
- rec_print(stderr, ibuf_rec);
+ rec_print_old(stderr, ibuf_rec);
fputs("\n from the insert buffer!\n\n", stderr);
} else if (page) {
/* Now we have at pcur a record which should be
@@ -3081,19 +3212,22 @@ loop:
copies pointers to fields in ibuf_rec, and we must
keep the latch to the ibuf_rec page until the
insertion is finished! */
-
- dulint max_trx_id = page_get_max_trx_id(
+ dict_index_t* dummy_index;
+ dulint max_trx_id = page_get_max_trx_id(
buf_frame_align(ibuf_rec));
page_update_max_trx_id(page, max_trx_id);
- entry = ibuf_build_entry_from_ibuf_rec(ibuf_rec, heap);
+ entry = ibuf_build_entry_from_ibuf_rec(ibuf_rec,
+ heap, &dummy_index);
#ifdef UNIV_IBUF_DEBUG
- volume += rec_get_converted_size(entry)
+ volume += rec_get_converted_size(dummy_index, entry)
+ page_dir_calc_reserved_space(1);
ut_a(volume <= 4 * UNIV_PAGE_SIZE
/ IBUF_PAGE_SIZE_PER_FREE_SPACE);
#endif
- ibuf_insert_to_index_page(entry, page, &mtr);
+ ibuf_insert_to_index_page(entry, page,
+ dummy_index, &mtr);
+ ibuf_dummy_index_free(dummy_index);
}
n_inserts++;
@@ -3267,11 +3401,11 @@ leave_loop:
ibuf_data->n_merged_recs += n_inserts;
mutex_exit(&ibuf_mutex);
-
+ /*
fprintf(stderr,
"InnoDB: Discarded %lu ibuf entries for space %lu\n",
(ulong) n_inserts, (ulong) space);
-
+ */
ibuf_exit();
mem_heap_free(heap);
diff --git a/innobase/include/btr0btr.h b/innobase/include/btr0btr.h
index 8606fcd2a5c..0b19e64d4e0 100644
--- a/innobase/include/btr0btr.h
+++ b/innobase/include/btr0btr.h
@@ -155,7 +155,8 @@ ulint
btr_node_ptr_get_child_page_no(
/*===========================*/
/* out: child node address */
- rec_t* rec); /* in: node pointer record */
+ rec_t* rec, /* in: node pointer record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/****************************************************************
Creates the root node for a new index tree. */
@@ -167,6 +168,7 @@ btr_create(
ulint type, /* in: type of the index */
ulint space, /* in: space where created */
dulint index_id,/* in: index id */
+ ibool comp, /* in: TRUE=compact page format */
mtr_t* mtr); /* in: mini-transaction handle */
/****************************************************************
Frees a B-tree except the root page, which MUST be freed after this
@@ -210,8 +212,9 @@ Reorganizes an index page. */
void
btr_page_reorganize(
/*================*/
- page_t* page, /* in: page to be reorganized */
- mtr_t* mtr); /* in: mtr */
+ page_t* page, /* in: page to be reorganized */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Decides if the page should be split at the convergence point of
inserts converging to left. */
@@ -273,6 +276,7 @@ void
btr_set_min_rec_mark(
/*=================*/
rec_t* rec, /* in: record */
+ ibool comp, /* in: TRUE=compact page format */
mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes on the upper level the node pointer to a page. */
@@ -332,6 +336,7 @@ btr_parse_set_min_rec_mark(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
+ ibool comp, /* in: TRUE=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
@@ -340,11 +345,12 @@ Parses a redo log record of reorganizing a page. */
byte*
btr_parse_page_reorganize(
/*======================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/******************************************************************
Gets the number of pages in a B-tree. */
diff --git a/innobase/include/btr0btr.ic b/innobase/include/btr0btr.ic
index b0aa0756307..1d1f97d3668 100644
--- a/innobase/include/btr0btr.ic
+++ b/innobase/include/btr0btr.ic
@@ -183,17 +183,18 @@ ulint
btr_node_ptr_get_child_page_no(
/*===========================*/
/* out: child node address */
- rec_t* rec) /* in: node pointer record */
+ rec_t* rec, /* in: node pointer record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n_fields;
byte* field;
ulint len;
ulint page_no;
- n_fields = rec_get_n_fields(rec);
+ ut_ad(!rec_offs_comp(offsets) || rec_get_node_ptr_flag(rec));
/* The child address is in the last field */
- field = rec_get_nth_field(rec, n_fields - 1, &len);
+ field = rec_get_nth_field(rec, offsets,
+ rec_offs_n_fields(offsets) - 1, &len);
ut_ad(len == 4);
diff --git a/innobase/include/btr0cur.h b/innobase/include/btr0cur.h
index f1334656d53..0a8d8ceaeb7 100644
--- a/innobase/include/btr0cur.h
+++ b/innobase/include/btr0cur.h
@@ -34,7 +34,7 @@ page_cur_t*
btr_cur_get_page_cur(
/*=================*/
/* out: pointer to page cursor component */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the record pointer of a tree cursor. */
UNIV_INLINE
@@ -42,14 +42,14 @@ rec_t*
btr_cur_get_rec(
/*============*/
/* out: pointer to record */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Invalidates a tree cursor by setting record pointer to NULL. */
UNIV_INLINE
void
btr_cur_invalidate(
/*===============*/
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the page of a tree cursor. */
UNIV_INLINE
@@ -57,7 +57,7 @@ page_t*
btr_cur_get_page(
/*=============*/
/* out: pointer to page */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Returns the tree of a cursor. */
UNIV_INLINE
@@ -65,7 +65,7 @@ dict_tree_t*
btr_cur_get_tree(
/*=============*/
/* out: tree */
- btr_cur_t* cursor); /* in: tree cursor */
+ btr_cur_t* cursor);/* in: tree cursor */
/*************************************************************
Positions a tree cursor at a given record. */
UNIV_INLINE
@@ -283,8 +283,9 @@ only used by the insert buffer insert merge mechanism. */
void
btr_cur_del_unmark_for_ibuf(
/*========================*/
- rec_t* rec, /* in: record to delete unmark */
- mtr_t* mtr); /* in: mtr */
+ rec_t* rec, /* in: record to delete unmark */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Tries to compress a page of the tree on the leaf level. It is assumed
that mtr holds an x-latch on the tree and on the cursor page. To avoid
@@ -361,10 +362,11 @@ Parses a redo log record of updating a record in-place. */
byte*
btr_cur_parse_update_in_place(
/*==========================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ page_t* page, /* in: page or NULL */
+ dict_index_t* index); /* in: index corresponding to page */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a clustered
index record. */
@@ -372,10 +374,11 @@ index record. */
byte*
btr_cur_parse_del_mark_set_clust_rec(
/*=================================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: index corresponding to page */
+ page_t* page); /* in: page or NULL */
/********************************************************************
Parses the redo log record for delete marking or unmarking of a secondary
index record. */
@@ -383,10 +386,11 @@ index record. */
byte*
btr_cur_parse_del_mark_set_sec_rec(
/*===============================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page); /* in: page or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: index corresponding to page */
+ page_t* page); /* in: page or NULL */
/***********************************************************************
Estimates the number of rows in a given index range. */
@@ -417,9 +421,10 @@ to free the field. */
void
btr_cur_mark_extern_inherited_fields(
/*=================================*/
- rec_t* rec, /* in: record in a clustered index */
- upd_t* update, /* in: update vector */
- mtr_t* mtr); /* in: mtr */
+ rec_t* rec, /* in: record in a clustered index */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update, /* in: update vector */
+ mtr_t* mtr); /* in: mtr */
/***********************************************************************
The complement of the previous function: in an update entry may inherit
some externally stored fields from a record. We must mark them as inherited
@@ -456,6 +461,7 @@ btr_store_big_rec_extern_fields(
dict_index_t* index, /* in: index of rec; the index tree
MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
big_rec_t* big_rec_vec, /* in: vector containing fields
to be stored externally */
mtr_t* local_mtr); /* in: mtr containing the latch to
@@ -496,6 +502,7 @@ btr_rec_free_externally_stored_fields(
dict_index_t* index, /* in: index of the data, the index
tree MUST be X-latched */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ibool do_not_free_inherited,/* in: TRUE if called in a
rollback and we do not want to free
inherited fields */
@@ -510,6 +517,7 @@ btr_rec_copy_externally_stored_field(
/*=================================*/
/* out: the field copied to heap */
rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint no, /* in: field number */
ulint* len, /* out: length of the field */
mem_heap_t* heap); /* in: mem heap */
@@ -540,10 +548,10 @@ ulint
btr_push_update_extern_fields(
/*==========================*/
/* out: number of values stored in ext_vect */
- ulint* ext_vect, /* in: array of ulints, must be preallocated
- to have place for all fields in rec */
- rec_t* rec, /* in: record */
- upd_t* update); /* in: update vector */
+ ulint* ext_vect,/* in: array of ulints, must be preallocated
+ to have space for all fields in rec */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update);/* in: update vector or NULL */
/*######################################################################*/
diff --git a/innobase/include/btr0cur.ic b/innobase/include/btr0cur.ic
index a3a04b60c45..dcad3e9e14d 100644
--- a/innobase/include/btr0cur.ic
+++ b/innobase/include/btr0cur.ic
@@ -134,17 +134,15 @@ btr_cur_can_delete_without_compress(
/* out: TRUE if can be deleted without
recommended compression */
btr_cur_t* cursor, /* in: btr cursor */
+ ulint rec_size,/* in: rec_get_size(btr_cur_get_rec(cursor))*/
mtr_t* mtr) /* in: mtr */
{
- ulint rec_size;
page_t* page;
ut_ad(mtr_memo_contains(mtr, buf_block_align(
btr_cur_get_page(cursor)),
MTR_MEMO_PAGE_X_FIX));
- rec_size = rec_get_size(btr_cur_get_rec(cursor));
-
page = btr_cur_get_page(cursor);
if ((page_get_data_size(page) - rec_size < BTR_CUR_PAGE_COMPRESS_LIMIT)
diff --git a/innobase/include/btr0pcur.h b/innobase/include/btr0pcur.h
index 81f19af4d40..6384222be51 100644
--- a/innobase/include/btr0pcur.h
+++ b/innobase/include/btr0pcur.h
@@ -462,6 +462,7 @@ struct btr_pcur_struct{
contains an initial segment of the
latest record cursor was positioned
either on, before, or after */
+ ulint old_n_fields; /* number of fields in old_rec */
ulint rel_pos; /* BTR_PCUR_ON, BTR_PCUR_BEFORE, or
BTR_PCUR_AFTER, depending on whether
cursor was on, before, or after the
diff --git a/innobase/include/btr0sea.h b/innobase/include/btr0sea.h
index ce4140ecf92..73cd95d1464 100644
--- a/innobase/include/btr0sea.h
+++ b/innobase/include/btr0sea.h
@@ -77,8 +77,10 @@ parameters as page (this often happens when a page is split). */
void
btr_search_move_or_delete_hash_entries(
/*===================================*/
- page_t* new_page, /* in: records are copied to this page */
- page_t* page); /* in: index page */
+ page_t* new_page, /* in: records are copied
+ to this page */
+ page_t* page, /* in: index page */
+ dict_index_t* index); /* in: record descriptor */
/************************************************************************
Drops a page hash index. */
@@ -128,9 +130,10 @@ btr_search_update_hash_on_delete(
Validates the search system. */
ibool
-btr_search_validate(void);
-/*=====================*/
-
+btr_search_validate(
+/*================*/
+ /* out: TRUE if ok */
+ dict_index_t* index); /* in: record descriptor */
/* Search info directions */
#define BTR_SEA_NO_DIRECTION 1
diff --git a/innobase/include/buf0buf.h b/innobase/include/buf0buf.h
index f72207be29c..b46b8ce40be 100644
--- a/innobase/include/buf0buf.h
+++ b/innobase/include/buf0buf.h
@@ -58,6 +58,8 @@ extern buf_pool_t* buf_pool; /* The buffer pool of the database */
extern ibool buf_debug_prints;/* If this is set TRUE, the program
prints info whenever read or flush
occurs */
+extern ulint srv_buf_pool_write_requests; /* variable to count write request
+ issued */
/************************************************************************
Creates the buffer pool. */
@@ -497,6 +499,12 @@ void
buf_print(void);
/*============*/
/*************************************************************************
+Returns the number of latched pages in the buffer pool. */
+
+ulint
+buf_get_latched_pages_number(void);
+/*==============================*/
+/*************************************************************************
Returns the number of pending buf pool ios. */
ulint
diff --git a/innobase/include/buf0flu.ic b/innobase/include/buf0flu.ic
index d6dbdcc0865..9a8a021e029 100644
--- a/innobase/include/buf0flu.ic
+++ b/innobase/include/buf0flu.ic
@@ -61,6 +61,8 @@ buf_flush_note_modification(
ut_ad(ut_dulint_cmp(block->oldest_modification,
mtr->start_lsn) <= 0);
}
+
+ ++srv_buf_pool_write_requests;
}
/************************************************************************
diff --git a/innobase/include/buf0lru.h b/innobase/include/buf0lru.h
index 69a376f8cab..45164dd561e 100644
--- a/innobase/include/buf0lru.h
+++ b/innobase/include/buf0lru.h
@@ -25,6 +25,16 @@ wasted. */
void
buf_LRU_try_free_flushed_blocks(void);
/*==================================*/
+/**********************************************************************
+Returns TRUE if less than 15 % of the buffer pool is available. This can be
+used in heuristics to prevent huge transactions eating up the whole buffer
+pool for their locks. */
+
+ibool
+buf_LRU_buf_pool_running_out(void);
+/*==============================*/
+ /* out: TRUE if less than 15 % of buffer pool
+ left */
/*#######################################################################
These are low-level functions
diff --git a/innobase/include/data0type.ic b/innobase/include/data0type.ic
index 946b646ffbf..0b92ffbe7f1 100644
--- a/innobase/include/data0type.ic
+++ b/innobase/include/data0type.ic
@@ -8,6 +8,17 @@ Created 1/16/1996 Heikki Tuuri
#include "mach0data.h"
+/**********************************************************************
+Determines whether the given character set is of variable length.
+
+NOTE: the prototype of this function is copied from ha_innodb.cc! If you change
+this function, you MUST change also the prototype here! */
+extern
+ibool
+innobase_is_mb_cset(
+/*================*/
+ ulint cset); /* in: MySQL charset-collation code */
+
/*************************************************************************
Sets a data type structure. */
UNIV_INLINE
@@ -149,8 +160,10 @@ dtype_new_store_for_order_and_null_size(
bytes where we store the info */
dtype_t* type) /* in: type struct */
{
- ut_ad(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
-
+#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
+#endif
+
buf[0] = (byte)(type->mtype & 0xFFUL);
if (type->prtype & DATA_BINARY_TYPE) {
@@ -166,10 +179,12 @@ dtype_new_store_for_order_and_null_size(
mach_write_to_2(buf + 2, type->len & 0xFFFFUL);
+ ut_ad(dtype_get_charset_coll(type->prtype) < 256);
mach_write_to_2(buf + 4, dtype_get_charset_coll(type->prtype));
- /* Note that the second last byte is left unused, because the
- charset-collation code is always < 256 */
+ if (type->prtype & DATA_NOT_NULL) {
+ buf[4] |= 128;
+ }
}
/**************************************************************************
@@ -211,20 +226,26 @@ dtype_new_read_for_order_and_null_size(
{
ulint charset_coll;
- ut_ad(6 == DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE);
+#if 6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE
+#error "6 != DATA_NEW_ORDER_NULL_TYPE_BUF_SIZE"
+#endif
type->mtype = buf[0] & 63;
type->prtype = buf[1];
if (buf[0] & 128) {
- type->prtype = type->prtype | DATA_BINARY_TYPE;
+ type->prtype |= DATA_BINARY_TYPE;
+ }
+
+ if (buf[4] & 128) {
+ type->prtype |= DATA_NOT_NULL;
}
type->len = mach_read_from_2(buf + 2);
mach_read_from_2(buf + 4);
- charset_coll = mach_read_from_2(buf + 4);
+ charset_coll = mach_read_from_2(buf + 4) & 0x7fff;
if (dtype_is_string_type(type->mtype)) {
ut_a(charset_coll < 256);
@@ -257,23 +278,39 @@ dtype_get_fixed_size(
mtype = dtype_get_mtype(type);
switch (mtype) {
+ case DATA_SYS:
+#ifdef UNIV_DEBUG
+ switch (type->prtype & DATA_MYSQL_TYPE_MASK) {
+ default:
+ ut_ad(0);
+ return(0);
+ case DATA_ROW_ID:
+ ut_ad(type->len == DATA_ROW_ID_LEN);
+ break;
+ case DATA_TRX_ID:
+ ut_ad(type->len == DATA_TRX_ID_LEN);
+ break;
+ case DATA_ROLL_PTR:
+ ut_ad(type->len == DATA_ROLL_PTR_LEN);
+ break;
+ case DATA_MIX_ID:
+ ut_ad(type->len == DATA_MIX_ID_LEN);
+ break;
+ }
+#endif /* UNIV_DEBUG */
case DATA_CHAR:
case DATA_FIXBINARY:
case DATA_INT:
case DATA_FLOAT:
case DATA_DOUBLE:
case DATA_MYSQL:
- return(dtype_get_len(type));
-
- case DATA_SYS: if (type->prtype == DATA_ROW_ID) {
- return(DATA_ROW_ID_LEN);
- } else if (type->prtype == DATA_TRX_ID) {
- return(DATA_TRX_ID_LEN);
- } else if (type->prtype == DATA_ROLL_PTR) {
- return(DATA_ROLL_PTR_LEN);
- } else {
- return(0);
+ if ((type->prtype & DATA_BINARY_TYPE)
+ || !innobase_is_mb_cset(
+ dtype_get_charset_coll(
+ type->prtype))) {
+ return(dtype_get_len(type));
}
+ /* fall through for variable-length charsets */
case DATA_VARCHAR:
case DATA_BINARY:
case DATA_DECIMAL:
diff --git a/innobase/include/db0err.h b/innobase/include/db0err.h
index be7667bfd0c..de5ac44e73f 100644
--- a/innobase/include/db0err.h
+++ b/innobase/include/db0err.h
@@ -53,7 +53,11 @@ Created 5/24/1996 Heikki Tuuri
name already exists */
#define DB_TABLESPACE_DELETED 44 /* tablespace does not exist or is
being dropped right now */
-
+#define DB_LOCK_TABLE_FULL 45 /* lock structs have exhausted the
+ buffer pool (for big transactions,
+ InnoDB stores the lock structs in the
+ buffer pool) */
+
/* The following are partial failure codes */
#define DB_FAIL 1000
#define DB_OVERFLOW 1001
diff --git a/innobase/include/dict0dict.h b/innobase/include/dict0dict.h
index ca632691450..a2399a81ca9 100644
--- a/innobase/include/dict0dict.h
+++ b/innobase/include/dict0dict.h
@@ -639,6 +639,16 @@ dict_index_get_sys_col_pos(
dict_index_t* index, /* in: index */
ulint type); /* in: DATA_ROW_ID, ... */
/***********************************************************************
+Adds a column to index. */
+
+void
+dict_index_add_col(
+/*===============*/
+ dict_index_t* index, /* in: index */
+ dict_col_t* col, /* in: column */
+ ulint order, /* in: order criterion */
+ ulint prefix_len); /* in: column prefix length */
+/***********************************************************************
Copies types of fields contained in index to tuple. */
void
@@ -657,6 +667,7 @@ dict_index_rec_get_sys_col(
/*=======================*/
/* out: system column value */
dict_index_t* index, /* in: clustered index describing the record */
+ const ulint* offsets,/* in: offsets returned by rec_get_offsets() */
ulint type, /* in: column type: DATA_ROLL_PTR, ... */
rec_t* rec); /* in: record */
/*************************************************************************
@@ -770,6 +781,7 @@ dict_tree_copy_rec_order_prefix(
/* out: pointer to the prefix record */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to copy prefix */
+ ulint* n_fields,/* out: number of fields copied */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size);/* in/out: buffer size */
@@ -782,6 +794,7 @@ dict_tree_build_data_tuple(
/* out, own: data tuple */
dict_tree_t* tree, /* in: index tree */
rec_t* rec, /* in: record for which to build data tuple */
+ ulint n_fields,/* in: number of data fields */
mem_heap_t* heap); /* in: memory heap where tuple created */
/*************************************************************************
Gets the space id of the root of the index tree. */
diff --git a/innobase/include/dict0dict.ic b/innobase/include/dict0dict.ic
index 0f7cc8973db..7f754e316b3 100644
--- a/innobase/include/dict0dict.ic
+++ b/innobase/include/dict0dict.ic
@@ -168,7 +168,7 @@ dict_table_get_sys_col(
col = dict_table_get_nth_col(table, table->n_cols
- DATA_N_SYS_COLS + sys);
ut_ad(col->type.mtype == DATA_SYS);
- ut_ad(col->type.prtype == sys);
+ ut_ad(col->type.prtype == (sys | DATA_NOT_NULL));
return(col);
}
@@ -322,6 +322,7 @@ dict_index_rec_get_sys_col(
/*=======================*/
/* out: system column value */
dict_index_t* index, /* in: clustered index describing the record */
+ const ulint* offsets,/* in: offsets returned by rec_get_offsets() */
ulint type, /* in: column type: DATA_ROLL_PTR, ... */
rec_t* rec) /* in: record */
{
@@ -331,24 +332,28 @@ dict_index_rec_get_sys_col(
ut_ad(index);
ut_ad(index->type & DICT_CLUSTERED);
-
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
pos = dict_index_get_sys_col_pos(index, type);
ut_ad(pos != ULINT_UNDEFINED);
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
if (type == DATA_ROLL_PTR) {
ut_ad(len == 7);
return(trx_read_roll_ptr(field));
- } else if ((type == DATA_ROW_ID) || (type == DATA_MIX_ID)) {
+ } else if (type == DATA_TRX_ID) {
+
+ return(trx_read_trx_id(field));
+ } else if (type == DATA_MIX_ID) {
return(mach_dulint_read_compressed(field));
} else {
- ut_ad(type == DATA_TRX_ID);
+ ut_a(type == DATA_ROW_ID);
- return(trx_read_trx_id(field));
+ return(mach_read_from_6(field));
}
}
@@ -674,7 +679,10 @@ dict_is_mixed_table_rec(
byte* mix_id_field;
ulint len;
- mix_id_field = rec_get_nth_field(rec, table->mix_len, &len);
+ ut_ad(!table->comp);
+
+ mix_id_field = rec_get_nth_field_old(rec,
+ table->mix_len, &len);
if ((len != table->mix_id_len)
|| (0 != ut_memcmp(table->mix_id_buf, mix_id_field, len))) {
diff --git a/innobase/include/dict0mem.h b/innobase/include/dict0mem.h
index 1e496a25477..670b3445a55 100644
--- a/innobase/include/dict0mem.h
+++ b/innobase/include/dict0mem.h
@@ -54,7 +54,8 @@ dict_mem_table_create(
of the table is placed; this parameter
is ignored if the table is made
a member of a cluster */
- ulint n_cols); /* in: number of columns */
+ ulint n_cols, /* in: number of columns */
+ ibool comp); /* in: TRUE=compact page format */
/**************************************************************************
Creates a cluster memory object. */
@@ -171,6 +172,13 @@ struct dict_field_struct{
DICT_MAX_COL_PREFIX_LEN; NOTE that
in the UTF-8 charset, MySQL sets this
to 3 * the prefix len in UTF-8 chars */
+ ulint fixed_len; /* 0 or the fixed length of the
+ column if smaller than
+ DICT_MAX_COL_PREFIX_LEN */
+ ulint fixed_offs; /* offset to the field, or
+ ULINT_UNDEFINED if it is not fixed
+ within the record (due to preceding
+ variable-length fields) */
};
/* Data structure for an index tree */
@@ -225,6 +233,7 @@ struct dict_index_struct{
ulint n_def; /* number of fields defined so far */
ulint n_fields;/* number of fields in the index */
dict_field_t* fields; /* array of field descriptions */
+ ulint n_nullable;/* number of nullable fields */
UT_LIST_NODE_T(dict_index_t)
indexes;/* list of indexes of the table */
dict_tree_t* tree; /* index tree struct */
@@ -320,6 +329,7 @@ struct dict_table_struct{
ibool tablespace_discarded;/* this flag is set TRUE when the
user calls DISCARD TABLESPACE on this table,
and reset to FALSE in IMPORT TABLESPACE */
+ ibool comp; /* flag: TRUE=compact page format */
hash_node_t name_hash; /* hash chain node */
hash_node_t id_hash; /* hash chain node */
ulint n_def; /* number of columns defined so far */
diff --git a/innobase/include/fil0fil.h b/innobase/include/fil0fil.h
index 5a5db77073a..75b32937e0b 100644
--- a/innobase/include/fil0fil.h
+++ b/innobase/include/fil0fil.h
@@ -89,6 +89,8 @@ extern fil_addr_t fil_addr_null;
#define FIL_TABLESPACE 501
#define FIL_LOG 502
+extern ulint fil_n_log_flushes;
+
extern ulint fil_n_pending_log_flushes;
extern ulint fil_n_pending_tablespace_flushes;
@@ -478,7 +480,7 @@ fil_extend_space_to_desired_size(
ulint* actual_size, /* out: size of the space after extension;
if we ran out of disk space this may be lower
than the desired size */
- ulint space_id, /* in: space id, must be != 0 */
+ ulint space_id, /* in: space id */
ulint size_after_extend);/* in: desired size in pages after the
extension; if the current space size is bigger
than this already, the function does nothing */
diff --git a/innobase/include/lock0lock.h b/innobase/include/lock0lock.h
index 9f525042dcc..b99359fe998 100644
--- a/innobase/include/lock0lock.h
+++ b/innobase/include/lock0lock.h
@@ -47,7 +47,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index); /* in: secondary index */
+ dict_index_t* index, /* in: secondary index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Checks if some transaction has an implicit x-lock on a record in a clustered
index. */
@@ -58,7 +59,8 @@ lock_clust_rec_some_has_impl(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*****************************************************************
Resets the lock bits for a single record. Releases transactions
waiting for lock requests here. */
@@ -275,6 +277,7 @@ lock_clust_rec_modify_check_and_lock(
does nothing */
rec_t* rec, /* in: record which should be modified */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr); /* in: query thread */
/*************************************************************************
Checks if locks of other transactions prevent an immediate modify
@@ -308,6 +311,7 @@ lock_sec_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: secondary index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -333,6 +337,7 @@ lock_clust_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -350,6 +355,7 @@ lock_clust_rec_cons_read_sees(
rec_t* rec, /* in: user record which should be read or
passed over by a read cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
read_view_t* view); /* in: consistent read view */
/*************************************************************************
Checks that a non-clustered index record is seen in a consistent read. */
@@ -463,6 +469,33 @@ lock_rec_hash(
ulint space, /* in: space */
ulint page_no);/* in: page number */
/*************************************************************************
+Gets the source table of an ALTER TABLE transaction. The table must be
+covered by an IX or IS table lock. */
+
+dict_table_t*
+lock_get_src_table(
+/*===============*/
+ /* out: the source table of transaction,
+ if it is covered by an IX or IS table lock;
+ dest if there is no source table, and
+ NULL if the transaction is locking more than
+ two tables or an inconsistency is found */
+ trx_t* trx, /* in: transaction */
+ dict_table_t* dest, /* in: destination of ALTER TABLE */
+ ulint* mode); /* out: lock mode of the source table */
+/*************************************************************************
+Determine if the given table is exclusively "owned" by the given
+transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
+on the table. */
+
+ibool
+lock_is_table_exclusive(
+/*====================*/
+ /* out: TRUE if table is only locked by trx,
+ with LOCK_IX, and possibly LOCK_AUTO_INC */
+ dict_table_t* table, /* in: table */
+ trx_t* trx); /* in: transaction */
+/*************************************************************************
Checks that a transaction id is sensible, i.e., not in the future. */
ibool
@@ -472,6 +505,7 @@ lock_check_trx_id_sanity(
dulint trx_id, /* in: trx id */
rec_t* rec, /* in: user record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
ibool has_kernel_mutex);/* in: TRUE if the caller owns the
kernel mutex */
/*************************************************************************
@@ -482,7 +516,8 @@ lock_rec_queue_validate(
/*====================*/
/* out: TRUE if ok */
rec_t* rec, /* in: record to look at */
- dict_index_t* index); /* in: index, or NULL if not known */
+ dict_index_t* index, /* in: index, or NULL if not known */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Prints info of a table lock. */
diff --git a/innobase/include/lock0lock.ic b/innobase/include/lock0lock.ic
index fabc9256401..c7a71bb45d8 100644
--- a/innobase/include/lock0lock.ic
+++ b/innobase/include/lock0lock.ic
@@ -60,7 +60,8 @@ lock_clust_rec_some_has_impl(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
dulint trx_id;
@@ -70,7 +71,7 @@ lock_clust_rec_some_has_impl(
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(page_rec_is_user_rec(rec));
- trx_id = row_get_rec_trx_id(rec, index);
+ trx_id = row_get_rec_trx_id(rec, index, offsets);
if (trx_is_active(trx_id)) {
/* The modifying or inserting transaction is active */
diff --git a/innobase/include/mtr0log.h b/innobase/include/mtr0log.h
index 9c9c6f696e8..c0636ea1e1e 100644
--- a/innobase/include/mtr0log.h
+++ b/innobase/include/mtr0log.h
@@ -11,6 +11,7 @@ Created 12/7/1995 Heikki Tuuri
#include "univ.i"
#include "mtr0mtr.h"
+#include "dict0types.h"
/************************************************************
Writes 1 - 4 bytes to a file page buffered in the buffer pool.
@@ -173,6 +174,38 @@ mlog_parse_string(
byte* page); /* in: page where to apply the log record, or NULL */
+/************************************************************
+Opens a buffer for mlog, writes the initial log record and,
+if needed, the field lengths of an index. Reserves space
+for further log entries. The log entry must be closed with
+mtr_close(). */
+
+byte*
+mlog_open_and_write_index(
+/*======================*/
+ /* out: buffer, NULL if log mode
+ MTR_LOG_NONE */
+ mtr_t* mtr, /* in: mtr */
+ byte* rec, /* in: index record or page */
+ dict_index_t* index, /* in: record descriptor */
+ byte type, /* in: log item type */
+ ulint size); /* in: requested buffer size in bytes
+ (if 0, calls mlog_close() and returns NULL) */
+
+/************************************************************
+Parses a log record written by mlog_open_and_write_index. */
+
+byte*
+mlog_parse_index(
+/*=============*/
+ /* out: parsed record end,
+ NULL if not a complete record */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ /* out: new value of log_ptr */
+ ibool comp, /* in: TRUE=compact record format */
+ dict_index_t** index); /* out, own: dummy index */
+
/* Insert, update, and maybe other functions may use this value to define an
extra mlog buffer size for variable size data */
#define MLOG_BUF_MARGIN 256
diff --git a/innobase/include/mtr0mtr.h b/innobase/include/mtr0mtr.h
index e8c68a91dad..071279d5259 100644
--- a/innobase/include/mtr0mtr.h
+++ b/innobase/include/mtr0mtr.h
@@ -102,7 +102,31 @@ flag value must give the length also! */
file rename */
#define MLOG_FILE_DELETE ((byte)35) /* log record about an .ibd
file deletion */
-#define MLOG_BIGGEST_TYPE ((byte)35) /* biggest value (used in
+#define MLOG_COMP_REC_MIN_MARK ((byte)36) /* mark a compact index record
+ as the predefined minimum
+ record */
+#define MLOG_COMP_PAGE_CREATE ((byte)37) /* create a compact
+ index page */
+#define MLOG_COMP_REC_INSERT ((byte)38) /* compact record insert */
+#define MLOG_COMP_REC_CLUST_DELETE_MARK ((byte)39)
+ /* mark compact clustered index
+ record deleted */
+#define MLOG_COMP_REC_SEC_DELETE_MARK ((byte)40)/* mark compact secondary index
+ record deleted */
+#define MLOG_COMP_REC_UPDATE_IN_PLACE ((byte)41)/* update of a compact record,
+ preserves record field sizes */
+#define MLOG_COMP_REC_DELETE ((byte)42) /* delete a compact record
+ from a page */
+#define MLOG_COMP_LIST_END_DELETE ((byte)43) /* delete compact record list
+ end on index page */
+#define MLOG_COMP_LIST_START_DELETE ((byte)44) /* delete compact record list
+ start on index page */
+#define MLOG_COMP_LIST_END_COPY_CREATED ((byte)45)
+ /* copy compact record list end
+ to a new created index page */
+#define MLOG_COMP_PAGE_REORGANIZE ((byte)46) /* reorganize an index page */
+
+#define MLOG_BIGGEST_TYPE ((byte)46) /* biggest value (used in
asserts) */
/*******************************************************************
diff --git a/innobase/include/os0file.h b/innobase/include/os0file.h
index d1439faf29f..599e78bab48 100644
--- a/innobase/include/os0file.h
+++ b/innobase/include/os0file.h
@@ -24,6 +24,9 @@ extern ibool os_aio_print_debug;
extern ulint os_file_n_pending_preads;
extern ulint os_file_n_pending_pwrites;
+extern ulint os_n_pending_reads;
+extern ulint os_n_pending_writes;
+
#ifdef __WIN__
/* We define always WIN_ASYNC_IO, and check at run-time whether
diff --git a/innobase/include/page0cur.h b/innobase/include/page0cur.h
index c85669ed4df..a693931968e 100644
--- a/innobase/include/page0cur.h
+++ b/innobase/include/page0cur.h
@@ -128,7 +128,8 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple */
+ dtuple_t* tuple, /* in: pointer to a data tuple */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/***************************************************************
Inserts a record next to page cursor. Returns pointer to inserted record if
@@ -142,6 +143,7 @@ page_cur_rec_insert(
otherwise */
page_cur_t* cursor, /* in: a page cursor */
rec_t* rec, /* in: record to insert */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/***************************************************************
Inserts a record next to page cursor. Returns pointer to inserted record if
@@ -155,9 +157,9 @@ page_cur_insert_rec_low(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
- ulint data_size,/* in: data size of tuple */
- rec_t* rec, /* in: pointer to a physical record or NULL */
+ dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
+ dict_index_t* index, /* in: record descriptor */
+ rec_t* rec, /* in: pointer to a physical record or NULL */
mtr_t* mtr); /* in: mini-transaction handle */
/*****************************************************************
Copies records from page to a newly created page, from a given record onward,
@@ -166,10 +168,11 @@ including that record. Infimum and supremum records are not copied. */
void
page_copy_rec_list_end_to_created_page(
/*===================================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: first record to copy */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: first record to copy */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/***************************************************************
Deletes a record at the page cursor. The cursor is moved to the
next record after the deleted one. */
@@ -178,6 +181,7 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /* in: a page cursor */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr); /* in: mini-transaction handle */
/********************************************************************
Searches the right position for a page cursor. */
@@ -187,6 +191,7 @@ page_cur_search(
/*============*/
/* out: number of matched fields on the left */
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -198,6 +203,7 @@ void
page_cur_search_with_match(
/*=======================*/
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -229,34 +235,37 @@ Parses a log record of a record insert on a page. */
byte*
page_cur_parse_insert_rec(
/*======================*/
- /* out: end of log record or NULL */
- ibool is_short,/* in: TRUE if short inserts */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ ibool is_short,/* in: TRUE if short inserts */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/**************************************************************
Parses a log record of copying a record list end to a new created page. */
byte*
page_parse_copy_rec_list_to_created_page(
/*=====================================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
Parses log record of a record delete on a page. */
byte*
page_cur_parse_delete_rec(
/*======================*/
- /* out: pointer to record end or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: pointer to record end or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/* Index page cursor */
diff --git a/innobase/include/page0cur.ic b/innobase/include/page0cur.ic
index 39f8ab11513..03010fbd766 100644
--- a/innobase/include/page0cur.ic
+++ b/innobase/include/page0cur.ic
@@ -143,7 +143,7 @@ UNIV_INLINE
void
page_cur_move_to_prev(
/*==================*/
- page_cur_t* cur) /* in: cursor; must not before first */
+ page_cur_t* cur) /* in: page cursor, not before first */
{
ut_ad(!page_cur_is_before_first(cur));
@@ -158,6 +158,7 @@ page_cur_search(
/*============*/
/* out: number of matched fields on the left */
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -170,7 +171,7 @@ page_cur_search(
ut_ad(dtuple_check_typed(tuple));
- page_cur_search_with_match(page, tuple, mode,
+ page_cur_search_with_match(page, index, tuple, mode,
&up_matched_fields,
&up_matched_bytes,
&low_matched_fields,
@@ -190,16 +191,11 @@ page_cur_tuple_insert(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple */
+ dtuple_t* tuple, /* in: pointer to a data tuple */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
- ulint data_size;
-
- ut_ad(dtuple_check_typed(tuple));
-
- data_size = dtuple_get_data_size(tuple);
-
- return(page_cur_insert_rec_low(cursor, tuple, data_size, NULL, mtr));
+ return(page_cur_insert_rec_low(cursor, tuple, index, NULL, mtr));
}
/***************************************************************
@@ -214,8 +210,9 @@ page_cur_rec_insert(
otherwise */
page_cur_t* cursor, /* in: a page cursor */
rec_t* rec, /* in: record to insert */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
- return(page_cur_insert_rec_low(cursor, NULL, 0, rec, mtr));
+ return(page_cur_insert_rec_low(cursor, NULL, index, rec, mtr));
}
diff --git a/innobase/include/page0page.h b/innobase/include/page0page.h
index 969313614e3..d3ef8214eb6 100644
--- a/innobase/include/page0page.h
+++ b/innobase/include/page0page.h
@@ -37,7 +37,8 @@ typedef byte page_header_t;
/*-----------------------------*/
#define PAGE_N_DIR_SLOTS 0 /* number of slots in page directory */
#define PAGE_HEAP_TOP 2 /* pointer to record heap top */
-#define PAGE_N_HEAP 4 /* number of records in the heap */
+#define PAGE_N_HEAP 4 /* number of records in the heap,
+ bit 15=flag: new-style compact page format */
#define PAGE_FREE 6 /* pointer to start of page free record list */
#define PAGE_GARBAGE 8 /* number of bytes in deleted records */
#define PAGE_LAST_INSERT 10 /* pointer to the last inserted record, or
@@ -79,15 +80,24 @@ typedef byte page_header_t;
#define PAGE_DATA (PAGE_HEADER + 36 + 2 * FSEG_HEADER_SIZE)
/* start of data on the page */
-#define PAGE_INFIMUM (PAGE_DATA + 1 + REC_N_EXTRA_BYTES)
- /* offset of the page infimum record on the
- page */
-#define PAGE_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_EXTRA_BYTES + 8)
- /* offset of the page supremum record on the
- page */
-#define PAGE_SUPREMUM_END (PAGE_SUPREMUM + 9)
+#define PAGE_OLD_INFIMUM (PAGE_DATA + 1 + REC_N_OLD_EXTRA_BYTES)
+ /* offset of the page infimum record on an
+ old-style page */
+#define PAGE_OLD_SUPREMUM (PAGE_DATA + 2 + 2 * REC_N_OLD_EXTRA_BYTES + 8)
+ /* offset of the page supremum record on an
+ old-style page */
+#define PAGE_OLD_SUPREMUM_END (PAGE_OLD_SUPREMUM + 9)
/* offset of the page supremum record end on
- the page */
+ an old-style page */
+#define PAGE_NEW_INFIMUM (PAGE_DATA + REC_N_NEW_EXTRA_BYTES)
+ /* offset of the page infimum record on a
+ new-style compact page */
+#define PAGE_NEW_SUPREMUM (PAGE_DATA + 2 * REC_N_NEW_EXTRA_BYTES + 8)
+ /* offset of the page supremum record on a
+ new-style compact page */
+#define PAGE_NEW_SUPREMUM_END (PAGE_NEW_SUPREMUM + 8)
+ /* offset of the page supremum record end on
+ a new-style compact page */
/*-----------------------------*/
/* Directions of cursor movement */
@@ -233,6 +243,7 @@ page_cmp_dtuple_rec_with_match(
be page infimum or supremum, in which case
matched-parameter values below are not
affected */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns
contains the value for current comparison */
@@ -259,6 +270,22 @@ page_rec_get_n_recs_before(
/* out: number of records */
rec_t* rec); /* in: the physical record */
/*****************************************************************
+Gets the number of records in the heap. */
+UNIV_INLINE
+ulint
+page_dir_get_n_heap(
+/*================*/
+ /* out: number of user records */
+ page_t* page); /* in: index page */
+/*****************************************************************
+Sets the number of records in the heap. */
+UNIV_INLINE
+void
+page_dir_set_n_heap(
+/*================*/
+ page_t* page, /* in: index page */
+ ulint n_heap);/* in: number of records */
+/*****************************************************************
Gets the number of dir slots in directory. */
UNIV_INLINE
ulint
@@ -267,6 +294,15 @@ page_dir_get_n_slots(
/* out: number of slots */
page_t* page); /* in: index page */
/*****************************************************************
+Sets the number of dir slots in directory. */
+UNIV_INLINE
+void
+page_dir_set_n_slots(
+/*=================*/
+ /* out: number of slots */
+ page_t* page, /* in: index page */
+ ulint n_slots);/* in: number of slots */
+/*****************************************************************
Gets pointer to nth directory slot. */
UNIV_INLINE
page_dir_slot_t*
@@ -333,7 +369,16 @@ ulint
page_dir_find_owner_slot(
/*=====================*/
/* out: the directory slot number */
- rec_t* rec); /* in: the physical record */
+ rec_t* rec); /* in: the physical record */
+/****************************************************************
+Determine whether the page is in new-style compact format. */
+UNIV_INLINE
+ibool
+page_is_comp(
+/*=========*/
+ /* out: TRUE if the page is in compact format
+ FALSE if it is in old-style format */
+ page_t* page); /* in: index page */
/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
@@ -359,9 +404,10 @@ UNIV_INLINE
rec_t*
page_rec_get_prev(
/*==============*/
- /* out: pointer to previous record */
- rec_t* rec); /* in: pointer to record, must not be page
- infimum */
+ /* out: pointer to previous record */
+ rec_t* rec); /* in: pointer to record,
+ must not be page infimum */
+
/****************************************************************
TRUE if the record is a user record on the page. */
UNIV_INLINE
@@ -446,9 +492,11 @@ page_get_max_insert_size_after_reorganize(
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
-page_get_free_space_of_empty(void);
-/*==============================*/
- /* out: free space */
+page_get_free_space_of_empty(
+/*=========================*/
+ /* out: free space */
+ ibool comp) /* in: TRUE=compact page format */
+ __attribute__((const));
/****************************************************************
Returns the sum of the sizes of the records in the record list
excluding the infimum and supremum records. */
@@ -464,20 +512,23 @@ Allocates a block of memory from an index page. */
byte*
page_mem_alloc(
/*===========*/
- /* out: pointer to start of allocated
- buffer, or NULL if allocation fails */
- page_t* page, /* in: index page */
- ulint need, /* in: number of bytes needed */
- ulint* heap_no);/* out: this contains the heap number
- of the allocated record if allocation succeeds */
+ /* out: pointer to start of allocated
+ buffer, or NULL if allocation fails */
+ page_t* page, /* in: index page */
+ ulint need, /* in: number of bytes needed */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* heap_no);/* out: this contains the heap number
+ of the allocated record
+ if allocation succeeds */
/****************************************************************
Puts a record to free list. */
UNIV_INLINE
void
page_mem_free(
/*==========*/
- page_t* page, /* in: index page */
- rec_t* rec); /* in: pointer to the (origin of) record */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: pointer to the (origin of) record */
+ dict_index_t* index); /* in: record descriptor */
/**************************************************************
The index page creation function. */
@@ -487,7 +538,8 @@ page_create(
/* out: pointer to the page */
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
- mtr_t* mtr); /* in: mini-transaction handle */
+ mtr_t* mtr, /* in: mini-transaction handle */
+ ibool comp); /* in: TRUE=compact page format */
/*****************************************************************
Differs from page_copy_rec_list_end, because this function does not
touch the lock table and max trx id on page. */
@@ -495,10 +547,11 @@ touch the lock table and max trx id on page. */
void
page_copy_rec_list_end_no_locks(
/*============================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Copies records from page to new_page, from the given record onward,
including that record. Infimum and supremum records are not copied.
@@ -507,10 +560,11 @@ The records are copied to the start of the record list on new_page. */
void
page_copy_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Copies records from page to new_page, up to the given record, NOT
including that record. Infimum and supremum records are not copied.
@@ -519,10 +573,11 @@ The records are copied to the end of the record list on new_page. */
void
page_copy_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes records from a page from a given record onward, including that record.
The infimum and supremum records are not deleted. */
@@ -530,14 +585,15 @@ The infimum and supremum records are not deleted. */
void
page_delete_rec_list_end(
/*=====================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- ulint n_recs, /* in: number of records to delete, or ULINT_UNDEFINED
- if not known */
- ulint size, /* in: the sum of the sizes of the records in the end
- of the chain to delete, or ULINT_UNDEFINED if not
- known */
- mtr_t* mtr); /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_recs, /* in: number of records to delete,
+ or ULINT_UNDEFINED if not known */
+ ulint size, /* in: the sum of the sizes of the
+ records in the end of the chain to
+ delete, or ULINT_UNDEFINED if not known */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Deletes records from page, up to the given record, NOT including
that record. Infimum and supremum records are not deleted. */
@@ -545,9 +601,10 @@ that record. Infimum and supremum records are not deleted. */
void
page_delete_rec_list_start(
/*=======================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr); /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Moves record list end to another page. Moved records include
split_rec. */
@@ -555,10 +612,11 @@ split_rec. */
void
page_move_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record to move */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/*****************************************************************
Moves record list start to another page. Moved records do not include
split_rec. */
@@ -566,10 +624,11 @@ split_rec. */
void
page_move_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record not to move */
- mtr_t* mtr); /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record not to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr); /* in: mtr */
/********************************************************************
Splits a directory slot which owns too many records. */
@@ -595,13 +654,16 @@ Parses a log record of a record list end or start deletion. */
byte*
page_parse_delete_rec_list(
/*=======================*/
- /* out: end of log record or NULL */
- byte type, /* in: MLOG_LIST_END_DELETE or
- MLOG_LIST_START_DELETE */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr); /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte type, /* in: MLOG_LIST_END_DELETE,
+ MLOG_LIST_START_DELETE,
+ MLOG_COMP_LIST_END_DELETE or
+ MLOG_COMP_LIST_START_DELETE */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr); /* in: mtr or NULL */
/***************************************************************
Parses a redo log record of creating a page. */
@@ -611,6 +673,7 @@ page_parse_create(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr,/* in: buffer end */
+ ibool comp, /* in: TRUE=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
/****************************************************************
@@ -620,7 +683,8 @@ the index page context. */
void
page_rec_print(
/*===========*/
- rec_t* rec);
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: record descriptor */
/*******************************************************************
This is used to print the contents of the directory for
debugging purposes. */
@@ -637,8 +701,9 @@ debugging purposes. */
void
page_print_list(
/*============*/
- page_t* page, /* in: index page */
- ulint pr_n); /* in: print n first and n last entries */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint pr_n); /* in: print n first and n last entries */
/*******************************************************************
Prints the info in a page header. */
@@ -653,9 +718,12 @@ debugging purposes. */
void
page_print(
/*======*/
- page_t* page, /* in: index page */
- ulint dn, /* in: print dn first and last entries in directory */
- ulint rn); /* in: print rn first and last records on page */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint dn, /* in: print dn first and last entries
+ in directory */
+ ulint rn); /* in: print rn first and last records
+ in directory */
/*******************************************************************
The following is used to validate a record on a page. This function
differs from rec_validate as it can also check the n_owned field and
@@ -664,8 +732,9 @@ the heap_no field. */
ibool
page_rec_validate(
/*==============*/
- /* out: TRUE if ok */
- rec_t* rec); /* in: record on the page */
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Checks that the first directory slot points to the infimum record and
the last to the supremum. This function is intended to track if the
diff --git a/innobase/include/page0page.ic b/innobase/include/page0page.ic
index 3d2bf3b090e..1d5ea337031 100644
--- a/innobase/include/page0page.ic
+++ b/innobase/include/page0page.ic
@@ -73,7 +73,8 @@ page_header_set_field(
{
ut_ad(page);
ut_ad(field <= PAGE_N_RECS);
- ut_ad(val < UNIV_PAGE_SIZE);
+ ut_ad(field == PAGE_N_HEAP || val < UNIV_PAGE_SIZE);
+ ut_ad(field != PAGE_N_HEAP || (val & 0x7fff) < UNIV_PAGE_SIZE);
mach_write_to_2(page + PAGE_HEADER + field, val);
}
@@ -162,7 +163,11 @@ page_get_infimum_rec(
{
ut_ad(page);
- return(page + PAGE_INFIMUM);
+ if (page_is_comp(page)) {
+ return(page + PAGE_NEW_INFIMUM);
+ } else {
+ return(page + PAGE_OLD_INFIMUM);
+ }
}
/****************************************************************
@@ -176,7 +181,11 @@ page_get_supremum_rec(
{
ut_ad(page);
- return(page + PAGE_SUPREMUM);
+ if (page_is_comp(page)) {
+ return(page + PAGE_NEW_SUPREMUM);
+ } else {
+ return(page + PAGE_OLD_SUPREMUM);
+ }
}
/****************************************************************
@@ -309,6 +318,7 @@ page_cmp_dtuple_rec_with_match(
be page infimum or supremum, in which case
matched-parameter values below are not
affected */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns
contains the value for current comparison */
@@ -320,6 +330,7 @@ page_cmp_dtuple_rec_with_match(
page_t* page;
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
page = buf_frame_align(rec);
@@ -328,7 +339,7 @@ page_cmp_dtuple_rec_with_match(
} else if (rec == page_get_supremum_rec(page)) {
return(-1);
} else {
- return(cmp_dtuple_rec_with_match(dtuple, rec,
+ return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
matched_fields,
matched_bytes));
}
@@ -358,6 +369,45 @@ page_dir_get_n_slots(
{
return(page_header_get_field(page, PAGE_N_DIR_SLOTS));
}
+/*****************************************************************
+Sets the number of dir slots in directory. */
+UNIV_INLINE
+void
+page_dir_set_n_slots(
+/*=================*/
+ /* out: number of slots */
+ page_t* page, /* in: index page */
+ ulint n_slots)/* in: number of slots */
+{
+ page_header_set_field(page, PAGE_N_DIR_SLOTS, n_slots);
+}
+
+/*****************************************************************
+Gets the number of records in the heap. */
+UNIV_INLINE
+ulint
+page_dir_get_n_heap(
+/*================*/
+ /* out: number of user records */
+ page_t* page) /* in: index page */
+{
+ return(page_header_get_field(page, PAGE_N_HEAP) & 0x7fff);
+}
+
+/*****************************************************************
+Sets the number of records in the heap. */
+UNIV_INLINE
+void
+page_dir_set_n_heap(
+/*================*/
+ page_t* page, /* in: index page */
+ ulint n_heap) /* in: number of records */
+{
+ ut_ad(n_heap < 0x8000);
+
+ page_header_set_field(page, PAGE_N_HEAP, n_heap | (0x8000 &
+ page_header_get_field(page, PAGE_N_HEAP)));
+}
/*****************************************************************
Gets pointer to nth directory slot. */
@@ -369,7 +419,7 @@ page_dir_get_nth_slot(
page_t* page, /* in: index page */
ulint n) /* in: position */
{
- ut_ad(page_header_get_field(page, PAGE_N_DIR_SLOTS) > n);
+ ut_ad(page_dir_get_n_slots(page) > n);
return(page + UNIV_PAGE_SIZE - PAGE_DIR
- (n + 1) * PAGE_DIR_SLOT_SIZE);
@@ -431,7 +481,8 @@ page_dir_slot_get_n_owned(
/* out: number of records */
page_dir_slot_t* slot) /* in: page directory slot */
{
- return(rec_get_n_owned(page_dir_slot_get_rec(slot)));
+ return(rec_get_n_owned(page_dir_slot_get_rec(slot),
+ page_is_comp(buf_frame_align(slot))));
}
/*******************************************************************
@@ -444,7 +495,8 @@ page_dir_slot_set_n_owned(
ulint n) /* in: number of records owned
by the slot */
{
- rec_set_n_owned(page_dir_slot_get_rec(slot), n);
+ rec_set_n_owned(page_dir_slot_get_rec(slot),
+ page_is_comp(buf_frame_align(slot)), n);
}
/****************************************************************
@@ -462,6 +514,19 @@ page_dir_calc_reserved_space(
}
/****************************************************************
+Determine whether the page is in new-style compact format. */
+UNIV_INLINE
+ibool
+page_is_comp(
+/*=========*/
+ /* out: TRUE if the page is in compact format
+ FALSE if it is in old-style format */
+ page_t* page) /* in: index page */
+{
+ return(!!(page_header_get_field(page, PAGE_N_HEAP) & 0x8000));
+}
+
+/****************************************************************
Gets the pointer to the next record on the page. */
UNIV_INLINE
rec_t*
@@ -477,7 +542,7 @@ page_rec_get_next(
page = buf_frame_align(rec);
- offs = rec_get_next_offs(rec);
+ offs = rec_get_next_offs(rec, page_is_comp(page));
if (offs >= UNIV_PAGE_SIZE) {
fprintf(stderr,
@@ -513,6 +578,7 @@ page_rec_set_next(
infimum */
{
page_t* page;
+ ulint offs;
ut_ad(page_rec_check(rec));
ut_a((next == NULL)
@@ -523,11 +589,13 @@ page_rec_set_next(
ut_ad(rec != page_get_supremum_rec(page));
ut_ad(next != page_get_infimum_rec(page));
- if (next == NULL) {
- rec_set_next_offs(rec, 0);
+ if (next) {
+ offs = (ulint) (next - page);
} else {
- rec_set_next_offs(rec, (ulint)(next - page));
+ offs = 0;
}
+
+ rec_set_next_offs(rec, page_is_comp(page), offs);
}
/****************************************************************
@@ -545,6 +613,7 @@ page_rec_get_prev(
rec_t* rec2;
rec_t* prev_rec = NULL;
page_t* page;
+ ibool comp;
ut_ad(page_rec_check(rec));
@@ -559,6 +628,7 @@ page_rec_get_prev(
slot = page_dir_get_nth_slot(page, slot_no - 1);
rec2 = page_dir_slot_get_rec(slot);
+ comp = page_is_comp(page);
while (rec != rec2) {
prev_rec = rec2;
@@ -579,9 +649,12 @@ page_rec_find_owner_rec(
/* out: the owner record */
rec_t* rec) /* in: the physical record */
{
+ ibool comp;
+
ut_ad(page_rec_check(rec));
+ comp = page_is_comp(buf_frame_align(rec));
- while (rec_get_n_owned(rec) == 0) {
+ while (rec_get_n_owned(rec, comp) == 0) {
rec = page_rec_get_next(rec);
}
@@ -601,7 +674,9 @@ page_get_data_size(
ulint ret;
ret = (ulint)(page_header_get_field(page, PAGE_HEAP_TOP)
- - PAGE_SUPREMUM_END
+ - (page_is_comp(page)
+ ? PAGE_NEW_SUPREMUM_END
+ : PAGE_OLD_SUPREMUM_END)
- page_header_get_field(page, PAGE_GARBAGE));
ut_ad(ret < UNIV_PAGE_SIZE);
@@ -613,12 +688,13 @@ page_get_data_size(
Calculates free space if a page is emptied. */
UNIV_INLINE
ulint
-page_get_free_space_of_empty(void)
-/*==============================*/
+page_get_free_space_of_empty(
+/*=========================*/
/* out: free space */
+ ibool comp) /* in: TRUE=compact page layout */
{
return((ulint)(UNIV_PAGE_SIZE
- - PAGE_SUPREMUM_END
+ - (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
- PAGE_DIR
- 2 * PAGE_DIR_SLOT_SIZE));
}
@@ -640,13 +716,16 @@ page_get_max_insert_size(
{
ulint occupied;
ulint free_space;
+ ibool comp;
+
+ comp = page_is_comp(page);
occupied = page_header_get_field(page, PAGE_HEAP_TOP)
- - PAGE_SUPREMUM_END
+ - (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END)
+ page_dir_calc_reserved_space(
- n_recs + (page_header_get_field(page, PAGE_N_HEAP) - 2));
+ n_recs + page_dir_get_n_heap(page) - 2);
- free_space = page_get_free_space_of_empty();
+ free_space = page_get_free_space_of_empty(comp);
/* Above the 'n_recs +' part reserves directory space for the new
inserted records; the '- 2' excludes page infimum and supremum
@@ -673,11 +752,14 @@ page_get_max_insert_size_after_reorganize(
{
ulint occupied;
ulint free_space;
+ ibool comp;
+
+ comp = page_is_comp(page);
occupied = page_get_data_size(page)
+ page_dir_calc_reserved_space(n_recs + page_get_n_recs(page));
- free_space = page_get_free_space_of_empty();
+ free_space = page_get_free_space_of_empty(comp);
if (occupied > free_space) {
@@ -693,11 +775,12 @@ UNIV_INLINE
void
page_mem_free(
/*==========*/
- page_t* page, /* in: index page */
- rec_t* rec) /* in: pointer to the (origin of) record */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: pointer to the (origin of) record */
+ dict_index_t* index) /* in: record descriptor */
{
- rec_t* free;
- ulint garbage;
+ rec_t* free;
+ ulint garbage;
free = page_header_get_ptr(page, PAGE_FREE);
@@ -707,7 +790,7 @@ page_mem_free(
garbage = page_header_get_field(page, PAGE_GARBAGE);
page_header_set_field(page, PAGE_GARBAGE,
- garbage + rec_get_size(rec));
+ garbage + rec_get_size(rec, index));
}
#ifdef UNIV_MATERIALIZE
diff --git a/innobase/include/rem0cmp.h b/innobase/include/rem0cmp.h
index 712e263350e..77a5a42c2d5 100644
--- a/innobase/include/rem0cmp.h
+++ b/innobase/include/rem0cmp.h
@@ -90,6 +90,7 @@ cmp_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns,
contains the value for current comparison */
@@ -107,7 +108,8 @@ cmp_dtuple_rec(
less than rec, respectively; see the comments
for cmp_dtuple_rec_with_match */
dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/******************************************************************
Checks if a dtuple is a prefix of a record. The last field in dtuple
is allowed to be a prefix of the corresponding field in the record. */
@@ -116,23 +118,9 @@ ibool
cmp_dtuple_is_prefix_of_rec(
/*========================*/
/* out: TRUE if prefix */
- dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec); /* in: physical record */
-/******************************************************************
-Compares a prefix of a data tuple to a prefix of a physical record for
-equality. If there are less fields in rec than parameter n_fields, FALSE
-is returned. NOTE that n_fields_cmp of dtuple does not affect this
-comparison. */
-
-ibool
-cmp_dtuple_rec_prefix_equal(
-/*========================*/
- /* out: TRUE if equal */
dtuple_t* dtuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
- ulint n_fields); /* in: number of fields which should be
- compared; must not exceed the number of
- fields in dtuple */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*****************************************************************
This function is used to compare two physical records. Only the common
first fields are compared, and if an externally stored field is
@@ -146,7 +134,13 @@ cmp_rec_rec_with_match(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index, /* in: data dictionary index */
+ ulint n, /* in: number of fields to compare,
+ or ULINT_UNDEFINED if both records
+ contain all fields, and all fields
+ should be compared */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when the function returns,
contains the value the for current
@@ -167,6 +161,12 @@ cmp_rec_rec(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
+ ulint n, /* in: number of fields to compare,
+ or ULINT_UNDEFINED if both records
+ contain all fields, and all fields
+ should be compared */
dict_index_t* index); /* in: data dictionary index */
diff --git a/innobase/include/rem0cmp.ic b/innobase/include/rem0cmp.ic
index 75cb3ef04e8..d4c30f25f03 100644
--- a/innobase/include/rem0cmp.ic
+++ b/innobase/include/rem0cmp.ic
@@ -57,10 +57,14 @@ cmp_rec_rec(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
+ ulint n, /* in: number of fields to compare */
dict_index_t* index) /* in: data dictionary index */
{
ulint match_f = 0;
ulint match_b = 0;
- return(cmp_rec_rec_with_match(rec1, rec2, index, &match_f, &match_b));
+ return(cmp_rec_rec_with_match(rec1, rec2, offsets1, offsets2, index, n,
+ &match_f, &match_b));
}
diff --git a/innobase/include/rem0rec.h b/innobase/include/rem0rec.h
index 86bf263170f..d450df82311 100644
--- a/innobase/include/rem0rec.h
+++ b/innobase/include/rem0rec.h
@@ -23,9 +23,18 @@ Created 5/30/1994 Heikki Tuuri
info bits of a record */
#define REC_INFO_MIN_REC_FLAG 0x10UL
-/* Number of extra bytes in a record, in addition to the data and the
-offsets */
-#define REC_N_EXTRA_BYTES 6
+/* Number of extra bytes in an old-style record,
+in addition to the data and the offsets */
+#define REC_N_OLD_EXTRA_BYTES 6
+/* Number of extra bytes in a new-style record,
+in addition to the data and the offsets */
+#define REC_N_NEW_EXTRA_BYTES 5
+
+/* Record status values */
+#define REC_STATUS_ORDINARY 0
+#define REC_STATUS_NODE_PTR 1
+#define REC_STATUS_INFIMUM 2
+#define REC_STATUS_SUPREMUM 3
/**********************************************************
The following function is used to get the offset of the
@@ -36,7 +45,8 @@ rec_get_next_offs(
/*==============*/
/* out: the page offset of the next
chained record */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the next record offset field
of the record. */
@@ -45,14 +55,15 @@ void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint next); /* in: offset of the next record */
/**********************************************************
The following function is used to get the number of fields
-in the record. */
+in an old-style record. */
UNIV_INLINE
ulint
-rec_get_n_fields(
-/*=============*/
+rec_get_n_fields_old(
+/*=================*/
/* out: number of data fields */
rec_t* rec); /* in: physical record */
/**********************************************************
@@ -63,7 +74,8 @@ ulint
rec_get_n_owned(
/*============*/
/* out: number of owned records */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the number of owned
records. */
@@ -72,6 +84,7 @@ void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint n_owned); /* in: the number of owned */
/**********************************************************
The following function is used to retrieve the info bits of
@@ -81,7 +94,8 @@ ulint
rec_get_info_bits(
/*==============*/
/* out: info bits */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the info bits of a record. */
UNIV_INLINE
@@ -89,15 +103,26 @@ void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint bits); /* in: info bits */
/**********************************************************
-Gets the value of the deleted falg in info bits. */
+The following function retrieves the status bits of a new-style record. */
UNIV_INLINE
-ibool
-rec_info_bits_get_deleted_flag(
-/*===========================*/
- /* out: TRUE if deleted flag set */
- ulint info_bits); /* in: info bits from a record */
+ulint
+rec_get_status(
+/*===========*/
+ /* out: status bits */
+ rec_t* rec); /* in: physical record */
+
+/**********************************************************
+The following function is used to set the status bits of a new-style record. */
+UNIV_INLINE
+void
+rec_set_status(
+/*===========*/
+ rec_t* rec, /* in: physical record */
+ ulint bits); /* in: info bits */
+
/**********************************************************
The following function tells if record is delete marked. */
UNIV_INLINE
@@ -105,7 +130,8 @@ ibool
rec_get_deleted_flag(
/*=================*/
/* out: TRUE if delete marked */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the deleted bit. */
UNIV_INLINE
@@ -113,8 +139,25 @@ void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ibool flag); /* in: TRUE if delete marked */
/**********************************************************
+The following function tells if a new-style record is a node pointer. */
+UNIV_INLINE
+ibool
+rec_get_node_ptr_flag(
+/*=================*/
+ /* out: TRUE if node pointer */
+ rec_t* rec); /* in: physical record */
+/**********************************************************
+The following function is used to flag a record as a node pointer. */
+UNIV_INLINE
+void
+rec_set_node_ptr_flag(
+/*=================*/
+ rec_t* rec, /* in: physical record */
+ ibool flag); /* in: TRUE if the record is a node pointer */
+/**********************************************************
The following function is used to get the order number
of the record in the heap of the index page. */
UNIV_INLINE
@@ -122,7 +165,8 @@ ulint
rec_get_heap_no(
/*=============*/
/* out: heap order number */
- rec_t* rec); /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp); /* in: TRUE=compact page format */
/**********************************************************
The following function is used to set the heap number
field in the record. */
@@ -131,6 +175,7 @@ void
rec_set_heap_no(
/*=============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint heap_no);/* in: the heap number */
/**********************************************************
The following function is used to test whether the data offsets
@@ -141,31 +186,84 @@ rec_get_1byte_offs_flag(
/*====================*/
/* out: TRUE if 1-byte form */
rec_t* rec); /* in: physical record */
+/**********************************************************
+The following function determines the offsets to each field
+in the record. The offsets are returned in an array of
+ulint, with [0] being the number of fields (n), [1] being the
+extra size (if REC_OFFS_COMPACT is set, the record is in the new
+format), and [2]..[n+1] being the offsets past the end of
+fields 0..n, or to the beginning of fields 1..n+1. When the
+high-order bit of the offset at [n+1] is set (REC_OFFS_SQL_NULL),
+the field n is NULL. When the second high-order bit of the offset
+at [n+1] is set (REC_OFFS_EXTERNAL), the field n is being stored
+externally. */
+
+ulint*
+rec_get_offsets(
+/*============*/
+ /* out: the offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_fields,/* in: maximum number of initialized fields
+ (ULINT_UNDEFINED if all fields) */
+ mem_heap_t* heap); /* in: memory heap */
+/**********************************************************
+The following function determines the offsets to each field
+in the record. It differs from rec_get_offsets() by trying to
+reuse a previously returned array. */
+
+ulint*
+rec_reget_offsets(
+/*==============*/
+ /* out: the new offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* offsets,/* in: array of offsets
+ from rec_get_offsets()
+ or rec_reget_offsets(), or NULL */
+ ulint n_fields,/* in: maximum number of initialized fields
+ (ULINT_UNDEFINED if all fields) */
+ mem_heap_t* heap); /* in: memory heap */
+
+/****************************************************************
+Validates offsets returned by rec_get_offsets() or rec_reget_offsets(). */
+UNIV_INLINE
+ibool
+rec_offs_validate(
+/*==============*/
+ /* out: TRUE if valid */
+ rec_t* rec, /* in: record or NULL */
+ dict_index_t* index, /* in: record descriptor or NULL */
+ const ulint* offsets);/* in: array returned by rec_get_offsets()
+ or rec_reget_offsets() */
+/****************************************************************
+Updates debug data in offsets, in order to avoid bogus
+rec_offs_validate() failures. */
+UNIV_INLINE
+void
+rec_offs_make_valid(
+/*================*/
+ const rec_t* rec, /* in: record */
+ const dict_index_t* index,/* in: record descriptor */
+ ulint* offsets);/* in: array returned by rec_get_offsets()
+ or rec_reget_offsets() */
+
/****************************************************************
The following function is used to get a pointer to the nth
-data field in the record. */
+data field in an old-style record. */
byte*
-rec_get_nth_field(
-/*==============*/
+rec_get_nth_field_old(
+/*==================*/
/* out: pointer to the field */
rec_t* rec, /* in: record */
ulint n, /* in: index of the field */
ulint* len); /* out: length of the field; UNIV_SQL_NULL
if SQL null */
/****************************************************************
-Return field length or UNIV_SQL_NULL. */
-UNIV_INLINE
-ulint
-rec_get_nth_field_len(
-/*==================*/
- /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
- rec_t* rec, /* in: record */
- ulint n); /* in: index of the field */
-/****************************************************************
-Gets the physical size of a field. Also an SQL null may have a field of
-size > 0, if the data type is of a fixed size. */
+Gets the physical size of an old-style field.
+Also an SQL null may have a field of size > 0,
+if the data type is of a fixed size. */
UNIV_INLINE
ulint
rec_get_nth_field_size(
@@ -173,131 +271,194 @@ rec_get_nth_field_size(
/* out: field size in bytes */
rec_t* rec, /* in: record */
ulint n); /* in: index of the field */
-/***************************************************************
-Gets the value of the ith field extern storage bit. If it is TRUE
-it means that the field is stored on another page. */
+/****************************************************************
+The following function is used to get a pointer to the nth
+data field in an old-style record. */
+UNIV_INLINE
+byte*
+rec_get_nth_field(
+/*==============*/
+ /* out: pointer to the field */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index of the field */
+ ulint* len); /* out: length of the field; UNIV_SQL_NULL
+ if SQL null */
+/**********************************************************
+Determine if the offsets are for a record in the new
+compact format. */
UNIV_INLINE
ibool
-rec_get_nth_field_extern_bit(
-/*=========================*/
- /* in: TRUE or FALSE */
- rec_t* rec, /* in: record */
- ulint i); /* in: ith field */
+rec_offs_comp(
+/*==========*/
+ /* out: TRUE if compact format */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**********************************************************
+Returns TRUE if the nth field of rec is SQL NULL. */
+UNIV_INLINE
+ibool
+rec_offs_nth_null(
+/*==============*/
+ /* out: TRUE if SQL NULL */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n); /* in: nth field */
+/**********************************************************
+Returns TRUE if the extern bit is set in nth field of rec. */
+UNIV_INLINE
+ibool
+rec_offs_nth_extern(
+/*================*/
+ /* out: TRUE if externally stored */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n); /* in: nth field */
+/**********************************************************
+Gets the physical size of a field. */
+UNIV_INLINE
+ulint
+rec_offs_nth_size(
+/*==============*/
+ /* out: length of field */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n); /* in: nth field */
+
/**********************************************************
Returns TRUE if the extern bit is set in any of the fields
of rec. */
UNIV_INLINE
ibool
-rec_contains_externally_stored_field(
-/*=================================*/
- /* out: TRUE if a field is stored externally */
- rec_t* rec); /* in: record */
+rec_offs_any_extern(
+/*================*/
+ /* out: TRUE if a field is stored externally */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/***************************************************************
Sets the value of the ith field extern storage bit. */
-
+UNIV_INLINE
void
rec_set_nth_field_extern_bit(
/*=========================*/
- rec_t* rec, /* in: record */
- ulint i, /* in: ith field */
- ibool val, /* in: value to set */
- mtr_t* mtr); /* in: mtr holding an X-latch to the page where
- rec is, or NULL; in the NULL case we do not
- write to log about the change */
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint i, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
/***************************************************************
Sets TRUE the extern storage bits of fields mentioned in an array. */
void
rec_set_field_extern_bits(
/*======================*/
- rec_t* rec, /* in: record */
- ulint* vec, /* in: array of field numbers */
- ulint n_fields, /* in: number of fields numbers */
- mtr_t* mtr); /* in: mtr holding an X-latch to the page
- where rec is, or NULL; in the NULL case we
- do not write to log about the change */
-/****************************************************************
-The following function is used to get a copy of the nth
-data field in the record to a buffer. */
-UNIV_INLINE
-void
-rec_copy_nth_field(
-/*===============*/
- void* buf, /* in: pointer to the buffer */
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- ulint* len); /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ const ulint* vec, /* in: array of field numbers */
+ ulint n_fields,/* in: number of fields numbers */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
/***************************************************************
-This is used to modify the value of an already existing field in
-a physical record. The previous value must have exactly the same
-size as the new value. If len is UNIV_SQL_NULL then the field is
-treated as SQL null. */
+This is used to modify the value of an already existing field in a record.
+The previous value must have exactly the same size as the new value. If len
+is UNIV_SQL_NULL then the field is treated as an SQL null for old-style
+records. For new-style records, len must not be UNIV_SQL_NULL. */
UNIV_INLINE
void
rec_set_nth_field(
/*==============*/
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- void* data, /* in: pointer to the data if not SQL null */
- ulint len); /* in: length of the data or UNIV_SQL_NULL.
- If not SQL null, must have the same length as the
- previous value. If SQL null, previous value must be
- SQL null. */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index number of the field */
+ const void* data, /* in: pointer to the data if not SQL null */
+ ulint len); /* in: length of the data or UNIV_SQL_NULL.
+ If not SQL null, must have the same
+ length as the previous value.
+ If SQL null, previous value must be
+ SQL null. */
/**************************************************************
-The following function returns the data size of a physical
+The following function returns the data size of an old-style physical
record, that is the sum of field lengths. SQL null fields
are counted as length 0 fields. The value returned by the function
is the distance from record origin to record end in bytes. */
UNIV_INLINE
ulint
-rec_get_data_size(
-/*==============*/
- /* out: size */
+rec_get_data_size_old(
+/*==================*/
+ /* out: size */
rec_t* rec); /* in: physical record */
/**************************************************************
+The following function returns the number of fields in a record. */
+UNIV_INLINE
+ulint
+rec_offs_n_fields(
+/*===============*/
+ /* out: number of fields */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
+The following function returns the data size of a physical
+record, that is the sum of field lengths. SQL null fields
+are counted as length 0 fields. The value returned by the function
+is the distance from record origin to record end in bytes. */
+UNIV_INLINE
+ulint
+rec_offs_data_size(
+/*===============*/
+ /* out: size */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
Returns the total size of record minus data size of record.
The value returned by the function is the distance from record
start to record origin in bytes. */
UNIV_INLINE
ulint
-rec_get_extra_size(
-/*===============*/
- /* out: size */
- rec_t* rec); /* in: physical record */
-/**************************************************************
+rec_offs_extra_size(
+/*================*/
+ /* out: size */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
Returns the total size of a physical record. */
UNIV_INLINE
ulint
+rec_offs_size(
+/*==========*/
+ /* out: size */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/**************************************************************
+Returns the total size of a physical record. */
+
+ulint
rec_get_size(
/*=========*/
- /* out: size */
- rec_t* rec); /* in: physical record */
+ /* out: size */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index); /* in: record descriptor */
/**************************************************************
Returns a pointer to the start of the record. */
UNIV_INLINE
byte*
rec_get_start(
/*==========*/
- /* out: pointer to start */
- rec_t* rec); /* in: pointer to record */
+ /* out: pointer to start */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/**************************************************************
Returns a pointer to the end of the record. */
UNIV_INLINE
byte*
rec_get_end(
/*========*/
- /* out: pointer to end */
- rec_t* rec); /* in: pointer to record */
+ /* out: pointer to end */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Copies a physical record to a buffer. */
UNIV_INLINE
rec_t*
rec_copy(
/*=====*/
- /* out: pointer to the origin of the copied record */
- void* buf, /* in: buffer */
- rec_t* rec); /* in: physical record */
+ /* out: pointer to the origin of the copy */
+ void* buf, /* in: buffer */
+ const rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/******************************************************************
Copies the first n fields of a physical record to a new physical record in
a buffer. */
@@ -305,49 +466,43 @@ a buffer. */
rec_t*
rec_copy_prefix_to_buf(
/*===================*/
- /* out, own: copied record */
- rec_t* rec, /* in: physical record */
- ulint n_fields, /* in: number of fields to copy */
- byte** buf, /* in/out: memory buffer for the copied prefix,
- or NULL */
- ulint* buf_size); /* in/out: buffer size */
+ /* out, own: copied record */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_fields, /* in: number of fields to copy */
+ byte** buf, /* in/out: memory buffer
+ for the copied prefix, or NULL */
+ ulint* buf_size); /* in/out: buffer size */
/****************************************************************
Folds a prefix of a physical record to a ulint. */
UNIV_INLINE
ulint
rec_fold(
/*=====*/
- /* out: the folded value */
- rec_t* rec, /* in: the physical record */
- ulint n_fields, /* in: number of complete fields to fold */
- ulint n_bytes, /* in: number of bytes to fold in an
- incomplete last field */
- dulint tree_id); /* in: index tree id */
+ /* out: the folded value */
+ rec_t* rec, /* in: the physical record */
+ const ulint* offsets, /* in: array returned by
+ rec_get_offsets() */
+ ulint n_fields, /* in: number of complete
+ fields to fold */
+ ulint n_bytes, /* in: number of bytes to fold
+ in an incomplete last field */
+ dulint tree_id); /* in: index tree id */
/*************************************************************
Builds a physical record out of a data tuple and stores it beginning from
address destination. */
-UNIV_INLINE
+
rec_t*
rec_convert_dtuple_to_rec(
/*======================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple); /* in: data tuple */
-/*************************************************************
-Builds a physical record out of a data tuple and stores it beginning from
-address destination. */
-
-rec_t*
-rec_convert_dtuple_to_rec_low(
-/*==========================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple, /* in: data tuple */
- ulint data_size); /* in: data size of dtuple */
+ /* out: pointer to the origin
+ of physical record */
+ byte* buf, /* in: start address of the
+ physical record */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple);/* in: data tuple */
/**************************************************************
-Returns the extra size of a physical record if we know its
+Returns the extra size of an old-style physical record if we know its
data size and number of fields. */
UNIV_INLINE
ulint
@@ -355,7 +510,8 @@ rec_get_converted_extra_size(
/*=========================*/
/* out: extra size */
ulint data_size, /* in: data size */
- ulint n_fields); /* in: number of fields */
+ ulint n_fields) /* in: number of fields */
+ __attribute__((const));
/**************************************************************
The following function returns the size of a data tuple when converted to
a physical record. */
@@ -364,6 +520,7 @@ ulint
rec_get_converted_size(
/*===================*/
/* out: size */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* dtuple);/* in: data tuple */
/******************************************************************
Copies the first n fields of a physical record to a data tuple.
@@ -374,6 +531,7 @@ rec_copy_prefix_to_dtuple(
/*======================*/
dtuple_t* tuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
ulint n_fields, /* in: number of fields to copy */
mem_heap_t* heap); /* in: memory heap */
/*******************************************************************
@@ -382,16 +540,27 @@ Validates the consistency of a physical record. */
ibool
rec_validate(
/*=========*/
- /* out: TRUE if ok */
- rec_t* rec); /* in: physical record */
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
+/*******************************************************************
+Prints an old-style physical record. */
+
+void
+rec_print_old(
+/*==========*/
+ FILE* file, /* in: file where to print */
+ rec_t* rec); /* in: physical record */
+
/*******************************************************************
Prints a physical record. */
void
rec_print(
/*======*/
- FILE* file, /* in: file where to print */
- rec_t* rec); /* in: physical record */
+ FILE* file, /* in: file where to print */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
#define REC_INFO_BITS 6 /* This is single byte bit-field */
diff --git a/innobase/include/rem0rec.ic b/innobase/include/rem0rec.ic
index c36bf8f6d6e..8443b5fa07d 100644
--- a/innobase/include/rem0rec.ic
+++ b/innobase/include/rem0rec.ic
@@ -8,9 +8,19 @@ Created 5/30/1994 Heikki Tuuri
#include "mach0data.h"
#include "ut0byte.h"
+#include "dict0dict.h"
-/* Offsets of the bit-fields in the record. NOTE! In the table the most
-significant bytes and bits are written below less significant.
+/* Compact flag ORed to the extra size returned by rec_get_offsets() */
+#define REC_OFFS_COMPACT ((ulint) 1 << 31)
+/* SQL NULL flag in offsets returned by rec_get_offsets() */
+#define REC_OFFS_SQL_NULL ((ulint) 1 << 31)
+/* External flag in offsets returned by rec_get_offsets() */
+#define REC_OFFS_EXTERNAL ((ulint) 1 << 30)
+/* Mask for offsets returned by rec_get_offsets() */
+#define REC_OFFS_MASK (REC_OFFS_EXTERNAL - 1)
+
+/* Offsets of the bit-fields in an old-style record. NOTE! In the table the
+most significant bytes and bits are written below less significant.
(1) byte offset (2) bit usage within byte
downward from
@@ -25,6 +35,25 @@ significant bytes and bits are written below less significant.
4 bits info bits
*/
+/* Offsets of the bit-fields in a new-style record. NOTE! In the table the
+most significant bytes and bits are written below less significant.
+
+ (1) byte offset (2) bit usage within byte
+ downward from
+ origin -> 1 8 bits pointer to next record (relative)
+ 2 8 bits pointer to next record (relative)
+ 3 3 bits status:
+ 000=conventional record
+ 001=node pointer record (inside B-tree)
+ 010=infimum record
+ 011=supremum record
+ 1xx=reserved
+ 5 bits heap number
+ 4 8 bits heap number
+ 5 4 bits n_owned
+ 4 bits info bits
+*/
+
/* We list the byte offsets from the origin of the record, the mask,
and the shift needed to obtain each bit-field of the record. */
@@ -32,22 +61,30 @@ and the shift needed to obtain each bit-field of the record. */
#define REC_NEXT_MASK 0xFFFFUL
#define REC_NEXT_SHIFT 0
-#define REC_SHORT 3 /* This is single byte bit-field */
-#define REC_SHORT_MASK 0x1UL
-#define REC_SHORT_SHIFT 0
+#define REC_OLD_SHORT 3 /* This is single byte bit-field */
+#define REC_OLD_SHORT_MASK 0x1UL
+#define REC_OLD_SHORT_SHIFT 0
+
+#define REC_OLD_N_FIELDS 4
+#define REC_OLD_N_FIELDS_MASK 0x7FEUL
+#define REC_OLD_N_FIELDS_SHIFT 1
-#define REC_N_FIELDS 4
-#define REC_N_FIELDS_MASK 0x7FEUL
-#define REC_N_FIELDS_SHIFT 1
+#define REC_NEW_STATUS 3 /* This is single byte bit-field */
+#define REC_NEW_STATUS_MASK 0x7UL
+#define REC_NEW_STATUS_SHIFT 0
-#define REC_HEAP_NO 5
+#define REC_OLD_HEAP_NO 5
+#define REC_NEW_HEAP_NO 4
#define REC_HEAP_NO_MASK 0xFFF8UL
#define REC_HEAP_NO_SHIFT 3
-#define REC_N_OWNED 6 /* This is single byte bit-field */
+#define REC_OLD_N_OWNED 6 /* This is single byte bit-field */
+#define REC_NEW_N_OWNED 5 /* This is single byte bit-field */
#define REC_N_OWNED_MASK 0xFUL
#define REC_N_OWNED_SHIFT 0
+#define REC_OLD_INFO_BITS 6 /* This is single byte bit-field */
+#define REC_NEW_INFO_BITS 5 /* This is single byte bit-field */
#define REC_INFO_BITS_MASK 0xF0UL
#define REC_INFO_BITS_SHIFT 0
@@ -65,26 +102,24 @@ a field stored to another page: */
#define REC_2BYTE_EXTERN_MASK 0x4000UL
-/****************************************************************
-Return field length or UNIV_SQL_NULL. */
-UNIV_INLINE
-ulint
-rec_get_nth_field_len(
-/*==================*/
- /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
- rec_t* rec, /* in: record */
- ulint n) /* in: index of the field */
-{
- ulint len;
-
- rec_get_nth_field(rec, n, &len);
-
- return(len);
-}
+#if REC_OLD_SHORT_MASK << (8 * (REC_OLD_SHORT - 3)) \
+ ^ REC_OLD_N_FIELDS_MASK << (8 * (REC_OLD_N_FIELDS - 4)) \
+ ^ REC_HEAP_NO_MASK << (8 * (REC_OLD_HEAP_NO - 4)) \
+ ^ REC_N_OWNED_MASK << (8 * (REC_OLD_N_OWNED - 3)) \
+ ^ REC_INFO_BITS_MASK << (8 * (REC_OLD_INFO_BITS - 3)) \
+ ^ 0xFFFFFFFFUL
+# error "sum of old-style masks != 0xFFFFFFFFUL"
+#endif
+#if REC_NEW_STATUS_MASK << (8 * (REC_NEW_STATUS - 3)) \
+ ^ REC_HEAP_NO_MASK << (8 * (REC_NEW_HEAP_NO - 4)) \
+ ^ REC_N_OWNED_MASK << (8 * (REC_NEW_N_OWNED - 3)) \
+ ^ REC_INFO_BITS_MASK << (8 * (REC_NEW_INFO_BITS - 3)) \
+ ^ 0xFFFFFFUL
+# error "sum of new-style masks != 0xFFFFFFUL"
+#endif
/***************************************************************
-Sets the value of the ith field SQL null bit. */
+Sets the value of the ith field SQL null bit of an old-style record. */
void
rec_set_nth_field_null_bit(
@@ -93,8 +128,8 @@ rec_set_nth_field_null_bit(
ulint i, /* in: ith field */
ibool val); /* in: value to set */
/***************************************************************
-Sets a record field to SQL null. The physical size of the field is not
-changed. */
+Sets an old-style record field to SQL null.
+The physical size of the field is not changed. */
void
rec_set_nth_field_sql_null(
@@ -102,6 +137,32 @@ rec_set_nth_field_sql_null(
rec_t* rec, /* in: record */
ulint n); /* in: index of the field */
+/***************************************************************
+Sets the value of the ith field extern storage bit of an old-style record. */
+
+void
+rec_set_nth_field_extern_bit_old(
+/*=============================*/
+ rec_t* rec, /* in: old-style record */
+ ulint i, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page where
+ rec is, or NULL; in the NULL case we do not
+ write to log about the change */
+/***************************************************************
+Sets the value of the ith field extern storage bit of a new-style record. */
+
+void
+rec_set_nth_field_extern_bit_new(
+/*=============================*/
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint ith, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr); /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
+
/**********************************************************
Gets a bit field from within 1 byte. */
UNIV_INLINE
@@ -131,7 +192,7 @@ rec_set_bit_field_1(
ulint shift) /* in: shift right applied after masking */
{
ut_ad(rec);
- ut_ad(offs <= REC_N_EXTRA_BYTES);
+ ut_ad(offs <= REC_N_OLD_EXTRA_BYTES);
ut_ad(mask);
ut_ad(mask <= 0xFFUL);
ut_ad(((mask >> shift) << shift) == mask);
@@ -171,30 +232,14 @@ rec_set_bit_field_2(
ulint shift) /* in: shift right applied after masking */
{
ut_ad(rec);
- ut_ad(offs <= REC_N_EXTRA_BYTES);
+ ut_ad(offs <= REC_N_OLD_EXTRA_BYTES);
ut_ad(mask > 0xFFUL);
ut_ad(mask <= 0xFFFFUL);
ut_ad((mask >> shift) & 1);
ut_ad(0 == ((mask >> shift) & ((mask >> shift) + 1)));
ut_ad(((mask >> shift) << shift) == mask);
ut_ad(((val << shift) & mask) == (val << shift));
-#ifdef UNIV_DEBUG
- {
- ulint m;
-
- /* The following assertion checks that the masks of currently
- defined bit-fields in bytes 3-6 do not overlap. */
- m = (ulint)((REC_SHORT_MASK << (8 * (REC_SHORT - 3)))
- + (REC_N_FIELDS_MASK << (8 * (REC_N_FIELDS - 4)))
- + (REC_HEAP_NO_MASK << (8 * (REC_HEAP_NO - 4)))
- + (REC_N_OWNED_MASK << (8 * (REC_N_OWNED - 3)))
- + (REC_INFO_BITS_MASK << (8 * (REC_INFO_BITS - 3))));
- if (m != ut_dbg_zero + 0xFFFFFFFFUL) {
- fprintf(stderr, "Sum of masks %lx\n", m);
- ut_error;
- }
- }
-#endif
+
mach_write_to_2(rec - offs,
(mach_read_from_2(rec - offs) & ~mask)
| (val << shift));
@@ -208,17 +253,26 @@ ulint
rec_get_next_offs(
/*==============*/
/* out: the page offset of the next chained record */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
- ulint ret;
-
- ut_ad(rec);
-
- ret = rec_get_bit_field_2(rec, REC_NEXT, REC_NEXT_MASK,
- REC_NEXT_SHIFT);
- ut_ad(ret < UNIV_PAGE_SIZE);
-
- return(ret);
+ if (comp) {
+ lint ret = (int16_t) rec_get_bit_field_2(rec, REC_NEXT,
+ REC_NEXT_MASK, REC_NEXT_SHIFT);
+#if UNIV_PAGE_SIZE <= 32768
+ /* with 64 KiB page size, the pointer will "wrap around",
+ and the following assertions are invalid */
+ ut_ad(ret + ut_align_offset(rec, UNIV_PAGE_SIZE) <
+ UNIV_PAGE_SIZE);
+#endif
+ return(ret ? ut_align_offset(rec + ret, UNIV_PAGE_SIZE) : 0);
+ }
+ else {
+ ulint ret = rec_get_bit_field_2(rec, REC_NEXT,
+ REC_NEXT_MASK, REC_NEXT_SHIFT);
+ ut_ad(ret < UNIV_PAGE_SIZE);
+ return(ret);
+ }
}
/**********************************************************
@@ -229,21 +283,32 @@ void
rec_set_next_offs(
/*==============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint next) /* in: offset of the next record */
{
ut_ad(rec);
ut_ad(UNIV_PAGE_SIZE > next);
- rec_set_bit_field_2(rec, next, REC_NEXT, REC_NEXT_MASK,
- REC_NEXT_SHIFT);
+ if (comp) {
+ rec_set_bit_field_2(rec, next
+ ? (next - ut_align_offset(rec, UNIV_PAGE_SIZE))
+#ifdef UNIV_DEBUG /* avoid an assertion failure */
+ & (REC_NEXT_MASK >> REC_NEXT_SHIFT)
+#endif
+ : 0, REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT);
+ } else {
+ rec_set_bit_field_2(rec, next,
+ REC_NEXT, REC_NEXT_MASK, REC_NEXT_SHIFT);
+ }
}
/**********************************************************
-The following function is used to get the number of fields in the record. */
+The following function is used to get the number of fields
+in an old-style record. */
UNIV_INLINE
ulint
-rec_get_n_fields(
-/*=============*/
+rec_get_n_fields_old(
+/*=================*/
/* out: number of data fields */
rec_t* rec) /* in: physical record */
{
@@ -251,8 +316,8 @@ rec_get_n_fields(
ut_ad(rec);
- ret = rec_get_bit_field_2(rec, REC_N_FIELDS, REC_N_FIELDS_MASK,
- REC_N_FIELDS_SHIFT);
+ ret = rec_get_bit_field_2(rec, REC_OLD_N_FIELDS,
+ REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT);
ut_ad(ret <= REC_MAX_N_FIELDS);
ut_ad(ret > 0);
@@ -260,12 +325,12 @@ rec_get_n_fields(
}
/**********************************************************
-The following function is used to set the number of fields field in the
-record. */
+The following function is used to set the number of fields
+in an old-style record. */
UNIV_INLINE
void
-rec_set_n_fields(
-/*=============*/
+rec_set_n_fields_old(
+/*=================*/
rec_t* rec, /* in: physical record */
ulint n_fields) /* in: the number of fields */
{
@@ -273,8 +338,38 @@ rec_set_n_fields(
ut_ad(n_fields <= REC_MAX_N_FIELDS);
ut_ad(n_fields > 0);
- rec_set_bit_field_2(rec, n_fields, REC_N_FIELDS, REC_N_FIELDS_MASK,
- REC_N_FIELDS_SHIFT);
+ rec_set_bit_field_2(rec, n_fields, REC_OLD_N_FIELDS,
+ REC_OLD_N_FIELDS_MASK, REC_OLD_N_FIELDS_SHIFT);
+}
+
+/**********************************************************
+The following function is used to get the number of fields
+in a record. */
+UNIV_INLINE
+ulint
+rec_get_n_fields(
+/*=============*/
+ /* out: number of data fields */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index) /* in: record descriptor */
+{
+ ut_ad(rec);
+ ut_ad(index);
+ if (!index->table->comp) {
+ return(rec_get_n_fields_old(rec));
+ }
+ switch (rec_get_status(rec)) {
+ case REC_STATUS_ORDINARY:
+ return(dict_index_get_n_fields(index));
+ case REC_STATUS_NODE_PTR:
+ return(dict_index_get_n_unique_in_tree(index) + 1);
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ return(1);
+ default:
+ ut_error;
+ return(ULINT_UNDEFINED);
+ }
}
/**********************************************************
@@ -285,14 +380,16 @@ ulint
rec_get_n_owned(
/*============*/
/* out: number of owned records */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
ulint ret;
ut_ad(rec);
- ret = rec_get_bit_field_1(rec, REC_N_OWNED, REC_N_OWNED_MASK,
- REC_N_OWNED_SHIFT);
+ ret = rec_get_bit_field_1(rec,
+ comp ? REC_NEW_N_OWNED : REC_OLD_N_OWNED,
+ REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
ut_ad(ret <= REC_MAX_N_OWNED);
return(ret);
@@ -305,13 +402,15 @@ void
rec_set_n_owned(
/*============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint n_owned) /* in: the number of owned */
{
ut_ad(rec);
ut_ad(n_owned <= REC_MAX_N_OWNED);
- rec_set_bit_field_1(rec, n_owned, REC_N_OWNED, REC_N_OWNED_MASK,
- REC_N_OWNED_SHIFT);
+ rec_set_bit_field_1(rec, n_owned,
+ comp ? REC_NEW_N_OWNED : REC_OLD_N_OWNED,
+ REC_N_OWNED_MASK, REC_N_OWNED_SHIFT);
}
/**********************************************************
@@ -321,14 +420,16 @@ ulint
rec_get_info_bits(
/*==============*/
/* out: info bits */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
ulint ret;
ut_ad(rec);
- ret = rec_get_bit_field_1(rec, REC_INFO_BITS, REC_INFO_BITS_MASK,
- REC_INFO_BITS_SHIFT);
+ ret = rec_get_bit_field_1(rec,
+ comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS,
+ REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
ut_ad((ret & ~REC_INFO_BITS_MASK) == 0);
return(ret);
@@ -341,30 +442,51 @@ void
rec_set_info_bits(
/*==============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint bits) /* in: info bits */
{
ut_ad(rec);
ut_ad((bits & ~REC_INFO_BITS_MASK) == 0);
- rec_set_bit_field_1(rec, bits, REC_INFO_BITS, REC_INFO_BITS_MASK,
- REC_INFO_BITS_SHIFT);
+ rec_set_bit_field_1(rec, bits,
+ comp ? REC_NEW_INFO_BITS : REC_OLD_INFO_BITS,
+ REC_INFO_BITS_MASK, REC_INFO_BITS_SHIFT);
}
/**********************************************************
-Gets the value of the deleted flag in info bits. */
+The following function retrieves the status bits of a new-style record. */
UNIV_INLINE
-ibool
-rec_info_bits_get_deleted_flag(
-/*===========================*/
- /* out: TRUE if deleted flag set */
- ulint info_bits) /* in: info bits from a record */
+ulint
+rec_get_status(
+/*===========*/
+ /* out: status bits */
+ rec_t* rec) /* in: physical record */
{
- if (info_bits & REC_INFO_DELETED_FLAG) {
+ ulint ret;
- return(TRUE);
- }
+ ut_ad(rec);
- return(FALSE);
+ ret = rec_get_bit_field_1(rec, REC_NEW_STATUS,
+ REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT);
+ ut_ad((ret & ~REC_NEW_STATUS_MASK) == 0);
+
+ return(ret);
+}
+
+/**********************************************************
+The following function is used to set the status bits of a new-style record. */
+UNIV_INLINE
+void
+rec_set_status(
+/*===========*/
+ rec_t* rec, /* in: physical record */
+ ulint bits) /* in: info bits */
+{
+ ut_ad(rec);
+ ut_ad((bits & ~REC_NEW_STATUS_MASK) == 0);
+
+ rec_set_bit_field_1(rec, bits, REC_NEW_STATUS,
+ REC_NEW_STATUS_MASK, REC_NEW_STATUS_SHIFT);
}
/**********************************************************
@@ -374,9 +496,10 @@ ibool
rec_get_deleted_flag(
/*=================*/
/* out: TRUE if delete marked */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
- if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec)) {
+ if (REC_INFO_DELETED_FLAG & rec_get_info_bits(rec, comp)) {
return(TRUE);
}
@@ -391,6 +514,7 @@ void
rec_set_deleted_flag(
/*=================*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ibool flag) /* in: TRUE if delete marked */
{
ulint old_val;
@@ -399,7 +523,7 @@ rec_set_deleted_flag(
ut_ad(TRUE == 1);
ut_ad(flag <= TRUE);
- old_val = rec_get_info_bits(rec);
+ old_val = rec_get_info_bits(rec, comp);
if (flag) {
new_val = REC_INFO_DELETED_FLAG | old_val;
@@ -407,7 +531,39 @@ rec_set_deleted_flag(
new_val = ~REC_INFO_DELETED_FLAG & old_val;
}
- rec_set_info_bits(rec, new_val);
+ rec_set_info_bits(rec, comp, new_val);
+}
+
+/**********************************************************
+The following function tells if a new-style record is a node pointer. */
+UNIV_INLINE
+ibool
+rec_get_node_ptr_flag(
+/*=================*/
+ /* out: TRUE if node pointer */
+ rec_t* rec) /* in: physical record */
+{
+ return(REC_STATUS_NODE_PTR == rec_get_status(rec));
+}
+
+/**********************************************************
+The following function is used to flag a record as a node pointer. */
+UNIV_INLINE
+void
+rec_set_node_ptr_flag(
+/*=================*/
+ rec_t* rec, /* in: physical record */
+ ibool flag) /* in: TRUE if the record is a node pointer */
+{
+ ulint status;
+ ut_ad(flag <= TRUE);
+ ut_ad(REC_STATUS_NODE_PTR >= rec_get_status(rec));
+ if (flag) {
+ status = REC_STATUS_NODE_PTR;
+ } else {
+ status = REC_STATUS_ORDINARY;
+ }
+ rec_set_status(rec, status);
}
/**********************************************************
@@ -418,14 +574,16 @@ ulint
rec_get_heap_no(
/*=============*/
/* out: heap order number */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ ibool comp) /* in: TRUE=compact page format */
{
ulint ret;
ut_ad(rec);
- ret = rec_get_bit_field_2(rec, REC_HEAP_NO, REC_HEAP_NO_MASK,
- REC_HEAP_NO_SHIFT);
+ ret = rec_get_bit_field_2(rec,
+ comp ? REC_NEW_HEAP_NO : REC_OLD_HEAP_NO,
+ REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
ut_ad(ret <= REC_MAX_HEAP_NO);
return(ret);
@@ -438,12 +596,14 @@ void
rec_set_heap_no(
/*=============*/
rec_t* rec, /* in: physical record */
+ ibool comp, /* in: TRUE=compact page format */
ulint heap_no)/* in: the heap number */
{
ut_ad(heap_no <= REC_MAX_HEAP_NO);
- rec_set_bit_field_2(rec, heap_no, REC_HEAP_NO, REC_HEAP_NO_MASK,
- REC_HEAP_NO_SHIFT);
+ rec_set_bit_field_2(rec, heap_no,
+ comp ? REC_NEW_HEAP_NO : REC_OLD_HEAP_NO,
+ REC_HEAP_NO_MASK, REC_HEAP_NO_SHIFT);
}
/**********************************************************
@@ -456,10 +616,12 @@ rec_get_1byte_offs_flag(
/* out: TRUE if 1-byte form */
rec_t* rec) /* in: physical record */
{
- ut_ad(TRUE == 1);
+#if TRUE != 1
+#error "TRUE != 1"
+#endif
- return(rec_get_bit_field_1(rec, REC_SHORT, REC_SHORT_MASK,
- REC_SHORT_SHIFT));
+ return(rec_get_bit_field_1(rec, REC_OLD_SHORT, REC_OLD_SHORT_MASK,
+ REC_OLD_SHORT_SHIFT));
}
/**********************************************************
@@ -471,11 +633,13 @@ rec_set_1byte_offs_flag(
rec_t* rec, /* in: physical record */
ibool flag) /* in: TRUE if 1byte form */
{
- ut_ad(TRUE == 1);
+#if TRUE != 1
+#error "TRUE != 1"
+#endif
ut_ad(flag <= TRUE);
- rec_set_bit_field_1(rec, flag, REC_SHORT, REC_SHORT_MASK,
- REC_SHORT_SHIFT);
+ rec_set_bit_field_1(rec, flag, REC_OLD_SHORT, REC_OLD_SHORT_MASK,
+ REC_OLD_SHORT_SHIFT);
}
/**********************************************************
@@ -492,9 +656,9 @@ rec_1_get_field_end_info(
ulint n) /* in: field index */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- return(mach_read_from_1(rec - (REC_N_EXTRA_BYTES + n + 1)));
+ return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1)));
}
/**********************************************************
@@ -511,68 +675,234 @@ rec_2_get_field_end_info(
ulint n) /* in: field index */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- return(mach_read_from_2(rec - (REC_N_EXTRA_BYTES + 2 * n + 2)));
+ return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2)));
}
-/***************************************************************
-Gets the value of the ith field extern storage bit. If it is TRUE
-it means that the field is stored on another page. */
+#ifdef UNIV_DEBUG
+# define REC_OFFS_HEADER_SIZE 3
+#else /* UNIV_DEBUG */
+# define REC_OFFS_HEADER_SIZE 1
+#endif /* UNIV_DEBUG */
+
+/* Get the base address of offsets. The extra_size is stored at
+this position, and following positions hold the end offsets of
+the fields. */
+#define rec_offs_base(offsets) (offsets + REC_OFFS_HEADER_SIZE)
+
+/****************************************************************
+Validates offsets returned by rec_get_offsets() or rec_reget_offsets(). */
UNIV_INLINE
ibool
-rec_get_nth_field_extern_bit(
-/*=========================*/
- /* in: TRUE or FALSE */
- rec_t* rec, /* in: record */
- ulint i) /* in: ith field */
+rec_offs_validate(
+/*==============*/
+ /* out: TRUE if valid */
+ rec_t* rec, /* in: record or NULL */
+ dict_index_t* index, /* in: record descriptor or NULL */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint i = rec_offs_n_fields(offsets);
+ ulint last = ULINT_MAX;
+ ibool comp = (*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0;
+ ut_a(offsets);
+ if (rec) {
+ ut_ad((ulint) rec == offsets[1]);
+ if (!comp) {
+ ut_a(rec_get_n_fields_old(rec) >= i);
+ }
+ }
+ if (index) {
+ ulint max_n_fields;
+ ut_ad((ulint) index == offsets[2]);
+ max_n_fields = ut_max(
+ dict_index_get_n_fields(index),
+ dict_index_get_n_unique_in_tree(index) + 1);
+ if (comp && rec) {
+ switch (rec_get_status(rec)) {
+ case REC_STATUS_ORDINARY:
+ break;
+ case REC_STATUS_NODE_PTR:
+ max_n_fields =
+ dict_index_get_n_unique_in_tree(index) + 1;
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ max_n_fields = 1;
+ break;
+ default:
+ ut_error;
+ }
+ }
+ ut_a(i <= max_n_fields);
+ }
+ while (i--) {
+ ulint curr = rec_offs_base(offsets)[1 + i] & REC_OFFS_MASK;
+ ut_a(curr <= last);
+ last = curr;
+ }
+ return(TRUE);
+}
+/****************************************************************
+Updates debug data in offsets, in order to avoid bogus
+rec_offs_validate() failures. */
+UNIV_INLINE
+void
+rec_offs_make_valid(
+/*================*/
+ const rec_t* rec __attribute__((unused)),
+ /* in: record */
+ const dict_index_t* index __attribute__((unused)),
+ /* in: record descriptor */
+ ulint* offsets __attribute__((unused)))
+ /* in: array returned by rec_get_offsets()
+ or rec_reget_offsets() */
{
- ulint info;
+#ifdef UNIV_DEBUG
+ offsets[1] = (ulint) rec;
+ offsets[2] = (ulint) index;
+#endif /* UNIV_DEBUG */
+}
- if (rec_get_1byte_offs_flag(rec)) {
+/****************************************************************
+The following function is used to get a pointer to the nth
+data field in an old-style record. */
+UNIV_INLINE
+byte*
+rec_get_nth_field(
+/*==============*/
+ /* out: pointer to the field */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index of the field */
+ ulint* len) /* out: length of the field; UNIV_SQL_NULL
+ if SQL null */
+{
+ byte* field;
+ ulint length;
+ ut_ad(rec);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ ut_ad(len);
- return(FALSE);
+ if (n == 0) {
+ field = rec;
+ } else {
+ field = rec + (rec_offs_base(offsets)[n] & REC_OFFS_MASK);
}
- info = rec_2_get_field_end_info(rec, i);
+ length = rec_offs_base(offsets)[1 + n];
- if (info & REC_2BYTE_EXTERN_MASK) {
- return(TRUE);
+ if (length & REC_OFFS_SQL_NULL) {
+ field = NULL;
+ length = UNIV_SQL_NULL;
+ } else {
+ length &= REC_OFFS_MASK;
+ length -= field - rec;
}
- return(FALSE);
+ *len = length;
+ return(field);
}
/**********************************************************
-Returns TRUE if the extern bit is set in any of the fields
-of rec. */
+Determine if the offsets are for a record in the new
+compact format. */
UNIV_INLINE
ibool
-rec_contains_externally_stored_field(
-/*=================================*/
- /* out: TRUE if a field is stored externally */
- rec_t* rec) /* in: record */
+rec_offs_comp(
+/*==========*/
+ /* out: TRUE if compact format */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n;
- ulint i;
-
- if (rec_get_1byte_offs_flag(rec)) {
-
- return(FALSE);
- }
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ return((*rec_offs_base(offsets) & REC_OFFS_COMPACT) != 0);
+}
- n = rec_get_n_fields(rec);
+/**********************************************************
+Returns TRUE if the nth field of rec is SQL NULL. */
+UNIV_INLINE
+ibool
+rec_offs_nth_null(
+/*==============*/
+ /* out: TRUE if SQL NULL */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: nth field */
+{
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ return((rec_offs_base(offsets)[1 + n] & REC_OFFS_SQL_NULL) != 0);
+}
+/**********************************************************
+Returns TRUE if the extern bit is set in nth field of rec. */
+UNIV_INLINE
+ibool
+rec_offs_nth_extern(
+/*================*/
+ /* out: TRUE if externally stored */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: nth field */
+{
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ return((rec_offs_base(offsets)[1 + n] & REC_OFFS_EXTERNAL) != 0);
+}
- for (i = 0; i < n; i++) {
- if (rec_get_nth_field_extern_bit(rec, i)) {
+/**********************************************************
+Gets the physical size of a field. */
+UNIV_INLINE
+ulint
+rec_offs_nth_size(
+/*==============*/
+ /* out: length of field */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: nth field */
+{
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ ut_ad(n < rec_offs_n_fields(offsets));
+ return(rec_offs_base(offsets)[1 + n] & REC_OFFS_MASK);
+}
+/**********************************************************
+Returns TRUE if the extern bit is set in any of the fields
+of an old-style record. */
+UNIV_INLINE
+ibool
+rec_offs_any_extern(
+/*================*/
+ /* out: TRUE if a field is stored externally */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint i;
+ for (i = rec_offs_n_fields(offsets); i--; ) {
+ if (rec_offs_nth_extern(offsets, i)) {
return(TRUE);
}
}
-
return(FALSE);
}
+/***************************************************************
+Sets the value of the ith field extern storage bit. */
+UNIV_INLINE
+void
+rec_set_nth_field_extern_bit(
+/*=========================*/
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint i, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr) /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
+{
+ if (index->table->comp) {
+ rec_set_nth_field_extern_bit_new(rec, index, i, val, mtr);
+ } else {
+ rec_set_nth_field_extern_bit_old(rec, i, val, mtr);
+ }
+}
+
/**********************************************************
Returns the offset of n - 1th field end if the record is stored in the 1-byte
offsets form. If the field is SQL null, the flag is ORed in the returned
@@ -589,9 +919,9 @@ rec_1_get_prev_field_end_info(
ulint n) /* in: field index */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
- return(mach_read_from_1(rec - (REC_N_EXTRA_BYTES + n)));
+ return(mach_read_from_1(rec - (REC_N_OLD_EXTRA_BYTES + n)));
}
/**********************************************************
@@ -608,9 +938,9 @@ rec_2_get_prev_field_end_info(
ulint n) /* in: field index */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
- return(mach_read_from_2(rec - (REC_N_EXTRA_BYTES + 2 * n)));
+ return(mach_read_from_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n)));
}
/**********************************************************
@@ -625,9 +955,9 @@ rec_1_set_field_end_info(
ulint info) /* in: value to set */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- mach_write_to_1(rec - (REC_N_EXTRA_BYTES + n + 1), info);
+ mach_write_to_1(rec - (REC_N_OLD_EXTRA_BYTES + n + 1), info);
}
/**********************************************************
@@ -642,9 +972,9 @@ rec_2_set_field_end_info(
ulint info) /* in: value to set */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- mach_write_to_2(rec - (REC_N_EXTRA_BYTES + 2 * n + 2), info);
+ mach_write_to_2(rec - (REC_N_OLD_EXTRA_BYTES + 2 * n + 2), info);
}
/**********************************************************
@@ -659,7 +989,7 @@ rec_1_get_field_start_offs(
ulint n) /* in: field index */
{
ut_ad(rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
if (n == 0) {
@@ -682,7 +1012,7 @@ rec_2_get_field_start_offs(
ulint n) /* in: field index */
{
ut_ad(!rec_get_1byte_offs_flag(rec));
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
if (n == 0) {
@@ -707,7 +1037,7 @@ rec_get_field_start_offs(
ulint n) /* in: field index */
{
ut_ad(rec);
- ut_ad(n <= rec_get_n_fields(rec));
+ ut_ad(n <= rec_get_n_fields_old(rec));
if (n == 0) {
@@ -723,8 +1053,9 @@ rec_get_field_start_offs(
}
/****************************************************************
-Gets the physical size of a field. Also an SQL null may have a field of
-size > 0, if the data type is of a fixed size. */
+Gets the physical size of an old-style field.
+Also an SQL null may have a field of size > 0,
+if the data type is of a fixed size. */
UNIV_INLINE
ulint
rec_get_nth_field_size(
@@ -744,133 +1075,132 @@ rec_get_nth_field_size(
return(next_os - os);
}
-/****************************************************************
-The following function is used to get a copy of the nth data field in a
-record to a buffer. */
-UNIV_INLINE
-void
-rec_copy_nth_field(
-/*===============*/
- void* buf, /* in: pointer to the buffer */
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- ulint* len) /* out: length of the field; UNIV_SQL_NULL if SQL
- null */
-{
- byte* ptr;
-
- ut_ad(buf && rec && len);
-
- ptr = rec_get_nth_field(rec, n, len);
-
- if (*len == UNIV_SQL_NULL) {
-
- return;
- }
-
- ut_memcpy(buf, ptr, *len);
-}
-
/***************************************************************
This is used to modify the value of an already existing field in a record.
The previous value must have exactly the same size as the new value. If len
-is UNIV_SQL_NULL then the field is treated as an SQL null. */
+is UNIV_SQL_NULL then the field is treated as an SQL null for old-style
+records. For new-style records, len must not be UNIV_SQL_NULL. */
UNIV_INLINE
void
rec_set_nth_field(
/*==============*/
- rec_t* rec, /* in: record */
- ulint n, /* in: index of the field */
- void* data, /* in: pointer to the data if not SQL null */
- ulint len) /* in: length of the data or UNIV_SQL_NULL */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n, /* in: index number of the field */
+ const void* data, /* in: pointer to the data
+ if not SQL null */
+ ulint len) /* in: length of the data or UNIV_SQL_NULL.
+ If not SQL null, must have the same
+ length as the previous value.
+ If SQL null, previous value must be
+ SQL null. */
{
byte* data2;
ulint len2;
- ut_ad((len == UNIV_SQL_NULL)
- || (rec_get_nth_field_size(rec, n) == len));
-
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+
if (len == UNIV_SQL_NULL) {
+ ut_ad(!rec_offs_comp(offsets));
rec_set_nth_field_sql_null(rec, n);
return;
}
- data2 = rec_get_nth_field(rec, n, &len2);
+ data2 = rec_get_nth_field(rec, offsets, n, &len2);
+ ut_ad(len2 == len);
ut_memcpy(data2, data, len);
if (len2 == UNIV_SQL_NULL) {
-
+ ut_ad(!rec_offs_comp(offsets));
rec_set_nth_field_null_bit(rec, n, FALSE);
}
}
/**************************************************************
-The following function returns the data size of a physical
+The following function returns the data size of an old-style physical
record, that is the sum of field lengths. SQL null fields
are counted as length 0 fields. The value returned by the function
is the distance from record origin to record end in bytes. */
UNIV_INLINE
ulint
-rec_get_data_size(
-/*==============*/
- /* out: size */
+rec_get_data_size_old(
+/*==================*/
+ /* out: size */
rec_t* rec) /* in: physical record */
{
ut_ad(rec);
- return(rec_get_field_start_offs(rec, rec_get_n_fields(rec)));
+ return(rec_get_field_start_offs(rec, rec_get_n_fields_old(rec)));
}
/**************************************************************
-Returns the total size of record minus data size of record. The value
-returned by the function is the distance from record start to record origin
-in bytes. */
+The following function returns the number of fields in a record. */
UNIV_INLINE
ulint
-rec_get_extra_size(
+rec_offs_n_fields(
/*===============*/
- /* out: size */
- rec_t* rec) /* in: physical record */
+ /* out: number of fields */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_fields;
-
- ut_ad(rec);
-
- n_fields = rec_get_n_fields(rec);
+ ut_ad(offsets);
+ n_fields = offsets[0];
+ ut_ad(n_fields > 0);
+ ut_ad(n_fields <= REC_MAX_N_FIELDS);
+ return(n_fields);
+}
- if (rec_get_1byte_offs_flag(rec)) {
+/**************************************************************
+The following function returns the data size of a physical
+record, that is the sum of field lengths. SQL null fields
+are counted as length 0 fields. The value returned by the function
+is the distance from record origin to record end in bytes. */
+UNIV_INLINE
+ulint
+rec_offs_data_size(
+/*===============*/
+ /* out: size */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint size;
- return(REC_N_EXTRA_BYTES + n_fields);
- }
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ size = rec_offs_base(offsets)[rec_offs_n_fields(offsets)]
+ & REC_OFFS_MASK;
+ ut_ad(size < UNIV_PAGE_SIZE);
+ return(size);
+}
- return(REC_N_EXTRA_BYTES + 2 * n_fields);
+/**************************************************************
+Returns the total size of record minus data size of record. The value
+returned by the function is the distance from record start to record origin
+in bytes. */
+UNIV_INLINE
+ulint
+rec_offs_extra_size(
+/*================*/
+ /* out: size */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ ulint size;
+ ut_ad(rec_offs_validate(NULL, NULL, offsets));
+ size = *rec_offs_base(offsets) & ~REC_OFFS_COMPACT;
+ ut_ad(size < UNIV_PAGE_SIZE);
+ return(size);
}
-/**************************************************************
+/**************************************************************
Returns the total size of a physical record. */
UNIV_INLINE
ulint
-rec_get_size(
-/*=========*/
- /* out: size */
- rec_t* rec) /* in: physical record */
+rec_offs_size(
+/*==========*/
+ /* out: size */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- ulint n_fields;
-
- ut_ad(rec);
-
- n_fields = rec_get_n_fields(rec);
-
- if (rec_get_1byte_offs_flag(rec)) {
-
- return(REC_N_EXTRA_BYTES + n_fields
- + rec_1_get_field_start_offs(rec, n_fields));
- }
-
- return(REC_N_EXTRA_BYTES + 2 * n_fields
- + rec_2_get_field_start_offs(rec, n_fields));
+ return(rec_offs_data_size(offsets) + rec_offs_extra_size(offsets));
}
/**************************************************************
@@ -879,10 +1209,11 @@ UNIV_INLINE
byte*
rec_get_end(
/*========*/
- /* out: pointer to end */
- rec_t* rec) /* in: pointer to record */
+ /* out: pointer to end */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- return(rec + rec_get_data_size(rec));
+ return(rec + rec_offs_data_size(offsets));
}
/**************************************************************
@@ -891,10 +1222,11 @@ UNIV_INLINE
byte*
rec_get_start(
/*==========*/
- /* out: pointer to start */
- rec_t* rec) /* in: pointer to record */
+ /* out: pointer to start */
+ rec_t* rec, /* in: pointer to record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- return(rec - rec_get_extra_size(rec));
+ return(rec - rec_offs_extra_size(offsets));
}
/*******************************************************************
@@ -903,18 +1235,20 @@ UNIV_INLINE
rec_t*
rec_copy(
/*=====*/
- /* out: pointer to the origin of the copied record */
- void* buf, /* in: buffer */
- rec_t* rec) /* in: physical record */
+ /* out: pointer to the origin of the copy */
+ void* buf, /* in: buffer */
+ const rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint extra_len;
ulint data_len;
ut_ad(rec && buf);
- ut_ad(rec_validate(rec));
+ ut_ad(rec_offs_validate((rec_t*) rec, NULL, offsets));
+ ut_ad(rec_validate((rec_t*) rec, offsets));
- extra_len = rec_get_extra_size(rec);
- data_len = rec_get_data_size(rec);
+ extra_len = rec_offs_extra_size(offsets);
+ data_len = rec_offs_data_size(offsets);
ut_memcpy(buf, rec - extra_len, extra_len + data_len);
@@ -922,8 +1256,8 @@ rec_copy(
}
/**************************************************************
-Returns the extra size of a physical record if we know its data size and
-the number of fields. */
+Returns the extra size of an old-style physical record if we know its
+data size and number of fields. */
UNIV_INLINE
ulint
rec_get_converted_extra_size(
@@ -934,28 +1268,51 @@ rec_get_converted_extra_size(
{
if (data_size <= REC_1BYTE_OFFS_LIMIT) {
- return(REC_N_EXTRA_BYTES + n_fields);
+ return(REC_N_OLD_EXTRA_BYTES + n_fields);
}
- return(REC_N_EXTRA_BYTES + 2 * n_fields);
+ return(REC_N_OLD_EXTRA_BYTES + 2 * n_fields);
}
/**************************************************************
The following function returns the size of a data tuple when converted to
+a new-style physical record. */
+
+ulint
+rec_get_converted_size_new(
+/*=======================*/
+ /* out: size */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple);/* in: data tuple */
+/**************************************************************
+The following function returns the size of a data tuple when converted to
a physical record. */
UNIV_INLINE
ulint
rec_get_converted_size(
/*===================*/
/* out: size */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* dtuple) /* in: data tuple */
{
ulint data_size;
ulint extra_size;
-
+
+ ut_ad(index);
ut_ad(dtuple);
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(index->type & DICT_UNIVERSAL
+ || dtuple_get_n_fields(dtuple) ==
+ (((dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK)
+ == REC_STATUS_NODE_PTR)
+ ? dict_index_get_n_unique_in_tree(index) + 1
+ : dict_index_get_n_fields(index)));
+
+ if (index->table->comp) {
+ return(rec_get_converted_size_new(index, dtuple));
+ }
+
data_size = dtuple_get_data_size(dtuple);
extra_size = rec_get_converted_extra_size(
@@ -971,12 +1328,15 @@ UNIV_INLINE
ulint
rec_fold(
/*=====*/
- /* out: the folded value */
- rec_t* rec, /* in: the physical record */
- ulint n_fields, /* in: number of complete fields to fold */
- ulint n_bytes, /* in: number of bytes to fold in an
- incomplete last field */
- dulint tree_id) /* in: index tree id */
+ /* out: the folded value */
+ rec_t* rec, /* in: the physical record */
+ const ulint* offsets, /* in: array returned by
+ rec_get_offsets() */
+ ulint n_fields, /* in: number of complete
+ fields to fold */
+ ulint n_bytes, /* in: number of bytes to fold
+ in an incomplete last field */
+ dulint tree_id) /* in: index tree id */
{
ulint i;
byte* data;
@@ -984,12 +1344,13 @@ rec_fold(
ulint fold;
ulint n_fields_rec;
- ut_ad(rec_validate(rec));
- ut_ad(n_fields <= rec_get_n_fields(rec));
- ut_ad((n_fields < rec_get_n_fields(rec)) || (n_bytes == 0));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ ut_ad(rec_validate((rec_t*) rec, offsets));
ut_ad(n_fields + n_bytes > 0);
-
- n_fields_rec = rec_get_n_fields(rec);
+
+ n_fields_rec = rec_offs_n_fields(offsets);
+ ut_ad(n_fields <= n_fields_rec);
+ ut_ad(n_fields < n_fields_rec || n_bytes == 0);
if (n_fields > n_fields_rec) {
n_fields = n_fields_rec;
@@ -1002,7 +1363,7 @@ rec_fold(
fold = ut_fold_dulint(tree_id);
for (i = 0; i < n_fields; i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
if (len != UNIV_SQL_NULL) {
fold = ut_fold_ulint_pair(fold,
@@ -1011,7 +1372,7 @@ rec_fold(
}
if (n_bytes > 0) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
if (len != UNIV_SQL_NULL) {
if (len > n_bytes) {
@@ -1025,19 +1386,3 @@ rec_fold(
return(fold);
}
-
-/*************************************************************
-Builds a physical record out of a data tuple and stores it beginning from
-the address destination. */
-UNIV_INLINE
-rec_t*
-rec_convert_dtuple_to_rec(
-/*======================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple) /* in: data tuple */
-{
- return(rec_convert_dtuple_to_rec_low(destination, dtuple,
- dtuple_get_data_size(dtuple)));
-}
diff --git a/innobase/include/row0mysql.h b/innobase/include/row0mysql.h
index 6e1865dae1d..c23a0e025ad 100644
--- a/innobase/include/row0mysql.h
+++ b/innobase/include/row0mysql.h
@@ -175,8 +175,14 @@ int
row_lock_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
- row_prebuilt_t* prebuilt); /* in: prebuilt struct in the MySQL
+ row_prebuilt_t* prebuilt, /* in: prebuilt struct in the MySQL
table handle */
+ dict_table_t* table, /* in: table to lock, or NULL
+ if prebuilt->table should be
+ locked as LOCK_TABLE_EXP |
+ prebuilt->select_lock_type */
+ ulint mode); /* in: lock mode of table */
+
/*************************************************************************
Does an insert for MySQL. */
@@ -233,6 +239,17 @@ row_update_for_mysql(
the MySQL format */
row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
handle */
+
+/*************************************************************************
+Does an unlock of a row for MySQL. */
+
+int
+row_unlock_for_mysql(
+/*=================*/
+ /* out: error code or DB_SUCCESS */
+ row_prebuilt_t* prebuilt); /* in: prebuilt struct in MySQL
+ handle */
+
/*************************************************************************
Creates an query graph node of 'update' type to be used in the MySQL
interface. */
@@ -532,7 +549,10 @@ struct row_prebuilt_struct {
format */
ulint hint_need_to_fetch_extra_cols;
/* normally this is set to 0; if this
- is set to ROW_RETRIEVE_PRIMARY_KEY,
+ is set to ROW_RETRIEVE_PRIMARY_KEY
+ (that value is obsolete starting from
+ 5.0.2, because we always fetch the
+ primary key cols),
then we should at least retrieve all
columns in the primary key; if this
is set to ROW_RETRIEVE_ALL_COLS, then
@@ -605,6 +625,9 @@ struct row_prebuilt_struct {
/* Values for hint_need_to_fetch_extra_cols */
#define ROW_RETRIEVE_PRIMARY_KEY 1
+ /* value 1 is obsolete starting from
+ 5.0.2, because we always fetch the
+ primary key cols */
#define ROW_RETRIEVE_ALL_COLS 2
diff --git a/innobase/include/row0row.h b/innobase/include/row0row.h
index 951e211fb37..782973d8f5d 100644
--- a/innobase/include/row0row.h
+++ b/innobase/include/row0row.h
@@ -27,7 +27,8 @@ row_get_rec_trx_id(
/*===============*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Reads the roll pointer field from a clustered index record. */
UNIV_INLINE
@@ -36,7 +37,8 @@ row_get_rec_roll_ptr(
/*=================*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Writes the trx id field to a clustered index record. */
UNIV_INLINE
@@ -45,7 +47,8 @@ row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
- dulint trx_id); /* in: value of the field */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
+ dulint trx_id);/* in: value of the field */
/*************************************************************************
Sets the roll pointer field in a clustered index record. */
UNIV_INLINE
@@ -54,6 +57,7 @@ row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr);/* in: value of the field */
/*********************************************************************
When an insert to a table is performed, this function builds the entry which
@@ -90,6 +94,9 @@ row_build(
the buffer page of this record must be
at least s-latched and the latch held
as long as the row dtuple is used! */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index)
+ or NULL, in which case this function
+ will invoke rec_get_offsets() */
mem_heap_t* heap); /* in: memory heap from which the memory
needed is allocated */
/***********************************************************************
@@ -175,14 +182,15 @@ UNIV_INLINE
void
row_build_row_ref_fast(
/*===================*/
- dtuple_t* ref, /* in: typed data tuple where the reference
- is built */
- ulint* map, /* in: array of field numbers in rec telling
- how ref should be built from the fields of
- rec */
- rec_t* rec); /* in: record in the index; must be preserved
- while ref is used, as we do not copy field
- values to heap */
+ dtuple_t* ref, /* in: typed data tuple where the
+ reference is built */
+ const ulint* map, /* in: array of field numbers in rec
+ telling how ref should be built from
+ the fields of rec */
+ rec_t* rec, /* in: record in the index; must be
+ preserved while ref is used, as we do
+ not copy field values to heap */
+ const ulint* offsets);/* in: array returned by rec_get_offsets() */
/*******************************************************************
Searches the clustered index record for a row, if we have the row
reference. */
diff --git a/innobase/include/row0row.ic b/innobase/include/row0row.ic
index 8e5121f5a96..85410beacf0 100644
--- a/innobase/include/row0row.ic
+++ b/innobase/include/row0row.ic
@@ -20,7 +20,8 @@ row_get_rec_sys_field(
/* out: value of the field */
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
- dict_index_t* index); /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*************************************************************************
Sets the trx id or roll ptr field in a clustered index record: this function
is slower than the specialized inline functions. */
@@ -32,6 +33,7 @@ row_set_rec_sys_field(
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint val); /* in: value to set */
/*************************************************************************
@@ -42,18 +44,21 @@ row_get_rec_trx_id(
/*===============*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
return(trx_read_trx_id(rec + offset));
} else {
- return(row_get_rec_sys_field(DATA_TRX_ID, rec, index));
+ return(row_get_rec_sys_field(DATA_TRX_ID,
+ rec, index, offsets));
}
}
@@ -65,18 +70,21 @@ row_get_rec_roll_ptr(
/*=================*/
/* out: value of the field */
rec_t* rec, /* in: record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
return(trx_read_roll_ptr(rec + offset + DATA_TRX_ID_LEN));
} else {
- return(row_get_rec_sys_field(DATA_ROLL_PTR, rec, index));
+ return(row_get_rec_sys_field(DATA_ROLL_PTR,
+ rec, index, offsets));
}
}
@@ -88,18 +96,21 @@ row_set_rec_trx_id(
/*===============*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint trx_id) /* in: value of the field */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
trx_write_trx_id(rec + offset, trx_id);
} else {
- row_set_rec_sys_field(DATA_TRX_ID, rec, index, trx_id);
+ row_set_rec_sys_field(DATA_TRX_ID,
+ rec, index, offsets, trx_id);
}
}
@@ -111,18 +122,21 @@ row_set_rec_roll_ptr(
/*=================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint roll_ptr)/* in: value of the field */
{
ulint offset;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
offset = index->trx_id_offset;
if (offset) {
trx_write_roll_ptr(rec + offset + DATA_TRX_ID_LEN, roll_ptr);
} else {
- row_set_rec_sys_field(DATA_ROLL_PTR, rec, index, roll_ptr);
+ row_set_rec_sys_field(DATA_ROLL_PTR,
+ rec, index, offsets, roll_ptr);
}
}
@@ -133,14 +147,15 @@ UNIV_INLINE
void
row_build_row_ref_fast(
/*===================*/
- dtuple_t* ref, /* in: typed data tuple where the reference
- is built */
- ulint* map, /* in: array of field numbers in rec telling
- how ref should be built from the fields of
- rec */
- rec_t* rec) /* in: record in the index; must be preserved
- while ref is used, as we do not copy field
- values to heap */
+ dtuple_t* ref, /* in: typed data tuple where the
+ reference is built */
+ const ulint* map, /* in: array of field numbers in rec
+ telling how ref should be built from
+ the fields of rec */
+ rec_t* rec, /* in: record in the index; must be
+ preserved while ref is used, as we do
+ not copy field values to heap */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
dfield_t* dfield;
byte* field;
@@ -149,6 +164,7 @@ row_build_row_ref_fast(
ulint field_no;
ulint i;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
ref_len = dtuple_get_n_fields(ref);
for (i = 0; i < ref_len; i++) {
@@ -158,7 +174,8 @@ row_build_row_ref_fast(
if (field_no != ULINT_UNDEFINED) {
- field = rec_get_nth_field(rec, field_no, &len);
+ field = rec_get_nth_field(rec, offsets,
+ field_no, &len);
dfield_set_data(dfield, field, len);
}
}
diff --git a/innobase/include/row0sel.h b/innobase/include/row0sel.h
index bb6fb70ca86..8d5187bfc1c 100644
--- a/innobase/include/row0sel.h
+++ b/innobase/include/row0sel.h
@@ -120,6 +120,7 @@ row_search_for_mysql(
/* out: DB_SUCCESS,
DB_RECORD_NOT_FOUND,
DB_END_OF_INDEX, DB_DEADLOCK,
+ DB_LOCK_TABLE_FULL,
or DB_TOO_BIG_RECORD */
byte* buf, /* in/out: buffer for the fetched
row in the MySQL format */
diff --git a/innobase/include/row0upd.h b/innobase/include/row0upd.h
index 28210364833..673e0511153 100644
--- a/innobase/include/row0upd.h
+++ b/innobase/include/row0upd.h
@@ -80,6 +80,7 @@ row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
dulint roll_ptr);/* in: roll ptr of the undo log record */
/*************************************************************************
@@ -124,8 +125,8 @@ row_upd_changes_field_size_or_external(
/* out: TRUE if the update changes the size of
some field in index or the field is external
in rec or update */
- rec_t* rec, /* in: record in index */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update);/* in: update vector */
/***************************************************************
Replaces the new column values stored in the update vector to the record
@@ -135,8 +136,9 @@ a clustered index */
void
row_upd_rec_in_place(
/*=================*/
- rec_t* rec, /* in/out: record where replaced */
- upd_t* update);/* in: update vector */
+ rec_t* rec, /* in/out: record where replaced */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update);/* in: update vector */
/*******************************************************************
Builds an update vector from those fields which in a secondary index entry
differ from a record that has the equal ordering fields. NOTE: we compare
@@ -274,10 +276,11 @@ recovery. */
void
row_upd_rec_sys_fields_in_recovery(
/*===============================*/
- rec_t* rec, /* in: record */
- ulint pos, /* in: TRX_ID position in rec */
- dulint trx_id, /* in: transaction id */
- dulint roll_ptr);/* in: roll ptr of the undo log record */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint pos, /* in: TRX_ID position in rec */
+ dulint trx_id, /* in: transaction id */
+ dulint roll_ptr);/* in: roll ptr of the undo log record */
/*************************************************************************
Parses the log data written by row_upd_index_write_log. */
diff --git a/innobase/include/row0upd.ic b/innobase/include/row0upd.ic
index a124228a0de..e2d81a39cfa 100644
--- a/innobase/include/row0upd.ic
+++ b/innobase/include/row0upd.ic
@@ -106,15 +106,17 @@ row_upd_rec_sys_fields(
/*===================*/
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
trx_t* trx, /* in: transaction */
dulint roll_ptr)/* in: roll ptr of the undo log record */
{
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
#ifdef UNIV_SYNC_DEBUG
ut_ad(!buf_block_align(rec)->is_hashed
|| rw_lock_own(&btr_search_latch, RW_LOCK_EX));
#endif /* UNIV_SYNC_DEBUG */
- row_set_rec_trx_id(rec, index, trx->id);
- row_set_rec_roll_ptr(rec, index, roll_ptr);
+ row_set_rec_trx_id(rec, index, offsets, trx->id);
+ row_set_rec_roll_ptr(rec, index, offsets, roll_ptr);
}
diff --git a/innobase/include/row0vers.h b/innobase/include/row0vers.h
index 30cf82144e9..0dd40fda65f 100644
--- a/innobase/include/row0vers.h
+++ b/innobase/include/row0vers.h
@@ -30,7 +30,8 @@ row_vers_impl_x_locked_off_kernel(
transaction; NOTE that the kernel mutex is
temporarily released! */
rec_t* rec, /* in: record in a secondary index */
- dict_index_t* index); /* in: the secondary index */
+ dict_index_t* index, /* in: the secondary index */
+ const ulint* offsets);/* in: rec_get_offsets(rec, index) */
/*********************************************************************
Finds out if we must preserve a delete marked earlier version of a clustered
index record, because it is >= the purge view. */
diff --git a/innobase/include/row0vers.ic b/innobase/include/row0vers.ic
index 5ece47c35d1..ab1e264635b 100644
--- a/innobase/include/row0vers.ic
+++ b/innobase/include/row0vers.ic
@@ -11,73 +11,3 @@ Created 2/6/1997 Heikki Tuuri
#include "read0read.h"
#include "page0page.h"
#include "log0recv.h"
-
-/*************************************************************************
-Fetches the trx id of a clustered index record or version. */
-UNIV_INLINE
-dulint
-row_vers_get_trx_id(
-/*================*/
- /* out: trx id or ut_dulint_zero if the
- clustered index record not found */
- rec_t* rec, /* in: clustered index record, or an old
- version of it */
- dict_table_t* table) /* in: table */
-{
- return(row_get_rec_trx_id(rec, dict_table_get_first_index(table)));
-}
-
-/*************************************************************************
-Checks if a consistent read can be performed immediately on the index
-record, or if an older version is needed. */
-UNIV_INLINE
-ibool
-row_vers_clust_rec_sees_older(
-/*==========================*/
- /* out: FALSE if can read immediately */
- rec_t* rec, /* in: record which should be read or passed
- over by a read cursor */
- dict_index_t* index, /* in: clustered index */
- read_view_t* view) /* in: read view */
-{
- ut_ad(index->type & DICT_CLUSTERED);
-
- if (read_view_sees_trx_id(view, row_get_rec_trx_id(rec, index))) {
-
- return(FALSE);
- }
-
- return(TRUE);
-}
-
-/*************************************************************************
-Checks if a secondary index record can be read immediately by a consistent
-read, or if an older version may be needed. To be sure, we will have to
-look in the clustered index. */
-UNIV_INLINE
-ibool
-row_vers_sec_rec_may_see_older(
-/*===========================*/
- /* out: FALSE if can be read immediately */
- rec_t* rec, /* in: record which should be read or passed */
- dict_index_t* index __attribute__((unused)),/* in: secondary index */
- read_view_t* view) /* in: read view */
-{
- page_t* page;
-
- ut_ad(!(index->type & DICT_CLUSTERED));
-
- page = buf_frame_align(rec);
-
- if ((ut_dulint_cmp(page_get_max_trx_id(page), view->up_limit_id) >= 0)
- || recv_recovery_is_on()) {
-
- /* It may be that the record was inserted or modified by a
- transaction the view should not see: we have to look in the
- clustered index */
-
- return(TRUE);
- }
-
- return(FALSE);
-}
diff --git a/innobase/include/srv0srv.h b/innobase/include/srv0srv.h
index 6cfe9cef927..d4cc7d8222f 100644
--- a/innobase/include/srv0srv.h
+++ b/innobase/include/srv0srv.h
@@ -184,6 +184,63 @@ i/o handler thread */
extern const char* srv_io_thread_op_info[];
extern const char* srv_io_thread_function[];
+/* the number of the log write requests done */
+extern ulint srv_log_write_requests;
+
+/* the number of physical writes to the log performed */
+extern ulint srv_log_writes;
+
+/* amount of data written to the log files in bytes */
+extern ulint srv_os_log_written;
+
+/* amount of writes being done to the log files */
+extern ulint srv_os_log_pending_writes;
+
+/* we increase this counter, when there we don't have enough space in the
+log buffer and have to flush it */
+extern ulint srv_log_waits;
+
+/* variable that counts amount of data read in total (in bytes) */
+extern ulint srv_data_read;
+
+/* here we count the amount of data written in total (in bytes) */
+extern ulint srv_data_written;
+
+/* this variable counts the amount of times, when the doublewrite buffer
+was flushed */
+extern ulint srv_dblwr_writes;
+
+/* here we store the number of pages that have been flushed to the
+doublewrite buffer */
+extern ulint srv_dblwr_pages_written;
+
+/* in this variable we store the number of write requests issued */
+extern ulint srv_buf_pool_write_requests;
+
+/* here we store the number of times when we had to wait for a free page
+in the buffer pool. It happens when the buffer pool is full and we need
+to make a flush, in order to be able to read or create a page. */
+extern ulint srv_buf_pool_wait_free;
+
+/* variable to count the number of pages that were written from the
+buffer pool to disk */
+extern ulint srv_buf_pool_flushed;
+
+/* variable to count the number of buffer pool reads that led to the
+reading of a disk page */
+extern ulint srv_buf_pool_reads;
+
+/* variable to count the number of sequential read-aheads were done */
+extern ulint srv_read_ahead_seq;
+
+/* variable to count the number of random read-aheads were done */
+extern ulint srv_read_ahead_rnd;
+
+/* In this structure we store status variables to be passed to MySQL */
+typedef struct export_var_struct export_struc;
+
+extern export_struc export_vars;
+
typedef struct srv_sys_struct srv_sys_t;
/* The server system */
@@ -400,7 +457,12 @@ void
srv_printf_innodb_monitor(
/*======================*/
FILE* file); /* in: output stream */
+/************************************************************************
+Function to pass InnoDB status variables to MySQL */
+void
+srv_export_innodb_status(void);
+/*=====================*/
/* Types for the threads existing in the system. Threads of types 4 - 9
are called utility threads. Note that utility threads are mainly disk
@@ -426,6 +488,48 @@ typedef struct srv_slot_struct srv_slot_t;
/* Thread table is an array of slots */
typedef srv_slot_t srv_table_t;
+/* In this structure we store status variables to be passed to MySQL */
+struct export_var_struct{
+ ulint innodb_data_pending_reads;
+ ulint innodb_data_pending_writes;
+ ulint innodb_data_pending_fsyncs;
+ ulint innodb_data_fsyncs;
+ ulint innodb_data_read;
+ ulint innodb_data_writes;
+ ulint innodb_data_written;
+ ulint innodb_data_reads;
+ ulint innodb_buffer_pool_pages_total;
+ ulint innodb_buffer_pool_pages_data;
+ ulint innodb_buffer_pool_pages_dirty;
+ ulint innodb_buffer_pool_pages_misc;
+ ulint innodb_buffer_pool_pages_free;
+ ulint innodb_buffer_pool_pages_latched;
+ ulint innodb_buffer_pool_read_requests;
+ ulint innodb_buffer_pool_reads;
+ ulint innodb_buffer_pool_wait_free;
+ ulint innodb_buffer_pool_pages_flushed;
+ ulint innodb_buffer_pool_write_requests;
+ ulint innodb_buffer_pool_read_ahead_seq;
+ ulint innodb_buffer_pool_read_ahead_rnd;
+ ulint innodb_dblwr_pages_written;
+ ulint innodb_dblwr_writes;
+ ulint innodb_log_waits;
+ ulint innodb_log_write_requests;
+ ulint innodb_log_writes;
+ ulint innodb_os_log_written;
+ ulint innodb_os_log_fsyncs;
+ ulint innodb_os_log_pending_writes;
+ ulint innodb_os_log_pending_fsyncs;
+ ulint innodb_page_size;
+ ulint innodb_pages_created;
+ ulint innodb_pages_read;
+ ulint innodb_pages_written;
+ ulint innodb_rows_read;
+ ulint innodb_rows_inserted;
+ ulint innodb_rows_updated;
+ ulint innodb_rows_deleted;
+};
+
/* The server system struct */
struct srv_sys_struct{
os_event_t operational; /* created threads must wait for the
@@ -434,6 +538,10 @@ struct srv_sys_struct{
srv_table_t* threads; /* server thread table */
UT_LIST_BASE_NODE_T(que_thr_t)
tasks; /* task queue */
+ dict_index_t* dummy_ind1; /* dummy index for old-style
+ supremum and infimum records */
+ dict_index_t* dummy_ind2; /* dummy index for new-style
+ supremum and infimum records */
};
extern ulint srv_n_threads_active[];
diff --git a/innobase/include/trx0rec.h b/innobase/include/trx0rec.h
index 9d7f41cd94e..4387ce1a61e 100644
--- a/innobase/include/trx0rec.h
+++ b/innobase/include/trx0rec.h
@@ -246,6 +246,7 @@ trx_undo_prev_version_build(
index_rec page and purge_view */
rec_t* rec, /* in: version of a clustered index record */
dict_index_t* index, /* in: clustered index */
+ ulint* offsets,/* in: rec_get_offsets(rec, index) */
mem_heap_t* heap, /* in: memory heap from which the memory
needed is allocated */
rec_t** old_vers);/* out, own: previous version, or NULL if
diff --git a/innobase/include/trx0roll.h b/innobase/include/trx0roll.h
index 6004551f456..893e5af6c01 100644
--- a/innobase/include/trx0roll.h
+++ b/innobase/include/trx0roll.h
@@ -104,11 +104,12 @@ trx_rollback(
/***********************************************************************
Rollback or clean up transactions which have no user session. If the
transaction already was committed, then we clean up a possible insert
-undo log. If the transaction was not yet committed, then we roll it back. */
+undo log. If the transaction was not yet committed, then we roll it back.
+Note: this is done in a background thread */
-void
-trx_rollback_or_clean_all_without_sess(void);
-/*========================================*/
+void *
+trx_rollback_or_clean_all_without_sess(void *);
+/*============================================*/
/********************************************************************
Finishes a transaction rollback. */
diff --git a/innobase/include/trx0trx.h b/innobase/include/trx0trx.h
index 7eb91048684..8eb71dac763 100644
--- a/innobase/include/trx0trx.h
+++ b/innobase/include/trx0trx.h
@@ -16,6 +16,7 @@ Created 3/26/1996 Heikki Tuuri
#include "que0types.h"
#include "mem0mem.h"
#include "read0types.h"
+#include "trx0xa.h"
extern ulint trx_n_mysql_transactions;
@@ -156,6 +157,36 @@ trx_commit_for_mysql(
/*=================*/
/* out: 0 or error number */
trx_t* trx); /* in: trx handle */
+
+/**************************************************************************
+Does the transaction prepare for MySQL. */
+
+ulint
+trx_prepare_for_mysql(
+/*=================*/
+ /* out: 0 or error number */
+ trx_t* trx); /* in: trx handle */
+
+/**************************************************************************
+This function is used to find number of prepared transactions and
+their transaction objects for a recovery. */
+
+int
+trx_recover_for_mysql(
+/*=================*/
+ /* out: number of prepared transactions */
+ XID* xid_list, /* in/out: prepared transactions */
+ uint len); /* in: number of slots in xid_list */
+
+/***********************************************************************
+This function is used to commit one X/Open XA distributed transaction
+which is in the prepared state */
+trx_t *
+trx_get_trx_by_xid(
+/*===============*/
+ /* out: trx or NULL */
+ XID* xid); /* in: X/Open XA Transaction Idenfication */
+
/**************************************************************************
If required, flushes the log to disk if we called trx_commit_for_mysql()
with trx->flush_log_later == TRUE. */
@@ -339,6 +370,9 @@ struct trx_struct{
if we can use the insert buffer for
them, we set this FALSE */
dulint id; /* transaction id */
+ XID xid; /* X/Open XA transaction
+ identification to identify a
+ transaction branch */
dulint no; /* transaction serialization number ==
max trx id when the transaction is
moved to COMMITTED_IN_MEMORY state */
@@ -353,8 +387,10 @@ struct trx_struct{
dulint table_id; /* table id if the preceding field is
TRUE */
/*------------------------------*/
- void* mysql_thd; /* MySQL thread handle corresponding
- to this trx, or NULL */
+ int active_trans; /* whether a transaction in MySQL
+ is active */
+ void* mysql_thd; /* MySQL thread handle corresponding
+ to this trx, or NULL */
char** mysql_query_str;/* pointer to the field in mysqld_thd
which contains the pointer to the
current SQL query string */
@@ -423,6 +459,8 @@ struct trx_struct{
lock_t* auto_inc_lock; /* possible auto-inc lock reserved by
the transaction; note that it is also
in the lock list trx_locks */
+ ibool trx_create_lock;/* this is TRUE if we have created a
+ new lock for a record accessed */
ulint n_lock_table_exp;/* number of explicit table locks
(LOCK TABLES) reserved by the
transaction, stored in trx_locks */
@@ -541,6 +579,7 @@ struct trx_struct{
#define TRX_NOT_STARTED 1
#define TRX_ACTIVE 2
#define TRX_COMMITTED_IN_MEMORY 3
+#define TRX_PREPARED 4 /* Support for 2PC/XA */
/* Transaction execution states when trx state is TRX_ACTIVE */
#define TRX_QUE_RUNNING 1 /* transaction is running */
diff --git a/innobase/include/trx0undo.h b/innobase/include/trx0undo.h
index 20002076cc3..fce62e46046 100644
--- a/innobase/include/trx0undo.h
+++ b/innobase/include/trx0undo.h
@@ -14,6 +14,7 @@ Created 3/26/1996 Heikki Tuuri
#include "mtr0mtr.h"
#include "trx0sys.h"
#include "page0types.h"
+#include "trx0xa.h"
/***************************************************************************
Builds a roll pointer dulint. */
@@ -36,7 +37,7 @@ trx_undo_decode_roll_ptr(
ibool* is_insert, /* out: TRUE if insert undo log */
ulint* rseg_id, /* out: rollback segment id */
ulint* page_no, /* out: page number */
- ulint* offset); /* out: offset of the undo entry within page */
+ ulint* offset); /* out: offset of the undo entry within page */
/***************************************************************************
Returns TRUE if the roll pointer is of the insert type. */
UNIV_INLINE
@@ -239,6 +240,18 @@ trx_undo_set_state_at_finish(
trx_t* trx, /* in: transaction */
trx_undo_t* undo, /* in: undo log memory copy */
mtr_t* mtr); /* in: mtr */
+/**********************************************************************
+Sets the state of the undo log segment at a transaction prepare. */
+
+page_t*
+trx_undo_set_state_at_prepare(
+/*==========================*/
+ /* out: undo log segment header page,
+ x-latched */
+ trx_t* trx, /* in: transaction */
+ trx_undo_t* undo, /* in: undo log memory copy */
+ mtr_t* mtr); /* in: mtr */
+
/**************************************************************************
Adds the update undo log header as the first in the history list, and
frees the memory object, or puts it to the list of cached update undo log
@@ -294,7 +307,23 @@ trx_undo_parse_discard_latest(
byte* end_ptr,/* in: buffer end */
page_t* page, /* in: page or NULL */
mtr_t* mtr); /* in: mtr or NULL */
+/************************************************************************
+Write X/Open XA Transaction Identification (XID) to undo log header */
+void
+trx_undo_write_xid(
+/*===============*/
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ XID* xid); /* in: X/Open XA Transaction Identification */
+
+/************************************************************************
+Read X/Open XA Transaction Identification (XID) from undo log header */
+
+void
+trx_undo_read_xid(
+/*==============*/
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ XID* xid); /* out: X/Open XA Transaction Identification */
/* Types of an undo log segment */
#define TRX_UNDO_INSERT 1 /* contains undo entries for inserts */
@@ -310,6 +339,8 @@ trx_undo_parse_discard_latest(
#define TRX_UNDO_TO_PURGE 4 /* update undo segment will not be
reused: it can be freed in purge when
all undo data in it is removed */
+#define TRX_UNDO_PREPARED 5 /* contains an undo log of an
+ prepared transaction */
/* Transaction undo log memory object; this is protected by the undo_mutex
in the corresponding transaction object */
@@ -332,6 +363,8 @@ struct trx_undo_struct{
field */
dulint trx_id; /* id of the trx assigned to the undo
log */
+ XID xid; /* X/Open XA transaction
+ identification */
ibool dict_operation; /* TRUE if a dict operation trx */
dulint table_id; /* if a dict operation, then the table
id */
@@ -436,7 +469,10 @@ page of an update undo log segment. */
log start, and therefore this is not
necessarily the same as this log
header end offset */
-#define TRX_UNDO_DICT_OPERATION 20 /* TRUE if the transaction is a table
+#define TRX_UNDO_XID_EXISTS 20 /* TRUE if undo log header includes
+ X/Open XA transaction identification
+ XID */
+#define TRX_UNDO_DICT_TRANS 21 /* TRUE if the transaction is a table
create, index create, or drop
transaction: in recovery
the transaction cannot be rolled back
@@ -452,7 +488,17 @@ page of an update undo log segment. */
#define TRX_UNDO_HISTORY_NODE 34 /* If the log is put to the history
list, the file list node is here */
/*-------------------------------------------------------------*/
-#define TRX_UNDO_LOG_HDR_SIZE (34 + FLST_NODE_SIZE)
+/* X/Open XA Transaction Identification (XID) */
+
+#define TRX_UNDO_XA_FORMAT (34 + FLST_NODE_SIZE)
+#define TRX_UNDO_XA_TRID_LEN (TRX_UNDO_XA_FORMAT + 4)
+#define TRX_UNDO_XA_BQUAL_LEN (TRX_UNDO_XA_TRID_LEN + 4)
+#define TRX_UNDO_XA_XID (TRX_UNDO_XA_BQUAL_LEN + 4)
+#define TRX_UNDO_XA_LEN (TRX_UNDO_XA_XID + XIDDATASIZE)
+
+/*-------------------------------------------------------------*/
+#define TRX_UNDO_LOG_HDR_SIZE (TRX_UNDO_XA_LEN)
+/*-------------------------------------------------------------*/
#ifndef UNIV_NONINL
#include "trx0undo.ic"
diff --git a/innobase/include/trx0xa.h b/innobase/include/trx0xa.h
new file mode 100644
index 00000000000..34b7a2f95a8
--- /dev/null
+++ b/innobase/include/trx0xa.h
@@ -0,0 +1,182 @@
+/*
+ * Start of xa.h header
+ *
+ * Define a symbol to prevent multiple inclusions of this header file
+ */
+#ifndef XA_H
+#define XA_H
+
+/*
+ * Transaction branch identification: XID and NULLXID:
+ */
+#ifndef XIDDATASIZE
+
+#define XIDDATASIZE 128 /* size in bytes */
+#define MAXGTRIDSIZE 64 /* maximum size in bytes of gtrid */
+#define MAXBQUALSIZE 64 /* maximum size in bytes of bqual */
+
+struct xid_t {
+ long formatID; /* format identifier */
+ long gtrid_length; /* value from 1 through 64 */
+ long bqual_length; /* value from 1 through 64 */
+ char data[XIDDATASIZE];
+};
+typedef struct xid_t XID;
+#endif
+/*
+ * A value of -1 in formatID means that the XID is null.
+ */
+
+
+#ifdef NOTDEFINED
+/* Let us comment this out to remove compiler errors!!!!!!!!!!!! */
+
+/*
+ * Declarations of routines by which RMs call TMs:
+ */
+extern int ax_reg __P((int, XID *, long));
+extern int ax_unreg __P((int, long));
+
+/*
+ * XA Switch Data Structure
+ */
+#define RMNAMESZ 32 /* length of resource manager name, */
+ /* including the null terminator */
+#define MAXINFOSIZE 256 /* maximum size in bytes of xa_info */
+ /* strings, including the null
+ terminator */
+
+
+struct xa_switch_t {
+ char name[RMNAMESZ]; /* name of resource manager */
+ long flags; /* resource manager specific options */
+ long version; /* must be 0 */
+ int (*xa_open_entry) /* xa_open function pointer */
+ __P((char *, int, long));
+ int (*xa_close_entry) /* xa_close function pointer */
+ __P((char *, int, long));
+ int (*xa_start_entry) /* xa_start function pointer */
+ __P((XID *, int, long));
+ int (*xa_end_entry) /* xa_end function pointer */
+ __P((XID *, int, long));
+ int (*xa_rollback_entry) /* xa_rollback function pointer */
+ __P((XID *, int, long));
+ int (*xa_prepare_entry) /* xa_prepare function pointer */
+ __P((XID *, int, long));
+ int (*xa_commit_entry) /* xa_commit function pointer */
+ __P((XID *, int, long));
+ int (*xa_recover_entry) /* xa_recover function pointer */
+ __P((XID *, long, int, long));
+ int (*xa_forget_entry) /* xa_forget function pointer */
+ __P((XID *, int, long));
+ int (*xa_complete_entry) /* xa_complete function pointer */
+ __P((int *, int *, int, long));
+};
+#endif /* NOTDEFINED */
+
+
+/*
+ * Flag definitions for the RM switch
+ */
+#define TMNOFLAGS 0x00000000L /* no resource manager features
+ selected */
+#define TMREGISTER 0x00000001L /* resource manager dynamically
+ registers */
+#define TMNOMIGRATE 0x00000002L /* resource manager does not support
+ association migration */
+#define TMUSEASYNC 0x00000004L /* resource manager supports
+ asynchronous operations */
+/*
+ * Flag definitions for xa_ and ax_ routines
+ */
+/* use TMNOFLAGGS, defined above, when not specifying other flags */
+#define TMASYNC 0x80000000L /* perform routine asynchronously */
+#define TMONEPHASE 0x40000000L /* caller is using one-phase commit
+ optimisation */
+#define TMFAIL 0x20000000L /* dissociates caller and marks
+ transaction branch rollback-only */
+#define TMNOWAIT 0x10000000L /* return if blocking condition
+ exists */
+#define TMRESUME 0x08000000L /* caller is resuming association with
+ suspended transaction branch */
+#define TMSUCCESS 0x04000000L /* dissociate caller from transaction
+ branch */
+#define TMSUSPEND 0x02000000L /* caller is suspending, not ending,
+ association */
+#define TMSTARTRSCAN 0x01000000L /* start a recovery scan */
+#define TMENDRSCAN 0x00800000L /* end a recovery scan */
+#define TMMULTIPLE 0x00400000L /* wait for any asynchronous
+ operation */
+#define TMJOIN 0x00200000L /* caller is joining existing
+ transaction branch */
+#define TMMIGRATE 0x00100000L /* caller intends to perform
+ migration */
+
+/*
+ * ax_() return codes (transaction manager reports to resource manager)
+ */
+#define TM_JOIN 2 /* caller is joining existing
+ transaction branch */
+#define TM_RESUME 1 /* caller is resuming association with
+ suspended transaction branch */
+#define TM_OK 0 /* normal execution */
+#define TMER_TMERR -1 /* an error occurred in the transaction
+ manager */
+#define TMER_INVAL -2 /* invalid arguments were given */
+#define TMER_PROTO -3 /* routine invoked in an improper
+ context */
+
+/*
+ * xa_() return codes (resource manager reports to transaction manager)
+ */
+#define XA_RBBASE 100 /* The inclusive lower bound of the
+ rollback codes */
+#define XA_RBROLLBACK XA_RBBASE /* The rollback was caused by an
+ unspecified reason */
+#define XA_RBCOMMFAIL XA_RBBASE+1 /* The rollback was caused by a
+ communication failure */
+#define XA_RBDEADLOCK XA_RBBASE+2 /* A deadlock was detected */
+#define XA_RBINTEGRITY XA_RBBASE+3 /* A condition that violates the
+ integrity of the resources was
+ detected */
+#define XA_RBOTHER XA_RBBASE+4 /* The resource manager rolled back the
+ transaction branch for a reason not
+ on this list */
+#define XA_RBPROTO XA_RBBASE+5 /* A protocol error occurred in the
+ resource manager */
+#define XA_RBTIMEOUT XA_RBBASE+6 /* A transaction branch took too long */
+#define XA_RBTRANSIENT XA_RBBASE+7 /* May retry the transaction branch */
+#define XA_RBEND XA_RBTRANSIENT /* The inclusive upper bound of the
+ rollback codes */
+#define XA_NOMIGRATE 9 /* resumption must occur where
+ suspension occurred */
+#define XA_HEURHAZ 8 /* the transaction branch may have
+ been heuristically completed */
+#define XA_HEURCOM 7 /* the transaction branch has been
+ heuristically committed */
+#define XA_HEURRB 6 /* the transaction branch has been
+ heuristically rolled back */
+#define XA_HEURMIX 5 /* the transaction branch has been
+ heuristically committed and rolled
+ back */
+#define XA_RETRY 4 /* routine returned with no effect and
+ may be re-issued */
+#define XA_RDONLY 3 /* the transaction branch was read-only
+ and has been committed */
+#define XA_OK 0 /* normal execution */
+#define XAER_ASYNC -2 /* asynchronous operation already
+ outstanding */
+#define XAER_RMERR -3 /* a resource manager error occurred in
+ the transaction branch */
+#define XAER_NOTA -4 /* the XID is not valid */
+#define XAER_INVAL -5 /* invalid arguments were given */
+#define XAER_PROTO -6 /* routine invoked in an improper
+ context */
+#define XAER_RMFAIL -7 /* resource manager unavailable */
+#define XAER_DUPID -8 /* the XID already exists */
+#define XAER_OUTSIDE -9 /* resource manager doing work outside
+ transaction */
+#endif /* ifndef XA_H */
+/*
+ * End of xa.h header
+ */
diff --git a/innobase/include/ut0byte.h b/innobase/include/ut0byte.h
index a62c2e2e318..22d488abeaf 100644
--- a/innobase/include/ut0byte.h
+++ b/innobase/include/ut0byte.h
@@ -208,7 +208,20 @@ ut_align_down(
/*==========*/
/* out: aligned pointer */
void* ptr, /* in: pointer */
- ulint align_no); /* in: align by this number */
+ ulint align_no) /* in: align by this number */
+ __attribute__((const));
+/*************************************************************
+The following function computes the offset of a pointer from the nearest
+aligned address. */
+UNIV_INLINE
+ulint
+ut_align_offset(
+/*==========*/
+ /* out: distance from aligned
+ pointer */
+ const void* ptr, /* in: pointer */
+ ulint align_no) /* in: align by this number */
+ __attribute__((const));
/*********************************************************************
Gets the nth bit of a ulint. */
UNIV_INLINE
diff --git a/innobase/include/ut0byte.ic b/innobase/include/ut0byte.ic
index 5a70dcf12a8..e141de3aa3f 100644
--- a/innobase/include/ut0byte.ic
+++ b/innobase/include/ut0byte.ic
@@ -335,6 +335,27 @@ ut_align_down(
return((void*)((((ulint)ptr)) & ~(align_no - 1)));
}
+/*************************************************************
+The following function computes the offset of a pointer from the nearest
+aligned address. */
+UNIV_INLINE
+ulint
+ut_align_offset(
+/*============*/
+ /* out: distance from
+ aligned pointer */
+ const void* ptr, /* in: pointer */
+ ulint align_no) /* in: align by this number */
+{
+ ut_ad(align_no > 0);
+ ut_ad(((align_no - 1) & align_no) == 0);
+ ut_ad(ptr);
+
+ ut_ad(sizeof(void*) == sizeof(ulint));
+
+ return(((ulint)ptr) & (align_no - 1));
+}
+
/*********************************************************************
Gets the nth bit of a ulint. */
UNIV_INLINE
diff --git a/innobase/include/ut0mem.h b/innobase/include/ut0mem.h
index 73ecb25101a..74357f6bf13 100644
--- a/innobase/include/ut0mem.h
+++ b/innobase/include/ut0mem.h
@@ -38,8 +38,10 @@ ut_malloc_low(
/*==========*/
/* out, own: allocated memory */
ulint n, /* in: number of bytes to allocate */
- ibool set_to_zero); /* in: TRUE if allocated memory should be set
+ ibool set_to_zero, /* in: TRUE if allocated memory should be set
to zero if UNIV_SET_MEM_TO_ZERO is defined */
+ ibool assert_on_error); /* in: if TRUE, we crash mysqld if the memory
+ cannot be allocated */
/**************************************************************************
Allocates memory. Sets it also to zero if UNIV_SET_MEM_TO_ZERO is
defined. */
diff --git a/innobase/lock/lock0lock.c b/innobase/lock/lock0lock.c
index 68073647248..d2d16a1ae4e 100644
--- a/innobase/lock/lock0lock.c
+++ b/innobase/lock/lock0lock.c
@@ -365,6 +365,21 @@ lock_deadlock_recursive(
ulint* cost); /* in/out: number of calculation steps thus
far: if this exceeds LOCK_MAX_N_STEPS_...
we return TRUE */
+
+/*************************************************************************
+Gets the type of a lock. */
+UNIV_INLINE
+ulint
+lock_get_type(
+/*==========*/
+ /* out: LOCK_TABLE or LOCK_REC */
+ lock_t* lock) /* in: lock */
+{
+ ut_ad(lock);
+
+ return(lock->type_mode & LOCK_TYPE_MASK);
+}
+
/*************************************************************************
Gets the nth bit of a record lock. */
UNIV_INLINE
@@ -410,11 +425,14 @@ lock_check_trx_id_sanity(
dulint trx_id, /* in: trx id */
rec_t* rec, /* in: user record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
ibool has_kernel_mutex)/* in: TRUE if the caller owns the
kernel mutex */
{
ibool is_ok = TRUE;
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (!has_kernel_mutex) {
mutex_enter(&kernel_mutex);
}
@@ -427,7 +445,7 @@ lock_check_trx_id_sanity(
fputs(" InnoDB: Error: transaction id associated"
" with record\n",
stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, offsets);
fputs("InnoDB: in ", stderr);
dict_index_name_print(stderr, NULL, index);
fprintf(stderr, "\n"
@@ -459,18 +477,20 @@ lock_clust_rec_cons_read_sees(
rec_t* rec, /* in: user record which should be read or
passed over by a read cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
read_view_t* view) /* in: consistent read view */
{
dulint trx_id;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(page_rec_is_user_rec(rec));
+ ut_ad(rec_offs_validate(rec, index, offsets));
/* NOTE that we call this function while holding the search
system latch. To obey the latching order we must NOT reserve the
kernel mutex here! */
- trx_id = row_get_rec_trx_id(rec, index);
+ trx_id = row_get_rec_trx_id(rec, index, offsets);
if (read_view_sees_trx_id(view, trx_id)) {
@@ -569,20 +589,6 @@ lock_get_mode(
}
/*************************************************************************
-Gets the type of a lock. */
-UNIV_INLINE
-ulint
-lock_get_type(
-/*==========*/
- /* out: LOCK_TABLE or LOCK_REC */
- lock_t* lock) /* in: lock */
-{
- ut_ad(lock);
-
- return(lock->type_mode & LOCK_TYPE_MASK);
-}
-
-/*************************************************************************
Gets the wait flag of a lock. */
UNIV_INLINE
ibool
@@ -602,6 +608,128 @@ lock_get_wait(
}
/*************************************************************************
+Gets the source table of an ALTER TABLE transaction. The table must be
+covered by an IX or IS table lock. */
+
+dict_table_t*
+lock_get_src_table(
+/*===============*/
+ /* out: the source table of transaction,
+ if it is covered by an IX or IS table lock;
+ dest if there is no source table, and
+ NULL if the transaction is locking more than
+ two tables or an inconsistency is found */
+ trx_t* trx, /* in: transaction */
+ dict_table_t* dest, /* in: destination of ALTER TABLE */
+ ulint* mode) /* out: lock mode of the source table */
+{
+ dict_table_t* src;
+ lock_t* lock;
+
+ src = NULL;
+ *mode = LOCK_NONE;
+
+ for (lock = UT_LIST_GET_FIRST(trx->trx_locks);
+ lock;
+ lock = UT_LIST_GET_NEXT(trx_locks, lock)) {
+ lock_table_t* tab_lock;
+ ulint lock_mode;
+ if (!(lock_get_type(lock) & LOCK_TABLE)) {
+ /* We are only interested in table locks. */
+ continue;
+ }
+ tab_lock = &lock->un_member.tab_lock;
+ if (dest == tab_lock->table) {
+ /* We are not interested in the destination table. */
+ continue;
+ } else if (!src) {
+ /* This presumably is the source table. */
+ src = tab_lock->table;
+ if (UT_LIST_GET_LEN(src->locks) != 1 ||
+ UT_LIST_GET_FIRST(src->locks) != lock) {
+ /* We only support the case when
+ there is only one lock on this table. */
+ return(NULL);
+ }
+ } else if (src != tab_lock->table) {
+ /* The transaction is locking more than
+ two tables (src and dest): abort */
+ return(NULL);
+ }
+
+ /* Check that the source table is locked by
+ LOCK_IX or LOCK_IS. */
+ lock_mode = lock_get_mode(lock);
+ switch (lock_mode) {
+ case LOCK_IX:
+ case LOCK_IS:
+ if (*mode != LOCK_NONE && *mode != lock_mode) {
+ /* There are multiple locks on src. */
+ return(NULL);
+ }
+ *mode = lock_mode;
+ break;
+ }
+ }
+
+ if (!src) {
+ /* No source table lock found: flag the situation to caller */
+ src = dest;
+ }
+
+ return(src);
+}
+
+/*************************************************************************
+Determine if the given table is exclusively "owned" by the given
+transaction, i.e., transaction holds LOCK_IX and possibly LOCK_AUTO_INC
+on the table. */
+
+ibool
+lock_is_table_exclusive(
+/*====================*/
+ /* out: TRUE if table is only locked by trx,
+ with LOCK_IX, and possibly LOCK_AUTO_INC */
+ dict_table_t* table, /* in: table */
+ trx_t* trx) /* in: transaction */
+{
+ lock_t* lock;
+ bool ok = FALSE;
+
+ ut_ad(table && trx);
+
+ for (lock = UT_LIST_GET_FIRST(table->locks);
+ lock;
+ lock = UT_LIST_GET_NEXT(locks, &lock->un_member.tab_lock)) {
+ if (lock->trx != trx) {
+ /* A lock on the table is held
+ by some other transaction. */
+ return(FALSE);
+ }
+
+ if (!(lock_get_type(lock) & LOCK_TABLE)) {
+ /* We are interested in table locks only. */
+ continue;
+ }
+
+ switch (lock_get_mode(lock)) {
+ case LOCK_IX:
+ ok = TRUE;
+ break;
+ case LOCK_AUTO_INC:
+ /* It is allowed for trx to hold an
+ auto_increment lock. */
+ break;
+ default:
+ /* Other table locks than LOCK_IX are not allowed. */
+ return(FALSE);
+ }
+ }
+
+ return(ok);
+}
+
+/*************************************************************************
Sets the wait flag of a lock and the back pointer in trx to lock. */
UNIV_INLINE
void
@@ -1133,6 +1261,7 @@ lock_rec_get_next(
/*==============*/
/* out: next lock, NULL if none exists */
rec_t* rec, /* in: record on a page */
+ ibool comp, /* in: TRUE=compact page format */
lock_t* lock) /* in: lock */
{
#ifdef UNIV_SYNC_DEBUG
@@ -1148,7 +1277,7 @@ lock_rec_get_next(
return(NULL);
}
- if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec))) {
+ if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) {
return(lock);
}
@@ -1165,15 +1294,17 @@ lock_rec_get_first(
rec_t* rec) /* in: record on a page */
{
lock_t* lock;
+ ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first_on_page(rec);
+ comp = page_is_comp(buf_frame_align(rec));
while (lock) {
- if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec))) {
+ if (lock_rec_get_nth_bit(lock, rec_get_heap_no(rec, comp))) {
break;
}
@@ -1340,6 +1471,7 @@ lock_rec_has_expl(
for a supremum record we regard this always a gap
type request */
rec_t* rec, /* in: record */
+ ibool comp, /* in: TRUE=compact page format */
trx_t* trx) /* in: transaction */
{
lock_t* lock;
@@ -1369,7 +1501,7 @@ lock_rec_has_expl(
return(lock);
}
- lock = lock_rec_get_next(rec, lock);
+ lock = lock_rec_get_next(rec, comp, lock);
}
return(NULL);
@@ -1388,6 +1520,7 @@ lock_rec_other_has_expl_req(
ulint wait, /* in: LOCK_WAIT if also waiting locks are
taken into account, or 0 if not */
rec_t* rec, /* in: record to look at */
+ ibool comp, /* in: TRUE=compact record format */
trx_t* trx) /* in: transaction, or NULL if requests by all
transactions are taken into account */
{
@@ -1412,7 +1545,7 @@ lock_rec_other_has_expl_req(
return(lock);
}
- lock = lock_rec_get_next(rec, lock);
+ lock = lock_rec_get_next(rec, comp, lock);
}
return(NULL);
@@ -1433,12 +1566,13 @@ lock_rec_other_has_conflicting(
trx_t* trx) /* in: our transaction */
{
lock_t* lock;
-
+ ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
+ comp = page_is_comp(buf_frame_align(rec));
while (lock) {
if (lock_rec_has_to_wait(trx, mode, lock,
@@ -1447,7 +1581,7 @@ lock_rec_other_has_conflicting(
return(lock);
}
- lock = lock_rec_get_next(rec, lock);
+ lock = lock_rec_get_next(rec, comp, lock);
}
return(NULL);
@@ -1473,8 +1607,7 @@ lock_rec_find_similar_on_page(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- heap_no = rec_get_heap_no(rec);
-
+ heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec)));
lock = lock_rec_get_first_on_page(rec);
while (lock != NULL) {
@@ -1501,7 +1634,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* out: transaction which has the x-lock, or
NULL */
rec_t* rec, /* in: user record */
- dict_index_t* index) /* in: secondary index */
+ dict_index_t* index, /* in: secondary index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
page_t* page;
@@ -1510,6 +1644,7 @@ lock_sec_rec_some_has_impl_off_kernel(
#endif /* UNIV_SYNC_DEBUG */
ut_ad(!(index->type & DICT_CLUSTERED));
ut_ad(page_rec_is_user_rec(rec));
+ ut_ad(rec_offs_validate(rec, index, offsets));
page = buf_frame_align(rec);
@@ -1529,8 +1664,8 @@ lock_sec_rec_some_has_impl_off_kernel(
/* Ok, in this case it is possible that some transaction has an
implicit x-lock. We have to look in the clustered index. */
- if (!lock_check_trx_id_sanity(page_get_max_trx_id(page), rec, index,
- TRUE)) {
+ if (!lock_check_trx_id_sanity(page_get_max_trx_id(page),
+ rec, index, offsets, TRUE)) {
buf_page_print(page);
/* The page is corrupt: try to avoid a crash by returning
@@ -1538,7 +1673,7 @@ lock_sec_rec_some_has_impl_off_kernel(
return(NULL);
}
- return(row_vers_impl_x_locked_off_kernel(rec, index));
+ return(row_vers_impl_x_locked_off_kernel(rec, index, offsets));
}
/*============== RECORD LOCK CREATION AND QUEUE MANAGEMENT =============*/
@@ -1572,7 +1707,7 @@ lock_rec_create(
page = buf_frame_align(rec);
space = buf_frame_get_space_id(page);
page_no = buf_frame_get_page_no(page);
- heap_no = rec_get_heap_no(rec);
+ heap_no = rec_get_heap_no(rec, page_is_comp(page));
/* If rec is the supremum record, then we reset the gap and
LOCK_REC_NOT_GAP bits, as all locks on the supremum are
@@ -1585,8 +1720,7 @@ lock_rec_create(
}
/* Make lock bitmap bigger by a safety margin */
- n_bits = page_header_get_field(page, PAGE_N_HEAP)
- + LOCK_PAGE_BITMAP_MARGIN;
+ n_bits = page_dir_get_n_heap(page) + LOCK_PAGE_BITMAP_MARGIN;
n_bytes = 1 + n_bits / 8;
lock = mem_heap_alloc(trx->lock_heap, sizeof(lock_t) + n_bytes);
@@ -1617,6 +1751,9 @@ lock_rec_create(
HASH_INSERT(lock_t, hash, lock_sys->rec_hash,
lock_rec_fold(space, page_no), lock);
+ /* Note that we have create a new lock */
+ trx->trx_create_lock = TRUE;
+
if (type_mode & LOCK_WAIT) {
lock_set_lock_and_trx_wait(lock, trx);
@@ -1688,7 +1825,8 @@ lock_rec_enqueue_waiting(
if (lock_deadlock_occurs(lock, trx)) {
lock_reset_lock_and_trx_wait(lock);
- lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec));
+ lock_rec_reset_nth_bit(lock, rec_get_heap_no(rec,
+ page_is_comp(buf_frame_align(rec))));
return(DB_DEADLOCK);
}
@@ -1738,7 +1876,7 @@ lock_rec_add_to_queue(
lock_t* lock;
lock_t* similar_lock = NULL;
ulint heap_no;
- page_t* page;
+ page_t* page = buf_frame_align(rec);
ibool somebody_waits = FALSE;
#ifdef UNIV_SYNC_DEBUG
@@ -1746,15 +1884,15 @@ lock_rec_add_to_queue(
#endif /* UNIV_SYNC_DEBUG */
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_S)
- || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT, rec, trx));
+ || !lock_rec_other_has_expl_req(LOCK_X, 0, LOCK_WAIT,
+ rec, page_is_comp(page), trx));
ut_ad((type_mode & (LOCK_WAIT | LOCK_GAP))
|| ((type_mode & LOCK_MODE_MASK) != LOCK_X)
- || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT, rec, trx));
+ || !lock_rec_other_has_expl_req(LOCK_S, 0, LOCK_WAIT,
+ rec, page_is_comp(page), trx));
type_mode = type_mode | LOCK_REC;
- page = buf_frame_align(rec);
-
/* If rec is the supremum record, then we can reset the gap bit, as
all locks on the supremum are automatically of the gap type, and we
try to avoid unnecessary memory consumption of a new record lock
@@ -1771,7 +1909,7 @@ lock_rec_add_to_queue(
/* Look for a waiting lock request on the same record or on a gap */
- heap_no = rec_get_heap_no(rec);
+ heap_no = rec_get_heap_no(rec, page_is_comp(page));
lock = lock_rec_get_first_on_page(rec);
while (lock != NULL) {
@@ -1791,6 +1929,15 @@ lock_rec_add_to_queue(
if (similar_lock && !somebody_waits && !(type_mode & LOCK_WAIT)) {
+ /* If the nth bit of a record lock is already set then we
+ do not set a new lock bit, otherwice we set */
+
+ if (lock_rec_get_nth_bit(similar_lock, heap_no)) {
+ trx->trx_create_lock = FALSE;
+ } else {
+ trx->trx_create_lock = TRUE;
+ }
+
lock_rec_set_nth_bit(similar_lock, heap_no);
return(similar_lock);
@@ -1822,6 +1969,7 @@ lock_rec_lock_fast(
{
lock_t* lock;
ulint heap_no;
+ trx_t* trx;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -1836,13 +1984,16 @@ lock_rec_lock_fast(
|| mode - (LOCK_MODE_MASK & mode) == 0
|| mode - (LOCK_MODE_MASK & mode) == LOCK_REC_NOT_GAP);
- heap_no = rec_get_heap_no(rec);
+ heap_no = rec_get_heap_no(rec, page_is_comp(buf_frame_align(rec)));
lock = lock_rec_get_first_on_page(rec);
+ trx = thr_get_trx(thr);
+ trx->trx_create_lock = FALSE;
+
if (lock == NULL) {
if (!impl) {
- lock_rec_create(mode, rec, index, thr_get_trx(thr));
+ lock_rec_create(mode, rec, index, trx);
}
return(TRUE);
@@ -1853,13 +2004,23 @@ lock_rec_lock_fast(
return(FALSE);
}
- if (lock->trx != thr_get_trx(thr)
+ if (lock->trx != trx
|| lock->type_mode != (mode | LOCK_REC)
|| lock_rec_get_n_bits(lock) <= heap_no) {
return(FALSE);
}
if (!impl) {
+
+ /* If the nth bit of a record lock is already set then we
+ do not set a new lock bit, otherwice we set */
+
+ if (lock_rec_get_nth_bit(lock, heap_no)) {
+ trx->trx_create_lock = FALSE;
+ } else {
+ trx->trx_create_lock = TRUE;
+ }
+
lock_rec_set_nth_bit(lock, heap_no);
}
@@ -1904,7 +2065,8 @@ lock_rec_lock_slow(
trx = thr_get_trx(thr);
- if (lock_rec_has_expl(mode, rec, trx)) {
+ if (lock_rec_has_expl(mode, rec,
+ page_is_comp(buf_frame_align(rec)), trx)) {
/* The trx already has a strong enough lock on rec: do
nothing */
@@ -2220,12 +2382,14 @@ lock_rec_reset_and_release_wait(
{
lock_t* lock;
ulint heap_no;
-
+ ibool comp;
+
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- heap_no = rec_get_heap_no(rec);
+ comp = page_is_comp(buf_frame_align(rec));
+ heap_no = rec_get_heap_no(rec, comp);
lock = lock_rec_get_first(rec);
@@ -2236,7 +2400,7 @@ lock_rec_reset_and_release_wait(
lock_rec_reset_nth_bit(lock, heap_no);
}
- lock = lock_rec_get_next(rec, lock);
+ lock = lock_rec_get_next(rec, comp, lock);
}
}
@@ -2254,12 +2418,13 @@ lock_rec_inherit_to_gap(
the locks on this record */
{
lock_t* lock;
-
+ ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
+ comp = page_is_comp(buf_frame_align(rec));
while (lock != NULL) {
if (!lock_rec_get_insert_intention(lock)) {
@@ -2269,7 +2434,7 @@ lock_rec_inherit_to_gap(
heir, lock->index, lock->trx);
}
- lock = lock_rec_get_next(rec, lock);
+ lock = lock_rec_get_next(rec, comp, lock);
}
}
@@ -2286,12 +2451,13 @@ lock_rec_inherit_to_gap_if_gap_lock(
the locks on this record */
{
lock_t* lock;
-
+ ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
lock = lock_rec_get_first(rec);
+ comp = page_is_comp(buf_frame_align(rec));
while (lock != NULL) {
if (!lock_rec_get_insert_intention(lock)
@@ -2303,7 +2469,7 @@ lock_rec_inherit_to_gap_if_gap_lock(
heir, lock->index, lock->trx);
}
- lock = lock_rec_get_next(rec, lock);
+ lock = lock_rec_get_next(rec, comp, lock);
}
}
@@ -2316,7 +2482,8 @@ lock_rec_move(
/*==========*/
rec_t* receiver, /* in: record which gets locks; this record
must have no lock requests on it! */
- rec_t* donator) /* in: record which gives locks */
+ rec_t* donator, /* in: record which gives locks */
+ ibool comp) /* in: TRUE=compact page format */
{
lock_t* lock;
ulint heap_no;
@@ -2326,7 +2493,7 @@ lock_rec_move(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
- heap_no = rec_get_heap_no(donator);
+ heap_no = rec_get_heap_no(donator, comp);
lock = lock_rec_get_first(donator);
@@ -2346,7 +2513,7 @@ lock_rec_move(
lock_rec_add_to_queue(type_mode, receiver, lock->index,
lock->trx);
- lock = lock_rec_get_next(donator, lock);
+ lock = lock_rec_get_next(donator, comp, lock);
}
ut_ad(lock_rec_get_first(donator) == NULL);
@@ -2372,6 +2539,7 @@ lock_move_reorganize_page(
UT_LIST_BASE_NODE_T(lock_t) old_locks;
mem_heap_t* heap = NULL;
rec_t* sup;
+ ibool comp;
lock_mutex_enter_kernel();
@@ -2412,6 +2580,9 @@ lock_move_reorganize_page(
lock = UT_LIST_GET_FIRST(old_locks);
+ comp = page_is_comp(page);
+ ut_ad(comp == page_is_comp(old_page));
+
while (lock) {
/* NOTE: we copy also the locks set on the infimum and
supremum of the page; the infimum may carry locks if an
@@ -2423,12 +2594,12 @@ lock_move_reorganize_page(
/* Set locks according to old locks */
for (;;) {
- ut_ad(0 == ut_memcmp(page_cur_get_rec(&cur1),
+ ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1),
page_cur_get_rec(&cur2),
- rec_get_data_size(
+ rec_get_data_size_old(
page_cur_get_rec(&cur2))));
-
- old_heap_no = rec_get_heap_no(page_cur_get_rec(&cur2));
+ old_heap_no = rec_get_heap_no(page_cur_get_rec(&cur2),
+ comp);
if (lock_rec_get_nth_bit(lock, old_heap_no)) {
@@ -2487,6 +2658,7 @@ lock_move_rec_list_end(
ulint heap_no;
rec_t* sup;
ulint type_mode;
+ ibool comp;
lock_mutex_enter_kernel();
@@ -2500,6 +2672,8 @@ lock_move_rec_list_end(
lock = lock_rec_get_first_on_page(page);
+ comp = page_is_comp(page);
+
while (lock != NULL) {
page_cur_position(rec, &cur1);
@@ -2515,13 +2689,12 @@ lock_move_rec_list_end(
reset the lock bits on the old */
while (page_cur_get_rec(&cur1) != sup) {
-
- ut_ad(0 == ut_memcmp(page_cur_get_rec(&cur1),
+ ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1),
page_cur_get_rec(&cur2),
- rec_get_data_size(
+ rec_get_data_size_old(
page_cur_get_rec(&cur2))));
-
- heap_no = rec_get_heap_no(page_cur_get_rec(&cur1));
+ heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
+ comp);
if (lock_rec_get_nth_bit(lock, heap_no)) {
type_mode = lock->type_mode;
@@ -2571,12 +2744,15 @@ lock_move_rec_list_start(
page_cur_t cur2;
ulint heap_no;
ulint type_mode;
+ ibool comp;
ut_a(new_page);
lock_mutex_enter_kernel();
lock = lock_rec_get_first_on_page(page);
+ comp = page_is_comp(page);
+ ut_ad(comp == page_is_comp(new_page));
while (lock != NULL) {
@@ -2590,13 +2766,12 @@ lock_move_rec_list_start(
reset the lock bits on the old */
while (page_cur_get_rec(&cur1) != rec) {
-
- ut_ad(0 == ut_memcmp(page_cur_get_rec(&cur1),
+ ut_ad(comp || 0 == ut_memcmp(page_cur_get_rec(&cur1),
page_cur_get_rec(&cur2),
- rec_get_data_size(
+ rec_get_data_size_old(
page_cur_get_rec(&cur2))));
-
- heap_no = rec_get_heap_no(page_cur_get_rec(&cur1));
+ heap_no = rec_get_heap_no(page_cur_get_rec(&cur1),
+ comp);
if (lock_rec_get_nth_bit(lock, heap_no)) {
type_mode = lock->type_mode;
@@ -2636,13 +2811,16 @@ lock_update_split_right(
page_t* right_page, /* in: right page */
page_t* left_page) /* in: left page */
{
+ ibool comp;
lock_mutex_enter_kernel();
-
+ comp = page_is_comp(left_page);
+ ut_ad(comp == page_is_comp(right_page));
+
/* Move the locks on the supremum of the left page to the supremum
of the right page */
lock_rec_move(page_get_supremum_rec(right_page),
- page_get_supremum_rec(left_page));
+ page_get_supremum_rec(left_page), comp);
/* Inherit the locks to the supremum of left page from the successor
of the infimum on right page */
@@ -2696,13 +2874,16 @@ lock_update_root_raise(
page_t* new_page, /* in: index page to which copied */
page_t* root) /* in: root page */
{
+ ibool comp;
lock_mutex_enter_kernel();
-
+ comp = page_is_comp(root);
+ ut_ad(comp == page_is_comp(new_page));
+
/* Move the locks on the supremum of the root to the supremum
of new_page */
lock_rec_move(page_get_supremum_rec(new_page),
- page_get_supremum_rec(root));
+ page_get_supremum_rec(root), comp);
lock_mutex_exit_kernel();
}
@@ -2716,13 +2897,16 @@ lock_update_copy_and_discard(
page_t* new_page, /* in: index page to which copied */
page_t* page) /* in: index page; NOT the root! */
{
+ ibool comp;
lock_mutex_enter_kernel();
-
+ comp = page_is_comp(page);
+ ut_ad(comp == page_is_comp(new_page));
+
/* Move the locks on the supremum of the old page to the supremum
of new_page */
lock_rec_move(page_get_supremum_rec(new_page),
- page_get_supremum_rec(page));
+ page_get_supremum_rec(page), comp);
lock_rec_free_all_from_discard_page(page);
lock_mutex_exit_kernel();
@@ -2760,8 +2944,11 @@ lock_update_merge_left(
page_t* right_page) /* in: merged index page which will be
discarded */
{
+ ibool comp;
lock_mutex_enter_kernel();
-
+ comp = page_is_comp(left_page);
+ ut_ad(comp == page_is_comp(right_page));
+
if (page_rec_get_next(orig_pred) != page_get_supremum_rec(left_page)) {
/* Inherit the locks on the supremum of the left page to the
@@ -2781,7 +2968,7 @@ lock_update_merge_left(
of the left page */
lock_rec_move(page_get_supremum_rec(left_page),
- page_get_supremum_rec(right_page));
+ page_get_supremum_rec(right_page), comp);
lock_rec_free_all_from_discard_page(right_page);
@@ -2908,12 +3095,14 @@ lock_rec_store_on_page_infimum(
bits are reset on the record */
{
page_t* page;
+ ibool comp;
page = buf_frame_align(rec);
+ comp = page_is_comp(page);
lock_mutex_enter_kernel();
- lock_rec_move(page_get_infimum_rec(page), rec);
+ lock_rec_move(page_get_infimum_rec(page), rec, comp);
lock_mutex_exit_kernel();
}
@@ -2930,9 +3119,12 @@ lock_rec_restore_from_page_infimum(
whose infimum stored the lock state; lock bits are
reset on the infimum */
{
+ ibool comp;
lock_mutex_enter_kernel();
-
- lock_rec_move(rec, page_get_infimum_rec(page));
+ comp = page_is_comp(page);
+ ut_ad(comp == page_is_comp(buf_frame_align(rec)));
+
+ lock_rec_move(rec, page_get_infimum_rec(page), comp);
lock_mutex_exit_kernel();
}
@@ -3876,11 +4068,15 @@ lock_rec_print(
FILE* file, /* in: file where to print */
lock_t* lock) /* in: record type lock */
{
- page_t* page;
- ulint space;
- ulint page_no;
- ulint i;
- mtr_t mtr;
+ page_t* page;
+ ulint space;
+ ulint page_no;
+ ulint i;
+ mtr_t mtr;
+ mem_heap_t* heap;
+ ulint* offsets = NULL;
+
+ heap = mem_heap_create(100);
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -3959,8 +4155,11 @@ lock_rec_print(
fprintf(file, "Record lock, heap no %lu ", (ulong) i);
if (page) {
- rec_print(file,
- page_find_rec_with_heap_no(page, i));
+ rec_t* rec
+ = page_find_rec_with_heap_no(page, i);
+ offsets = rec_reget_offsets(rec, lock->index,
+ offsets, ULINT_UNDEFINED, heap);
+ rec_print(file, rec, offsets);
}
putc('\n', file);
@@ -3968,6 +4167,7 @@ lock_rec_print(
}
mtr_commit(&mtr);
+ mem_heap_free(heap);
}
/*************************************************************************
@@ -4051,6 +4251,9 @@ lock_print_info(
(ulong) ut_dulint_get_low(purge_sys->purge_undo_no));
fprintf(file,
+ "History list length %lu\n", (ulong) trx_sys->rseg_history_len);
+
+ fprintf(file,
"Total number of lock structs in row lock hash table %lu\n",
(ulong) lock_get_n_rec_locks());
@@ -4242,12 +4445,16 @@ lock_rec_queue_validate(
/*====================*/
/* out: TRUE if ok */
rec_t* rec, /* in: record to look at */
- dict_index_t* index) /* in: index, or NULL if not known */
+ dict_index_t* index, /* in: index, or NULL if not known */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
trx_t* impl_trx;
lock_t* lock;
-
+ ibool comp;
+
ut_a(rec);
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ comp = page_is_comp(buf_frame_align(rec));
lock_mutex_enter_kernel();
@@ -4270,7 +4477,7 @@ lock_rec_queue_validate(
ut_a(lock->index == index);
}
- lock = lock_rec_get_next(rec, lock);
+ lock = lock_rec_get_next(rec, comp, lock);
}
lock_mutex_exit_kernel();
@@ -4280,13 +4487,13 @@ lock_rec_queue_validate(
if (index && (index->type & DICT_CLUSTERED)) {
- impl_trx = lock_clust_rec_some_has_impl(rec, index);
+ impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
- LOCK_WAIT, rec, impl_trx)) {
+ LOCK_WAIT, rec, comp, impl_trx)) {
ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
- impl_trx));
+ comp, impl_trx));
}
}
@@ -4296,13 +4503,14 @@ lock_rec_queue_validate(
next function call: we have to release lock table mutex
to obey the latching order */
- impl_trx = lock_sec_rec_some_has_impl_off_kernel(rec, index);
+ impl_trx = lock_sec_rec_some_has_impl_off_kernel(
+ rec, index, offsets);
if (impl_trx && lock_rec_other_has_expl_req(LOCK_S, 0,
- LOCK_WAIT, rec, impl_trx)) {
+ LOCK_WAIT, rec, comp, impl_trx)) {
- ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
- impl_trx));
+ ut_a(lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP,
+ rec, comp, impl_trx));
}
}
@@ -4321,10 +4529,10 @@ lock_rec_queue_validate(
if (lock_get_mode(lock) == LOCK_S) {
ut_a(!lock_rec_other_has_expl_req(LOCK_X,
- 0, 0, rec, lock->trx));
+ 0, 0, rec, comp, lock->trx));
} else {
ut_a(!lock_rec_other_has_expl_req(LOCK_S,
- 0, 0, rec, lock->trx));
+ 0, 0, rec, comp, lock->trx));
}
} else if (lock_get_wait(lock) && !lock_rec_get_gap(lock)) {
@@ -4332,7 +4540,7 @@ lock_rec_queue_validate(
ut_a(lock_rec_has_to_wait_in_queue(lock));
}
- lock = lock_rec_get_next(rec, lock);
+ lock = lock_rec_get_next(rec, comp, lock);
}
lock_mutex_exit_kernel();
@@ -4358,6 +4566,8 @@ lock_rec_validate_page(
ulint nth_bit = 0;
ulint i;
mtr_t mtr;
+ mem_heap_t* heap = mem_heap_create(100);
+ ulint* offsets = NULL;
#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
@@ -4397,13 +4607,15 @@ loop:
index = lock->index;
rec = page_find_rec_with_heap_no(page, i);
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
fprintf(stderr,
"Validating %lu %lu\n", (ulong) space, (ulong) page_no);
lock_mutex_exit_kernel();
- lock_rec_queue_validate(rec, index);
+ lock_rec_queue_validate(rec, index, offsets);
lock_mutex_enter_kernel();
@@ -4423,6 +4635,7 @@ function_exit:
mtr_commit(&mtr);
+ mem_heap_free(heap);
return(TRUE);
}
@@ -4595,8 +4808,16 @@ lock_rec_insert_check_and_lock(
page_update_max_trx_id(buf_frame_align(rec),
thr_get_trx(thr)->id);
}
-
- ut_ad(lock_rec_queue_validate(next_rec, index));
+
+#ifdef UNIV_DEBUG
+ {
+ mem_heap_t* heap = mem_heap_create(100);
+ const ulint* offsets = rec_get_offsets(next_rec, index,
+ ULINT_UNDEFINED, heap);
+ ut_ad(lock_rec_queue_validate(next_rec, index, offsets));
+ mem_heap_free(heap);
+ }
+#endif /* UNIV_DEBUG */
return(err);
}
@@ -4610,7 +4831,8 @@ void
lock_rec_convert_impl_to_expl(
/*==========================*/
rec_t* rec, /* in: user record on page */
- dict_index_t* index) /* in: index of record */
+ dict_index_t* index, /* in: index of record */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
trx_t* impl_trx;
@@ -4618,11 +4840,14 @@ lock_rec_convert_impl_to_expl(
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
ut_ad(page_rec_is_user_rec(rec));
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_ad(page_is_comp(buf_frame_align(rec)) == index->table->comp);
if (index->type & DICT_CLUSTERED) {
- impl_trx = lock_clust_rec_some_has_impl(rec, index);
+ impl_trx = lock_clust_rec_some_has_impl(rec, index, offsets);
} else {
- impl_trx = lock_sec_rec_some_has_impl_off_kernel(rec, index);
+ impl_trx = lock_sec_rec_some_has_impl_off_kernel(
+ rec, index, offsets);
}
if (impl_trx) {
@@ -4630,7 +4855,7 @@ lock_rec_convert_impl_to_expl(
record, set one for it */
if (!lock_rec_has_expl(LOCK_X | LOCK_REC_NOT_GAP, rec,
- impl_trx)) {
+ index->table->comp, impl_trx)) {
lock_rec_add_to_queue(LOCK_REC | LOCK_X
| LOCK_REC_NOT_GAP, rec, index,
@@ -4656,17 +4881,19 @@ lock_clust_rec_modify_check_and_lock(
does nothing */
rec_t* rec, /* in: record which should be modified */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr) /* in: query thread */
{
ulint err;
-
+
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ ut_ad(index->type & DICT_CLUSTERED);
+
if (flags & BTR_NO_LOCKING_FLAG) {
return(DB_SUCCESS);
}
- ut_ad(index->type & DICT_CLUSTERED);
-
lock_mutex_enter_kernel();
ut_ad(lock_table_has(thr_get_trx(thr), index->table, LOCK_IX));
@@ -4674,13 +4901,13 @@ lock_clust_rec_modify_check_and_lock(
/* If a transaction has no explicit x-lock set on the record, set one
for it */
- lock_rec_convert_impl_to_expl(rec, index);
+ lock_rec_convert_impl_to_expl(rec, index, offsets);
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
lock_mutex_exit_kernel();
- ut_ad(lock_rec_queue_validate(rec, index));
+ ut_ad(lock_rec_queue_validate(rec, index, offsets));
return(err);
}
@@ -4724,8 +4951,16 @@ lock_sec_rec_modify_check_and_lock(
err = lock_rec_lock(TRUE, LOCK_X | LOCK_REC_NOT_GAP, rec, index, thr);
lock_mutex_exit_kernel();
-
- ut_ad(lock_rec_queue_validate(rec, index));
+
+#ifdef UNIV_DEBUG
+ {
+ mem_heap_t* heap = mem_heap_create(100);
+ const ulint* offsets = rec_get_offsets(rec, index,
+ ULINT_UNDEFINED, heap);
+ ut_ad(lock_rec_queue_validate(rec, index, offsets));
+ mem_heap_free(heap);
+ }
+#endif /* UNIV_DEBUG */
if (err == DB_SUCCESS) {
/* Update the page max trx id field */
@@ -4752,6 +4987,7 @@ lock_sec_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: secondary index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -4763,6 +4999,7 @@ lock_sec_rec_read_check_and_lock(
ut_ad(!(index->type & DICT_CLUSTERED));
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
+ ut_ad(rec_offs_validate(rec, index, offsets));
if (flags & BTR_NO_LOCKING_FLAG) {
@@ -4785,14 +5022,14 @@ lock_sec_rec_read_check_and_lock(
|| recv_recovery_is_on())
&& !page_rec_is_supremum(rec)) {
- lock_rec_convert_impl_to_expl(rec, index);
+ lock_rec_convert_impl_to_expl(rec, index, offsets);
}
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
lock_mutex_exit_kernel();
- ut_ad(lock_rec_queue_validate(rec, index));
+ ut_ad(lock_rec_queue_validate(rec, index, offsets));
return(err);
}
@@ -4816,6 +5053,7 @@ lock_clust_rec_read_check_and_lock(
which should be read or passed over by a read
cursor */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: mode of the lock which the read cursor
should set on records: LOCK_S or LOCK_X; the
latter is possible in SELECT FOR UPDATE */
@@ -4829,6 +5067,9 @@ lock_clust_rec_read_check_and_lock(
ut_ad(page_rec_is_user_rec(rec) || page_rec_is_supremum(rec));
ut_ad(gap_mode == LOCK_ORDINARY || gap_mode == LOCK_GAP
|| gap_mode == LOCK_REC_NOT_GAP);
+ ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (flags & BTR_NO_LOCKING_FLAG) {
return(DB_SUCCESS);
@@ -4843,14 +5084,14 @@ lock_clust_rec_read_check_and_lock(
if (!page_rec_is_supremum(rec)) {
- lock_rec_convert_impl_to_expl(rec, index);
+ lock_rec_convert_impl_to_expl(rec, index, offsets);
}
err = lock_rec_lock(FALSE, mode | gap_mode, rec, index, thr);
lock_mutex_exit_kernel();
- ut_ad(lock_rec_queue_validate(rec, index));
-
+ ut_ad(lock_rec_queue_validate(rec, index, offsets));
+
return(err);
}
diff --git a/innobase/log/log0log.c b/innobase/log/log0log.c
index e08adb013b5..1ab91b71e8f 100644
--- a/innobase/log/log0log.c
+++ b/innobase/log/log0log.c
@@ -190,6 +190,8 @@ loop:
log_buffer_flush_to_disk();
+ srv_log_waits++;
+
ut_ad(++count < 50);
goto loop;
@@ -292,6 +294,8 @@ part_loop:
if (str_len > 0) {
goto part_loop;
}
+
+ srv_log_write_requests++;
}
/****************************************************************
@@ -1112,11 +1116,15 @@ log_group_file_header_flush(
if (log_do_write) {
log_sys->n_log_ios++;
+ srv_os_log_pending_writes++;
+
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id,
dest_offset / UNIV_PAGE_SIZE,
dest_offset % UNIV_PAGE_SIZE,
OS_FILE_LOG_BLOCK_SIZE,
buf, group);
+
+ srv_os_log_pending_writes--;
}
}
@@ -1181,6 +1189,8 @@ loop:
log_group_file_header_flush(group,
next_offset / group->file_size, start_lsn);
+ srv_os_log_written+= OS_FILE_LOG_BLOCK_SIZE;
+ srv_log_writes++;
}
if ((next_offset % group->file_size) + len > group->file_size) {
@@ -1225,9 +1235,16 @@ loop:
if (log_do_write) {
log_sys->n_log_ios++;
+ srv_os_log_pending_writes++;
+
fil_io(OS_FILE_WRITE | OS_FILE_LOG, TRUE, group->space_id,
next_offset / UNIV_PAGE_SIZE,
next_offset % UNIV_PAGE_SIZE, write_len, buf, group);
+
+ srv_os_log_pending_writes--;
+
+ srv_os_log_written+= write_len;
+ srv_log_writes++;
}
if (write_len < len) {
diff --git a/innobase/log/log0recv.c b/innobase/log/log0recv.c
index 10f921bb1f0..f42f0eb8c72 100644
--- a/innobase/log/log0recv.c
+++ b/innobase/log/log0recv.c
@@ -756,81 +756,124 @@ recv_parse_or_apply_log_rec_body(
mtr_t* mtr) /* in: mtr or NULL; should be non-NULL if and only if
page is non-NULL */
{
- byte* new_ptr;
-
- if (type <= MLOG_8BYTES) {
- new_ptr = mlog_parse_nbytes(type, ptr, end_ptr, page);
-
- } else if (type == MLOG_REC_INSERT) {
- new_ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr, page,
- mtr);
- } else if (type == MLOG_REC_CLUST_DELETE_MARK) {
- new_ptr = btr_cur_parse_del_mark_set_clust_rec(ptr, end_ptr,
- page);
- } else if (type == MLOG_REC_SEC_DELETE_MARK) {
- new_ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr,
- page);
- } else if (type == MLOG_REC_UPDATE_IN_PLACE) {
- new_ptr = btr_cur_parse_update_in_place(ptr, end_ptr, page);
-
- } else if ((type == MLOG_LIST_END_DELETE)
- || (type == MLOG_LIST_START_DELETE)) {
- new_ptr = page_parse_delete_rec_list(type, ptr, end_ptr, page,
- mtr);
- } else if (type == MLOG_LIST_END_COPY_CREATED) {
- new_ptr = page_parse_copy_rec_list_to_created_page(ptr,
- end_ptr, page, mtr);
- } else if (type == MLOG_PAGE_REORGANIZE) {
- new_ptr = btr_parse_page_reorganize(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_PAGE_CREATE) {
- new_ptr = page_parse_create(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_UNDO_INSERT) {
- new_ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page);
-
- } else if (type == MLOG_UNDO_ERASE_END) {
- new_ptr = trx_undo_parse_erase_page_end(ptr, end_ptr, page,
- mtr);
- } else if (type == MLOG_UNDO_INIT) {
- new_ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_UNDO_HDR_DISCARD) {
- new_ptr = trx_undo_parse_discard_latest(ptr, end_ptr, page,
- mtr);
- } else if ((type == MLOG_UNDO_HDR_CREATE)
- || (type == MLOG_UNDO_HDR_REUSE)) {
- new_ptr = trx_undo_parse_page_header(type, ptr, end_ptr, page,
- mtr);
- } else if (type == MLOG_REC_MIN_MARK) {
- new_ptr = btr_parse_set_min_rec_mark(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_REC_DELETE) {
- new_ptr = page_cur_parse_delete_rec(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_IBUF_BITMAP_INIT) {
- new_ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr);
-
- } else if (type == MLOG_INIT_FILE_PAGE) {
- new_ptr = fsp_parse_init_file_page(ptr, end_ptr, page);
-
- } else if (type == MLOG_WRITE_STRING) {
- new_ptr = mlog_parse_string(ptr, end_ptr, page);
-
- } else if (type == MLOG_FILE_CREATE
- || type == MLOG_FILE_RENAME
- || type == MLOG_FILE_DELETE) {
- new_ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE,
+ dict_index_t* index = NULL;
+
+ switch (type) {
+ case MLOG_1BYTE: case MLOG_2BYTES: case MLOG_4BYTES: case MLOG_8BYTES:
+ ptr = mlog_parse_nbytes(type, ptr, end_ptr, page);
+ break;
+ case MLOG_REC_INSERT: case MLOG_COMP_REC_INSERT:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_REC_INSERT, &index))) {
+ ptr = page_cur_parse_insert_rec(FALSE, ptr, end_ptr,
+ index, page, mtr);
+ }
+ break;
+ case MLOG_REC_CLUST_DELETE_MARK: case MLOG_COMP_REC_CLUST_DELETE_MARK:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_REC_CLUST_DELETE_MARK, &index))) {
+ ptr = btr_cur_parse_del_mark_set_clust_rec(ptr,
+ end_ptr, index, page);
+ }
+ break;
+ case MLOG_REC_SEC_DELETE_MARK: case MLOG_COMP_REC_SEC_DELETE_MARK:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_REC_SEC_DELETE_MARK, &index))) {
+ ptr = btr_cur_parse_del_mark_set_sec_rec(ptr, end_ptr,
+ index, page);
+ }
+ break;
+ case MLOG_REC_UPDATE_IN_PLACE: case MLOG_COMP_REC_UPDATE_IN_PLACE:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_REC_UPDATE_IN_PLACE, &index))) {
+ ptr = btr_cur_parse_update_in_place(ptr, end_ptr,
+ page, index);
+ }
+ break;
+ case MLOG_LIST_END_DELETE: case MLOG_COMP_LIST_END_DELETE:
+ case MLOG_LIST_START_DELETE: case MLOG_COMP_LIST_START_DELETE:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_LIST_END_DELETE
+ || type == MLOG_COMP_LIST_START_DELETE, &index))) {
+ ptr = page_parse_delete_rec_list(type, ptr, end_ptr,
+ index, page, mtr);
+ }
+ break;
+ case MLOG_LIST_END_COPY_CREATED: case MLOG_COMP_LIST_END_COPY_CREATED:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_LIST_END_COPY_CREATED, &index))) {
+ ptr = page_parse_copy_rec_list_to_created_page(ptr,
+ end_ptr, index, page, mtr);
+ }
+ break;
+ case MLOG_PAGE_REORGANIZE: case MLOG_COMP_PAGE_REORGANIZE:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_PAGE_REORGANIZE, &index))) {
+ ptr = btr_parse_page_reorganize(ptr, end_ptr, index,
+ page, mtr);
+ }
+ break;
+ case MLOG_PAGE_CREATE: case MLOG_COMP_PAGE_CREATE:
+ ptr = page_parse_create(ptr, end_ptr,
+ type == MLOG_COMP_PAGE_CREATE, page, mtr);
+ break;
+ case MLOG_UNDO_INSERT:
+ ptr = trx_undo_parse_add_undo_rec(ptr, end_ptr, page);
+ break;
+ case MLOG_UNDO_ERASE_END:
+ ptr = trx_undo_parse_erase_page_end(ptr, end_ptr, page, mtr);
+ break;
+ case MLOG_UNDO_INIT:
+ ptr = trx_undo_parse_page_init(ptr, end_ptr, page, mtr);
+ break;
+ case MLOG_UNDO_HDR_DISCARD:
+ ptr = trx_undo_parse_discard_latest(ptr, end_ptr, page, mtr);
+ break;
+ case MLOG_UNDO_HDR_CREATE:
+ case MLOG_UNDO_HDR_REUSE:
+ ptr = trx_undo_parse_page_header(type, ptr, end_ptr,
+ page, mtr);
+ break;
+ case MLOG_REC_MIN_MARK: case MLOG_COMP_REC_MIN_MARK:
+ ptr = btr_parse_set_min_rec_mark(ptr, end_ptr,
+ type == MLOG_COMP_REC_MIN_MARK, page, mtr);
+ break;
+ case MLOG_REC_DELETE: case MLOG_COMP_REC_DELETE:
+ if (NULL != (ptr = mlog_parse_index(ptr, end_ptr,
+ type == MLOG_COMP_REC_DELETE, &index))) {
+ ptr = page_cur_parse_delete_rec(ptr, end_ptr,
+ index, page, mtr);
+ }
+ break;
+ case MLOG_IBUF_BITMAP_INIT:
+ ptr = ibuf_parse_bitmap_init(ptr, end_ptr, page, mtr);
+ break;
+ case MLOG_INIT_FILE_PAGE:
+ ptr = fsp_parse_init_file_page(ptr, end_ptr, page);
+ break;
+ case MLOG_WRITE_STRING:
+ ptr = mlog_parse_string(ptr, end_ptr, page);
+ break;
+ case MLOG_FILE_CREATE:
+ case MLOG_FILE_RENAME:
+ case MLOG_FILE_DELETE:
+ ptr = fil_op_log_parse_or_replay(ptr, end_ptr, type, FALSE,
ULINT_UNDEFINED);
- } else {
- new_ptr = NULL;
-
+ break;
+ default:
+ ptr = NULL;
recv_sys->found_corrupt_log = TRUE;
}
- ut_ad(!page || new_ptr);
+ ut_ad(!page || ptr);
+ if (index) {
+ dict_table_t* table = index->table;
+ mem_heap_free(index->heap);
+ mutex_free(&(table->autoinc_mutex));
+ mem_heap_free(table->heap);
+ }
- return(new_ptr);
+ return(ptr);
}
/*************************************************************************
@@ -2851,11 +2894,13 @@ void
recv_recovery_from_checkpoint_finish(void)
/*======================================*/
{
+ int i;
+ os_thread_id_t recovery_thread_id;
+
/* Rollback the uncommitted transactions which have no user session */
- if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
- trx_rollback_or_clean_all_without_sess();
- }
+ fprintf(stderr,
+ "InnoDB: Starting to apply log records to the database...\n");
/* Apply the hashed log records to the respective file pages */
@@ -2888,9 +2933,15 @@ recv_recovery_from_checkpoint_finish(void)
/* Free the resources of the recovery system */
recv_recovery_on = FALSE;
+
#ifndef UNIV_LOG_DEBUG
recv_sys_free();
#endif
+
+ if (srv_force_recovery < SRV_FORCE_NO_TRX_UNDO) {
+ os_thread_create(trx_rollback_or_clean_all_without_sess,
+ (void *)&i, &recovery_thread_id);
+ }
}
/**********************************************************
diff --git a/innobase/mem/mem0pool.c b/innobase/mem/mem0pool.c
index 023369e8ec5..cb891a03092 100644
--- a/innobase/mem/mem0pool.c
+++ b/innobase/mem/mem0pool.c
@@ -199,7 +199,7 @@ mem_pool_create(
but only when allocated at a higher level in mem0mem.c.
This is to avoid masking useful Purify warnings. */
- pool->buf = ut_malloc_low(size, FALSE);
+ pool->buf = ut_malloc_low(size, FALSE, TRUE);
pool->size = size;
mutex_create(&(pool->mutex));
diff --git a/innobase/mtr/mtr0log.c b/innobase/mtr/mtr0log.c
index 82baa8905ba..417093134c3 100644
--- a/innobase/mtr/mtr0log.c
+++ b/innobase/mtr/mtr0log.c
@@ -384,3 +384,160 @@ mlog_parse_string(
return(ptr + len);
}
+
+/************************************************************
+Opens a buffer for mlog, writes the initial log record and,
+if needed, the field lengths of an index. */
+
+byte*
+mlog_open_and_write_index(
+/*======================*/
+ /* out: buffer, NULL if log mode
+ MTR_LOG_NONE */
+ mtr_t* mtr, /* in: mtr */
+ byte* rec, /* in: index record or page */
+ dict_index_t* index, /* in: record descriptor */
+ byte type, /* in: log item type */
+ ulint size) /* in: requested buffer size in bytes
+ (if 0, calls mlog_close() and returns NULL) */
+{
+ byte* log_ptr;
+ const byte* log_start;
+ const byte* log_end;
+
+ if (!index->table->comp) {
+ log_start = log_ptr = mlog_open(mtr, 11 + size);
+ if (!log_ptr) {
+ return(NULL); /* logging is disabled */
+ }
+ log_ptr = mlog_write_initial_log_record_fast(rec, type,
+ log_ptr, mtr);
+ log_end = log_ptr + 11 + size;
+ } else {
+ ulint i;
+ ulint n = dict_index_get_n_fields(index);
+ /* total size needed */
+ ulint total = 11 + size + (n + 2) * 2;
+ ulint alloc = total;
+ /* allocate at most DYN_ARRAY_DATA_SIZE at a time */
+ if (alloc > DYN_ARRAY_DATA_SIZE) {
+ alloc = DYN_ARRAY_DATA_SIZE;
+ }
+ log_start = log_ptr = mlog_open(mtr, alloc);
+ if (!log_ptr) {
+ return(NULL); /* logging is disabled */
+ }
+ log_end = log_ptr + alloc;
+ log_ptr = mlog_write_initial_log_record_fast(rec, type,
+ log_ptr, mtr);
+ mach_write_to_2(log_ptr, n);
+ log_ptr += 2;
+ mach_write_to_2(log_ptr,
+ dict_index_get_n_unique_in_tree(index));
+ log_ptr += 2;
+ for (i = 0; i < n; i++) {
+ dict_field_t* field;
+ dtype_t* type;
+ ulint len;
+ field = dict_index_get_nth_field(index, i);
+ type = dict_col_get_type(dict_field_get_col(field));
+ len = field->fixed_len;
+ ut_ad(len < 0x7fff);
+ if (len == 0 && dtype_get_len(type) > 255) {
+ /* variable-length field
+ with maximum length > 255 */
+ len = 0x7fff;
+ }
+ if (dtype_get_prtype(type) & DATA_NOT_NULL) {
+ len |= 0x8000;
+ }
+ if (log_ptr + 2 > log_end) {
+ mlog_close(mtr, log_ptr);
+ ut_a(total > (ulint) (log_ptr - log_start));
+ total -= log_ptr - log_start;
+ alloc = total;
+ if (alloc > DYN_ARRAY_DATA_SIZE) {
+ alloc = DYN_ARRAY_DATA_SIZE;
+ }
+ log_start = log_ptr = mlog_open(mtr, alloc);
+ if (!log_ptr) {
+ return(NULL); /* logging is disabled */
+ }
+ log_end = log_ptr + alloc;
+ }
+ mach_write_to_2(log_ptr, len);
+ log_ptr += 2;
+ }
+ }
+ if (size == 0) {
+ mlog_close(mtr, log_ptr);
+ log_ptr = NULL;
+ } else if (log_ptr + size > log_end) {
+ mlog_close(mtr, log_ptr);
+ log_ptr = mlog_open(mtr, size);
+ }
+ return(log_ptr);
+}
+
+/************************************************************
+Parses a log record written by mlog_open_and_write_index. */
+
+byte*
+mlog_parse_index(
+/*=============*/
+ /* out: parsed record end,
+ NULL if not a complete record */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ /* out: new value of log_ptr */
+ ibool comp, /* in: TRUE=compact record format */
+ dict_index_t** index) /* out, own: dummy index */
+{
+ ulint i, n, n_uniq;
+ dict_table_t* table;
+ dict_index_t* ind;
+
+ if (comp) {
+ if (end_ptr < ptr + 4) {
+ return(NULL);
+ }
+ n = mach_read_from_2(ptr);
+ ptr += 2;
+ n_uniq = mach_read_from_2(ptr);
+ ut_ad(n_uniq <= n);
+ if (end_ptr < ptr + (n + 1) * 2) {
+ return(NULL);
+ }
+ } else {
+ n = n_uniq = 1;
+ }
+ table = dict_mem_table_create("LOG_DUMMY", DICT_HDR_SPACE, n, comp);
+ ind = dict_mem_index_create("LOG_DUMMY", "LOG_DUMMY",
+ DICT_HDR_SPACE, 0, n);
+ ind->table = table;
+ ind->n_uniq = n_uniq;
+ if (n_uniq != n) {
+ ind->type = DICT_CLUSTERED;
+ }
+ /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
+ ind->cached = TRUE;
+ if (comp) {
+ for (i = 0; i < n; i++) {
+ ulint len = mach_read_from_2(ptr += 2);
+ /* The high-order bit of len is the NOT NULL flag;
+ the rest is 0 or 0x7fff for variable-length fields,
+ and 1..0x7ffe for fixed-length fields. */
+ dict_mem_table_add_col(table, "DUMMY",
+ ((len + 1) & 0x7fff) <= 1
+ ? DATA_BINARY
+ : DATA_FIXBINARY,
+ len & 0x8000 ? DATA_NOT_NULL : 0,
+ len & 0x7fff, 0);
+ dict_index_add_col(ind,
+ dict_table_get_nth_col(table, i), 0, 0);
+ }
+ ptr += 2;
+ }
+ *index = ind;
+ return(ptr);
+}
diff --git a/innobase/os/os0file.c b/innobase/os/os0file.c
index 5c140e4b798..1e3eeb0de02 100644
--- a/innobase/os/os0file.c
+++ b/innobase/os/os0file.c
@@ -155,6 +155,10 @@ os_mutex_t os_file_count_mutex;
ulint os_file_n_pending_preads = 0;
ulint os_file_n_pending_pwrites = 0;
+/* These are not protected by any mutex */
+ulint os_n_pending_writes = 0;
+ulint os_n_pending_reads = 0;
+
/***************************************************************************
Gets the operating system version. Currently works only on Windows. */
@@ -711,13 +715,41 @@ http://www.mysql.com/doc/en/Windows_symbolic_links.html */
char* full_path;
int ret;
struct stat statinfo;
+#ifdef HAVE_READDIR_R
+ char dirent_buf[sizeof(struct dirent) + _POSIX_PATH_MAX +
+ 100];
+ /* In /mysys/my_lib.c, _POSIX_PATH_MAX + 1 is used as
+ the max file name len; but in most standards, the
+ length is NAME_MAX; we add 100 to be even safer */
+#endif
+
next_file:
- ent = readdir(dir);
+
+#ifdef HAVE_READDIR_R
+ ret = readdir_r(dir, (struct dirent*)dirent_buf, &ent);
+
+ if (ret != 0) {
+ fprintf(stderr,
+"InnoDB: cannot read directory %s, error %lu\n", dirname, (ulong)ret);
+
+ return(-1);
+ }
if (ent == NULL) {
+ /* End of directory */
+
return(1);
}
+ ut_a(strlen(ent->d_name) < _POSIX_PATH_MAX + 100 - 1);
+#else
+ ent = readdir(dir);
+
+ if (ent == NULL) {
+
+ return(1);
+ }
+#endif
ut_a(strlen(ent->d_name) < OS_FILE_MAX_PATH);
if (strcmp(ent->d_name, ".") == 0 || strcmp(ent->d_name, "..") == 0) {
@@ -1987,8 +2019,12 @@ try_again:
goto error_handling;
}
+ os_n_pending_reads++;
+
ret = ReadFile(file, buf, n, &len, NULL);
+ os_n_pending_reads--;
+
os_mutex_exit(os_file_seek_mutexes[i]);
if (ret && len == n) {
@@ -2001,8 +2037,12 @@ try_again:
os_bytes_read_since_printout += n;
try_again:
+ os_n_pending_reads++;
+
ret = os_file_pread(file, buf, n, offset, offset_high);
+ os_n_pending_reads--;
+
if ((ulint)ret == n) {
return(TRUE);
@@ -2090,8 +2130,12 @@ try_again:
goto error_handling;
}
+ os_n_pending_reads++;
+
ret = ReadFile(file, buf, n, &len, NULL);
+ os_n_pending_reads--;
+
os_mutex_exit(os_file_seek_mutexes[i]);
if (ret && len == n) {
@@ -2104,8 +2148,12 @@ try_again:
os_bytes_read_since_printout += n;
try_again:
+ os_n_pending_reads++;
+
ret = os_file_pread(file, buf, n, offset, offset_high);
+ os_n_pending_reads--;
+
if ((ulint)ret == n) {
return(TRUE);
@@ -2187,7 +2235,11 @@ retry:
return(FALSE);
}
+ os_n_pending_writes++;
+
ret = WriteFile(file, buf, n, &len, NULL);
+
+ os_n_pending_writes--;
/* Always do fsync to reduce the probability that when the OS crashes,
a database page is only partially physically written to disk. */
@@ -2248,8 +2300,12 @@ retry:
#else
ssize_t ret;
+ os_n_pending_writes++;
+
ret = os_file_pwrite(file, buf, n, offset, offset_high);
+ os_n_pending_writes--;
+
if ((ulint)ret == n) {
return(TRUE);
diff --git a/innobase/page/page0cur.c b/innobase/page/page0cur.c
index 459ab986610..8def8474d9a 100644
--- a/innobase/page/page0cur.c
+++ b/innobase/page/page0cur.c
@@ -30,6 +30,7 @@ ibool
page_cur_try_search_shortcut(
/*=========================*/
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint* iup_matched_fields,
/* in/out: already matched fields in upper
@@ -55,9 +56,14 @@ page_cur_try_search_shortcut(
#ifdef UNIV_SEARCH_DEBUG
page_cur_t cursor2;
#endif
+ mem_heap_t* heap;
+ ulint* offsets;
ut_ad(dtuple_check_typed(tuple));
rec = page_header_get_ptr(page, PAGE_LAST_INSERT);
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index,
+ dtuple_get_n_fields(tuple), heap);
ut_ad(rec);
ut_ad(page_rec_is_user_rec(rec));
@@ -69,26 +75,30 @@ page_cur_try_search_shortcut(
up_match = low_match;
up_bytes = low_bytes;
- cmp = page_cmp_dtuple_rec_with_match(tuple, rec, &low_match,
+ cmp = page_cmp_dtuple_rec_with_match(tuple, rec, offsets, &low_match,
&low_bytes);
if (cmp == -1) {
+ mem_heap_free(heap);
return(FALSE);
}
next_rec = page_rec_get_next(rec);
+ offsets = rec_reget_offsets(next_rec, index, offsets,
+ dtuple_get_n_fields(tuple), heap);
- cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, &up_match,
- &up_bytes);
+ cmp = page_cmp_dtuple_rec_with_match(tuple, next_rec, offsets,
+ &up_match, &up_bytes);
if (cmp != -1) {
+ mem_heap_free(heap);
return(FALSE);
}
cursor->rec = rec;
#ifdef UNIV_SEARCH_DEBUG
- page_cur_search_with_match(page, tuple, PAGE_CUR_DBG,
+ page_cur_search_with_match(page, index, tuple, PAGE_CUR_DBG,
iup_matched_fields,
iup_matched_bytes,
ilow_matched_fields,
@@ -117,6 +127,7 @@ page_cur_try_search_shortcut(
#ifdef UNIV_SEARCH_PERF_STAT
page_cur_short_succ++;
#endif
+ mem_heap_free(heap);
return(TRUE);
}
@@ -130,22 +141,24 @@ static
ibool
page_cur_rec_field_extends(
/*=======================*/
- /* out: TRUE if rec field extends tuple
- field */
- dtuple_t* tuple, /* in: data tuple */
- rec_t* rec, /* in: record */
- ulint n) /* in: compare nth field */
+ /* out: TRUE if rec field
+ extends tuple field */
+ dtuple_t* tuple, /* in: data tuple */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint n) /* in: compare nth field */
{
dtype_t* type;
dfield_t* dfield;
byte* rec_f;
ulint rec_f_len;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
dfield = dtuple_get_nth_field(tuple, n);
type = dfield_get_type(dfield);
- rec_f = rec_get_nth_field(rec, n, &rec_f_len);
+ rec_f = rec_get_nth_field(rec, offsets, n, &rec_f_len);
if (type->mtype == DATA_VARCHAR
|| type->mtype == DATA_CHAR
@@ -176,6 +189,7 @@ void
page_cur_search_with_match(
/*=======================*/
page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
dtuple_t* tuple, /* in: data tuple */
ulint mode, /* in: PAGE_CUR_L, PAGE_CUR_LE, PAGE_CUR_G,
or PAGE_CUR_GE */
@@ -212,6 +226,9 @@ page_cur_search_with_match(
ulint dbg_matched_fields;
ulint dbg_matched_bytes;
#endif
+ mem_heap_t* heap;
+ ulint* offsets = NULL;
+
ut_ad(page && tuple && iup_matched_fields && iup_matched_bytes
&& ilow_matched_fields && ilow_matched_bytes && cursor);
ut_ad(dtuple_validate(tuple));
@@ -229,7 +246,7 @@ page_cur_search_with_match(
&& (page_header_get_ptr(page, PAGE_LAST_INSERT))
&& (page_header_get_field(page, PAGE_DIRECTION) == PAGE_RIGHT)) {
- if (page_cur_try_search_shortcut(page, tuple,
+ if (page_cur_try_search_shortcut(page, index, tuple,
iup_matched_fields,
iup_matched_bytes,
ilow_matched_fields,
@@ -245,6 +262,8 @@ page_cur_search_with_match(
/*#endif */
#endif
+ heap = mem_heap_create(100);
+
/* The following flag does not work for non-latin1 char sets because
cmp_full_field does not tell how many bytes matched */
ut_a(mode != PAGE_CUR_LE_OR_EXTENDS);
@@ -279,7 +298,10 @@ page_cur_search_with_match(
low_matched_fields, low_matched_bytes,
up_matched_fields, up_matched_bytes);
- cmp = cmp_dtuple_rec_with_match(tuple, mid_rec,
+ offsets = rec_reget_offsets(mid_rec, index, offsets,
+ dtuple_get_n_fields_cmp(tuple), heap);
+
+ cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
&cur_matched_fields,
&cur_matched_bytes);
if (cmp == 1) {
@@ -288,10 +310,12 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
+ offsets = rec_reget_offsets(mid_rec, index,
+ offsets, dtuple_get_n_fields_cmp(tuple), heap);
if (mode == PAGE_CUR_LE_OR_EXTENDS
&& page_cur_rec_field_extends(tuple, mid_rec,
- cur_matched_fields)) {
+ offsets, cur_matched_fields)) {
low = mid;
low_matched_fields = cur_matched_fields;
low_matched_bytes = cur_matched_bytes;
@@ -329,7 +353,10 @@ page_cur_search_with_match(
low_matched_fields, low_matched_bytes,
up_matched_fields, up_matched_bytes);
- cmp = cmp_dtuple_rec_with_match(tuple, mid_rec,
+ offsets = rec_reget_offsets(mid_rec, index,
+ offsets, dtuple_get_n_fields_cmp(tuple), heap);
+
+ cmp = cmp_dtuple_rec_with_match(tuple, mid_rec, offsets,
&cur_matched_fields,
&cur_matched_bytes);
if (cmp == 1) {
@@ -338,9 +365,12 @@ page_cur_search_with_match(
low_matched_bytes = cur_matched_bytes;
} else if (cmp == -1) {
+ offsets = rec_reget_offsets(mid_rec, index,
+ offsets, dtuple_get_n_fields_cmp(tuple), heap);
+
if (mode == PAGE_CUR_LE_OR_EXTENDS
&& page_cur_rec_field_extends(tuple, mid_rec,
- cur_matched_fields)) {
+ offsets, cur_matched_fields)) {
low_rec = mid_rec;
low_matched_fields = cur_matched_fields;
low_matched_bytes = cur_matched_bytes;
@@ -368,7 +398,9 @@ page_cur_search_with_match(
dbg_matched_fields = 0;
dbg_matched_bytes = 0;
- dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, low_rec,
+ offsets = rec_reget_offsets(low_rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, low_rec, offsets,
&dbg_matched_fields,
&dbg_matched_bytes);
if (mode == PAGE_CUR_G) {
@@ -390,7 +422,9 @@ page_cur_search_with_match(
dbg_matched_fields = 0;
dbg_matched_bytes = 0;
- dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, up_rec,
+ offsets = rec_reget_offsets(up_rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ dbg_cmp = page_cmp_dtuple_rec_with_match(tuple, up_rec, offsets,
&dbg_matched_fields,
&dbg_matched_bytes);
if (mode == PAGE_CUR_G) {
@@ -419,6 +453,7 @@ page_cur_search_with_match(
*iup_matched_bytes = up_matched_bytes;
*ilow_matched_fields = low_matched_fields;
*ilow_matched_bytes = low_matched_bytes;
+ mem_heap_free(heap);
}
/***************************************************************
@@ -463,10 +498,12 @@ static
void
page_cur_insert_rec_write_log(
/*==========================*/
- rec_t* insert_rec, /* in: inserted physical record */
- ulint rec_size, /* in: insert_rec size */
- rec_t* cursor_rec, /* in: record the cursor is pointing to */
- mtr_t* mtr) /* in: mini-transaction handle */
+ rec_t* insert_rec, /* in: inserted physical record */
+ ulint rec_size, /* in: insert_rec size */
+ rec_t* cursor_rec, /* in: record the
+ cursor is pointing to */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mini-transaction handle */
{
ulint cur_rec_size;
ulint extra_size;
@@ -476,22 +513,29 @@ page_cur_insert_rec_write_log(
byte* cur_ptr;
ulint extra_info_yes;
byte* log_ptr;
+ byte* log_end;
ulint i;
ut_a(rec_size < UNIV_PAGE_SIZE);
- ut_ad(rec_size == rec_get_size(insert_rec));
- log_ptr = mlog_open(mtr, 30 + MLOG_BUF_MARGIN);
+ {
+ mem_heap_t* heap;
+ ulint* cur_offs;
+ ulint* ins_offs;
- if (log_ptr == NULL) {
+ heap = mem_heap_create(100);
+ cur_offs = rec_get_offsets(cursor_rec, index,
+ ULINT_UNDEFINED, heap);
+ ins_offs = rec_get_offsets(insert_rec, index,
+ ULINT_UNDEFINED, heap);
- return;
- }
-
- extra_size = rec_get_extra_size(insert_rec);
+ extra_size = rec_offs_extra_size(ins_offs);
+ cur_extra_size = rec_offs_extra_size(cur_offs);
+ ut_ad(rec_size == rec_offs_size(ins_offs));
+ cur_rec_size = rec_offs_size(cur_offs);
- cur_extra_size = rec_get_extra_size(cursor_rec);
- cur_rec_size = rec_get_size(cursor_rec);
+ mem_heap_free(heap);
+ }
ins_ptr = insert_rec - extra_size;
@@ -514,7 +558,9 @@ page_cur_insert_rec_write_log(
ins_ptr++;
cur_ptr++;
} else if ((i < extra_size)
- && (i >= extra_size - REC_N_EXTRA_BYTES)) {
+ && (i >= extra_size - (index->table->comp
+ ? REC_N_NEW_EXTRA_BYTES
+ : REC_N_OLD_EXTRA_BYTES))) {
i = extra_size;
ins_ptr = insert_rec;
cur_ptr = cursor_rec;
@@ -525,16 +571,35 @@ page_cur_insert_rec_write_log(
}
if (mtr_get_log_mode(mtr) != MTR_LOG_SHORT_INSERTS) {
-
- log_ptr = mlog_write_initial_log_record_fast(insert_rec,
- MLOG_REC_INSERT, log_ptr, mtr);
+
+ log_ptr = mlog_open_and_write_index(mtr, insert_rec, index,
+ index->table->comp
+ ? MLOG_COMP_REC_INSERT : MLOG_REC_INSERT,
+ 2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
+
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash
+ recovery: in that case mlog_open returns NULL */
+ return;
+ }
+
+ log_end = &log_ptr[2 + 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
/* Write the cursor rec offset as a 2-byte ulint */
mach_write_to_2(log_ptr, cursor_rec
- buf_frame_align(cursor_rec));
log_ptr += 2;
+ } else {
+ log_ptr = mlog_open(mtr, 5 + 1 + 5 + 5 + MLOG_BUF_MARGIN);
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash
+ recovery: in that case mlog_open returns NULL */
+ return;
+ }
+ log_end = &log_ptr[5 + 1 + 5 + 5 + MLOG_BUF_MARGIN];
}
- if ((rec_get_info_bits(insert_rec) != rec_get_info_bits(cursor_rec))
+ if ((rec_get_info_bits(insert_rec, index->table->comp) !=
+ rec_get_info_bits(cursor_rec, index->table->comp))
|| (extra_size != cur_extra_size)
|| (rec_size != cur_rec_size)) {
@@ -549,7 +614,8 @@ page_cur_insert_rec_write_log(
+ extra_info_yes);
if (extra_info_yes) {
/* Write the info bits */
- mach_write_to_1(log_ptr, rec_get_info_bits(insert_rec));
+ mach_write_to_1(log_ptr,
+ rec_get_info_bits(insert_rec, index->table->comp));
log_ptr++;
/* Write the record origin offset */
@@ -565,17 +631,15 @@ page_cur_insert_rec_write_log(
/* Write to the log the inserted index record end segment which
differs from the cursor record */
- if (rec_size - i < MLOG_BUF_MARGIN) {
- ut_memcpy(log_ptr, ins_ptr, rec_size - i);
- log_ptr += rec_size - i;
- }
-
- mlog_close(mtr, log_ptr);
-
- ut_a(rec_size - i < UNIV_PAGE_SIZE);
+ rec_size -= i;
- if (rec_size - i >= MLOG_BUF_MARGIN) {
- mlog_catenate_string(mtr, ins_ptr, rec_size - i);
+ if (log_ptr + rec_size <= log_end) {
+ memcpy(log_ptr, ins_ptr, rec_size);
+ mlog_close(mtr, log_ptr + rec_size);
+ } else {
+ mlog_close(mtr, log_ptr);
+ ut_a(rec_size < UNIV_PAGE_SIZE);
+ mlog_catenate_string(mtr, ins_ptr, rec_size);
}
}
@@ -585,12 +649,13 @@ Parses a log record of a record insert on a page. */
byte*
page_cur_parse_insert_rec(
/*======================*/
- /* out: end of log record or NULL */
- ibool is_short,/* in: TRUE if short inserts */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ ibool is_short,/* in: TRUE if short inserts */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
ulint extra_info_yes;
ulint offset = 0; /* remove warning */
@@ -603,6 +668,8 @@ page_cur_parse_insert_rec(
byte* ptr2 = ptr;
ulint info_bits = 0; /* remove warning */
page_cur_t cursor;
+ mem_heap_t* heap;
+ ulint* offsets;
if (!is_short) {
/* Read the cursor rec offset as a 2-byte ulint */
@@ -689,11 +756,14 @@ page_cur_parse_insert_rec(
cursor_rec = page + offset;
}
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(cursor_rec, index, ULINT_UNDEFINED, heap);
+
if (extra_info_yes == 0) {
- info_bits = rec_get_info_bits(cursor_rec);
- origin_offset = rec_get_extra_size(cursor_rec);
- mismatch_index = rec_get_size(cursor_rec) - end_seg_len;
- }
+ info_bits = rec_get_info_bits(cursor_rec, index->table->comp);
+ origin_offset = rec_offs_extra_size(offsets);
+ mismatch_index = rec_offs_size(offsets) - end_seg_len;
+ }
if (mismatch_index + end_seg_len < sizeof buf1) {
buf = buf1;
@@ -722,14 +792,24 @@ page_cur_parse_insert_rec(
ut_error;
}
- ut_memcpy(buf, rec_get_start(cursor_rec), mismatch_index);
+ ut_memcpy(buf, rec_get_start(cursor_rec, offsets), mismatch_index);
ut_memcpy(buf + mismatch_index, ptr, end_seg_len);
- rec_set_info_bits(buf + origin_offset, info_bits);
+ rec_set_info_bits(buf + origin_offset, index->table->comp, info_bits);
+
+ /* Set the status bits for new-style records. */
+ if (index->table->comp) {
+ /* Leaf pages (level 0) contain ordinary records;
+ non-leaf pages contain node pointer records. */
+ ulint level = page_header_get_field(
+ buf_frame_align(cursor_rec), PAGE_LEVEL);
+ rec_set_status(buf + origin_offset,
+ level ? REC_STATUS_NODE_PTR : REC_STATUS_ORDINARY);
+ }
page_cur_position(cursor_rec, &cursor);
- page_cur_rec_insert(&cursor, buf + origin_offset, mtr);
+ page_cur_rec_insert(&cursor, buf + origin_offset, index, mtr);
if (buf != buf1) {
@@ -751,68 +831,80 @@ page_cur_insert_rec_low(
/* out: pointer to record if succeed, NULL
otherwise */
page_cur_t* cursor, /* in: a page cursor */
- dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
- ulint data_size,/* in: data size of tuple */
- rec_t* rec, /* in: pointer to a physical record or NULL */
+ dtuple_t* tuple, /* in: pointer to a data tuple or NULL */
+ dict_index_t* index, /* in: record descriptor */
+ rec_t* rec, /* in: pointer to a physical record or NULL */
mtr_t* mtr) /* in: mini-transaction handle */
{
- byte* insert_buf = NULL;
- ulint rec_size;
- byte* page; /* the relevant page */
- rec_t* last_insert; /* cursor position at previous insert */
- rec_t* insert_rec; /* inserted record */
- ulint heap_no; /* heap number of the inserted record */
- rec_t* current_rec; /* current record after which the
- new record is inserted */
- rec_t* next_rec; /* next record after current before
- the insertion */
- ulint owner_slot; /* the slot which owns the inserted record */
- rec_t* owner_rec;
- ulint n_owned;
-
+ byte* insert_buf = NULL;
+ ulint rec_size;
+ byte* page; /* the relevant page */
+ rec_t* last_insert; /* cursor position at previous insert */
+ rec_t* insert_rec; /* inserted record */
+ ulint heap_no; /* heap number of the inserted record */
+ rec_t* current_rec; /* current record after which the
+ new record is inserted */
+ rec_t* next_rec; /* next record after current before
+ the insertion */
+ ulint owner_slot; /* the slot which owns the
+ inserted record */
+ rec_t* owner_rec;
+ ulint n_owned;
+ mem_heap_t* heap;
+ ulint* offsets;
+ ibool comp = index->table->comp;
+
ut_ad(cursor && mtr);
ut_ad(tuple || rec);
ut_ad(!(tuple && rec));
ut_ad(rec || dtuple_check_typed(tuple));
- ut_ad(rec || (dtuple_get_data_size(tuple) == data_size));
page = page_cur_get_page(cursor);
+ ut_ad(page_is_comp(page) == comp);
+
ut_ad(cursor->rec != page_get_supremum_rec(page));
+ heap = mem_heap_create(100);
+
/* 1. Get the size of the physical record in the page */
if (tuple != NULL) {
- rec_size = data_size + rec_get_converted_extra_size(
- data_size,
- dtuple_get_n_fields(tuple));
+ offsets = NULL;
+ rec_size = rec_get_converted_size(index, tuple);
} else {
- rec_size = rec_get_size(rec);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+ rec_size = rec_offs_size(offsets);
}
/* 2. Try to find suitable space from page memory management */
- insert_buf = page_mem_alloc(page, rec_size, &heap_no);
+ insert_buf = page_mem_alloc(page, rec_size, index, &heap_no);
if (insert_buf == NULL) {
-
+ mem_heap_free(heap);
return(NULL);
}
/* 3. Create the record */
if (tuple != NULL) {
- insert_rec = rec_convert_dtuple_to_rec_low(insert_buf, tuple,
- data_size);
+ insert_rec = rec_convert_dtuple_to_rec(insert_buf,
+ index, tuple);
} else {
- insert_rec = rec_copy(insert_buf, rec);
+ insert_rec = rec_copy(insert_buf, rec, offsets);
}
ut_ad(insert_rec);
- ut_ad(rec_size == rec_get_size(insert_rec));
+ offsets = rec_reget_offsets(insert_rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ ut_ad(rec_size == rec_offs_size(offsets));
/* 4. Insert the record in the linked list of records */
-
current_rec = cursor->rec;
+ ut_ad(!comp || rec_get_status(current_rec) <= REC_STATUS_INFIMUM);
+ ut_ad(!comp || rec_get_status(insert_rec) < REC_STATUS_INFIMUM);
+
next_rec = page_rec_get_next(current_rec);
+ ut_ad(!comp || rec_get_status(next_rec) != REC_STATUS_INFIMUM);
page_rec_set_next(insert_rec, next_rec);
page_rec_set_next(current_rec, insert_rec);
@@ -821,12 +913,15 @@ page_cur_insert_rec_low(
/* 5. Set the n_owned field in the inserted record to zero,
and set the heap_no field */
- rec_set_n_owned(insert_rec, 0);
- rec_set_heap_no(insert_rec, heap_no);
+ rec_set_n_owned(insert_rec, comp, 0);
+ rec_set_heap_no(insert_rec, comp, heap_no);
/* 6. Update the last insertion info in page header */
last_insert = page_header_get_ptr(page, PAGE_LAST_INSERT);
+ ut_ad(!last_insert || !comp
+ || rec_get_node_ptr_flag(last_insert)
+ == rec_get_node_ptr_flag(insert_rec));
if (last_insert == NULL) {
page_header_set_field(page, PAGE_DIRECTION, PAGE_NO_DIRECTION);
@@ -855,8 +950,8 @@ page_cur_insert_rec_low(
/* 7. It remains to update the owner record. */
owner_rec = page_rec_find_owner_rec(insert_rec);
- n_owned = rec_get_n_owned(owner_rec);
- rec_set_n_owned(owner_rec, n_owned + 1);
+ n_owned = rec_get_n_owned(owner_rec, comp);
+ rec_set_n_owned(owner_rec, comp, n_owned + 1);
/* 8. Now we have incremented the n_owned field of the owner
record. If the number exceeds PAGE_DIR_SLOT_MAX_N_OWNED,
@@ -868,8 +963,10 @@ page_cur_insert_rec_low(
}
/* 9. Write log record of the insert */
- page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec, mtr);
+ page_cur_insert_rec_write_log(insert_rec, rec_size, current_rec,
+ index, mtr);
+ mem_heap_free(heap);
return(insert_rec);
}
@@ -879,17 +976,19 @@ UNIV_INLINE
byte*
page_copy_rec_list_to_created_page_write_log(
/*=========================================*/
- /* out: 4-byte field where to write the log data
- length */
- page_t* page, /* in: index page */
- mtr_t* mtr) /* in: mtr */
+ /* out: 4-byte field where to
+ write the log data length */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
byte* log_ptr;
-
- mlog_write_initial_log_record(page, MLOG_LIST_END_COPY_CREATED, mtr);
-
- log_ptr = mlog_open(mtr, 4);
+ log_ptr = mlog_open_and_write_index(mtr, page, index,
+ index->table->comp
+ ? MLOG_COMP_LIST_END_COPY_CREATED
+ : MLOG_LIST_END_COPY_CREATED, 4);
+ ut_a(log_ptr);
mlog_close(mtr, log_ptr + 4);
return(log_ptr);
@@ -901,11 +1000,12 @@ Parses a log record of copying a record list end to a new created page. */
byte*
page_parse_copy_rec_list_to_created_page(
/*=====================================*/
- /* out: end of log record or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
byte* rec_end;
ulint log_data_len;
@@ -931,7 +1031,8 @@ page_parse_copy_rec_list_to_created_page(
}
while (ptr < rec_end) {
- ptr = page_cur_parse_insert_rec(TRUE, ptr, end_ptr, page, mtr);
+ ptr = page_cur_parse_insert_rec(TRUE, ptr, end_ptr,
+ index, page, mtr);
}
ut_a(ptr == rec_end);
@@ -950,10 +1051,11 @@ including that record. Infimum and supremum records are not copied. */
void
page_copy_rec_list_end_to_created_page(
/*===================================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: first record to copy */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: first record to copy */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_dir_slot_t* slot = 0; /* remove warning */
byte* heap_top;
@@ -966,9 +1068,13 @@ page_copy_rec_list_end_to_created_page(
ulint log_mode;
byte* log_ptr;
ulint log_data_len;
+ ibool comp = page_is_comp(page);
+ mem_heap_t* heap;
+ ulint* offsets = NULL;
- ut_ad(page_header_get_field(new_page, PAGE_N_HEAP) == 2);
+ ut_ad(page_dir_get_n_heap(new_page) == 2);
ut_ad(page != new_page);
+ ut_ad(comp == page_is_comp(new_page));
if (rec == page_get_infimum_rec(page)) {
@@ -983,12 +1089,13 @@ page_copy_rec_list_end_to_created_page(
#ifdef UNIV_DEBUG
/* To pass the debug tests we have to set these dummy values
in the debug version */
- page_header_set_field(new_page, PAGE_N_DIR_SLOTS, UNIV_PAGE_SIZE / 2);
+ page_dir_set_n_slots(new_page, UNIV_PAGE_SIZE / 2);
page_header_set_ptr(new_page, PAGE_HEAP_TOP,
new_page + UNIV_PAGE_SIZE - 1);
#endif
- log_ptr = page_copy_rec_list_to_created_page_write_log(new_page, mtr);
+ log_ptr = page_copy_rec_list_to_created_page_write_log(new_page,
+ index, mtr);
log_data_len = dyn_array_get_data_size(&(mtr->log));
@@ -997,22 +1104,29 @@ page_copy_rec_list_end_to_created_page(
log_mode = mtr_set_log_mode(mtr, MTR_LOG_SHORT_INSERTS);
prev_rec = page_get_infimum_rec(new_page);
- heap_top = new_page + PAGE_SUPREMUM_END;
+ if (comp) {
+ heap_top = new_page + PAGE_NEW_SUPREMUM_END;
+ } else {
+ heap_top = new_page + PAGE_OLD_SUPREMUM_END;
+ }
count = 0;
slot_index = 0;
n_recs = 0;
+ heap = mem_heap_create(100);
+
/* should be do ... until, comment by Jani */
while (rec != page_get_supremum_rec(page)) {
-
- insert_rec = rec_copy(heap_top, rec);
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ insert_rec = rec_copy(heap_top, rec, offsets);
- rec_set_next_offs(prev_rec, insert_rec - new_page);
+ rec_set_next_offs(prev_rec, comp, insert_rec - new_page);
- rec_set_n_owned(insert_rec, 0);
- rec_set_heap_no(insert_rec, 2 + n_recs);
+ rec_set_n_owned(insert_rec, comp, 0);
+ rec_set_heap_no(insert_rec, comp, 2 + n_recs);
- rec_size = rec_get_size(insert_rec);
+ rec_size = rec_offs_size(offsets);
heap_top = heap_top + rec_size;
@@ -1034,7 +1148,7 @@ page_copy_rec_list_end_to_created_page(
}
page_cur_insert_rec_write_log(insert_rec, rec_size, prev_rec,
- mtr);
+ index, mtr);
prev_rec = insert_rec;
rec = page_rec_get_next(rec);
}
@@ -1056,22 +1170,25 @@ page_copy_rec_list_end_to_created_page(
slot_index--;
}
+ mem_heap_free(heap);
+
log_data_len = dyn_array_get_data_size(&(mtr->log)) - log_data_len;
ut_a(log_data_len < 100 * UNIV_PAGE_SIZE);
mach_write_to_4(log_ptr, log_data_len);
- rec_set_next_offs(insert_rec, PAGE_SUPREMUM);
+ rec_set_next_offs(insert_rec, comp,
+ comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM);
slot = page_dir_get_nth_slot(new_page, 1 + slot_index);
page_dir_slot_set_rec(slot, page_get_supremum_rec(new_page));
page_dir_slot_set_n_owned(slot, count + 1);
- page_header_set_field(new_page, PAGE_N_DIR_SLOTS, 2 + slot_index);
+ page_dir_set_n_slots(new_page, 2 + slot_index);
page_header_set_ptr(new_page, PAGE_HEAP_TOP, heap_top);
- page_header_set_field(new_page, PAGE_N_HEAP, 2 + n_recs);
+ page_dir_set_n_heap(new_page, 2 + n_recs);
page_header_set_field(new_page, PAGE_N_RECS, n_recs);
page_header_set_ptr(new_page, PAGE_LAST_INSERT, NULL);
@@ -1089,14 +1206,27 @@ UNIV_INLINE
void
page_cur_delete_rec_write_log(
/*==========================*/
- rec_t* cursor_rec, /* in: record to be deleted */
- mtr_t* mtr) /* in: mini-transaction handle */
+ rec_t* rec, /* in: record to be deleted */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mini-transaction handle */
{
- mlog_write_initial_log_record(cursor_rec, MLOG_REC_DELETE, mtr);
+ byte* log_ptr;
+
+ log_ptr = mlog_open_and_write_index(mtr, rec, index,
+ index->table->comp
+ ? MLOG_COMP_REC_DELETE
+ : MLOG_REC_DELETE, 2);
+
+ if (!log_ptr) {
+ /* Logging in mtr is switched off during crash recovery:
+ in that case mlog_open returns NULL */
+ return;
+ }
/* Write the cursor rec offset as a 2-byte ulint */
- mlog_catenate_ulint(mtr, cursor_rec - buf_frame_align(cursor_rec),
- MLOG_2BYTES);
+ mach_write_to_2(log_ptr, rec - buf_frame_align(rec));
+
+ mlog_close(mtr, log_ptr + 2);
}
/***************************************************************
@@ -1105,11 +1235,12 @@ Parses log record of a record delete on a page. */
byte*
page_cur_parse_delete_rec(
/*======================*/
- /* out: pointer to record end or NULL */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: pointer to record end or NULL */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
ulint offset;
page_cur_t cursor;
@@ -1128,7 +1259,7 @@ page_cur_parse_delete_rec(
if (page) {
page_cur_position(page + offset, &cursor);
- page_cur_delete_rec(&cursor, mtr);
+ page_cur_delete_rec(&cursor, index, mtr);
}
return(ptr);
@@ -1142,6 +1273,7 @@ void
page_cur_delete_rec(
/*================*/
page_cur_t* cursor, /* in: a page cursor */
+ dict_index_t* index, /* in: record descriptor */
mtr_t* mtr) /* in: mini-transaction handle */
{
page_dir_slot_t* cur_dir_slot;
@@ -1169,7 +1301,7 @@ page_cur_delete_rec(
cur_n_owned = page_dir_slot_get_n_owned(cur_dir_slot);
/* 0. Write the log record */
- page_cur_delete_rec_write_log(current_rec, mtr);
+ page_cur_delete_rec_write_log(current_rec, index, mtr);
/* 1. Reset the last insert info in the page header and increment
the modify clock for the frame */
@@ -1223,7 +1355,7 @@ page_cur_delete_rec(
page_dir_slot_set_n_owned(cur_dir_slot, cur_n_owned - 1);
/* 6. Free the memory occupied by the record */
- page_mem_free(page, current_rec);
+ page_mem_free(page, current_rec, index);
/* 7. Now we have decremented the number of owned records of the slot.
If the number drops below PAGE_DIR_SLOT_MIN_N_OWNED, we balance the
diff --git a/innobase/page/page0page.c b/innobase/page/page0page.c
index 343f300fc77..38b1e503c8f 100644
--- a/innobase/page/page0page.c
+++ b/innobase/page/page0page.c
@@ -18,6 +18,8 @@ Created 2/2/1994 Heikki Tuuri
#include "fut0lst.h"
#include "btr0sea.h"
#include "buf0buf.h"
+#include "srv0srv.h"
+#include "btr0btr.h"
/* THE INDEX PAGE
==============
@@ -75,10 +77,14 @@ page_dir_find_owner_slot(
page_t* page;
page_dir_slot_t* slot;
rec_t* original_rec = rec;
+ ibool comp;
ut_ad(page_rec_check(rec));
- while (rec_get_n_owned(rec) == 0) {
+ page = buf_frame_align(rec);
+ comp = page_is_comp(page);
+
+ while (rec_get_n_owned(rec, comp) == 0) {
steps++;
rec = page_rec_get_next(rec);
}
@@ -96,14 +102,18 @@ page_dir_find_owner_slot(
"InnoDB: Original record ",
(ulong) buf_frame_get_page_no(page));
- rec_print(stderr, original_rec);
+ if (comp) {
+ fputs("(compact record)\n", stderr);
+ } else {
+ rec_print_old(stderr, original_rec);
+ }
fprintf(stderr, "\n"
"InnoDB: on that page. Steps %lu.\n", (ulong) steps);
fputs(
"InnoDB: Cannot find the dir slot for record ",
stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, NULL);
fputs("\n"
"InnoDB: on that page!\n", stderr);
@@ -136,14 +146,15 @@ page_dir_slot_check(
page = buf_frame_align(slot);
- n_slots = page_header_get_field(page, PAGE_N_DIR_SLOTS);
+ n_slots = page_dir_get_n_slots(page);
ut_a(slot <= page_dir_get_nth_slot(page, 0));
ut_a(slot >= page_dir_get_nth_slot(page, n_slots - 1));
- ut_a(page_rec_check(page + mach_read_from_2(slot)));
+ ut_a(page_rec_check(page_dir_slot_get_rec(slot)));
- n_owned = rec_get_n_owned(page + mach_read_from_2(slot));
+ n_owned = rec_get_n_owned(page_dir_slot_get_rec(slot),
+ page_is_comp(page));
if (slot == page_dir_get_nth_slot(page, 0)) {
ut_a(n_owned == 1);
@@ -194,12 +205,14 @@ Allocates a block of memory from an index page. */
byte*
page_mem_alloc(
/*===========*/
- /* out: pointer to start of allocated
- buffer, or NULL if allocation fails */
- page_t* page, /* in: index page */
- ulint need, /* in: number of bytes needed */
- ulint* heap_no)/* out: this contains the heap number
- of the allocated record if allocation succeeds */
+ /* out: pointer to start of allocated
+ buffer, or NULL if allocation fails */
+ page_t* page, /* in: index page */
+ ulint need, /* in: number of bytes needed */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* heap_no)/* out: this contains the heap number
+ of the allocated record
+ if allocation succeeds */
{
rec_t* rec;
byte* block;
@@ -213,18 +226,30 @@ page_mem_alloc(
rec = page_header_get_ptr(page, PAGE_FREE);
- if (rec && (rec_get_size(rec) >= need)) {
+ if (rec) {
+ mem_heap_t* heap
+ = mem_heap_create(100);
+ const ulint* offsets
+ = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
+ if (rec_offs_size(offsets) >= need) {
+ page_header_set_ptr(page, PAGE_FREE,
+ page_rec_get_next(rec));
- page_header_set_ptr(page, PAGE_FREE, page_rec_get_next(rec));
+ garbage = page_header_get_field(page, PAGE_GARBAGE);
+ ut_ad(garbage >= need);
- garbage = page_header_get_field(page, PAGE_GARBAGE);
- ut_ad(garbage >= need);
+ page_header_set_field(page, PAGE_GARBAGE,
+ garbage - need);
- page_header_set_field(page, PAGE_GARBAGE, garbage - need);
+ *heap_no = rec_get_heap_no(rec, page_is_comp(page));
- *heap_no = rec_get_heap_no(rec);
+ block = rec_get_start(rec, offsets);
+ mem_heap_free(heap);
+ return(block);
+ }
- return(rec_get_start(rec));
+ mem_heap_free(heap);
}
/* Could not find space from the free list, try top of heap */
@@ -235,9 +260,9 @@ page_mem_alloc(
block = page_header_get_ptr(page, PAGE_HEAP_TOP);
page_header_set_ptr(page, PAGE_HEAP_TOP, block + need);
- *heap_no = page_header_get_field(page, PAGE_N_HEAP);
+ *heap_no = page_dir_get_n_heap(page);
- page_header_set_field(page, PAGE_N_HEAP, 1 + *heap_no);
+ page_dir_set_n_heap(page, 1 + *heap_no);
return(block);
}
@@ -253,9 +278,11 @@ page_create_write_log(
/*==================*/
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr, /* in: mini-transaction handle */
+ ibool comp) /* in: TRUE=compact page format */
{
- mlog_write_initial_log_record(frame, MLOG_PAGE_CREATE, mtr);
+ mlog_write_initial_log_record(frame,
+ comp ? MLOG_COMP_PAGE_CREATE : MLOG_PAGE_CREATE, mtr);
}
/***************************************************************
@@ -267,6 +294,7 @@ page_parse_create(
/* out: end of log record or NULL */
byte* ptr, /* in: buffer */
byte* end_ptr __attribute__((unused)), /* in: buffer end */
+ ibool comp, /* in: TRUE=compact page format */
page_t* page, /* in: page or NULL */
mtr_t* mtr) /* in: mtr or NULL */
{
@@ -275,7 +303,7 @@ page_parse_create(
/* The record is empty, except for the record initial part */
if (page) {
- page_create(page, mtr);
+ page_create(page, mtr, comp);
}
return(ptr);
@@ -290,7 +318,8 @@ page_create(
/* out: pointer to the page */
buf_frame_t* frame, /* in: a buffer frame where the page is
created */
- mtr_t* mtr) /* in: mini-transaction handle */
+ mtr_t* mtr, /* in: mini-transaction handle */
+ ibool comp) /* in: TRUE=compact page format */
{
page_dir_slot_t* slot;
mem_heap_t* heap;
@@ -300,6 +329,10 @@ page_create(
rec_t* infimum_rec;
rec_t* supremum_rec;
page_t* page;
+ dict_index_t* index;
+ ulint* offsets;
+
+ index = comp ? srv_sys->dummy_ind2 : srv_sys->dummy_ind1;
ut_ad(frame && mtr);
ut_ad(PAGE_BTR_IBUF_FREE_LIST + FLST_BASE_NODE_SIZE
@@ -311,7 +344,7 @@ page_create(
buf_frame_modify_clock_inc(frame);
/* 2. WRITE LOG INFORMATION */
- page_create_write_log(frame, mtr);
+ page_create_write_log(frame, mtr, comp);
page = frame;
@@ -323,43 +356,52 @@ page_create(
/* Create first a data tuple for infimum record */
tuple = dtuple_create(heap, 1);
+ dtuple_set_info_bits(tuple, REC_STATUS_INFIMUM);
field = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(field, "infimum", sizeof "infimum");
- dtype_set(dfield_get_type(field), DATA_VARCHAR, DATA_ENGLISH, 20, 0);
-
+ dfield_set_data(field, "infimum", 8);
+ dtype_set(dfield_get_type(field),
+ DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, 8, 0);
/* Set the corresponding physical record to its place in the page
record heap */
heap_top = page + PAGE_DATA;
- infimum_rec = rec_convert_dtuple_to_rec(heap_top, tuple);
+ infimum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple);
+
+ ut_a(infimum_rec ==
+ page + (comp ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
+
+ rec_set_n_owned(infimum_rec, comp, 1);
+ rec_set_heap_no(infimum_rec, comp, 0);
+ offsets = rec_get_offsets(infimum_rec, index, ULINT_UNDEFINED, heap);
+
+ heap_top = rec_get_end(infimum_rec, offsets);
- ut_a(infimum_rec == page + PAGE_INFIMUM);
-
- rec_set_n_owned(infimum_rec, 1);
- rec_set_heap_no(infimum_rec, 0);
-
- heap_top = rec_get_end(infimum_rec);
-
/* Create then a tuple for supremum */
tuple = dtuple_create(heap, 1);
+ dtuple_set_info_bits(tuple, REC_STATUS_SUPREMUM);
field = dtuple_get_nth_field(tuple, 0);
- dfield_set_data(field, "supremum", sizeof "supremum");
- dtype_set(dfield_get_type(field), DATA_VARCHAR, DATA_ENGLISH, 20, 0);
+ dfield_set_data(field, "supremum", 9 - comp);
+ dtype_set(dfield_get_type(field),
+ DATA_VARCHAR, DATA_ENGLISH | DATA_NOT_NULL, 9 - comp, 0);
- supremum_rec = rec_convert_dtuple_to_rec(heap_top, tuple);
+ supremum_rec = rec_convert_dtuple_to_rec(heap_top, index, tuple);
- ut_a(supremum_rec == page + PAGE_SUPREMUM);
+ ut_a(supremum_rec ==
+ page + (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM));
- rec_set_n_owned(supremum_rec, 1);
- rec_set_heap_no(supremum_rec, 1);
-
- heap_top = rec_get_end(supremum_rec);
+ rec_set_n_owned(supremum_rec, comp, 1);
+ rec_set_heap_no(supremum_rec, comp, 1);
- ut_ad(heap_top == page + PAGE_SUPREMUM_END);
+ offsets = rec_reget_offsets(supremum_rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ heap_top = rec_get_end(supremum_rec, offsets);
+
+ ut_ad(heap_top ==
+ page + (comp ? PAGE_NEW_SUPREMUM_END : PAGE_OLD_SUPREMUM_END));
mem_heap_free(heap);
@@ -367,7 +409,7 @@ page_create(
page_header_set_field(page, PAGE_N_DIR_SLOTS, 2);
page_header_set_ptr(page, PAGE_HEAP_TOP, heap_top);
- page_header_set_field(page, PAGE_N_HEAP, 2);
+ page_header_set_field(page, PAGE_N_HEAP, comp ? 0x8002 : 2);
page_header_set_ptr(page, PAGE_FREE, NULL);
page_header_set_field(page, PAGE_GARBAGE, 0);
page_header_set_ptr(page, PAGE_LAST_INSERT, NULL);
@@ -388,8 +430,8 @@ page_create(
/* Set the next pointers in infimum and supremum */
- rec_set_next_offs(infimum_rec, (ulint)(supremum_rec - page));
- rec_set_next_offs(supremum_rec, 0);
+ rec_set_next_offs(infimum_rec, comp, (ulint)(supremum_rec - page));
+ rec_set_next_offs(supremum_rec, comp, 0);
return(page);
}
@@ -401,10 +443,11 @@ touch the lock table and max trx id on page. */
void
page_copy_rec_list_end_no_locks(
/*============================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_cur_t cur1;
page_cur_t cur2;
@@ -416,8 +459,11 @@ page_copy_rec_list_end_no_locks(
page_cur_move_to_next(&cur1);
}
-
- ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == PAGE_INFIMUM);
+
+ ut_a(index->table->comp == page_is_comp(page));
+ ut_a(index->table->comp == page_is_comp(new_page));
+ ut_a(mach_read_from_2(new_page + UNIV_PAGE_SIZE - 10) == (ulint)
+ (index->table->comp ? PAGE_NEW_INFIMUM : PAGE_OLD_INFIMUM));
page_cur_set_before_first(new_page, &cur2);
@@ -427,7 +473,7 @@ page_copy_rec_list_end_no_locks(
while (sup != page_cur_get_rec(&cur1)) {
if (!page_cur_rec_insert(&cur2,
- page_cur_get_rec(&cur1), mtr)) {
+ page_cur_get_rec(&cur1), index, mtr)) {
/* Track an assertion failure reported on the mailing
list on June 18th, 2003 */
@@ -456,16 +502,18 @@ The records are copied to the start of the record list on new_page. */
void
page_copy_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
- if (page_header_get_field(new_page, PAGE_N_HEAP) == 2) {
+ if (page_dir_get_n_heap(new_page) == 2) {
page_copy_rec_list_end_to_created_page(new_page, page, rec,
- mtr);
+ index, mtr);
} else {
- page_copy_rec_list_end_no_locks(new_page, page, rec, mtr);
+ page_copy_rec_list_end_no_locks(new_page, page, rec,
+ index, mtr);
}
/* Update the lock table, MAX_TRX_ID, and possible hash index */
@@ -474,7 +522,7 @@ page_copy_rec_list_end(
page_update_max_trx_id(new_page, page_get_max_trx_id(page));
- btr_search_move_or_delete_hash_entries(new_page, page);
+ btr_search_move_or_delete_hash_entries(new_page, page, index);
}
/*****************************************************************
@@ -485,10 +533,11 @@ The records are copied to the end of the record list on new_page. */
void
page_copy_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page to copy to */
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page to copy to */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_cur_t cur1;
page_cur_t cur2;
@@ -510,8 +559,8 @@ page_copy_rec_list_start(
/* Copy records from the original page to the new page */
while (page_cur_get_rec(&cur1) != rec) {
- ut_a(
- page_cur_rec_insert(&cur2, page_cur_get_rec(&cur1), mtr));
+ ut_a(page_cur_rec_insert(&cur2,
+ page_cur_get_rec(&cur1), index, mtr));
page_cur_move_to_next(&cur1);
page_cur_move_to_next(&cur2);
@@ -523,7 +572,7 @@ page_copy_rec_list_start(
page_update_max_trx_id(new_page, page_get_max_trx_id(page));
- btr_search_move_or_delete_hash_entries(new_page, page);
+ btr_search_move_or_delete_hash_entries(new_page, page, index);
}
/**************************************************************
@@ -532,18 +581,25 @@ UNIV_INLINE
void
page_delete_rec_list_write_log(
/*===========================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- byte type, /* in: operation type: MLOG_LIST_END_DELETE, ... */
- mtr_t* mtr) /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ byte type, /* in: operation type:
+ MLOG_LIST_END_DELETE, ... */
+ mtr_t* mtr) /* in: mtr */
{
- ut_ad((type == MLOG_LIST_END_DELETE)
- || (type == MLOG_LIST_START_DELETE));
-
- mlog_write_initial_log_record(page, type, mtr);
-
- /* Write the parameter as a 2-byte ulint */
- mlog_catenate_ulint(mtr, rec - page, MLOG_2BYTES);
+ byte* log_ptr;
+ ut_ad(type == MLOG_LIST_END_DELETE
+ || type == MLOG_LIST_START_DELETE
+ || type == MLOG_COMP_LIST_END_DELETE
+ || type == MLOG_COMP_LIST_START_DELETE);
+
+ log_ptr = mlog_open_and_write_index(mtr, page, index, type, 2);
+ if (log_ptr) {
+ /* Write the parameter as a 2-byte ulint */
+ mach_write_to_2(log_ptr, rec - page);
+ mlog_close(mtr, log_ptr + 2);
+ }
}
/**************************************************************
@@ -552,18 +608,23 @@ Parses a log record of a record list end or start deletion. */
byte*
page_parse_delete_rec_list(
/*=======================*/
- /* out: end of log record or NULL */
- byte type, /* in: MLOG_LIST_END_DELETE or
- MLOG_LIST_START_DELETE */
- byte* ptr, /* in: buffer */
- byte* end_ptr,/* in: buffer end */
- page_t* page, /* in: page or NULL */
- mtr_t* mtr) /* in: mtr or NULL */
+ /* out: end of log record or NULL */
+ byte type, /* in: MLOG_LIST_END_DELETE,
+ MLOG_LIST_START_DELETE,
+ MLOG_COMP_LIST_END_DELETE or
+ MLOG_COMP_LIST_START_DELETE */
+ byte* ptr, /* in: buffer */
+ byte* end_ptr,/* in: buffer end */
+ dict_index_t* index, /* in: record descriptor */
+ page_t* page, /* in: page or NULL */
+ mtr_t* mtr) /* in: mtr or NULL */
{
ulint offset;
- ut_ad((type == MLOG_LIST_END_DELETE)
- || (type == MLOG_LIST_START_DELETE));
+ ut_ad(type == MLOG_LIST_END_DELETE
+ || type == MLOG_LIST_START_DELETE
+ || type == MLOG_COMP_LIST_END_DELETE
+ || type == MLOG_COMP_LIST_START_DELETE);
/* Read the record offset as a 2-byte ulint */
@@ -580,11 +641,12 @@ page_parse_delete_rec_list(
return(ptr);
}
- if (type == MLOG_LIST_END_DELETE) {
- page_delete_rec_list_end(page, page + offset, ULINT_UNDEFINED,
- ULINT_UNDEFINED, mtr);
+ if (type == MLOG_LIST_END_DELETE
+ || type == MLOG_COMP_LIST_END_DELETE) {
+ page_delete_rec_list_end(page, page + offset, index,
+ ULINT_UNDEFINED, ULINT_UNDEFINED, mtr);
} else {
- page_delete_rec_list_start(page, page + offset, mtr);
+ page_delete_rec_list_start(page, page + offset, index, mtr);
}
return(ptr);
@@ -597,14 +659,15 @@ The infimum and supremum records are not deleted. */
void
page_delete_rec_list_end(
/*=====================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- ulint n_recs, /* in: number of records to delete, or ULINT_UNDEFINED
- if not known */
- ulint size, /* in: the sum of the sizes of the records in the end
- of the chain to delete, or ULINT_UNDEFINED if not
- known */
- mtr_t* mtr) /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_recs, /* in: number of records to delete,
+ or ULINT_UNDEFINED if not known */
+ ulint size, /* in: the sum of the sizes of the
+ records in the end of the chain to
+ delete, or ULINT_UNDEFINED if not known */
+ mtr_t* mtr) /* in: mtr */
{
page_dir_slot_t* slot;
ulint slot_index;
@@ -615,10 +678,12 @@ page_delete_rec_list_end(
ulint count;
ulint n_owned;
rec_t* sup;
+ ibool comp;
/* Reset the last insert info in the page header and increment
the modify clock for the frame */
+ ut_ad(size == ULINT_UNDEFINED || size < UNIV_PAGE_SIZE);
page_header_set_ptr(page, PAGE_LAST_INSERT, NULL);
/* The page gets invalid for optimistic searches: increment the
@@ -632,7 +697,9 @@ page_delete_rec_list_end(
rec = page_rec_get_next(rec);
}
- page_delete_rec_list_write_log(page, rec, MLOG_LIST_END_DELETE, mtr);
+ comp = page_is_comp(page);
+ page_delete_rec_list_write_log(page, rec, index,
+ comp ? MLOG_COMP_LIST_END_DELETE : MLOG_LIST_END_DELETE, mtr);
if (rec == sup) {
@@ -644,19 +711,32 @@ page_delete_rec_list_end(
last_rec = page_rec_get_prev(sup);
if ((size == ULINT_UNDEFINED) || (n_recs == ULINT_UNDEFINED)) {
+ mem_heap_t* heap = mem_heap_create(100);
+ ulint* offsets = NULL;
/* Calculate the sum of sizes and the number of records */
size = 0;
n_recs = 0;
rec2 = rec;
while (rec2 != sup) {
- size += rec_get_size(rec2);
+ ulint s;
+ offsets = rec_reget_offsets(rec2, index,
+ offsets, ULINT_UNDEFINED, heap);
+ s = rec_offs_size(offsets);
+ ut_ad(rec2 - page + s - rec_offs_extra_size(offsets)
+ < UNIV_PAGE_SIZE);
+ ut_ad(size + s < UNIV_PAGE_SIZE);
+ size += s;
n_recs++;
rec2 = page_rec_get_next(rec2);
}
+
+ mem_heap_free(heap);
}
+ ut_ad(size < UNIV_PAGE_SIZE);
+
/* Update the page directory; there is no need to balance the number
of the records owned by the supremum record, as it is allowed to be
less than PAGE_DIR_SLOT_MIN_N_OWNED */
@@ -664,15 +744,15 @@ page_delete_rec_list_end(
rec2 = rec;
count = 0;
- while (rec_get_n_owned(rec2) == 0) {
+ while (rec_get_n_owned(rec2, comp) == 0) {
count++;
rec2 = page_rec_get_next(rec2);
}
- ut_ad(rec_get_n_owned(rec2) - count > 0);
+ ut_ad(rec_get_n_owned(rec2, comp) - count > 0);
- n_owned = rec_get_n_owned(rec2) - count;
+ n_owned = rec_get_n_owned(rec2, comp) - count;
slot_index = page_dir_find_owner_slot(rec2);
slot = page_dir_get_nth_slot(page, slot_index);
@@ -680,7 +760,7 @@ page_delete_rec_list_end(
page_dir_slot_set_rec(slot, sup);
page_dir_slot_set_n_owned(slot, n_owned);
- page_header_set_field(page, PAGE_N_DIR_SLOTS, slot_index + 1);
+ page_dir_set_n_slots(page, slot_index + 1);
/* Remove the record chain segment from the record chain */
page_rec_set_next(prev_rec, page_get_supremum_rec(page));
@@ -706,14 +786,19 @@ that record. Infimum and supremum records are not deleted. */
void
page_delete_rec_list_start(
/*=======================*/
- page_t* page, /* in: index page */
- rec_t* rec, /* in: record on page */
- mtr_t* mtr) /* in: mtr */
+ page_t* page, /* in: index page */
+ rec_t* rec, /* in: record on page */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
page_cur_t cur1;
ulint log_mode;
- page_delete_rec_list_write_log(page, rec, MLOG_LIST_START_DELETE, mtr);
+ page_delete_rec_list_write_log(page, rec, index,
+ index->table->comp
+ ? MLOG_COMP_LIST_START_DELETE
+ : MLOG_LIST_START_DELETE,
+ mtr);
page_cur_set_before_first(page, &cur1);
@@ -730,7 +815,7 @@ page_delete_rec_list_start(
while (page_cur_get_rec(&cur1) != rec) {
- page_cur_delete_rec(&cur1, mtr);
+ page_cur_delete_rec(&cur1, index, mtr);
}
/* Restore log mode */
@@ -745,10 +830,11 @@ split_rec. */
void
page_move_rec_list_end(
/*===================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record to move */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
ulint old_data_size;
ulint new_data_size;
@@ -758,15 +844,15 @@ page_move_rec_list_end(
old_data_size = page_get_data_size(new_page);
old_n_recs = page_get_n_recs(new_page);
- page_copy_rec_list_end(new_page, page, split_rec, mtr);
+ page_copy_rec_list_end(new_page, page, split_rec, index, mtr);
new_data_size = page_get_data_size(new_page);
new_n_recs = page_get_n_recs(new_page);
ut_ad(new_data_size >= old_data_size);
- page_delete_rec_list_end(page, split_rec, new_n_recs - old_n_recs,
- new_data_size - old_data_size, mtr);
+ page_delete_rec_list_end(page, split_rec, index,
+ new_n_recs - old_n_recs, new_data_size - old_data_size, mtr);
}
/*****************************************************************
@@ -776,14 +862,15 @@ split_rec. */
void
page_move_rec_list_start(
/*=====================*/
- page_t* new_page, /* in: index page where to move */
- page_t* page, /* in: index page */
- rec_t* split_rec, /* in: first record not to move */
- mtr_t* mtr) /* in: mtr */
+ page_t* new_page, /* in: index page where to move */
+ page_t* page, /* in: index page */
+ rec_t* split_rec, /* in: first record not to move */
+ dict_index_t* index, /* in: record descriptor */
+ mtr_t* mtr) /* in: mtr */
{
- page_copy_rec_list_start(new_page, page, split_rec, mtr);
+ page_copy_rec_list_start(new_page, page, split_rec, index, mtr);
- page_delete_rec_list_start(page, split_rec, mtr);
+ page_delete_rec_list_start(page, split_rec, index, mtr);
}
/***************************************************************************
@@ -801,7 +888,7 @@ page_rec_write_index_page_no(
byte* data;
ulint len;
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field_old(rec, i, &len);
ut_ad(len == 4);
@@ -885,7 +972,7 @@ page_dir_add_slots(
ut_ad(start < n_slots - 1);
/* Update the page header */
- page_header_set_field(page, PAGE_N_DIR_SLOTS, n_slots + n);
+ page_dir_set_n_slots(page, n_slots + n);
/* Move slots up */
@@ -1006,8 +1093,8 @@ page_dir_balance_slot(
old_rec = page_dir_slot_get_rec(slot);
new_rec = page_rec_get_next(old_rec);
- rec_set_n_owned(old_rec, 0);
- rec_set_n_owned(new_rec, n_owned + 1);
+ rec_set_n_owned(old_rec, page_is_comp(page), 0);
+ rec_set_n_owned(new_rec, page_is_comp(page), n_owned + 1);
page_dir_slot_set_rec(slot, new_rec);
@@ -1080,13 +1167,15 @@ page_rec_get_n_recs_before(
rec_t* slot_rec;
page_t* page;
ulint i;
+ ibool comp;
lint n = 0;
ut_ad(page_rec_check(rec));
page = buf_frame_align(rec);
-
- while (rec_get_n_owned(rec) == 0) {
+ comp = page_is_comp(page);
+
+ while (rec_get_n_owned(rec, comp) == 0) {
rec = page_rec_get_next(rec);
n--;
@@ -1096,7 +1185,7 @@ page_rec_get_n_recs_before(
slot = page_dir_get_nth_slot(page, i);
slot_rec = page_dir_slot_get_rec(slot);
- n += rec_get_n_owned(slot_rec);
+ n += rec_get_n_owned(slot_rec, comp);
if (rec == slot_rec) {
@@ -1118,17 +1207,21 @@ the index page context. */
void
page_rec_print(
/*===========*/
- rec_t* rec)
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: record descriptor */
{
- rec_print(stderr, rec);
+ ibool comp = page_is_comp(buf_frame_align(rec));
+
+ ut_a(comp == rec_offs_comp(offsets));
+ rec_print(stderr, rec, offsets);
fprintf(stderr,
" n_owned: %lu; heap_no: %lu; next rec: %lu\n",
- (ulong) rec_get_n_owned(rec),
- (ulong) rec_get_heap_no(rec),
- (ulong) rec_get_next_offs(rec));
+ (ulong) rec_get_n_owned(rec, comp),
+ (ulong) rec_get_heap_no(rec, comp),
+ (ulong) rec_get_next_offs(rec, comp));
page_rec_check(rec);
- rec_validate(rec);
+ rec_validate(rec, offsets);
}
/*******************************************************************
@@ -1176,12 +1269,18 @@ debugging purposes. */
void
page_print_list(
/*============*/
- page_t* page, /* in: index page */
- ulint pr_n) /* in: print n first and n last entries */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint pr_n) /* in: print n first and n last entries */
{
page_cur_t cur;
ulint count;
ulint n_recs;
+ mem_heap_t* heap;
+ ulint* offsets = NULL;
+
+ ut_a(page_is_comp(page) == index->table->comp);
+ heap = mem_heap_create(100);
fprintf(stderr,
"--------------------------------\n"
@@ -1193,7 +1292,9 @@ page_print_list(
page_cur_set_before_first(page, &cur);
count = 0;
for (;;) {
- page_rec_print(cur.rec);
+ offsets = rec_reget_offsets(cur.rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ page_rec_print(cur.rec, offsets);
if (count == pr_n) {
break;
@@ -1213,7 +1314,9 @@ page_print_list(
page_cur_move_to_next(&cur);
if (count + pr_n >= n_recs) {
- page_rec_print(cur.rec);
+ offsets = rec_reget_offsets(cur.rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ page_rec_print(cur.rec, offsets);
}
count++;
}
@@ -1222,6 +1325,8 @@ page_print_list(
"Total of %lu records \n"
"--------------------------------\n",
(ulong) (count + 1));
+
+ mem_heap_free(heap);
}
/*******************************************************************
@@ -1235,14 +1340,15 @@ page_header_print(
fprintf(stderr,
"--------------------------------\n"
"PAGE HEADER INFO\n"
- "Page address %p, n records %lu\n"
+ "Page address %p, n records %lu (%s)\n"
"n dir slots %lu, heap top %lu\n"
"Page n heap %lu, free %lu, garbage %lu\n"
"Page last insert %lu, direction %lu, n direction %lu\n",
page, (ulong) page_header_get_field(page, PAGE_N_RECS),
+ page_is_comp(page) ? "compact format" : "original format",
(ulong) page_header_get_field(page, PAGE_N_DIR_SLOTS),
(ulong) page_header_get_field(page, PAGE_HEAP_TOP),
- (ulong) page_header_get_field(page, PAGE_N_HEAP),
+ (ulong) page_dir_get_n_heap(page),
(ulong) page_header_get_field(page, PAGE_FREE),
(ulong) page_header_get_field(page, PAGE_GARBAGE),
(ulong) page_header_get_field(page, PAGE_LAST_INSERT),
@@ -1257,13 +1363,16 @@ debugging purposes. */
void
page_print(
/*======*/
- page_t* page, /* in: index page */
- ulint dn, /* in: print dn first and last entries in directory */
- ulint rn) /* in: print rn first and last records on page */
+ page_t* page, /* in: index page */
+ dict_index_t* index, /* in: dictionary index of the page */
+ ulint dn, /* in: print dn first and last entries
+ in directory */
+ ulint rn) /* in: print rn first and last records
+ in directory */
{
page_header_print(page);
page_dir_print(page, dn);
- page_print_list(page, rn);
+ page_print_list(page, index, rn);
}
/*******************************************************************
@@ -1274,20 +1383,24 @@ the heap_no field. */
ibool
page_rec_validate(
/*==============*/
- /* out: TRUE if ok */
- rec_t* rec) /* in: record on the page */
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_owned;
ulint heap_no;
- page_t* page;
+ page_t* page;
+ ibool comp;
page = buf_frame_align(rec);
+ comp = page_is_comp(page);
+ ut_a(comp == rec_offs_comp(offsets));
page_rec_check(rec);
- rec_validate(rec);
+ rec_validate(rec, offsets);
- n_owned = rec_get_n_owned(rec);
- heap_no = rec_get_heap_no(rec);
+ n_owned = rec_get_n_owned(rec, comp);
+ heap_no = rec_get_heap_no(rec, comp);
if (!(n_owned <= PAGE_DIR_SLOT_MAX_N_OWNED)) {
fprintf(stderr,
@@ -1296,11 +1409,11 @@ page_rec_validate(
return(FALSE);
}
- if (!(heap_no < page_header_get_field(page, PAGE_N_HEAP))) {
+ if (!(heap_no < page_dir_get_n_heap(page))) {
fprintf(stderr,
"InnoDB: Heap no of rec %lu too big %lu %lu\n",
(ulong)(rec - page), (ulong) heap_no,
- (ulong) page_header_get_field(page, PAGE_N_HEAP));
+ (ulong) page_dir_get_n_heap(page));
return(FALSE);
}
@@ -1358,6 +1471,7 @@ page_simple_validate(
ulint count;
ulint own_count;
ibool ret = FALSE;
+ ibool comp = page_is_comp(page);
/* Check first that the record heap and the directory do not
overlap. */
@@ -1404,13 +1518,13 @@ page_simple_validate(
goto func_exit;
}
- if (rec_get_n_owned(rec) != 0) {
+ if (rec_get_n_owned(rec, comp) != 0) {
/* This is a record pointed to by a dir slot */
- if (rec_get_n_owned(rec) != own_count) {
+ if (rec_get_n_owned(rec, comp) != own_count) {
fprintf(stderr,
"InnoDB: Wrong owned count %lu, %lu, rec %lu\n",
- (ulong) rec_get_n_owned(rec),
+ (ulong) rec_get_n_owned(rec, comp),
(ulong) own_count,
(ulong)(rec - page));
@@ -1438,11 +1552,11 @@ page_simple_validate(
break;
}
- if (rec_get_next_offs(rec) < FIL_PAGE_DATA
- || rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
+ if (rec_get_next_offs(rec, comp) < FIL_PAGE_DATA
+ || rec_get_next_offs(rec, comp) >= UNIV_PAGE_SIZE) {
fprintf(stderr,
"InnoDB: Next record offset nonsensical %lu for rec %lu\n",
- (ulong) rec_get_next_offs(rec),
+ (ulong) rec_get_next_offs(rec, comp),
(ulong)(rec - page));
goto func_exit;
@@ -1461,7 +1575,7 @@ page_simple_validate(
own_count++;
}
- if (rec_get_n_owned(rec) == 0) {
+ if (rec_get_n_owned(rec, comp) == 0) {
fprintf(stderr, "InnoDB: n owned is zero in a supremum rec\n");
goto func_exit;
@@ -1514,10 +1628,10 @@ page_simple_validate(
rec = page_rec_get_next(rec);
}
- if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
+ if (page_dir_get_n_heap(page) != count + 1) {
fprintf(stderr, "InnoDB: N heap is wrong %lu, %lu\n",
- (ulong) page_header_get_field(page, PAGE_N_HEAP),
+ (ulong) page_dir_get_n_heap(page),
(ulong) (count + 1));
goto func_exit;
@@ -1549,12 +1663,19 @@ page_validate(
ulint slot_no;
ulint data_size;
rec_t* rec;
- rec_t* old_rec = NULL;
+ rec_t* old_rec = NULL;
ulint offs;
ulint n_slots;
- ibool ret = FALSE;
+ ibool ret = FALSE;
ulint i;
-
+ ibool comp = page_is_comp(page);
+ ulint* offsets = NULL;
+ ulint* old_offsets = NULL;
+
+ if (comp != index->table->comp) {
+ fputs("InnoDB: 'compact format' flag mismatch\n", stderr);
+ goto func_exit2;
+ }
if (!page_simple_validate(page)) {
goto func_exit2;
}
@@ -1599,22 +1720,33 @@ page_validate(
for (;;) {
rec = cur.rec;
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
- if (!page_rec_validate(rec)) {
+ if (comp && page_rec_is_user_rec(rec)
+ && rec_get_node_ptr_flag(rec)
+ == !btr_page_get_level_low(page)) {
+ fputs("InnoDB: node_ptr flag mismatch\n", stderr);
+ goto func_exit;
+ }
+
+ if (!page_rec_validate(rec, offsets)) {
goto func_exit;
}
/* Check that the records are in the ascending order */
if ((count >= 2) && (!page_cur_is_after_last(&cur))) {
- if (!(1 == cmp_rec_rec(rec, old_rec, index))) {
+ if (!(1 == cmp_rec_rec(rec, old_rec,
+ offsets, old_offsets,
+ ULINT_UNDEFINED, index))) {
fprintf(stderr,
"InnoDB: Records in wrong order on page %lu",
(ulong) buf_frame_get_page_no(page));
dict_index_name_print(stderr, NULL, index);
fputs("\nInnoDB: previous record ", stderr);
- rec_print(stderr, old_rec);
+ rec_print(stderr, old_rec, old_offsets);
fputs("\nInnoDB: record ", stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, offsets);
putc('\n', stderr);
goto func_exit;
@@ -1624,12 +1756,12 @@ page_validate(
if ((rec != page_get_supremum_rec(page))
&& (rec != page_get_infimum_rec(page))) {
- data_size += rec_get_size(rec);
+ data_size += rec_offs_size(offsets);
}
- offs = rec_get_start(rec) - page;
+ offs = rec_get_start(rec, offsets) - page;
- for (i = 0; i < rec_get_size(rec); i++) {
+ for (i = 0; i < rec_offs_size(offsets); i++) {
if (!buf[offs + i] == 0) {
/* No other record may overlap this */
@@ -1641,12 +1773,12 @@ page_validate(
buf[offs + i] = 1;
}
- if (rec_get_n_owned(rec) != 0) {
+ if (rec_get_n_owned(rec, comp) != 0) {
/* This is a record pointed to by a dir slot */
- if (rec_get_n_owned(rec) != own_count) {
+ if (rec_get_n_owned(rec, comp) != own_count) {
fprintf(stderr,
"InnoDB: Wrong owned count %lu, %lu\n",
- (ulong) rec_get_n_owned(rec),
+ (ulong) rec_get_n_owned(rec, comp),
(ulong) own_count);
goto func_exit;
}
@@ -1671,11 +1803,11 @@ page_validate(
break;
}
- if (rec_get_next_offs(rec) < FIL_PAGE_DATA
- || rec_get_next_offs(rec) >= UNIV_PAGE_SIZE) {
+ if (rec_get_next_offs(rec, comp) < FIL_PAGE_DATA
+ || rec_get_next_offs(rec, comp) >= UNIV_PAGE_SIZE) {
fprintf(stderr,
"InnoDB: Next record offset wrong %lu\n",
- (ulong) rec_get_next_offs(rec));
+ (ulong) rec_get_next_offs(rec, comp));
goto func_exit;
}
@@ -1683,9 +1815,15 @@ page_validate(
page_cur_move_to_next(&cur);
own_count++;
old_rec = rec;
+ /* set old_offsets to offsets; recycle offsets */
+ {
+ ulint* offs = old_offsets;
+ old_offsets = offsets;
+ offsets = offs;
+ }
}
- if (rec_get_n_owned(rec) == 0) {
+ if (rec_get_n_owned(rec, comp) == 0) {
fputs("InnoDB: n owned is zero\n", stderr);
goto func_exit;
}
@@ -1714,15 +1852,17 @@ page_validate(
rec = page_header_get_ptr(page, PAGE_FREE);
while (rec != NULL) {
- if (!page_rec_validate(rec)) {
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ if (!page_rec_validate(rec, offsets)) {
goto func_exit;
}
count++;
- offs = rec_get_start(rec) - page;
+ offs = rec_get_start(rec, offsets) - page;
- for (i = 0; i < rec_get_size(rec); i++) {
+ for (i = 0; i < rec_offs_size(offsets); i++) {
if (buf[offs + i] != 0) {
fputs(
@@ -1736,9 +1876,9 @@ page_validate(
rec = page_rec_get_next(rec);
}
- if (page_header_get_field(page, PAGE_N_HEAP) != count + 1) {
+ if (page_dir_get_n_heap(page) != count + 1) {
fprintf(stderr, "InnoDB: N heap is wrong %lu %lu\n",
- (ulong) page_header_get_field(page, PAGE_N_HEAP),
+ (ulong) page_dir_get_n_heap(page),
(ulong) count + 1);
goto func_exit;
}
@@ -1775,7 +1915,7 @@ page_find_rec_with_heap_no(
page_cur_set_before_first(page, &cur);
for (;;) {
- if (rec_get_heap_no(cur.rec) == heap_no) {
+ if (rec_get_heap_no(cur.rec, page_is_comp(page)) == heap_no) {
return(cur.rec);
}
diff --git a/innobase/pars/pars0pars.c b/innobase/pars/pars0pars.c
index 846cb060a7e..c62184abd85 100644
--- a/innobase/pars/pars0pars.c
+++ b/innobase/pars/pars0pars.c
@@ -259,9 +259,13 @@ pars_resolve_func_data_type(
dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
DATA_ENGLISH, 0, 0);
} else if (func == PARS_TO_BINARY_TOKEN) {
- ut_a(dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT);
- dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
+ if (dtype_get_mtype(que_node_get_data_type(arg)) == DATA_INT) {
+ dtype_set(que_node_get_data_type(node), DATA_VARCHAR,
DATA_ENGLISH, 0, 0);
+ } else {
+ dtype_set(que_node_get_data_type(node), DATA_BINARY,
+ 0, 0, 0);
+ }
} else if (func == PARS_TO_NUMBER_TOKEN) {
ut_a(dtype_get_mtype(que_node_get_data_type(arg))
== DATA_VARCHAR);
@@ -1510,8 +1514,11 @@ pars_create_table(
n_cols = que_node_list_get_len(column_defs);
- table = dict_mem_table_create(table_sym->name, 0, n_cols);
-
+ /* As the InnoDB SQL parser is for internal use only,
+ for creating some system tables, this function will only
+ create tables in the old (not compact) record format. */
+ table = dict_mem_table_create(table_sym->name, 0, n_cols, FALSE);
+
if (not_fit_in_memory != NULL) {
table->does_not_fit_in_memory = TRUE;
}
diff --git a/innobase/rem/rem0cmp.c b/innobase/rem/rem0cmp.c
index 041fb7914e2..974fc7a24d0 100644
--- a/innobase/rem/rem0cmp.c
+++ b/innobase/rem/rem0cmp.c
@@ -51,6 +51,7 @@ cmp_debug_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields);/* in/out: number of already
completely matched fields; when function
returns, contains the value for current
@@ -426,6 +427,7 @@ cmp_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when function returns,
contains the value for current comparison */
@@ -455,12 +457,13 @@ cmp_dtuple_rec_with_match(
ut_ad(dtuple && rec && matched_fields && matched_bytes);
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
cur_field = *matched_fields;
cur_bytes = *matched_bytes;
ut_ad(cur_field <= dtuple_get_n_fields_cmp(dtuple));
- ut_ad(cur_field <= rec_get_n_fields(rec));
+ ut_ad(cur_field <= rec_offs_n_fields(offsets));
/* Match fields in a loop; stop if we run out of fields in dtuple
or find an externally stored field */
@@ -472,7 +475,8 @@ cmp_dtuple_rec_with_match(
dtuple_f_len = dfield_get_len(dtuple_field);
- rec_b_ptr = rec_get_nth_field(rec, cur_field, &rec_f_len);
+ rec_b_ptr = rec_get_nth_field(rec, offsets,
+ cur_field, &rec_f_len);
/* If we have matched yet 0 bytes, it may be that one or
both the fields are SQL null, or the record or dtuple may be
@@ -482,7 +486,8 @@ cmp_dtuple_rec_with_match(
if (cur_bytes == 0) {
if (cur_field == 0) {
- if (rec_get_info_bits(rec)
+ if (rec_get_info_bits(rec,
+ rec_offs_comp(offsets))
& REC_INFO_MIN_REC_FLAG) {
if (dtuple_get_info_bits(dtuple)
@@ -504,7 +509,7 @@ cmp_dtuple_rec_with_match(
}
}
- if (rec_get_nth_field_extern_bit(rec, cur_field)) {
+ if (rec_offs_nth_extern(offsets, cur_field)) {
/* We do not compare to an externally
stored field */
@@ -635,7 +640,7 @@ cmp_dtuple_rec_with_match(
up to the common fields */
order_resolved:
ut_ad((ret >= - 1) && (ret <= 1));
- ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec,
+ ut_ad(ret == cmp_debug_dtuple_rec_with_match(dtuple, rec, offsets,
matched_fields));
ut_ad(*matched_fields == cur_field); /* In the debug version, the
above cmp_debug_... sets
@@ -656,13 +661,15 @@ cmp_dtuple_rec(
less than rec, respectively; see the comments
for cmp_dtuple_rec_with_match */
dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec) /* in: physical record */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint matched_fields = 0;
ulint matched_bytes = 0;
- return(cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
- &matched_bytes));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+ return(cmp_dtuple_rec_with_match(dtuple, rec, offsets,
+ &matched_fields, &matched_bytes));
}
/******************************************************************
@@ -673,22 +680,24 @@ ibool
cmp_dtuple_is_prefix_of_rec(
/*========================*/
/* out: TRUE if prefix */
- dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec) /* in: physical record */
+ dtuple_t* dtuple, /* in: data tuple */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
ulint n_fields;
ulint matched_fields = 0;
ulint matched_bytes = 0;
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
n_fields = dtuple_get_n_fields(dtuple);
- if (n_fields > rec_get_n_fields(rec)) {
+ if (n_fields > rec_offs_n_fields(offsets)) {
return(FALSE);
}
- cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
- &matched_bytes);
+ cmp_dtuple_rec_with_match(dtuple, rec, offsets,
+ &matched_fields, &matched_bytes);
if (matched_fields == n_fields) {
return(TRUE);
@@ -703,42 +712,6 @@ cmp_dtuple_is_prefix_of_rec(
return(FALSE);
}
-/******************************************************************
-Compares a prefix of a data tuple to a prefix of a physical record for
-equality. If there are less fields in rec than parameter n_fields, FALSE
-is returned. NOTE that n_fields_cmp of dtuple does not affect this
-comparison. */
-
-ibool
-cmp_dtuple_rec_prefix_equal(
-/*========================*/
- /* out: TRUE if equal */
- dtuple_t* dtuple, /* in: data tuple */
- rec_t* rec, /* in: physical record */
- ulint n_fields) /* in: number of fields which should be
- compared; must not exceed the number of
- fields in dtuple */
-{
- ulint matched_fields = 0;
- ulint matched_bytes = 0;
-
- ut_ad(n_fields <= dtuple_get_n_fields(dtuple));
-
- if (rec_get_n_fields(rec) < n_fields) {
-
- return(FALSE);
- }
-
- cmp_dtuple_rec_with_match(dtuple, rec, &matched_fields,
- &matched_bytes);
- if (matched_fields >= n_fields) {
-
- return(TRUE);
- }
-
- return(FALSE);
-}
-
/*****************************************************************
This function is used to compare two physical records. Only the common
first fields are compared, and if an externally stored field is
@@ -752,7 +725,13 @@ cmp_rec_rec_with_match(
first fields are compared */
rec_t* rec1, /* in: physical record */
rec_t* rec2, /* in: physical record */
+ const ulint* offsets1,/* in: rec_get_offsets(rec1, index) */
+ const ulint* offsets2,/* in: rec_get_offsets(rec2, index) */
dict_index_t* index, /* in: data dictionary index */
+ ulint n, /* in: number of fields to compare,
+ or ULINT_UNDEFINED if both records
+ contain all fields, and all fields
+ should be compared */
ulint* matched_fields, /* in/out: number of already completely
matched fields; when the function returns,
contains the value the for current
@@ -778,17 +757,27 @@ cmp_rec_rec_with_match(
ulint cur_bytes; /* number of already matched bytes in current
field */
int ret = 3333; /* return value */
+ ibool comp;
ut_ad(rec1 && rec2 && index);
-
- rec1_n_fields = rec_get_n_fields(rec1);
- rec2_n_fields = rec_get_n_fields(rec2);
+ ut_ad(rec_offs_validate(rec1, index, offsets1));
+ ut_ad(rec_offs_validate(rec2, index, offsets2));
+ ut_ad(rec_offs_comp(offsets1) == rec_offs_comp(offsets2));
+
+ comp = rec_offs_comp(offsets1);
+ if (n == ULINT_UNDEFINED) {
+ rec1_n_fields = rec_offs_n_fields(offsets1);
+ rec2_n_fields = rec_offs_n_fields(offsets2);
+ } else {
+ ut_ad(n <= rec_offs_n_fields(offsets1));
+ ut_ad(n <= rec_offs_n_fields(offsets2));
+ rec1_n_fields = rec2_n_fields = n;
+ }
cur_field = *matched_fields;
cur_bytes = *matched_bytes;
- /* Match fields in a loop; stop if we run out of fields in either
- record */
+ /* Match fields in a loop */
while ((cur_field < rec1_n_fields) && (cur_field < rec2_n_fields)) {
@@ -800,17 +789,19 @@ cmp_rec_rec_with_match(
dict_index_get_nth_field(index, cur_field)));
}
- rec1_b_ptr = rec_get_nth_field(rec1, cur_field, &rec1_f_len);
- rec2_b_ptr = rec_get_nth_field(rec2, cur_field, &rec2_f_len);
-
+ rec1_b_ptr = rec_get_nth_field(rec1, offsets1,
+ cur_field, &rec1_f_len);
+ rec2_b_ptr = rec_get_nth_field(rec2, offsets2,
+ cur_field, &rec2_f_len);
+
if (cur_bytes == 0) {
if (cur_field == 0) {
/* Test if rec is the predefined minimum
record */
- if (rec_get_info_bits(rec1)
+ if (rec_get_info_bits(rec1, comp)
& REC_INFO_MIN_REC_FLAG) {
- if (rec_get_info_bits(rec2)
+ if (rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG) {
ret = 0;
} else {
@@ -819,7 +810,7 @@ cmp_rec_rec_with_match(
goto order_resolved;
- } else if (rec_get_info_bits(rec2)
+ } else if (rec_get_info_bits(rec2, comp)
& REC_INFO_MIN_REC_FLAG) {
ret = 1;
@@ -828,8 +819,8 @@ cmp_rec_rec_with_match(
}
}
- if (rec_get_nth_field_extern_bit(rec1, cur_field)
- || rec_get_nth_field_extern_bit(rec2, cur_field)) {
+ if (rec_offs_nth_extern(offsets1, cur_field)
+ || rec_offs_nth_extern(offsets2, cur_field)) {
/* We do not compare to an externally
stored field */
@@ -984,6 +975,7 @@ cmp_debug_dtuple_rec_with_match(
dtuple in some of the common fields, or which
has an equal number or more fields than
dtuple */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
ulint* matched_fields) /* in/out: number of already
completely matched fields; when function
returns, contains the value for current
@@ -1003,14 +995,16 @@ cmp_debug_dtuple_rec_with_match(
ut_ad(dtuple && rec && matched_fields);
ut_ad(dtuple_check_typed(dtuple));
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_ad(*matched_fields <= dtuple_get_n_fields_cmp(dtuple));
- ut_ad(*matched_fields <= rec_get_n_fields(rec));
+ ut_ad(*matched_fields <= rec_offs_n_fields(offsets));
cur_field = *matched_fields;
if (cur_field == 0) {
- if (rec_get_info_bits(rec) & REC_INFO_MIN_REC_FLAG) {
+ if (rec_get_info_bits(rec, rec_offs_comp(offsets))
+ & REC_INFO_MIN_REC_FLAG) {
if (dtuple_get_info_bits(dtuple)
& REC_INFO_MIN_REC_FLAG) {
@@ -1040,9 +1034,10 @@ cmp_debug_dtuple_rec_with_match(
dtuple_f_data = dfield_get_data(dtuple_field);
dtuple_f_len = dfield_get_len(dtuple_field);
- rec_f_data = rec_get_nth_field(rec, cur_field, &rec_f_len);
+ rec_f_data = rec_get_nth_field(rec, offsets,
+ cur_field, &rec_f_len);
- if (rec_get_nth_field_extern_bit(rec, cur_field)) {
+ if (rec_offs_nth_extern(offsets, cur_field)) {
/* We do not compare to an externally stored field */
ret = 0;
diff --git a/innobase/rem/rem0rec.c b/innobase/rem/rem0rec.c
index 1db89241dff..e4fa213480f 100644
--- a/innobase/rem/rem0rec.c
+++ b/innobase/rem/rem0rec.c
@@ -15,8 +15,8 @@ Created 5/30/1994 Heikki Tuuri
#include "mtr0mtr.h"
#include "mtr0log.h"
-/* PHYSICAL RECORD
- ===============
+/* PHYSICAL RECORD (OLD STYLE)
+ ===========================
The physical record, which is the data type of all the records
found in index pages of the database, has the following format
@@ -39,7 +39,7 @@ represented on a higher text line):
| 10 bits giving the number of fields in this record |
| 1 bit which is set to 1 if the offsets above are given in
one byte format, 0 if in two byte format |
-| two bytes giving the pointer to the next record in the page |
+| two bytes giving an absolute pointer to the next record in the page |
ORIGIN of the record
| first field of data |
...
@@ -55,9 +55,50 @@ The offsets of the data fields are given as one-byte
(if there are less than 127 bytes of data in the record)
or two-byte unsigned integers. The most significant bit
is not part of the offset, instead it indicates the SQL-null
-if the bit is set to 1.
+if the bit is set to 1. */
-CANONICAL COORDINATES. A record can be seen as a single
+/* PHYSICAL RECORD (NEW STYLE)
+ ===========================
+
+The physical record, which is the data type of all the records
+found in index pages of the database, has the following format
+(lower addresses and more significant bits inside a byte are below
+represented on a higher text line):
+
+| length of the last non-null variable-length field of data:
+ if the maximum length is 255, one byte; otherwise,
+ 0xxxxxxx (one byte, length=0..127), or 1exxxxxxxxxxxxxx (two bytes,
+ length=128..16383, extern storage flag) |
+...
+| length of first variable-length field of data |
+| SQL-null flags (1 bit per nullable field), padded to full bytes |
+| 4 bits used to delete mark a record, and mark a predefined
+ minimum record in alphabetical order |
+| 4 bits giving the number of records owned by this record
+ (this term is explained in page0page.h) |
+| 13 bits giving the order number of this record in the
+ heap of the index page |
+| 3 bits record type: 000=conventional, 001=node pointer (inside B-tree),
+ 010=infimum, 011=supremum, 1xx=reserved |
+| two bytes giving a relative pointer to the next record in the page |
+ORIGIN of the record
+| first field of data |
+...
+| last field of data |
+
+The origin of the record is the start address of the first field
+of data. The offsets are given relative to the origin.
+The offsets of the data fields are stored in an inverted
+order because then the offset of the first fields are near the
+origin, giving maybe a better processor cache hit rate in searches.
+
+The offsets of the data fields are given as one-byte
+(if there are less than 127 bytes of data in the record)
+or two-byte unsigned integers. The most significant bit
+is not part of the offset, instead it indicates the SQL-null
+if the bit is set to 1. */
+
+/* CANONICAL COORDINATES. A record can be seen as a single
string of 'characters' in the following way: catenate the bytes
in each field, in the order of fields. An SQL-null field
is taken to be an empty sequence of bytes. Then after
@@ -86,13 +127,291 @@ the corresponding canonical strings have the same property. */
ulint rec_dummy; /* this is used to fool compiler in
rec_validate */
+/*******************************************************************
+Validates the consistency of an old-style physical record. */
+static
+ibool
+rec_validate_old(
+/*=============*/
+ /* out: TRUE if ok */
+ rec_t* rec); /* in: physical record */
+
+/**********************************************************
+The following function determines the offsets to each field
+in the record. The offsets are written to an array of
+ulint[n+2], with [0] being the number of fields (n), [1] being the
+extra size (if REC_OFFS_COMPACT is set, the record is in the new
+format), and [2]..[n+1] being the offsets past the end of
+fields 0..n, or to the beginning of fields 1..n+1. When the
+high-order bit of the offset at [n+1] is set (REC_OFFS_SQL_NULL),
+the field n is NULL. When the second high-order bit of the offset
+at [n+1] is set (REC_OFFS_EXTERNAL), the field n is being stored
+externally. */
+static
+void
+rec_init_offsets(
+/*=============*/
+ /* out: the offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* offsets)/* in:/out: ulint[n+2];
+ n=rec_offs_n_fields(offsets) */
+{
+ ulint n_fields = rec_offs_n_fields(offsets);
+ ulint i = 0;
+ ulint offs;
+
+ rec_offs_make_valid(rec, index, offsets);
+
+ if (index->table->comp) {
+ const byte* nulls;
+ const byte* lens;
+ dict_field_t* field;
+ dtype_t* type;
+ ulint null_mask;
+ ulint status = rec_get_status(rec);
+ ulint n_node_ptr_field = ULINT_UNDEFINED;
+
+ switch (status) {
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ /* the field is 8 bytes long */
+ rec_offs_base(offsets)[0] =
+ REC_N_NEW_EXTRA_BYTES | REC_OFFS_COMPACT;
+ rec_offs_base(offsets)[1] = 8;
+ return;
+ case REC_STATUS_NODE_PTR:
+ n_node_ptr_field =
+ dict_index_get_n_unique_in_tree(index);
+ break;
+ case REC_STATUS_ORDINARY:
+ break;
+ }
+
+ nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+ lens = nulls - (index->n_nullable + 7) / 8;
+ offs = 0;
+ null_mask = 1;
+
+ /* read the lengths of fields 0..n */
+ for (; i < n_fields; i++) {
+ ibool is_null = FALSE, is_external = FALSE;
+ ulint len;
+ if (i == n_node_ptr_field) {
+ len = 4;
+ goto resolved;
+ }
+
+ field = dict_index_get_nth_field(index, i);
+ type = dict_col_get_type(dict_field_get_col(field));
+ if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+ /* nullable field => read the null flag */
+ is_null = (*nulls & null_mask) != 0;
+ null_mask <<= 1;
+ if (null_mask == 0x100) {
+ nulls--;
+ null_mask = 1;
+ }
+ }
+
+ if (is_null) {
+ /* No length is stored for NULL fields. */
+ len = 0;
+ } else if (!field->fixed_len) {
+ /* Variable-length field: read the length */
+ len = *lens--;
+ if (dtype_get_len(type) > 255
+ || dtype_get_mtype(type) == DATA_BLOB) {
+ if (len & 0x80) {
+ /* 1exxxxxxx xxxxxxxx */
+ is_external = !!(len & 0x40);
+ len &= 0x3f;
+ len <<= 8;
+ len |= *lens--;
+ }
+ }
+ } else {
+ len = field->fixed_len;
+ }
+ resolved:
+ offs += len;
+ len = offs;
+ if (is_external) {
+ len |= REC_OFFS_EXTERNAL;
+ }
+ if (is_null) {
+ len |= REC_OFFS_SQL_NULL;
+ }
+ rec_offs_base(offsets)[i + 1] = len;
+ }
+
+ *rec_offs_base(offsets) =
+ (rec - (lens + 1)) | REC_OFFS_COMPACT;
+ } else {
+ /* Old-style record: determine extra size and end offsets */
+ offs = REC_N_OLD_EXTRA_BYTES;
+ if (rec_get_1byte_offs_flag(rec)) {
+ offs += n_fields;
+ *rec_offs_base(offsets) = offs;
+ /* Determine offsets to fields */
+ for (; i < n_fields; i++) {
+ offs = rec_1_get_field_end_info(rec, i);
+ if (offs & REC_1BYTE_SQL_NULL_MASK) {
+ offs &= ~REC_1BYTE_SQL_NULL_MASK;
+ offs |= REC_OFFS_SQL_NULL;
+ }
+ rec_offs_base(offsets)[1 + i] = offs;
+ }
+ } else {
+ offs += 2 * n_fields;
+ *rec_offs_base(offsets) = offs;
+ /* Determine offsets to fields */
+ for (; i < n_fields; i++) {
+ offs = rec_2_get_field_end_info(rec, i);
+ if (offs & REC_2BYTE_SQL_NULL_MASK) {
+ offs &= ~REC_2BYTE_SQL_NULL_MASK;
+ offs |= REC_OFFS_SQL_NULL;
+ }
+ if (offs & REC_2BYTE_EXTERN_MASK) {
+ offs &= ~REC_2BYTE_EXTERN_MASK;
+ offs |= REC_OFFS_EXTERNAL;
+ }
+ rec_offs_base(offsets)[1 + i] = offs;
+ }
+ }
+ }
+}
+
+/**********************************************************
+The following function determines the offsets to each field
+in the record. The offsets are returned in an array of
+ulint, with [0] being the number of fields (n), [1] being the
+extra size (if REC_OFFS_COMPACT is set, the record is in the new
+format), and [2]..[n+1] being the offsets past the end of
+fields 0..n, or to the beginning of fields 1..n+1. When the
+high-order bit of the offset at [n+1] is set (REC_OFFS_SQL_NULL),
+the field n is NULL. When the second high-order bit of the offset
+at [n+1] is set (REC_OFFS_EXTERNAL), the field n is being stored
+externally. */
+
+ulint*
+rec_get_offsets(
+/*============*/
+ /* out: the offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_fields,/* in: maximum number of initialized fields
+ (ULINT_UNDEFINED if all fields) */
+ mem_heap_t* heap) /* in: memory heap */
+{
+ ulint* offsets;
+ ulint n;
+
+ ut_ad(rec);
+ ut_ad(index);
+ ut_ad(heap);
+
+ if (index->table->comp) {
+ switch (rec_get_status(rec)) {
+ case REC_STATUS_ORDINARY:
+ n = dict_index_get_n_fields(index);
+ break;
+ case REC_STATUS_NODE_PTR:
+ n = dict_index_get_n_unique_in_tree(index) + 1;
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ /* infimum or supremum record */
+ n = 1;
+ break;
+ default:
+ ut_error;
+ return(NULL);
+ }
+ } else {
+ n = rec_get_n_fields_old(rec);
+ }
+
+ if (n_fields < n) {
+ n = n_fields;
+ }
+
+ offsets = mem_heap_alloc(heap,
+ (n + (1 + REC_OFFS_HEADER_SIZE)) * sizeof(ulint));
+
+ offsets[0] = n;
+
+ rec_init_offsets(rec, index, offsets);
+ return(offsets);
+}
+
+/**********************************************************
+The following function determines the offsets to each field
+in the record. It differs from rec_get_offsets() by trying to
+reuse a previously returned array. */
+
+ulint*
+rec_reget_offsets(
+/*==============*/
+ /* out: the new offsets */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint* offsets,/* in: array of offsets
+ from rec_get_offsets()
+ or rec_reget_offsets(), or NULL */
+ ulint n_fields,/* in: maximum number of initialized fields
+ (ULINT_UNDEFINED if all fields) */
+ mem_heap_t* heap) /* in: memory heap */
+{
+ ulint n;
+
+ ut_ad(rec);
+ ut_ad(index);
+ ut_ad(heap);
+
+ if (index->table->comp) {
+ switch (rec_get_status(rec)) {
+ case REC_STATUS_ORDINARY:
+ n = dict_index_get_n_fields(index);
+ break;
+ case REC_STATUS_NODE_PTR:
+ n = dict_index_get_n_unique_in_tree(index) + 1;
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ /* infimum or supremum record */
+ n = 1;
+ break;
+ default:
+ ut_error;
+ return(NULL);
+ }
+ } else {
+ n = rec_get_n_fields_old(rec);
+ }
+
+ if (n_fields < n) {
+ n = n_fields;
+ }
+
+ if (!offsets || rec_offs_n_fields(offsets) < n) {
+ offsets = mem_heap_alloc(heap,
+ (n + (1 + REC_OFFS_HEADER_SIZE)) * sizeof(ulint));
+ }
+
+ offsets[0] = n;
+
+ rec_init_offsets(rec, index, offsets);
+ return(offsets);
+}
+
/****************************************************************
-The following function is used to get a pointer to the nth data field in a
-record. */
+The following function is used to get a pointer to the nth
+data field in an old-style record. */
byte*
-rec_get_nth_field(
-/*==============*/
+rec_get_nth_field_old(
+/*==================*/
/* out: pointer to the field */
rec_t* rec, /* in: record */
ulint n, /* in: index of the field */
@@ -103,9 +422,9 @@ rec_get_nth_field(
ulint next_os;
ut_ad(rec && len);
- ut_ad(n < rec_get_n_fields(rec));
+ ut_ad(n < rec_get_n_fields_old(rec));
- if (n > 1024) {
+ if (n > REC_MAX_N_FIELDS) {
fprintf(stderr, "Error: trying to access field %lu in rec\n",
(ulong) n);
ut_error;
@@ -150,8 +469,78 @@ rec_get_nth_field(
return(rec + os);
}
+/**************************************************************
+The following function returns the size of a data tuple when converted to
+a new-style physical record. */
+
+ulint
+rec_get_converted_size_new(
+/*=======================*/
+ /* out: size */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple) /* in: data tuple */
+{
+ ulint size = REC_N_NEW_EXTRA_BYTES
+ + (index->n_nullable + 7) / 8;
+ dict_field_t* field;
+ dtype_t* type;
+ ulint i;
+ ulint n_fields;
+ ut_ad(index && dtuple);
+ ut_ad(index->table->comp);
+
+ switch (dtuple_get_info_bits(dtuple) & REC_NEW_STATUS_MASK) {
+ case REC_STATUS_ORDINARY:
+ n_fields = dict_index_get_n_fields(index);
+ ut_ad(n_fields == dtuple_get_n_fields(dtuple));
+ break;
+ case REC_STATUS_NODE_PTR:
+ n_fields = dict_index_get_n_unique_in_tree(index);
+ ut_ad(n_fields + 1 == dtuple_get_n_fields(dtuple));
+ ut_ad(dtuple_get_nth_field(dtuple, n_fields)->len == 4);
+ size += 4; /* child page number */
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ /* infimum or supremum record, 8 bytes */
+ return(size + 8); /* no extra data needed */
+ default:
+ ut_a(0);
+ return(ULINT_UNDEFINED);
+ }
+
+ /* read the lengths of fields 0..n */
+ for (i = 0; i < n_fields; i++) {
+ ulint len = dtuple_get_nth_field(dtuple, i)->len;
+ field = dict_index_get_nth_field(index, i);
+ type = dict_col_get_type(dict_field_get_col(field));
+ ut_ad(len != UNIV_SQL_NULL ||
+ !(dtype_get_prtype(type) & DATA_NOT_NULL));
+
+ if (len == UNIV_SQL_NULL) {
+ /* No length is stored for NULL fields. */
+ continue;
+ }
+
+ ut_ad(len <= dtype_get_len(type)
+ || dtype_get_mtype(type) == DATA_BLOB);
+ ut_ad(!field->fixed_len || len == field->fixed_len);
+
+ if (field->fixed_len) {
+ } else if (len < 128 || (dtype_get_len(type) < 256
+ && dtype_get_mtype(type) != DATA_BLOB)) {
+ size++;
+ } else {
+ size += 2;
+ }
+ size += len;
+ }
+
+ return(size);
+}
+
/***************************************************************
-Sets the value of the ith field SQL null bit. */
+Sets the value of the ith field SQL null bit of an old-style record. */
void
rec_set_nth_field_null_bit(
@@ -189,12 +578,12 @@ rec_set_nth_field_null_bit(
}
/***************************************************************
-Sets the value of the ith field extern storage bit. */
+Sets the value of the ith field extern storage bit of an old-style record. */
void
-rec_set_nth_field_extern_bit(
-/*=========================*/
- rec_t* rec, /* in: record */
+rec_set_nth_field_extern_bit_old(
+/*=============================*/
+ rec_t* rec, /* in: old-style record */
ulint i, /* in: ith field */
ibool val, /* in: value to set */
mtr_t* mtr) /* in: mtr holding an X-latch to the page where
@@ -204,7 +593,7 @@ rec_set_nth_field_extern_bit(
ulint info;
ut_a(!rec_get_1byte_offs_flag(rec));
- ut_a(i < rec_get_n_fields(rec));
+ ut_a(i < rec_get_n_fields_old(rec));
info = rec_2_get_field_end_info(rec, i);
@@ -215,36 +604,138 @@ rec_set_nth_field_extern_bit(
}
if (mtr) {
- mlog_write_ulint(rec - REC_N_EXTRA_BYTES - 2 * (i + 1), info,
- MLOG_2BYTES, mtr);
+ mlog_write_ulint(rec - REC_N_OLD_EXTRA_BYTES - 2 * (i + 1),
+ info, MLOG_2BYTES, mtr);
} else {
rec_2_set_field_end_info(rec, i, info);
}
}
/***************************************************************
+Sets the value of the ith field extern storage bit of a new-style record. */
+
+void
+rec_set_nth_field_extern_bit_new(
+/*=============================*/
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint ith, /* in: ith field */
+ ibool val, /* in: value to set */
+ mtr_t* mtr) /* in: mtr holding an X-latch to the page
+ where rec is, or NULL; in the NULL case
+ we do not write to log about the change */
+{
+ byte* nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+ byte* lens = nulls - (index->n_nullable + 7) / 8;
+ dict_field_t* field;
+ dtype_t* type;
+ ulint i;
+ ulint n_fields;
+ ulint null_mask = 1;
+ ut_ad(rec && index);
+ ut_ad(index->table->comp);
+ ut_ad(rec_get_status(rec) == REC_STATUS_ORDINARY);
+
+ n_fields = dict_index_get_n_fields(index);
+
+ ut_ad(ith < n_fields);
+
+ /* read the lengths of fields 0..n */
+ for (i = 0; i < n_fields; i++) {
+ ibool is_null;
+ ulint len;
+ field = dict_index_get_nth_field(index, i);
+ type = dict_col_get_type(dict_field_get_col(field));
+ is_null = !(dtype_get_prtype(type) & DATA_NOT_NULL);
+ if (is_null) {
+ /* nullable field => read the null flag */
+ is_null = !!(*nulls & null_mask);
+ null_mask <<= 1;
+ if (null_mask == 0x100)
+ nulls--, null_mask = 1;
+ }
+ if (is_null || field->fixed_len) {
+ /* No length (or extern bit) is stored for
+ fields that are NULL or fixed-length. */
+ ut_ad(i != ith);
+ continue;
+ }
+ len = *lens--;
+ if (dtype_get_len(type) > 255
+ || dtype_get_mtype(type) == DATA_BLOB) {
+ if (len & 0x80) { /* 1exxxxxx: 2-byte length */
+ if (i == ith) {
+ if (!val == !(len & 0x20)) {
+ return; /* no change */
+ }
+ /* toggle the extern bit */
+ len ^= 0x40;
+ if (mtr) {
+ mlog_write_ulint(lens + 1, len,
+ MLOG_1BYTE, mtr);
+ } else {
+ lens[1] = len;
+ }
+ return;
+ }
+ lens--;
+ } else {
+ /* short fields cannot be external */
+ ut_ad(i != ith);
+ }
+ } else {
+ /* short fields cannot be external */
+ ut_ad(i != ith);
+ }
+ }
+}
+
+/***************************************************************
Sets TRUE the extern storage bits of fields mentioned in an array. */
void
rec_set_field_extern_bits(
/*======================*/
- rec_t* rec, /* in: record */
- ulint* vec, /* in: array of field numbers */
- ulint n_fields, /* in: number of fields numbers */
- mtr_t* mtr) /* in: mtr holding an X-latch to the page
- where rec is, or NULL; in the NULL case we
- do not write to log about the change */
+ rec_t* rec, /* in: record */
+ dict_index_t* index, /* in: record descriptor */
+ const ulint* vec, /* in: array of field numbers */
+ ulint n_fields,/* in: number of fields numbers */
+ mtr_t* mtr) /* in: mtr holding an X-latch to the
+ page where rec is, or NULL;
+ in the NULL case we do not write
+ to log about the change */
{
ulint i;
for (i = 0; i < n_fields; i++) {
- rec_set_nth_field_extern_bit(rec, vec[i], TRUE, mtr);
+ rec_set_nth_field_extern_bit(rec, index, vec[i], TRUE, mtr);
}
}
+/**************************************************************
+Returns the total size of a physical record. */
+
+ulint
+rec_get_size(
+/*=========*/
+ /* out: size */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index) /* in: record descriptor */
+{
+ mem_heap_t* heap
+ = mem_heap_create(100);
+ ulint* offsets
+ = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+ ulint size
+ = rec_offs_size(offsets);
+
+ mem_heap_free(heap);
+ return(size);
+}
+
/***************************************************************
-Sets a record field to SQL null. The physical size of the field is not
-changed. */
+Sets an old-style record field to SQL null.
+The physical size of the field is not changed. */
void
rec_set_nth_field_sql_null(
@@ -262,20 +753,20 @@ rec_set_nth_field_sql_null(
}
/*************************************************************
-Builds a physical record out of a data tuple and stores it beginning from
-address destination. */
-
-rec_t*
-rec_convert_dtuple_to_rec_low(
+Builds an old-style physical record out of a data tuple and
+stores it beginning from the start of the given buffer. */
+static
+rec_t*
+rec_convert_dtuple_to_rec_old(
/*==========================*/
- /* out: pointer to the origin of physical
- record */
- byte* destination, /* in: start address of the physical record */
- dtuple_t* dtuple, /* in: data tuple */
- ulint data_size) /* in: data size of dtuple */
+ /* out: pointer to the origin of
+ physical record */
+ byte* buf, /* in: start address of the physical record */
+ dtuple_t* dtuple)/* in: data tuple */
{
dfield_t* field;
ulint n_fields;
+ ulint data_size;
rec_t* rec;
ulint end_offset;
ulint ored_offset;
@@ -283,24 +774,25 @@ rec_convert_dtuple_to_rec_low(
ulint len;
ulint i;
- ut_ad(destination && dtuple);
+ ut_ad(buf && dtuple);
ut_ad(dtuple_validate(dtuple));
ut_ad(dtuple_check_typed(dtuple));
- ut_ad(dtuple_get_data_size(dtuple) == data_size);
n_fields = dtuple_get_n_fields(dtuple);
+ data_size = dtuple_get_data_size(dtuple);
ut_ad(n_fields > 0);
/* Calculate the offset of the origin in the physical record */
- rec = destination + rec_get_converted_extra_size(data_size, n_fields);
+ rec = buf + rec_get_converted_extra_size(data_size, n_fields);
/* Store the number of fields */
- rec_set_n_fields(rec, n_fields);
+ rec_set_n_fields_old(rec, n_fields);
/* Set the info bits of the record */
- rec_set_info_bits(rec, dtuple_get_info_bits(dtuple));
+ rec_set_info_bits(rec, FALSE,
+ dtuple_get_info_bits(dtuple) & REC_INFO_BITS_MASK);
/* Store the data and the offsets */
@@ -361,11 +853,194 @@ rec_convert_dtuple_to_rec_low(
}
}
- ut_ad(rec_validate(rec));
+ return(rec);
+}
+
+/*************************************************************
+Builds a new-style physical record out of a data tuple and
+stores it beginning from the start of the given buffer. */
+static
+rec_t*
+rec_convert_dtuple_to_rec_new(
+/*==========================*/
+ /* out: pointer to the origin
+ of physical record */
+ byte* buf, /* in: start address of the physical record */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple) /* in: data tuple */
+{
+ dfield_t* field;
+ dtype_t* type;
+ rec_t* rec = buf + REC_N_NEW_EXTRA_BYTES;
+ byte* end;
+ byte* nulls;
+ byte* lens;
+ ulint len;
+ ulint i;
+ ulint fixed_len;
+ ulint null_mask = 1;
+ const ulint n_fields = dtuple_get_n_fields(dtuple);
+ const ulint status = dtuple_get_info_bits(dtuple)
+ & REC_NEW_STATUS_MASK;
+ ut_ad(index->table->comp);
+
+ ut_ad(n_fields > 0);
+ switch (status) {
+ case REC_STATUS_ORDINARY:
+ ut_ad(n_fields <= dict_index_get_n_fields(index));
+ break;
+ case REC_STATUS_NODE_PTR:
+ ut_ad(n_fields == dict_index_get_n_unique_in_tree(index) + 1);
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ ut_ad(n_fields == 1);
+ goto init;
+ default:
+ ut_a(0);
+ return(0);
+ }
+
+ /* Calculate the offset of the origin in the physical record.
+ We must loop over all fields to do this. */
+ rec += (index->n_nullable + 7) / 8;
+
+ for (i = 0; i < n_fields; i++) {
+ field = dtuple_get_nth_field(dtuple, i);
+ type = dfield_get_type(field);
+ len = dfield_get_len(field);
+ if (status == REC_STATUS_NODE_PTR && i == n_fields - 1) {
+ fixed_len = 4;
+ ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
+ ut_ad(len == 4);
+ continue;
+ }
+ fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
+
+ if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+ if (len == UNIV_SQL_NULL)
+ continue;
+ }
+ /* only nullable fields can be null */
+ ut_ad(len != UNIV_SQL_NULL);
+ if (fixed_len) {
+ ut_ad(len == fixed_len);
+ } else {
+ ut_ad(len <= dtype_get_len(type)
+ || dtype_get_mtype(type) == DATA_BLOB);
+ rec++;
+ if (len >= 128 && (dtype_get_len(type) >= 256
+ || dtype_get_mtype(type) == DATA_BLOB)) {
+ rec++;
+ }
+ }
+ }
+
+init:
+ end = rec;
+ nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+ lens = nulls - (index->n_nullable + 7) / 8;
+ /* clear the SQL-null flags */
+ memset (lens + 1, 0, nulls - lens);
+
+ /* Set the info bits of the record */
+ rec_set_status(rec, status);
+
+ rec_set_info_bits(rec, TRUE,
+ dtuple_get_info_bits(dtuple) & REC_INFO_BITS_MASK);
+
+ /* Store the data and the offsets */
+
+ for (i = 0; i < n_fields; i++) {
+ field = dtuple_get_nth_field(dtuple, i);
+ type = dfield_get_type(field);
+ len = dfield_get_len(field);
+
+ if (status == REC_STATUS_NODE_PTR && i == n_fields - 1) {
+ fixed_len = 4;
+ ut_ad(dtype_get_prtype(type) & DATA_NOT_NULL);
+ ut_ad(len == 4);
+ goto copy;
+ }
+ fixed_len = dict_index_get_nth_field(index, i)->fixed_len;
+
+ if (!(dtype_get_prtype(type) & DATA_NOT_NULL)) {
+ /* nullable field */
+ ut_ad(index->n_nullable > 0);
+ ut_ad(*nulls < null_mask);
+ /* set the null flag if necessary */
+ if (len == UNIV_SQL_NULL) {
+ *nulls |= null_mask;
+ }
+ null_mask <<= 1;
+ if (null_mask == 0x100)
+ nulls--, null_mask = 1;
+ if (len == UNIV_SQL_NULL)
+ continue;
+ }
+ /* only nullable fields can be null */
+ ut_ad(len != UNIV_SQL_NULL);
+ if (fixed_len) {
+ ut_ad(len == fixed_len);
+ } else {
+ ut_ad(len <= dtype_get_len(type)
+ || dtype_get_mtype(type) == DATA_BLOB);
+ if (len < 128 || (dtype_get_len(type) < 256
+ && dtype_get_mtype(type) != DATA_BLOB)) {
+ *lens-- = len;
+ }
+ else {
+ /* the extern bits will be set later */
+ ut_ad(len < 16384);
+ *lens-- = len >> 8 | 0x80;
+ *lens-- = len;
+ }
+ }
+ copy:
+ memcpy(end, dfield_get_data(field), len);
+ end += len;
+ }
return(rec);
}
+/*************************************************************
+Builds a physical record out of a data tuple and
+stores it beginning from the start of the given buffer. */
+
+rec_t*
+rec_convert_dtuple_to_rec(
+/*======================*/
+ /* out: pointer to the origin
+ of physical record */
+ byte* buf, /* in: start address of the
+ physical record */
+ dict_index_t* index, /* in: record descriptor */
+ dtuple_t* dtuple) /* in: data tuple */
+{
+ rec_t* rec;
+
+ ut_ad(buf && index && dtuple);
+ ut_ad(dtuple_validate(dtuple));
+ ut_ad(dtuple_check_typed(dtuple));
+
+ if (index->table->comp) {
+ rec = rec_convert_dtuple_to_rec_new(buf, index, dtuple);
+ } else {
+ rec = rec_convert_dtuple_to_rec_old(buf, dtuple);
+ }
+
+#ifdef UNIV_DEBUG
+ {
+ mem_heap_t* heap = mem_heap_create(100);
+ ut_ad(rec_validate(rec,
+ rec_get_offsets(rec, index, ULINT_UNDEFINED, heap)));
+ mem_heap_free(heap);
+ }
+#endif /* UNIV_DEBUG */
+ return(rec);
+}
+
/******************************************************************
Copies the first n fields of a physical record to a data tuple. The fields
are copied to the memory heap. */
@@ -375,6 +1050,7 @@ rec_copy_prefix_to_dtuple(
/*======================*/
dtuple_t* tuple, /* in: data tuple */
rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
ulint n_fields, /* in: number of fields to copy */
mem_heap_t* heap) /* in: memory heap */
{
@@ -383,16 +1059,20 @@ rec_copy_prefix_to_dtuple(
ulint len;
byte* buf = NULL;
ulint i;
-
- ut_ad(rec_validate(rec));
+ ulint* offsets;
+
+ offsets = rec_get_offsets(rec, index, n_fields, heap);
+
+ ut_ad(rec_validate(rec, offsets));
ut_ad(dtuple_check_typed(tuple));
- dtuple_set_info_bits(tuple, rec_get_info_bits(rec));
+ dtuple_set_info_bits(tuple,
+ rec_get_info_bits(rec, index->table->comp));
for (i = 0; i < n_fields; i++) {
field = dtuple_get_nth_field(tuple, i);
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
if (len != UNIV_SQL_NULL) {
buf = mem_heap_alloc(heap, len);
@@ -405,32 +1085,28 @@ rec_copy_prefix_to_dtuple(
}
/******************************************************************
-Copies the first n fields of a physical record to a new physical record in
-a buffer. */
-
+Copies the first n fields of an old-style physical record
+to a new physical record in a buffer. */
+static
rec_t*
-rec_copy_prefix_to_buf(
-/*===================*/
+rec_copy_prefix_to_buf_old(
+/*=======================*/
/* out, own: copied record */
rec_t* rec, /* in: physical record */
ulint n_fields, /* in: number of fields to copy */
+ ulint area_end, /* in: end of the prefix data */
byte** buf, /* in/out: memory buffer for the copied prefix,
or NULL */
ulint* buf_size) /* in/out: buffer size */
{
rec_t* copy_rec;
ulint area_start;
- ulint area_end;
ulint prefix_len;
- ut_ad(rec_validate(rec));
-
- area_end = rec_get_field_start_offs(rec, n_fields);
-
if (rec_get_1byte_offs_flag(rec)) {
- area_start = REC_N_EXTRA_BYTES + n_fields;
+ area_start = REC_N_OLD_EXTRA_BYTES + n_fields;
} else {
- area_start = REC_N_EXTRA_BYTES + 2 * n_fields;
+ area_start = REC_N_OLD_EXTRA_BYTES + 2 * n_fields;
}
prefix_len = area_start + area_end;
@@ -448,17 +1124,114 @@ rec_copy_prefix_to_buf(
copy_rec = *buf + area_start;
- rec_set_n_fields(copy_rec, n_fields);
+ rec_set_n_fields_old(copy_rec, n_fields);
return(copy_rec);
}
-/*******************************************************************
-Validates the consistency of a physical record. */
+/******************************************************************
+Copies the first n fields of a physical record to a new physical record in
+a buffer. */
+
+rec_t*
+rec_copy_prefix_to_buf(
+/*===================*/
+ /* out, own: copied record */
+ rec_t* rec, /* in: physical record */
+ dict_index_t* index, /* in: record descriptor */
+ ulint n_fields, /* in: number of fields to copy */
+ byte** buf, /* in/out: memory buffer
+ for the copied prefix, or NULL */
+ ulint* buf_size) /* in/out: buffer size */
+{
+ byte* nulls = rec - (REC_N_NEW_EXTRA_BYTES + 1);
+ byte* lens = nulls - (index->n_nullable + 7) / 8;
+ dict_field_t* field;
+ dtype_t* type;
+ ulint i;
+ ulint prefix_len = 0;
+ ibool is_null;
+ ulint null_mask = 1;
+ ulint status;
+
+ if (!index->table->comp) {
+ ut_ad(rec_validate_old(rec));
+ return(rec_copy_prefix_to_buf_old(rec, n_fields,
+ rec_get_field_start_offs(rec, n_fields),
+ buf, buf_size));
+ }
+
+ status = rec_get_status(rec);
+
+ switch (status) {
+ case REC_STATUS_ORDINARY:
+ ut_ad(n_fields <= dict_index_get_n_fields(index));
+ break;
+ case REC_STATUS_NODE_PTR:
+ /* it doesn't make sense to copy the child page number field */
+ ut_ad(n_fields <= dict_index_get_n_unique_in_tree(index));
+ break;
+ case REC_STATUS_INFIMUM:
+ case REC_STATUS_SUPREMUM:
+ /* infimum or supremum record: no sense to copy anything */
+ default:
+ ut_a(0);
+ return(NULL);
+ }
+ /* read the lengths of fields 0..n */
+ for (i = 0; i < n_fields; i++) {
+ field = dict_index_get_nth_field(index, i);
+ type = dict_col_get_type(dict_field_get_col(field));
+ is_null = !(dtype_get_prtype(type) & DATA_NOT_NULL);
+ if (is_null) {
+ /* nullable field => read the null flag */
+ is_null = !!(*nulls & null_mask);
+ null_mask <<= 1;
+ if (null_mask == 0x100)
+ nulls--, null_mask = 1;
+ }
+
+ if (is_null) {
+ } else if (field->fixed_len) {
+ prefix_len += field->fixed_len;
+ } else {
+ ulint len = *lens--;
+ if (dtype_get_len(type) > 255
+ || dtype_get_mtype(type) == DATA_BLOB) {
+ if (len & 0x80) {
+ /* 1exxxxxx */
+ len &= 0x3f;
+ len <<= 8;
+ len |= *lens--;
+ }
+ }
+ prefix_len += len;
+ }
+ }
+
+ prefix_len += rec - (lens + 1);
+
+ if ((*buf == NULL) || (*buf_size < prefix_len)) {
+ if (*buf != NULL) {
+ mem_free(*buf);
+ }
+
+ *buf = mem_alloc(prefix_len);
+ *buf_size = prefix_len;
+ }
+
+ memcpy(*buf, lens + 1, prefix_len);
+
+ return(*buf + (rec - (lens + 1)));
+}
+
+/*******************************************************************
+Validates the consistency of an old-style physical record. */
+static
ibool
-rec_validate(
-/*=========*/
+rec_validate_old(
+/*=============*/
/* out: TRUE if ok */
rec_t* rec) /* in: physical record */
{
@@ -470,7 +1243,7 @@ rec_validate(
ulint i;
ut_a(rec);
- n_fields = rec_get_n_fields(rec);
+ n_fields = rec_get_n_fields_old(rec);
if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) {
fprintf(stderr, "InnoDB: Error: record has %lu fields\n",
@@ -479,7 +1252,7 @@ rec_validate(
}
for (i = 0; i < n_fields; i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field_old(rec, i, &len);
if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) {
fprintf(stderr,
@@ -499,45 +1272,165 @@ rec_validate(
}
}
- if (len_sum != (ulint)(rec_get_end(rec) - rec)) {
+ if (len_sum != rec_get_data_size_old(rec)) {
fprintf(stderr,
"InnoDB: Error: record len should be %lu, len %lu\n",
(ulong) len_sum,
- (ulong) (rec_get_end(rec) - rec));
+ rec_get_data_size_old(rec));
+ return(FALSE);
+ }
+
+ rec_dummy = sum; /* This is here only to fool the compiler */
+
+ return(TRUE);
+}
+
+/*******************************************************************
+Validates the consistency of a physical record. */
+
+ibool
+rec_validate(
+/*=========*/
+ /* out: TRUE if ok */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
+{
+ const byte* data;
+ ulint len;
+ ulint n_fields;
+ ulint len_sum = 0;
+ ulint sum = 0;
+ ulint i;
+
+ ut_a(rec);
+ n_fields = rec_offs_n_fields(offsets);
+
+ if ((n_fields == 0) || (n_fields > REC_MAX_N_FIELDS)) {
+ fprintf(stderr, "InnoDB: Error: record has %lu fields\n",
+ (ulong) n_fields);
+ return(FALSE);
+ }
+
+ ut_a(rec_offs_comp(offsets) || n_fields <= rec_get_n_fields_old(rec));
+
+ for (i = 0; i < n_fields; i++) {
+ data = rec_get_nth_field(rec, offsets, i, &len);
+
+ if (!((len < UNIV_PAGE_SIZE) || (len == UNIV_SQL_NULL))) {
+ fprintf(stderr,
+ "InnoDB: Error: record field %lu len %lu\n", (ulong) i,
+ (ulong) len);
+ return(FALSE);
+ }
+
+ if (len != UNIV_SQL_NULL) {
+ len_sum += len;
+ sum += *(data + len -1); /* dereference the
+ end of the field to
+ cause a memory trap
+ if possible */
+ } else if (!rec_offs_comp(offsets)) {
+ len_sum += rec_get_nth_field_size(rec, i);
+ }
+ }
+
+ if (len_sum != (ulint)(rec_get_end(rec, offsets) - rec)) {
+ fprintf(stderr,
+ "InnoDB: Error: record len should be %lu, len %lu\n",
+ (ulong) len_sum,
+ (ulong) (rec_get_end(rec, offsets) - rec));
return(FALSE);
}
rec_dummy = sum; /* This is here only to fool the compiler */
+ if (!rec_offs_comp(offsets)) {
+ ut_a(rec_validate_old(rec));
+ }
+
return(TRUE);
}
/*******************************************************************
+Prints an old-style physical record. */
+
+void
+rec_print_old(
+/*==========*/
+ FILE* file, /* in: file where to print */
+ rec_t* rec) /* in: physical record */
+{
+ const byte* data;
+ ulint len;
+ ulint n;
+ ulint i;
+
+ ut_ad(rec);
+
+ n = rec_get_n_fields_old(rec);
+
+ fprintf(file, "PHYSICAL RECORD: n_fields %lu;"
+ " %u-byte offsets; info bits %lu\n",
+ (ulong) n,
+ rec_get_1byte_offs_flag(rec) ? 1 : 2,
+ (ulong) rec_get_info_bits(rec, FALSE));
+
+ for (i = 0; i < n; i++) {
+
+ data = rec_get_nth_field_old(rec, i, &len);
+
+ fprintf(file, " %lu:", (ulong) i);
+
+ if (len != UNIV_SQL_NULL) {
+ if (len <= 30) {
+
+ ut_print_buf(file, data, len);
+ } else {
+ ut_print_buf(file, data, 30);
+
+ fputs("...(truncated)", file);
+ }
+ } else {
+ fprintf(file, " SQL NULL, size %lu ",
+ rec_get_nth_field_size(rec, i));
+ }
+ putc(';', file);
+ }
+
+ putc('\n', file);
+
+ rec_validate_old(rec);
+}
+
+/*******************************************************************
Prints a physical record. */
void
rec_print(
/*======*/
- FILE* file, /* in: file where to print */
- rec_t* rec) /* in: physical record */
+ FILE* file, /* in: file where to print */
+ rec_t* rec, /* in: physical record */
+ const ulint* offsets)/* in: array returned by rec_get_offsets() */
{
- byte* data;
- ulint len;
- ulint n;
- ulint i;
+ const byte* data;
+ ulint len;
+ ulint i;
+
+ if (!rec_offs_comp(offsets)) {
+ rec_print_old(file, rec);
+ return;
+ }
ut_ad(rec);
-
- n = rec_get_n_fields(rec);
fprintf(file, "PHYSICAL RECORD: n_fields %lu;"
- " 1-byte offs %s; info bits %lu\n",
- (ulong) n, rec_get_1byte_offs_flag(rec) ? "TRUE" : "FALSE",
- (ulong) rec_get_info_bits(rec));
+ " compact format; info bits %lu\n",
+ (ulong) rec_offs_n_fields(offsets),
+ (ulong) rec_get_info_bits(rec, TRUE));
- for (i = 0; i < n; i++) {
+ for (i = 0; i < rec_offs_n_fields(offsets); i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
fprintf(file, " %lu:", (ulong) i);
@@ -551,14 +1444,12 @@ rec_print(
fputs("...(truncated)", file);
}
} else {
- fprintf(file, " SQL NULL, size %lu ",
- (ulong) rec_get_nth_field_size(rec, i));
-
+ fputs(" SQL NULL", file);
}
putc(';', file);
}
putc('\n', file);
- rec_validate(rec);
+ rec_validate(rec, offsets);
}
diff --git a/innobase/row/row0ins.c b/innobase/row/row0ins.c
index c45818ddd26..1c55005dcfa 100644
--- a/innobase/row/row0ins.c
+++ b/innobase/row/row0ins.c
@@ -251,7 +251,7 @@ row_ins_sec_index_entry_by_modify(
rec = btr_cur_get_rec(cursor);
ut_ad((cursor->index->type & DICT_CLUSTERED) == 0);
- ut_ad(rec_get_deleted_flag(rec));
+ ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp));
/* We know that in the alphabetical ordering, entry and rec are
identified. But in their binary form there may be differences if
@@ -316,7 +316,7 @@ row_ins_clust_index_entry_by_modify(
rec = btr_cur_get_rec(cursor);
- ut_ad(rec_get_deleted_flag(rec));
+ ut_ad(rec_get_deleted_flag(rec, cursor->index->table->comp));
heap = mem_heap_create(1024);
@@ -473,6 +473,8 @@ row_ins_cascade_calc_update_vec(
if (parent_ufield->field_no == parent_field_no) {
+ ulint fixed_size;
+
/* A field in the parent index record is
updated. Let us make the update vector
field for the child table. */
@@ -512,22 +514,22 @@ row_ins_cascade_calc_update_vec(
need to pad with spaces the new value of the
child column */
- if (dtype_is_fixed_size(type)
+ fixed_size = dtype_get_fixed_size(type);
+
+ if (fixed_size
&& ufield->new_val.len != UNIV_SQL_NULL
- && ufield->new_val.len
- < dtype_get_fixed_size(type)) {
+ && ufield->new_val.len < fixed_size) {
ufield->new_val.data =
mem_heap_alloc(heap,
- dtype_get_fixed_size(type));
- ufield->new_val.len =
- dtype_get_fixed_size(type);
+ fixed_size);
+ ufield->new_val.len = fixed_size;
ut_a(dtype_get_pad_char(type)
!= ULINT_UNDEFINED);
memset(ufield->new_val.data,
(byte)dtype_get_pad_char(type),
- dtype_get_fixed_size(type));
+ fixed_size);
ut_memcpy(ufield->new_val.data,
parent_ufield->new_val.data,
parent_ufield->new_val.len);
@@ -588,8 +590,16 @@ row_ins_foreign_report_err(
fputs(", in index ", ef);
ut_print_name(ef, trx, foreign->foreign_index->name);
if (rec) {
+ mem_heap_t* heap;
+ ulint* offsets;
+
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, foreign->foreign_index,
+ ULINT_UNDEFINED, heap);
+
fputs(", there is a record:\n", ef);
- rec_print(ef, rec);
+ rec_print(ef, rec, offsets);
+ mem_heap_free(heap);
} else {
fputs(", the record is not available\n", ef);
}
@@ -644,7 +654,16 @@ row_ins_foreign_report_add_err(
}
if (rec) {
- rec_print(ef, rec);
+ mem_heap_t* heap;
+ ulint* offsets;
+
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, foreign->foreign_index,
+ ULINT_UNDEFINED, heap);
+
+ rec_print(ef, rec, offsets);
+
+ mem_heap_free(heap);
}
putc('\n', ef);
@@ -706,7 +725,6 @@ row_ins_foreign_check_on_constraint(
dict_index_t* index;
dict_index_t* clust_index;
dtuple_t* ref;
- mem_heap_t* tmp_heap;
mem_heap_t* upd_vec_heap = NULL;
rec_t* rec;
rec_t* clust_rec;
@@ -715,8 +733,9 @@ row_ins_foreign_check_on_constraint(
ulint err;
ulint i;
trx_t* trx;
+ mem_heap_t* tmp_heap = NULL;
+ ulint* offsets;
-
ut_a(thr && foreign && pcur && mtr);
trx = thr_get_trx(thr);
@@ -816,7 +835,7 @@ row_ins_foreign_check_on_constraint(
err = DB_ROW_IS_REFERENCED;
row_ins_foreign_report_err(
-(char*)"Trying a too deep cascaded delete or update\n",
+"Trying a too deep cascaded delete or update\n",
thr, foreign, btr_pcur_get_rec(pcur), entry);
goto nonstandard_exit_func;
@@ -848,8 +867,6 @@ row_ins_foreign_check_on_constraint(
PAGE_CUR_LE, BTR_SEARCH_LEAF,
cascade->pcur, 0, mtr);
- mem_heap_free(tmp_heap);
-
clust_rec = btr_pcur_get_rec(cascade->pcur);
if (!page_rec_is_user_rec(clust_rec)
@@ -863,10 +880,14 @@ row_ins_foreign_check_on_constraint(
fputs("\n"
"InnoDB: record ", stderr);
- rec_print(stderr, rec);
+ offsets = rec_get_offsets(rec, index,
+ ULINT_UNDEFINED, tmp_heap);
+ rec_print(stderr, rec, offsets);
fputs("\n"
"InnoDB: clustered record ", stderr);
- rec_print(stderr, clust_rec);
+ offsets = rec_reget_offsets(clust_rec, clust_index,
+ offsets, ULINT_UNDEFINED, tmp_heap);
+ rec_print(stderr, clust_rec, offsets);
fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
@@ -884,9 +905,14 @@ row_ins_foreign_check_on_constraint(
/* Here it suffices to use a LOCK_REC_NOT_GAP type lock;
we already have a normal shared lock on the appropriate
gap if the search criterion was not unique */
-
+
+ if (!tmp_heap) {
+ tmp_heap = mem_heap_create(256);
+ }
+ offsets = rec_get_offsets(clust_rec, clust_index,
+ ULINT_UNDEFINED, tmp_heap);
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
- clust_index, LOCK_X, LOCK_REC_NOT_GAP, thr);
+ clust_index, offsets, LOCK_X, LOCK_REC_NOT_GAP, thr);
}
if (err != DB_SUCCESS) {
@@ -894,7 +920,7 @@ row_ins_foreign_check_on_constraint(
goto nonstandard_exit_func;
}
- if (rec_get_deleted_flag(clust_rec)) {
+ if (rec_get_deleted_flag(clust_rec, table->comp)) {
/* This can happen if there is a circular reference of
rows such that cascading delete comes to delete a row
already in the process of being delete marked */
@@ -1003,6 +1029,10 @@ row_ins_foreign_check_on_constraint(
btr_pcur_restore_position(BTR_SEARCH_LEAF, pcur, mtr);
+ if (tmp_heap) {
+ mem_heap_free(tmp_heap);
+ }
+
if (upd_vec_heap) {
mem_heap_free(upd_vec_heap);
}
@@ -1010,6 +1040,9 @@ row_ins_foreign_check_on_constraint(
return(err);
nonstandard_exit_func:
+ if (tmp_heap) {
+ mem_heap_free(tmp_heap);
+ }
if (upd_vec_heap) {
mem_heap_free(upd_vec_heap);
@@ -1037,16 +1070,19 @@ row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr) /* in: query thread */
{
ulint err;
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (index->type & DICT_CLUSTERED) {
- err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_S,
- type, thr);
+ err = lock_clust_rec_read_check_and_lock(0,
+ rec, index, offsets, LOCK_S, type, thr);
} else {
- err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_S,
- type, thr);
+ err = lock_sec_rec_read_check_and_lock(0,
+ rec, index, offsets, LOCK_S, type, thr);
}
return(err);
@@ -1064,16 +1100,19 @@ row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP type lock */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
que_thr_t* thr) /* in: query thread */
{
ulint err;
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (index->type & DICT_CLUSTERED) {
- err = lock_clust_rec_read_check_and_lock(0, rec, index, LOCK_X,
- type, thr);
+ err = lock_clust_rec_read_check_and_lock(0,
+ rec, index, offsets, LOCK_X, type, thr);
} else {
- err = lock_sec_rec_read_check_and_lock(0, rec, index, LOCK_X,
- type, thr);
+ err = lock_sec_rec_read_check_and_lock(0,
+ rec, index, offsets, LOCK_X, type, thr);
}
return(err);
@@ -1114,6 +1153,10 @@ row_ins_check_foreign_constraint(
ulint i;
mtr_t mtr;
trx_t* trx = thr_get_trx(thr);
+ mem_heap_t* heap;
+ ulint* offsets = NULL;
+
+ heap = mem_heap_create(100);
run_again:
#ifdef UNIV_SYNC_DEBUG
@@ -1125,7 +1168,7 @@ run_again:
if (trx->check_foreigns == FALSE) {
/* The user has suppressed foreign key checks currently for
this session */
-
+ mem_heap_free(heap);
return(DB_SUCCESS);
}
@@ -1137,6 +1180,7 @@ run_again:
if (UNIV_SQL_NULL == dfield_get_len(
dtuple_get_nth_field(entry, i))) {
+ mem_heap_free(heap);
return(DB_SUCCESS);
}
}
@@ -1160,7 +1204,8 @@ run_again:
with each foreign key constraint, one after
another, and the user has problems predicting in
which order they are performed. */
-
+
+ mem_heap_free(heap);
return(DB_SUCCESS);
}
}
@@ -1174,6 +1219,8 @@ run_again:
}
if (check_table == NULL) {
+ mem_heap_free(heap);
+
if (check_ref) {
FILE* ef = dict_foreign_err_file;
mutex_enter(&dict_foreign_err_mutex);
@@ -1244,10 +1291,13 @@ run_again:
goto next_rec;
}
+ offsets = rec_reget_offsets(rec, check_index,
+ offsets, ULINT_UNDEFINED, heap);
+
if (rec == page_get_supremum_rec(buf_frame_align(rec))) {
-
+
err = row_ins_set_shared_rec_lock(LOCK_ORDINARY, rec,
- check_index, thr);
+ check_index, offsets, thr);
if (err != DB_SUCCESS) {
break;
@@ -1256,29 +1306,30 @@ run_again:
goto next_rec;
}
- cmp = cmp_dtuple_rec(entry, rec);
+ cmp = cmp_dtuple_rec(entry, rec, offsets);
if (cmp == 0) {
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec,
+ rec_offs_comp(offsets))) {
err = row_ins_set_shared_rec_lock(
- LOCK_ORDINARY,
- rec, check_index, thr);
+ LOCK_ORDINARY, rec,
+ check_index, offsets, thr);
if (err != DB_SUCCESS) {
break;
}
} else {
/* Found a matching record */
+ ulint lock_type;
if (unique_search) {
- err = row_ins_set_shared_rec_lock(
- LOCK_REC_NOT_GAP,
- rec, check_index, thr);
+ lock_type = LOCK_REC_NOT_GAP;
} else {
- err = row_ins_set_shared_rec_lock(
- LOCK_ORDINARY,
- rec, check_index, thr);
+ lock_type = LOCK_ORDINARY;
}
+
+ err = row_ins_set_shared_rec_lock(lock_type,
+ rec, check_index, offsets, thr);
if (err != DB_SUCCESS) {
@@ -1315,7 +1366,7 @@ run_again:
if (cmp < 0) {
err = row_ins_set_shared_rec_lock(LOCK_GAP,
- rec, check_index, thr);
+ rec, check_index, offsets, thr);
if (err != DB_SUCCESS) {
break;
@@ -1373,6 +1424,7 @@ do_possible_lock_wait:
err = trx->error_state;
}
+ mem_heap_free(heap);
return(err);
}
@@ -1444,19 +1496,23 @@ row_ins_dupl_error_with_rec(
that the caller already has a record lock on
the record! */
dtuple_t* entry, /* in: entry to insert */
- dict_index_t* index) /* in: index */
+ dict_index_t* index, /* in: index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
ulint matched_fields;
ulint matched_bytes;
ulint n_unique;
ulint i;
-
+
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
n_unique = dict_index_get_n_unique(index);
matched_fields = 0;
matched_bytes = 0;
- cmp_dtuple_rec_with_match(entry, rec, &matched_fields, &matched_bytes);
+ cmp_dtuple_rec_with_match(entry, rec, offsets,
+ &matched_fields, &matched_bytes);
if (matched_fields < n_unique) {
@@ -1477,7 +1533,7 @@ row_ins_dupl_error_with_rec(
}
}
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, index->table->comp)) {
return(TRUE);
}
@@ -1509,8 +1565,9 @@ row_ins_scan_sec_index_for_duplicate(
ibool moved;
mtr_t mtr;
trx_t* trx;
- const char* ptr;
-
+ mem_heap_t* heap;
+ ulint* offsets = NULL;
+
n_unique = dict_index_get_n_unique(index);
/* If the secondary index is unique, but one of the fields in the
@@ -1525,6 +1582,7 @@ row_ins_scan_sec_index_for_duplicate(
}
}
+ heap = mem_heap_create(100);
mtr_start(&mtr);
/* Store old value on n_fields_cmp */
@@ -1550,6 +1608,9 @@ row_ins_scan_sec_index_for_duplicate(
trx = thr_get_trx(thr);
ut_ad(trx);
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+
if (innobase_query_is_replace()) {
/* The manual defines the REPLACE semantics that it
@@ -1557,12 +1618,12 @@ row_ins_scan_sec_index_for_duplicate(
+ INSERT. Therefore, we should take X-lock for
duplicates */
- err = row_ins_set_exclusive_rec_lock(
- LOCK_ORDINARY,rec,index,thr);
+ err = row_ins_set_exclusive_rec_lock(LOCK_ORDINARY,
+ rec, index, offsets, thr);
} else {
- err = row_ins_set_shared_rec_lock(
- LOCK_ORDINARY, rec, index,thr);
+ err = row_ins_set_shared_rec_lock(LOCK_ORDINARY,
+ rec, index, offsets, thr);
}
if (err != DB_SUCCESS) {
@@ -1575,10 +1636,11 @@ row_ins_scan_sec_index_for_duplicate(
goto next_rec;
}
- cmp = cmp_dtuple_rec(entry, rec);
+ cmp = cmp_dtuple_rec(entry, rec, offsets);
if (cmp == 0) {
- if (row_ins_dupl_error_with_rec(rec, entry, index)) {
+ if (row_ins_dupl_error_with_rec(rec, entry,
+ index, offsets)) {
err = DB_DUPLICATE_KEY;
thr_get_trx(thr)->error_info = index;
@@ -1600,6 +1662,7 @@ next_rec:
}
}
+ mem_heap_free(heap);
mtr_commit(&mtr);
/* Restore old value */
@@ -1630,7 +1693,6 @@ row_ins_duplicate_error_in_clust(
page_t* page;
ulint n_unique;
trx_t* trx = thr_get_trx(thr);
- const char* ptr;
UT_NOT_USED(mtr);
@@ -1658,6 +1720,12 @@ row_ins_duplicate_error_in_clust(
page = buf_frame_align(rec);
if (rec != page_get_infimum_rec(page)) {
+ mem_heap_t* heap;
+ ulint* offsets;
+
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, cursor->index,
+ ULINT_UNDEFINED, heap);
/* We set a lock on the possible duplicate: this
is needed in logical logging of MySQL to make
@@ -1673,24 +1741,26 @@ row_ins_duplicate_error_in_clust(
err = row_ins_set_exclusive_rec_lock(
LOCK_REC_NOT_GAP,rec,cursor->index,
- thr);
+ offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
LOCK_REC_NOT_GAP,rec, cursor->index,
- thr);
+ offsets, thr);
}
if (err != DB_SUCCESS) {
-
+ mem_heap_free(heap);
return(err);
}
if (row_ins_dupl_error_with_rec(rec, entry,
- cursor->index)) {
+ cursor->index, offsets)) {
trx->error_info = cursor->index;
+ mem_heap_free(heap);
return(DB_DUPLICATE_KEY);
}
+ mem_heap_free(heap);
}
}
@@ -1700,7 +1770,12 @@ row_ins_duplicate_error_in_clust(
page = buf_frame_align(rec);
if (rec != page_get_supremum_rec(page)) {
+ mem_heap_t* heap;
+ ulint* offsets;
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, cursor->index,
+ ULINT_UNDEFINED, heap);
/* The manual defines the REPLACE semantics that it
is either an INSERT or DELETE(s) for duplicate key
@@ -1710,25 +1785,27 @@ row_ins_duplicate_error_in_clust(
if (innobase_query_is_replace()) {
err = row_ins_set_exclusive_rec_lock(
- LOCK_REC_NOT_GAP,
- rec,cursor->index,thr);
+ LOCK_REC_NOT_GAP, rec,
+ cursor->index, offsets, thr);
} else {
err = row_ins_set_shared_rec_lock(
- LOCK_REC_NOT_GAP,rec,
- cursor->index, thr);
+ LOCK_REC_NOT_GAP, rec,
+ cursor->index, offsets, thr);
}
if (err != DB_SUCCESS) {
-
+ mem_heap_free(heap);
return(err);
}
if (row_ins_dupl_error_with_rec(rec, entry,
- cursor->index)) {
+ cursor->index, offsets)) {
trx->error_info = cursor->index;
+ mem_heap_free(heap);
return(DB_DUPLICATE_KEY);
}
+ mem_heap_free(heap);
}
ut_a(!(cursor->index->type & DICT_CLUSTERED));
@@ -1817,6 +1894,8 @@ row_ins_index_entry_low(
ulint n_unique;
big_rec_t* big_rec = NULL;
mtr_t mtr;
+ mem_heap_t* heap = mem_heap_create(100);
+ ulint* offsets = NULL;
log_free_check();
@@ -1849,8 +1928,9 @@ row_ins_index_entry_low(
buf_frame_align(btr_cur_get_rec(&cursor))));
if (!page_rec_is_supremum(first_rec)) {
- ut_a((rec_get_n_fields(first_rec))
- == dtuple_get_n_fields(entry));
+ offsets = rec_get_offsets(first_rec, index,
+ ULINT_UNDEFINED, heap);
+ ut_a(rec_offs_n_fields(offsets) == dtuple_get_n_fields(entry));
}
n_unique = dict_index_get_n_unique(index);
@@ -1928,7 +2008,7 @@ row_ins_index_entry_low(
if (err == DB_SUCCESS) {
if (ext_vec) {
- rec_set_field_extern_bits(insert_rec,
+ rec_set_field_extern_bits(insert_rec, index,
ext_vec, n_ext_vec, &mtr);
}
}
@@ -1938,14 +2018,18 @@ function_exit:
mtr_commit(&mtr);
if (big_rec) {
+ rec_t* rec;
mtr_start(&mtr);
btr_cur_search_to_nth_level(index, 0, entry, PAGE_CUR_LE,
BTR_MODIFY_TREE, &cursor, 0, &mtr);
+ rec = btr_cur_get_rec(&cursor);
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+
+ err = btr_store_big_rec_extern_fields(index, rec,
+ offsets, big_rec, &mtr);
- err = btr_store_big_rec_extern_fields(index,
- btr_cur_get_rec(&cursor),
- big_rec, &mtr);
if (modify) {
dtuple_big_rec_free(big_rec);
} else {
@@ -1955,6 +2039,7 @@ function_exit:
mtr_commit(&mtr);
}
+ mem_heap_free(heap);
return(err);
}
diff --git a/innobase/row/row0mysql.c b/innobase/row/row0mysql.c
index 241ddc310e8..be243b44488 100644
--- a/innobase/row/row0mysql.c
+++ b/innobase/row/row0mysql.c
@@ -308,7 +308,8 @@ handle_new_error:
return(TRUE);
- } else if (err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT) {
+ } else if (err == DB_DEADLOCK || err == DB_LOCK_WAIT_TIMEOUT
+ || err == DB_LOCK_TABLE_FULL) {
/* Roll back the whole transaction; this resolution was added
to version 3.23.43 */
@@ -779,8 +780,13 @@ int
row_lock_table_for_mysql(
/*=====================*/
/* out: error code or DB_SUCCESS */
- row_prebuilt_t* prebuilt) /* in: prebuilt struct in the MySQL
+ row_prebuilt_t* prebuilt, /* in: prebuilt struct in the MySQL
table handle */
+ dict_table_t* table, /* in: table to lock, or NULL
+ if prebuilt->table should be
+ locked as LOCK_TABLE_EXP |
+ prebuilt->select_lock_type */
+ ulint mode) /* in: lock mode of table */
{
trx_t* trx = prebuilt->trx;
que_thr_t* thr;
@@ -813,8 +819,12 @@ run_again:
trx_start_if_not_started(trx);
- err = lock_table(LOCK_TABLE_EXP, prebuilt->table,
- prebuilt->select_lock_type, thr);
+ if (table) {
+ err = lock_table(0, table, mode, thr);
+ } else {
+ err = lock_table(LOCK_TABLE_EXP, prebuilt->table,
+ prebuilt->select_lock_type, thr);
+ }
trx->error_state = err;
@@ -1186,6 +1196,57 @@ run_again:
return((int) err);
}
+/*************************************************************************
+Does an unlock of a row for MySQL. */
+
+int
+row_unlock_for_mysql(
+/*=================*/
+ /* out: error code or DB_SUCCESS */
+ row_prebuilt_t* prebuilt) /* in: prebuilt struct in MySQL
+ handle */
+{
+ rec_t* rec;
+ btr_pcur_t* cur = prebuilt->pcur;
+ trx_t* trx = prebuilt->trx;
+ mtr_t mtr;
+
+ ut_ad(prebuilt && trx);
+ ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
+
+ trx->op_info = "unlock_row";
+
+ if (srv_locks_unsafe_for_binlog) {
+ if (trx->trx_create_lock == TRUE) {
+
+ mtr_start(&mtr);
+
+ /* Restore a cursor position and find a record */
+ btr_pcur_restore_position(BTR_SEARCH_LEAF, cur, &mtr);
+ rec = btr_pcur_get_rec(cur);
+
+ if (rec) {
+
+ lock_rec_reset_and_release_wait(rec);
+ } else {
+ fputs("InnoDB: Error: "
+ "Record for the lock not found\n",
+ stderr);
+ mem_analyze_corruption((byte*) trx);
+ ut_error;
+ }
+
+ trx->trx_create_lock = FALSE;
+ mtr_commit(&mtr);
+ }
+
+ }
+
+ trx->op_info = "";
+
+ return(DB_SUCCESS);
+}
+
/**************************************************************************
Does a cascaded delete or set null in a foreign key operation. */
@@ -2314,7 +2375,8 @@ row_drop_table_for_mysql(
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = table_name;\n"
+ " WHERE FOR_NAME = table_name\n"
+ " AND TO_BINARY(FOR_NAME) = TO_BINARY(table_name);\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE"
@@ -2769,7 +2831,8 @@ row_rename_table_for_mysql(
"WHILE found = 1 LOOP\n"
" SELECT ID INTO foreign_id\n"
" FROM SYS_FOREIGN\n"
- " WHERE FOR_NAME = old_table_name;\n"
+ " WHERE FOR_NAME = old_table_name\n"
+ " AND TO_BINARY(FOR_NAME) = TO_BINARY(old_table_name);\n"
" IF (SQL % NOTFOUND) THEN\n"
" found := 0;\n"
" ELSE\n"
@@ -2802,7 +2865,8 @@ row_rename_table_for_mysql(
" END IF;\n"
"END LOOP;\n"
"UPDATE SYS_FOREIGN SET REF_NAME = new_table_name\n"
- "WHERE REF_NAME = old_table_name;\n";
+ "WHERE REF_NAME = old_table_name\n"
+ " AND TO_BINARY(REF_NAME) = TO_BINARY(old_table_name);\n";
static const char str5[] =
"END;\n";
@@ -3012,7 +3076,11 @@ row_rename_table_for_mysql(
if (err != DB_SUCCESS) {
if (err == DB_DUPLICATE_KEY) {
ut_print_timestamp(stderr);
- fputs(" InnoDB: Error: table ", stderr);
+ fputs(
+ " InnoDB: Error; possible reasons:\n"
+ "InnoDB: 1) Table rename would cause two FOREIGN KEY constraints\n"
+ "InnoDB: to have the same internal name in case-insensitive comparison.\n"
+ "InnoDB: 2) table ", stderr);
ut_print_name(stderr, trx, new_name);
fputs(" exists in the InnoDB internal data\n"
"InnoDB: dictionary though MySQL is trying rename table ", stderr);
@@ -3158,7 +3226,8 @@ row_scan_and_check_index(
int cmp;
ibool contains_null;
ulint i;
-
+ ulint* offsets = NULL;
+
*n_rows = 0;
buf = mem_alloc(UNIV_PAGE_SIZE);
@@ -3198,8 +3267,10 @@ loop:
if (prev_entry != NULL) {
matched_fields = 0;
matched_bytes = 0;
-
- cmp = cmp_dtuple_rec_with_match(prev_entry, rec,
+
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ cmp = cmp_dtuple_rec_with_match(prev_entry, rec, offsets,
&matched_fields,
&matched_bytes);
contains_null = FALSE;
@@ -3228,7 +3299,7 @@ loop:
dtuple_print(stderr, prev_entry);
fputs("\n"
"InnoDB: record ", stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, offsets);
putc('\n', stderr);
is_ok = FALSE;
} else if ((index->type & DICT_UNIQUE)
@@ -3242,6 +3313,7 @@ loop:
}
mem_heap_empty(heap);
+ offsets = NULL;
prev_entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec, heap);
@@ -3326,7 +3398,7 @@ row_check_table_for_mysql(
/* We validate also the whole adaptive hash index for all tables
at every CHECK TABLE */
- if (!btr_search_validate()) {
+ if (!btr_search_validate(index)) {
ret = DB_ERROR;
}
diff --git a/innobase/row/row0purge.c b/innobase/row/row0purge.c
index f7e01169b9d..109d0f3b976 100644
--- a/innobase/row/row0purge.c
+++ b/innobase/row/row0purge.c
@@ -99,6 +99,8 @@ row_purge_remove_clust_if_poss_low(
ibool success;
ulint err;
mtr_t mtr;
+ rec_t* rec;
+ mem_heap_t* heap;
index = dict_table_get_first_index(node->table);
@@ -117,15 +119,21 @@ row_purge_remove_clust_if_poss_low(
return(TRUE);
}
+ rec = btr_pcur_get_rec(pcur);
+ heap = mem_heap_create(100);
+
if (0 != ut_dulint_cmp(node->roll_ptr,
- row_get_rec_roll_ptr(btr_pcur_get_rec(pcur), index))) {
-
+ row_get_rec_roll_ptr(rec, index, rec_get_offsets(
+ rec, index, ULINT_UNDEFINED, heap)))) {
+ mem_heap_free(heap);
/* Someone else has modified the record later: do not remove */
btr_pcur_commit_specify_mtr(pcur, &mtr);
return(TRUE);
}
+ mem_heap_free(heap);
+
if (mode == BTR_MODIFY_LEAF) {
success = btr_cur_optimistic_delete(btr_cur, &mtr);
} else {
diff --git a/innobase/row/row0row.c b/innobase/row/row0row.c
index 38714b0c49b..9cf285a519d 100644
--- a/innobase/row/row0row.c
+++ b/innobase/row/row0row.c
@@ -37,17 +37,18 @@ row_get_rec_sys_field(
/* out: value of the field */
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
- dict_index_t* index) /* in: clustered index */
+ dict_index_t* index, /* in: clustered index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
- ulint pos;
- byte* field;
- ulint len;
+ ulint pos;
+ byte* field;
+ ulint len;
ut_ad(index->type & DICT_CLUSTERED);
pos = dict_index_get_sys_col_pos(index, type);
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
if (type == DATA_TRX_ID) {
@@ -70,6 +71,7 @@ row_set_rec_sys_field(
ulint type, /* in: DATA_TRX_ID or DATA_ROLL_PTR */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: clustered index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
dulint val) /* in: value to set */
{
ulint pos;
@@ -77,10 +79,11 @@ row_set_rec_sys_field(
ulint len;
ut_ad(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
pos = dict_index_get_sys_col_pos(index, type);
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
if (type == DATA_TRX_ID) {
@@ -182,6 +185,9 @@ row_build(
the buffer page of this record must be
at least s-latched and the latch held
as long as the row dtuple is used! */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index)
+ or NULL, in which case this function
+ will invoke rec_get_offsets() */
mem_heap_t* heap) /* in: memory heap from which the memory
needed is allocated */
{
@@ -196,14 +202,26 @@ row_build(
ulint row_len;
byte* buf;
ulint i;
-
+ mem_heap_t* tmp_heap;
+
ut_ad(index && rec && heap);
ut_ad(index->type & DICT_CLUSTERED);
+ if (!offsets) {
+ tmp_heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index,
+ ULINT_UNDEFINED, tmp_heap);
+ } else {
+ tmp_heap = NULL;
+ ut_ad(rec_offs_validate(rec, index, offsets));
+ }
+
if (type != ROW_COPY_POINTERS) {
/* Take a copy of rec to heap */
- buf = mem_heap_alloc(heap, rec_get_size(rec));
- rec = rec_copy(buf, rec);
+ buf = mem_heap_alloc(heap, rec_offs_size(offsets));
+ rec = rec_copy(buf, rec, offsets);
+ /* Avoid a debug assertion in rec_offs_validate(). */
+ rec_offs_make_valid(rec, index, (ulint*) offsets);
}
table = index->table;
@@ -211,11 +229,9 @@ row_build(
row = dtuple_create(heap, row_len);
- dtuple_set_info_bits(row, rec_get_info_bits(rec));
-
- n_fields = dict_index_get_n_fields(index);
+ dtuple_set_info_bits(row, rec_get_info_bits(rec, table->comp));
- ut_ad(n_fields == rec_get_n_fields(rec));
+ n_fields = rec_offs_n_fields(offsets);
dict_table_copy_types(row, table);
@@ -227,13 +243,13 @@ row_build(
col = dict_field_get_col(ind_field);
dfield = dtuple_get_nth_field(row,
dict_col_get_no(col));
- field = rec_get_nth_field(rec, i, &len);
+ field = rec_get_nth_field(rec, offsets, i, &len);
if (type == ROW_COPY_ALSO_EXTERNALS
- && rec_get_nth_field_extern_bit(rec, i)) {
+ && rec_offs_nth_extern(offsets, i)) {
field = btr_rec_copy_externally_stored_field(
- rec, i, &len, heap);
+ rec, offsets, i, &len, heap);
}
dfield_set_data(dfield, field, len);
@@ -242,6 +258,10 @@ row_build(
ut_ad(dtuple_check_typed(row));
+ if (tmp_heap) {
+ mem_heap_free(tmp_heap);
+ }
+
return(row);
}
@@ -276,16 +296,23 @@ row_rec_to_index_entry(
ulint len;
ulint rec_len;
byte* buf;
-
+ mem_heap_t* tmp_heap;
+ ulint* offsets;
+
ut_ad(rec && heap && index);
+ tmp_heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, tmp_heap);
+
if (type == ROW_COPY_DATA) {
/* Take a copy of rec to heap */
- buf = mem_heap_alloc(heap, rec_get_size(rec));
- rec = rec_copy(buf, rec);
+ buf = mem_heap_alloc(heap, rec_offs_size(offsets));
+ rec = rec_copy(buf, rec, offsets);
+ /* Avoid a debug assertion in rec_offs_validate(). */
+ rec_offs_make_valid(rec, index, offsets);
}
- rec_len = rec_get_n_fields(rec);
+ rec_len = rec_offs_n_fields(offsets);
entry = dtuple_create(heap, rec_len);
@@ -295,17 +322,19 @@ row_rec_to_index_entry(
dict_index_copy_types(entry, index, rec_len);
- dtuple_set_info_bits(entry, rec_get_info_bits(rec));
+ dtuple_set_info_bits(entry,
+ rec_get_info_bits(rec, rec_offs_comp(offsets)));
for (i = 0; i < rec_len; i++) {
dfield = dtuple_get_nth_field(entry, i);
- field = rec_get_nth_field(rec, i, &len);
+ field = rec_get_nth_field(rec, offsets, i, &len);
dfield_set_data(dfield, field, len);
}
ut_ad(dtuple_check_typed(entry));
+ mem_heap_free(tmp_heap);
return(entry);
}
@@ -345,15 +374,22 @@ row_build_row_ref(
byte* buf;
ulint clust_col_prefix_len;
ulint i;
+ mem_heap_t* tmp_heap;
+ ulint* offsets;
ut_ad(index && rec && heap);
-
+
+ tmp_heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, tmp_heap);
+
if (type == ROW_COPY_DATA) {
/* Take a copy of rec to heap */
- buf = mem_heap_alloc(heap, rec_get_size(rec));
+ buf = mem_heap_alloc(heap, rec_offs_size(offsets));
- rec = rec_copy(buf, rec);
+ rec = rec_copy(buf, rec, offsets);
+ /* Avoid a debug assertion in rec_offs_validate(). */
+ rec_offs_make_valid(rec, index, offsets);
}
table = index->table;
@@ -373,7 +409,7 @@ row_build_row_ref(
ut_a(pos != ULINT_UNDEFINED);
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
dfield_set_data(dfield, field, len);
@@ -397,6 +433,7 @@ row_build_row_ref(
}
ut_ad(dtuple_check_typed(ref));
+ mem_heap_free(tmp_heap);
return(ref);
}
@@ -427,7 +464,9 @@ row_build_row_ref_in_tuple(
ulint pos;
ulint clust_col_prefix_len;
ulint i;
-
+ mem_heap_t* heap;
+ ulint* offsets;
+
ut_a(ref && index && rec);
if (!index->table) {
@@ -446,7 +485,10 @@ row_build_row_ref_in_tuple(
fputs("InnoDB: clust index for table ", stderr);
goto notfound;
}
-
+
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
ref_len = dict_index_get_n_unique(clust_index);
ut_ad(ref_len == dtuple_get_n_fields(ref));
@@ -459,8 +501,8 @@ row_build_row_ref_in_tuple(
pos = dict_index_get_nth_field_pos(index, clust_index, i);
ut_a(pos != ULINT_UNDEFINED);
-
- field = rec_get_nth_field(rec, pos, &len);
+
+ field = rec_get_nth_field(rec, offsets, pos, &len);
dfield_set_data(dfield, field, len);
@@ -484,6 +526,7 @@ row_build_row_ref_in_tuple(
}
ut_ad(dtuple_check_typed(ref));
+ mem_heap_free(heap);
}
/***********************************************************************
diff --git a/innobase/row/row0sel.c b/innobase/row/row0sel.c
index 71163bc35b6..2b40b62e5bc 100644
--- a/innobase/row/row0sel.c
+++ b/innobase/row/row0sel.c
@@ -31,6 +31,7 @@ Created 12/19/1997 Heikki Tuuri
#include "pars0pars.h"
#include "row0mysql.h"
#include "read0read.h"
+#include "buf0lru.h"
/* Maximum number of rows to prefetch; MySQL interface has another parameter */
#define SEL_MAX_N_PREFETCH 16
@@ -77,8 +78,14 @@ row_sel_sec_rec_is_for_clust_rec(
ulint n;
ulint i;
dtype_t* cur_type;
+ mem_heap_t* heap;
+ ulint* clust_offs;
+ ulint* sec_offs;
- UT_NOT_USED(clust_index);
+ heap = mem_heap_create(100);
+ clust_offs = rec_get_offsets(clust_rec, clust_index,
+ ULINT_UNDEFINED, heap);
+ sec_offs = rec_get_offsets(sec_rec, sec_index, ULINT_UNDEFINED, heap);
n = dict_index_get_n_ordering_defined_by_user(sec_index);
@@ -86,10 +93,10 @@ row_sel_sec_rec_is_for_clust_rec(
ifield = dict_index_get_nth_field(sec_index, i);
col = dict_field_get_col(ifield);
- clust_field = rec_get_nth_field(clust_rec,
+ clust_field = rec_get_nth_field(clust_rec, clust_offs,
dict_col_get_clust_pos(col),
&clust_len);
- sec_field = rec_get_nth_field(sec_rec, i, &sec_len);
+ sec_field = rec_get_nth_field(sec_rec, sec_offs, i, &sec_len);
if (ifield->prefix_len > 0
&& clust_len != UNIV_SQL_NULL) {
@@ -106,10 +113,12 @@ row_sel_sec_rec_is_for_clust_rec(
if (0 != cmp_data_data(dict_col_get_type(col),
clust_field, clust_len,
sec_field, sec_len)) {
+ mem_heap_free(heap);
return(FALSE);
}
}
+ mem_heap_free(heap);
return(TRUE);
}
@@ -265,6 +274,7 @@ row_sel_fetch_columns(
dict_index_t* index, /* in: record index */
rec_t* rec, /* in: record in a clustered or non-clustered
index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
sym_node_t* column) /* in: first column in a column list, or
NULL */
{
@@ -274,6 +284,8 @@ row_sel_fetch_columns(
byte* data;
ulint len;
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (index->type & DICT_CLUSTERED) {
index_type = SYM_CLUST_FIELD_NO;
} else {
@@ -285,7 +297,7 @@ row_sel_fetch_columns(
if (field_no != ULINT_UNDEFINED) {
- data = rec_get_nth_field(rec, field_no, &len);
+ data = rec_get_nth_field(rec, offsets, field_no, &len);
if (column->copy_val) {
eval_node_copy_and_alloc_val(column, data,
@@ -600,8 +612,15 @@ row_sel_get_clust_rec(
rec_t* clust_rec;
rec_t* old_vers;
ulint err;
+ mem_heap_t* heap;
+ ulint* offsets;
+
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec,
+ btr_pcur_get_btr_cur(&plan->pcur)->index,
+ ULINT_UNDEFINED, heap);
- row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec);
+ row_build_row_ref_fast(plan->clust_ref, plan->clust_map, rec, offsets);
index = dict_table_get_first_index(plan->table);
@@ -618,7 +637,7 @@ row_sel_get_clust_rec(
|| btr_pcur_get_low_match(&(plan->clust_pcur))
< dict_index_get_n_unique(index)) {
- ut_a(rec_get_deleted_flag(rec));
+ ut_a(rec_get_deleted_flag(rec, plan->table->comp));
ut_a(node->read_view);
/* In a rare case it is possible that no clust rec is found
@@ -635,27 +654,30 @@ row_sel_get_clust_rec(
goto func_exit;
}
+ offsets = rec_reget_offsets(clust_rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+
if (!node->read_view) {
/* Try to place a lock on the index record */
- /* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
- if ( srv_locks_unsafe_for_binlog )
- {
- err = lock_clust_rec_read_check_and_lock(0, clust_rec,
- index,node->row_lock_mode, LOCK_REC_NOT_GAP, thr);
- }
- else
- {
- err = lock_clust_rec_read_check_and_lock(0, clust_rec, index,
- node->row_lock_mode, LOCK_ORDINARY, thr);
-
- }
-
- if (err != DB_SUCCESS) {
+ /* If innodb_locks_unsafe_for_binlog option is used,
+ we lock only the record, i.e., next-key locking is
+ not used. */
+ ulint lock_type;
+
+ if (srv_locks_unsafe_for_binlog) {
+ lock_type = LOCK_REC_NOT_GAP;
+ } else {
+ lock_type = LOCK_ORDINARY;
+ }
+ err = lock_clust_rec_read_check_and_lock(0,
+ clust_rec, index, offsets,
+ node->row_lock_mode, lock_type, thr);
+
+ if (err != DB_SUCCESS) {
+
+ mem_heap_free(heap);
return(err);
}
} else {
@@ -664,22 +686,21 @@ row_sel_get_clust_rec(
old_vers = NULL;
- if (!lock_clust_rec_cons_read_sees(clust_rec, index,
+ if (!lock_clust_rec_cons_read_sees(clust_rec, index, offsets,
node->read_view)) {
err = row_sel_build_prev_vers(node->read_view, plan,
clust_rec, &old_vers, mtr);
if (err != DB_SUCCESS) {
+ mem_heap_free(heap);
return(err);
}
clust_rec = old_vers;
if (clust_rec == NULL) {
- *out_rec = clust_rec;
-
- return(DB_SUCCESS);
+ goto func_exit;
}
}
@@ -696,23 +717,22 @@ row_sel_get_clust_rec(
visit through secondary index records that would not really
exist in our snapshot. */
- if ((old_vers || rec_get_deleted_flag(rec))
+ if ((old_vers || rec_get_deleted_flag(rec, plan->table->comp))
&& !row_sel_sec_rec_is_for_clust_rec(rec, plan->index,
clust_rec, index)) {
clust_rec = NULL;
- *out_rec = clust_rec;
-
- return(DB_SUCCESS);
+ goto func_exit;
}
}
/* Fetch the columns needed in test conditions */
-
- row_sel_fetch_columns(index, clust_rec,
+
+ row_sel_fetch_columns(index, clust_rec, offsets,
UT_LIST_GET_FIRST(plan->columns));
func_exit:
*out_rec = clust_rec;
+ mem_heap_free(heap);
return(DB_SUCCESS);
}
@@ -725,18 +745,29 @@ sel_set_rec_lock(
/* out: DB_SUCCESS or error code */
rec_t* rec, /* in: record */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
ulint mode, /* in: lock mode */
ulint type, /* in: LOCK_ORDINARY, LOCK_GAP, or LOC_REC_NOT_GAP */
que_thr_t* thr) /* in: query thread */
{
+ trx_t* trx;
ulint err;
+ trx = thr_get_trx(thr);
+
+ if (UT_LIST_GET_LEN(trx->trx_locks) > 10000) {
+ if (buf_LRU_buf_pool_running_out()) {
+
+ return(DB_LOCK_TABLE_FULL);
+ }
+ }
+
if (index->type & DICT_CLUSTERED) {
- err = lock_clust_rec_read_check_and_lock(0, rec, index, mode,
- type, thr);
+ err = lock_clust_rec_read_check_and_lock(0,
+ rec, index, offsets, mode, type, thr);
} else {
- err = lock_sec_rec_read_check_and_lock(0, rec, index, mode,
- type, thr);
+ err = lock_sec_rec_read_check_and_lock(0,
+ rec, index, offsets, mode, type, thr);
}
return(err);
@@ -944,6 +975,8 @@ row_sel_try_search_shortcut(
{
dict_index_t* index;
rec_t* rec;
+ mem_heap_t* heap;
+ ulint* offsets;
index = plan->index;
@@ -977,21 +1010,28 @@ row_sel_try_search_shortcut(
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
if (index->type & DICT_CLUSTERED) {
- if (!lock_clust_rec_cons_read_sees(rec, index,
+ if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
node->read_view)) {
+ mem_heap_free(heap);
return(SEL_RETRY);
}
} else if (!lock_sec_rec_cons_read_sees(rec, index, node->read_view)) {
+ mem_heap_free(heap);
return(SEL_RETRY);
}
/* Test deleted flag. Fetch the columns needed in test conditions. */
-
- row_sel_fetch_columns(index, rec, UT_LIST_GET_FIRST(plan->columns));
- if (rec_get_deleted_flag(rec)) {
+ row_sel_fetch_columns(index, rec, offsets,
+ UT_LIST_GET_FIRST(plan->columns));
+ mem_heap_free(heap);
+
+ if (rec_get_deleted_flag(rec, plan->table->comp)) {
return(SEL_EXHAUSTED);
}
@@ -1055,7 +1095,9 @@ row_sel(
to the next non-clustered record */
ulint found_flag;
ulint err;
-
+ mem_heap_t* heap = mem_heap_create(100);
+ ulint* offsets = NULL;
+
ut_ad(thr->run_node == node);
search_latch_locked = FALSE;
@@ -1205,22 +1247,25 @@ rec_loop:
if (!consistent_read) {
- /* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
-
- if ( srv_locks_unsafe_for_binlog )
- {
- err = sel_set_rec_lock(page_rec_get_next(rec), index,
- node->row_lock_mode, LOCK_REC_NOT_GAP, thr);
- }
- else
- {
- err = sel_set_rec_lock(page_rec_get_next(rec), index,
- node->row_lock_mode, LOCK_ORDINARY, thr);
- }
- if (err != DB_SUCCESS) {
+ /* If innodb_locks_unsafe_for_binlog option is used,
+ we lock only the record, i.e., next-key locking is
+ not used. */
+
+ rec_t* next_rec = page_rec_get_next(rec);
+ ulint lock_type;
+ offsets = rec_reget_offsets(next_rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+
+ if (srv_locks_unsafe_for_binlog) {
+ lock_type = LOCK_REC_NOT_GAP;
+ } else {
+ lock_type = LOCK_ORDINARY;
+ }
+
+ err = sel_set_rec_lock(next_rec, index, offsets,
+ node->row_lock_mode, lock_type, thr);
+
+ if (err != DB_SUCCESS) {
/* Note that in this case we will store in pcur
the PREDECESSOR of the record we are waiting
the lock for */
@@ -1245,21 +1290,22 @@ rec_loop:
if (!consistent_read) {
/* Try to place a lock on the index record */
- /* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
-
- if ( srv_locks_unsafe_for_binlog )
- {
- err = sel_set_rec_lock(rec, index, node->row_lock_mode,
- LOCK_REC_NOT_GAP, thr);
- }
- else
- {
- err = sel_set_rec_lock(rec, index, node->row_lock_mode,
- LOCK_ORDINARY, thr);
- }
+ /* If innodb_locks_unsafe_for_binlog option is used,
+ we lock only the record, i.e., next-key locking is
+ not used. */
+
+ ulint lock_type;
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+
+ if (srv_locks_unsafe_for_binlog) {
+ lock_type = LOCK_REC_NOT_GAP;
+ } else {
+ lock_type = LOCK_ORDINARY;
+ }
+
+ err = sel_set_rec_lock(rec, index, offsets,
+ node->row_lock_mode, lock_type, thr);
if (err != DB_SUCCESS) {
@@ -1323,6 +1369,8 @@ rec_loop:
/* PHASE 3: Get previous version in a consistent read */
cons_read_requires_clust_rec = FALSE;
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
if (consistent_read) {
/* This is a non-locking consistent read: if necessary, fetch
@@ -1330,7 +1378,7 @@ rec_loop:
if (index->type & DICT_CLUSTERED) {
- if (!lock_clust_rec_cons_read_sees(rec, index,
+ if (!lock_clust_rec_cons_read_sees(rec, index, offsets,
node->read_view)) {
err = row_sel_build_prev_vers(node->read_view,
@@ -1343,6 +1391,7 @@ rec_loop:
if (old_vers == NULL) {
row_sel_fetch_columns(index, rec,
+ offsets,
UT_LIST_GET_FIRST(plan->columns));
if (!row_sel_test_end_conds(plan)) {
@@ -1354,6 +1403,8 @@ rec_loop:
}
rec = old_vers;
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
}
} else if (!lock_sec_rec_cons_read_sees(rec, index,
node->read_view)) {
@@ -1365,7 +1416,8 @@ rec_loop:
/* Fetch the columns needed in test conditions */
- row_sel_fetch_columns(index, rec, UT_LIST_GET_FIRST(plan->columns));
+ row_sel_fetch_columns(index, rec, offsets,
+ UT_LIST_GET_FIRST(plan->columns));
/* Test the selection end conditions: these can only contain columns
which already are found in the index, even though the index might be
@@ -1380,7 +1432,8 @@ rec_loop:
goto table_exhausted;
}
- if (rec_get_deleted_flag(rec) && !cons_read_requires_clust_rec) {
+ if (rec_get_deleted_flag(rec, plan->table->comp)
+ && !cons_read_requires_clust_rec) {
/* The record is delete marked: we can skip it if this is
not a consistent read which might see an earlier version
@@ -1423,7 +1476,7 @@ rec_loop:
goto next_rec;
}
- if (rec_get_deleted_flag(clust_rec)) {
+ if (rec_get_deleted_flag(clust_rec, plan->table->comp)) {
/* The record is delete marked: we can skip it */
@@ -1581,7 +1634,8 @@ next_table_no_mtr:
if (search_latch_locked) {
rw_lock_s_unlock(&btr_search_latch);
}
-
+
+ mem_heap_free(heap);
return(DB_SUCCESS);
}
@@ -1615,6 +1669,7 @@ table_exhausted:
table_exhausted_no_mtr:
if (node->fetch_table == 0) {
+ mem_heap_free(heap);
if (node->is_aggregate && !node->aggregate_already_fetched) {
@@ -1663,7 +1718,7 @@ stop_for_a_while:
mtr_commit(&mtr);
ut_ad(sync_thread_levels_empty_gen(TRUE));
-
+ mem_heap_free(heap);
return(DB_SUCCESS);
commit_mtr_for_a_while:
@@ -1699,6 +1754,7 @@ lock_wait_or_error:
ut_ad(sync_thread_levels_empty_gen(TRUE));
+ mem_heap_free(heap);
return(err);
}
@@ -2122,11 +2178,16 @@ row_sel_store_row_id_to_prebuilt(
/*=============================*/
row_prebuilt_t* prebuilt, /* in: prebuilt */
rec_t* index_rec, /* in: record */
- dict_index_t* index) /* in: index of the record */
+ dict_index_t* index, /* in: index of the record */
+ const ulint* offsets) /* in: rec_get_offsets
+ (index_rec, index) */
{
byte* data;
ulint len;
- data = rec_get_nth_field(index_rec,
+
+ ut_ad(rec_offs_validate(index_rec, index, offsets));
+
+ data = rec_get_nth_field(index_rec, offsets,
dict_index_get_sys_col_pos(index, DATA_ROW_ID), &len);
if (len != DATA_ROW_ID_LEN) {
@@ -2136,7 +2197,7 @@ row_sel_store_row_id_to_prebuilt(
fprintf(stderr, "\n"
"InnoDB: Field number %lu, record:\n",
(ulong) dict_index_get_sys_col_pos(index, DATA_ROW_ID));
- rec_print(stderr, index_rec);
+ rec_print(stderr, index_rec, offsets);
putc('\n', stderr);
ut_error;
}
@@ -2225,9 +2286,11 @@ row_sel_store_mysql_rec(
case) */
byte* mysql_rec, /* out: row in the MySQL format */
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
- rec_t* rec) /* in: Innobase record in the index
+ rec_t* rec, /* in: Innobase record in the index
which was described in prebuilt's
template */
+ const ulint* offsets) /* in: array returned by
+ rec_get_offsets() */
{
mysql_row_templ_t* templ;
mem_heap_t* extern_field_heap = NULL;
@@ -2236,8 +2299,15 @@ row_sel_store_mysql_rec(
byte* blob_buf;
int pad_char;
ulint i;
+ dict_index_t* index;
ut_ad(prebuilt->mysql_template);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+
+ index = prebuilt->index;
+ if (prebuilt->need_to_access_clustered) {
+ index = dict_table_get_first_index(index->table);
+ }
if (prebuilt->blob_heap != NULL) {
mem_heap_free(prebuilt->blob_heap);
@@ -2253,9 +2323,10 @@ row_sel_store_mysql_rec(
templ = prebuilt->mysql_template + i;
- data = rec_get_nth_field(rec, templ->rec_field_no, &len);
+ data = rec_get_nth_field(rec, offsets,
+ templ->rec_field_no, &len);
- if (rec_get_nth_field_extern_bit(rec, templ->rec_field_no)) {
+ if (rec_offs_nth_extern(offsets, templ->rec_field_no)) {
/* Copy an externally stored field to the temporary
heap */
@@ -2269,7 +2340,7 @@ row_sel_store_mysql_rec(
causes an assert */
data = btr_rec_copy_externally_stored_field(rec,
- templ->rec_field_no, &len,
+ offsets, templ->rec_field_no, &len,
extern_field_heap);
ut_a(len != UNIV_SQL_NULL);
@@ -2425,6 +2496,8 @@ row_sel_get_clust_rec_for_mysql(
rec_t* old_vers;
ulint err;
trx_t* trx;
+ mem_heap_t* heap = mem_heap_create(100);
+ ulint* offsets = NULL;
*out_rec = NULL;
trx = thr_get_trx(thr);
@@ -2455,9 +2528,8 @@ row_sel_get_clust_rec_for_mysql(
clustered index record did not exist in the read view of
trx. */
- if (!rec_get_deleted_flag(rec)
+ if (!rec_get_deleted_flag(rec, sec_index->table->comp)
|| prebuilt->select_lock_type != LOCK_NONE) {
-
ut_print_timestamp(stderr);
fputs(" InnoDB: error clustered record"
" for sec rec not found\n"
@@ -2465,10 +2537,14 @@ row_sel_get_clust_rec_for_mysql(
dict_index_name_print(stderr, trx, sec_index);
fputs("\n"
"InnoDB: sec index record ", stderr);
- rec_print(stderr, rec);
+ offsets = rec_get_offsets(rec, sec_index,
+ ULINT_UNDEFINED, heap);
+ rec_print(stderr, rec, offsets);
fputs("\n"
"InnoDB: clust index record ", stderr);
- rec_print(stderr, clust_rec);
+ offsets = rec_reget_offsets(clust_rec, clust_index,
+ offsets, ULINT_UNDEFINED, heap);
+ rec_print(stderr, clust_rec, offsets);
putc('\n', stderr);
trx_print(stderr, trx);
@@ -2481,17 +2557,21 @@ row_sel_get_clust_rec_for_mysql(
goto func_exit;
}
+ offsets = rec_get_offsets(clust_rec, clust_index,
+ ULINT_UNDEFINED, heap);
+
if (prebuilt->select_lock_type != LOCK_NONE) {
/* Try to place a lock on the index record; we are searching
the clust rec with a unique condition, hence
we set a LOCK_REC_NOT_GAP type lock */
err = lock_clust_rec_read_check_and_lock(0, clust_rec,
- clust_index,
+ clust_index, offsets,
prebuilt->select_lock_type,
LOCK_REC_NOT_GAP, thr);
if (err != DB_SUCCESS) {
+ mem_heap_free(heap);
return(err);
}
} else {
@@ -2505,7 +2585,7 @@ row_sel_get_clust_rec_for_mysql(
if (trx->isolation_level > TRX_ISO_READ_UNCOMMITTED
&& !lock_clust_rec_cons_read_sees(clust_rec, clust_index,
- trx->read_view)) {
+ offsets, trx->read_view)) {
err = row_sel_build_prev_vers_for_mysql(
trx->read_view, clust_index,
@@ -2514,6 +2594,7 @@ row_sel_get_clust_rec_for_mysql(
if (err != DB_SUCCESS) {
+ mem_heap_free(heap);
return(err);
}
@@ -2533,7 +2614,8 @@ row_sel_get_clust_rec_for_mysql(
visit through secondary index records that would not really
exist in our snapshot. */
- if (clust_rec && (old_vers || rec_get_deleted_flag(rec))
+ if (clust_rec && (old_vers
+ || rec_get_deleted_flag(rec, sec_index->table->comp))
&& !row_sel_sec_rec_is_for_clust_rec(rec, sec_index,
clust_rec, clust_index)) {
clust_rec = NULL;
@@ -2555,6 +2637,7 @@ func_exit:
btr_pcur_store_position(prebuilt->clust_pcur, mtr);
}
+ mem_heap_free(heap);
return(DB_SUCCESS);
}
@@ -2676,12 +2759,14 @@ void
row_sel_push_cache_row_for_mysql(
/*=============================*/
row_prebuilt_t* prebuilt, /* in: prebuilt struct */
- rec_t* rec) /* in: record to push */
+ rec_t* rec, /* in: record to push */
+ const ulint* offsets) /* in: rec_get_offsets() */
{
byte* buf;
ulint i;
ut_ad(prebuilt->n_fetch_cached < MYSQL_FETCH_CACHE_SIZE);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
ut_a(!prebuilt->templ_contains_blob);
if (prebuilt->fetch_cache[0] == NULL) {
@@ -2707,7 +2792,7 @@ row_sel_push_cache_row_for_mysql(
ut_a(row_sel_store_mysql_rec(
prebuilt->fetch_cache[prebuilt->n_fetch_cached],
- prebuilt, rec));
+ prebuilt, rec, offsets));
prebuilt->n_fetch_cached++;
}
@@ -2724,6 +2809,8 @@ row_sel_try_search_shortcut_for_mysql(
/* out: SEL_FOUND, SEL_EXHAUSTED, SEL_RETRY */
rec_t** out_rec,/* out: record if found */
row_prebuilt_t* prebuilt,/* in: prebuilt struct */
+ ulint** offsets,/* in/out: for rec_reget_offsets(*out_rec) */
+ mem_heap_t* heap, /* in: heap for rec_reget_offsets() */
mtr_t* mtr) /* in: started mtr */
{
dict_index_t* index = prebuilt->index;
@@ -2761,13 +2848,17 @@ row_sel_try_search_shortcut_for_mysql(
/* This is a non-locking consistent read: if necessary, fetch
a previous version of the record */
-
- if (!lock_clust_rec_cons_read_sees(rec, index, trx->read_view)) {
+
+ *offsets = rec_reget_offsets(rec, index,
+ *offsets, ULINT_UNDEFINED, heap);
+
+ if (!lock_clust_rec_cons_read_sees(rec, index,
+ *offsets, trx->read_view)) {
return(SEL_RETRY);
}
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, index->table->comp)) {
return(SEL_EXHAUSTED);
}
@@ -2790,6 +2881,7 @@ row_search_for_mysql(
/* out: DB_SUCCESS,
DB_RECORD_NOT_FOUND,
DB_END_OF_INDEX, DB_DEADLOCK,
+ DB_LOCK_TABLE_FULL,
or DB_TOO_BIG_RECORD */
byte* buf, /* in/out: buffer for the fetched
row in the MySQL format */
@@ -2835,9 +2927,12 @@ row_search_for_mysql(
level is <= TRX_ISO_READ_COMMITTED,
then this is set to FALSE */
ibool success;
+ ibool comp;
ulint cnt = 0;
ulint next_offs;
mtr_t mtr;
+ mem_heap_t* heap;
+ ulint* offsets = NULL;
ut_ad(index && pcur && search_tuple);
ut_ad(trx->mysql_thread_id == os_thread_get_curr_id());
@@ -2991,6 +3086,7 @@ row_search_for_mysql(
}
mtr_start(&mtr);
+ heap = mem_heap_create(100);
/*-------------------------------------------------------------*/
/* PHASE 2: Try fast adaptive hash index search if possible */
@@ -3036,13 +3132,14 @@ row_search_for_mysql(
}
#endif
shortcut = row_sel_try_search_shortcut_for_mysql(&rec,
- prebuilt, &mtr);
+ prebuilt, &offsets, heap, &mtr);
if (shortcut == SEL_FOUND) {
#ifdef UNIV_SEARCH_DEBUG
- ut_a(0 == cmp_dtuple_rec(search_tuple, rec));
+ ut_a(0 == cmp_dtuple_rec(search_tuple,
+ rec, offsets));
#endif
if (!row_sel_store_mysql_rec(buf, prebuilt,
- rec)) {
+ rec, offsets)) {
err = DB_TOO_BIG_RECORD;
/* We let the main loop to do the
@@ -3070,7 +3167,7 @@ row_search_for_mysql(
/* NOTE that we do NOT store the cursor
position */
-
+ mem_heap_free(heap);
return(DB_SUCCESS);
} else if (shortcut == SEL_EXHAUSTED) {
@@ -3094,6 +3191,7 @@ row_search_for_mysql(
/* NOTE that we do NOT store the cursor
position */
+ mem_heap_free(heap);
return(DB_RECORD_NOT_FOUND);
}
shortcut_fails_too_big_rec:
@@ -3207,6 +3305,8 @@ rec_loop:
/* PHASE 4: Look for matching records in a loop */
rec = btr_pcur_get_rec(pcur);
+ comp = index->table->comp;
+ ut_ad(comp == page_is_comp(buf_frame_align(rec)));
/*
fputs("Using ", stderr);
dict_index_name_print(stderr, index);
@@ -3234,9 +3334,10 @@ rec_loop:
we do not lock gaps. Supremum record is really
a gap and therefore we do not set locks there. */
- if ( srv_locks_unsafe_for_binlog == FALSE )
- {
- err = sel_set_rec_lock(rec, index,
+ if (srv_locks_unsafe_for_binlog == FALSE) {
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ err = sel_set_rec_lock(rec, index, offsets,
prebuilt->select_lock_type,
LOCK_ORDINARY, thr);
}
@@ -3256,9 +3357,11 @@ rec_loop:
/* Do sanity checks in case our cursor has bumped into page
corruption */
- next_offs = rec_get_next_offs(rec);
+ next_offs = rec_get_next_offs(rec, comp);
- if (next_offs >= UNIV_PAGE_SIZE || next_offs < PAGE_SUPREMUM) {
+ if (next_offs >= UNIV_PAGE_SIZE
+ || next_offs <
+ (ulint) (comp ? PAGE_NEW_SUPREMUM : PAGE_OLD_SUPREMUM)) {
if (srv_force_recovery == 0 || moves_up == FALSE) {
ut_print_timestamp(stderr);
@@ -3303,9 +3406,12 @@ rec_loop:
}
}
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+
if (srv_force_recovery > 0) {
- if (!rec_validate(rec) || !btr_index_rec_validate(rec, index,
- FALSE)) {
+ if (!rec_validate(rec, offsets)
+ || !btr_index_rec_validate(rec, index, FALSE)) {
fprintf(stderr,
"InnoDB: Index corruption: rec offs %lu next offs %lu, page no %lu,\n"
"InnoDB: ",
@@ -3333,15 +3439,23 @@ rec_loop:
/* fputs("Comparing rec and search tuple\n", stderr); */
- if (0 != cmp_dtuple_rec(search_tuple, rec)) {
+ if (0 != cmp_dtuple_rec(search_tuple, rec, offsets)) {
if (prebuilt->select_lock_type != LOCK_NONE
&& set_also_gap_locks) {
- /* Try to place a lock on the index record */
- err = sel_set_rec_lock(rec, index,
+ /* Try to place a gap lock on the index
+ record only if innodb_locks_unsafe_for_binlog
+ option is not set */
+
+ if (srv_locks_unsafe_for_binlog == FALSE) {
+
+ err = sel_set_rec_lock(rec, index,
+ offsets,
prebuilt->select_lock_type,
LOCK_GAP, thr);
+ }
+
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
@@ -3359,15 +3473,23 @@ rec_loop:
} else if (match_mode == ROW_SEL_EXACT_PREFIX) {
- if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec)) {
+ if (!cmp_dtuple_is_prefix_of_rec(search_tuple, rec, offsets)) {
if (prebuilt->select_lock_type != LOCK_NONE
&& set_also_gap_locks) {
- /* Try to place a lock on the index record */
- err = sel_set_rec_lock(rec, index,
+ /* Try to place a gap lock on the index
+ record only if innodb_locks_unsafe_for_binlog
+ option is not set */
+
+ if (srv_locks_unsafe_for_binlog == FALSE) {
+
+ err = sel_set_rec_lock(rec, index,
+ offsets,
prebuilt->select_lock_type,
LOCK_GAP, thr);
+ }
+
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
@@ -3395,30 +3517,27 @@ rec_loop:
is a non-delete marked record, then it is enough to lock its
existence with LOCK_REC_NOT_GAP. */
+ ulint lock_type;
+
if (!set_also_gap_locks
- || (unique_search && !rec_get_deleted_flag(rec))) {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_REC_NOT_GAP, thr);
+ || (unique_search && !rec_get_deleted_flag(rec, comp))) {
+ lock_type = LOCK_REC_NOT_GAP;
} else {
- /* If innodb_locks_unsafe_for_binlog option is used,
- we lock only the record, i.e. next-key locking is
- not used.
- */
- if ( srv_locks_unsafe_for_binlog )
- {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_REC_NOT_GAP, thr);
- }
- else
- {
- err = sel_set_rec_lock(rec, index,
- prebuilt->select_lock_type,
- LOCK_ORDINARY, thr);
- }
+ /* If innodb_locks_unsafe_for_binlog option is used,
+ we lock only the record, i.e., next-key locking is
+ not used. */
+
+ if (srv_locks_unsafe_for_binlog) {
+ lock_type = LOCK_REC_NOT_GAP;
+ } else {
+ lock_type = LOCK_ORDINARY;
+ }
}
-
+
+ err = sel_set_rec_lock(rec, index, offsets,
+ prebuilt->select_lock_type,
+ lock_type, thr);
+
if (err != DB_SUCCESS) {
goto lock_wait_or_error;
@@ -3441,7 +3560,7 @@ rec_loop:
if (srv_force_recovery < 5
&& !lock_clust_rec_cons_read_sees(rec, index,
- trx->read_view)) {
+ offsets, trx->read_view)) {
err = row_sel_build_prev_vers_for_mysql(
trx->read_view, clust_index,
@@ -3474,7 +3593,8 @@ rec_loop:
}
}
- if (rec_get_deleted_flag(rec) && !cons_read_requires_clust_rec) {
+ if (rec_get_deleted_flag(rec, comp)
+ && !cons_read_requires_clust_rec) {
/* The record is delete-marked: we can skip it if this is
not a consistent read which might see an earlier version
@@ -3510,7 +3630,7 @@ rec_loop:
goto next_rec;
}
- if (rec_get_deleted_flag(clust_rec)) {
+ if (rec_get_deleted_flag(clust_rec, comp)) {
/* The record is delete marked: we can skip it */
@@ -3522,6 +3642,15 @@ rec_loop:
}
}
+ if (prebuilt->need_to_access_clustered) {
+ ut_ad(rec == clust_rec || index == clust_index);
+ offsets = rec_reget_offsets(rec, clust_index,
+ offsets, ULINT_UNDEFINED, heap);
+ } else {
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
+ }
+
/* We found a qualifying row */
if (prebuilt->n_rows_fetched >= MYSQL_FETCH_CACHE_THRESHOLD
@@ -3541,7 +3670,7 @@ rec_loop:
not cache rows because there the cursor is a scrollable
cursor. */
- row_sel_push_cache_row_for_mysql(prebuilt, rec);
+ row_sel_push_cache_row_for_mysql(prebuilt, rec, offsets);
if (prebuilt->n_fetch_cached == MYSQL_FETCH_CACHE_SIZE) {
@@ -3551,11 +3680,13 @@ rec_loop:
goto next_rec;
} else {
if (prebuilt->template_type == ROW_MYSQL_DUMMY_TEMPLATE) {
- ut_memcpy(buf + 4, rec - rec_get_extra_size(rec),
- rec_get_size(rec));
- mach_write_to_4(buf, rec_get_extra_size(rec) + 4);
+ memcpy(buf + 4, rec - rec_offs_extra_size(offsets),
+ rec_offs_size(offsets));
+ mach_write_to_4(buf,
+ rec_offs_extra_size(offsets) + 4);
} else {
- if (!row_sel_store_mysql_rec(buf, prebuilt, rec)) {
+ if (!row_sel_store_mysql_rec(buf, prebuilt,
+ rec, offsets)) {
err = DB_TOO_BIG_RECORD;
goto lock_wait_or_error;
@@ -3563,8 +3694,10 @@ rec_loop:
}
if (prebuilt->clust_index_was_generated) {
+ offsets = rec_reget_offsets(index_rec, index, offsets,
+ ULINT_UNDEFINED, heap);
row_sel_store_row_id_to_prebuilt(prebuilt, index_rec,
- index);
+ index, offsets);
}
}
got_row:
@@ -3666,6 +3799,7 @@ lock_wait_or_error:
fprintf(stderr, " cnt %lu ret value %lu err\n", cnt, err); */
trx->op_info = "";
+ mem_heap_free(heap);
return(err);
normal_return:
@@ -3689,6 +3823,7 @@ normal_return:
trx->op_info = "";
+ mem_heap_free(heap);
return(ret);
}
diff --git a/innobase/row/row0umod.c b/innobase/row/row0umod.c
index e16d696314b..ee9066a0d6f 100644
--- a/innobase/row/row0umod.c
+++ b/innobase/row/row0umod.c
@@ -430,6 +430,7 @@ row_undo_mod_del_unmark_sec_and_undo_update(
found = row_search_index_entry(index, entry, mode, &pcur, &mtr);
if (!found) {
+ heap = mem_heap_create(100);
fputs("InnoDB: error in sec index entry del undo in\n"
"InnoDB: ", stderr);
dict_index_name_print(stderr, trx, index);
@@ -438,11 +439,14 @@ row_undo_mod_del_unmark_sec_and_undo_update(
dtuple_print(stderr, entry);
fputs("\n"
"InnoDB: record ", stderr);
- rec_print(stderr, btr_pcur_get_rec(&pcur));
+ rec_print(stderr, btr_pcur_get_rec(&pcur),
+ rec_get_offsets(btr_pcur_get_rec(&pcur),
+ index, ULINT_UNDEFINED, heap));
putc('\n', stderr);
trx_print(stderr, trx);
fputs("\n"
"InnoDB: Submit a detailed bug report to http://bugs.mysql.com\n", stderr);
+ mem_heap_free(heap);
} else {
btr_cur_t* btr_cur = btr_pcur_get_btr_cur(&pcur);
diff --git a/innobase/row/row0undo.c b/innobase/row/row0undo.c
index bc3cc8ea9f3..42f5ef94854 100644
--- a/innobase/row/row0undo.c
+++ b/innobase/row/row0undo.c
@@ -151,6 +151,8 @@ row_undo_search_clust_to_pcur(
mtr_t mtr;
ibool ret;
rec_t* rec;
+ mem_heap_t* heap;
+ const ulint* offsets;
mtr_start(&mtr);
@@ -161,8 +163,11 @@ row_undo_search_clust_to_pcur(
rec = btr_pcur_get_rec(&(node->pcur));
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, clust_index, ULINT_UNDEFINED, heap);
+
if (!found || 0 != ut_dulint_cmp(node->roll_ptr,
- row_get_rec_roll_ptr(rec, clust_index))) {
+ row_get_rec_roll_ptr(rec, clust_index, offsets))) {
/* We must remove the reservation on the undo log record
BEFORE releasing the latch on the clustered index page: this
@@ -175,7 +180,7 @@ row_undo_search_clust_to_pcur(
ret = FALSE;
} else {
node->row = row_build(ROW_COPY_DATA, clust_index, rec,
- node->heap);
+ offsets, node->heap);
btr_pcur_store_position(&(node->pcur), &mtr);
ret = TRUE;
diff --git a/innobase/row/row0upd.c b/innobase/row/row0upd.c
index a449b9f1736..e080d0ba577 100644
--- a/innobase/row/row0upd.c
+++ b/innobase/row/row0upd.c
@@ -301,19 +301,20 @@ recovery. */
void
row_upd_rec_sys_fields_in_recovery(
/*===============================*/
- rec_t* rec, /* in: record */
- ulint pos, /* in: TRX_ID position in rec */
- dulint trx_id, /* in: transaction id */
- dulint roll_ptr)/* in: roll ptr of the undo log record */
+ rec_t* rec, /* in: record */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ ulint pos, /* in: TRX_ID position in rec */
+ dulint trx_id, /* in: transaction id */
+ dulint roll_ptr)/* in: roll ptr of the undo log record */
{
byte* field;
ulint len;
- field = rec_get_nth_field(rec, pos, &len);
+ field = rec_get_nth_field(rec, offsets, pos, &len);
ut_ad(len == DATA_TRX_ID_LEN);
trx_write_trx_id(field, trx_id);
- field = rec_get_nth_field(rec, pos + 1, &len);
+ field = rec_get_nth_field(rec, offsets, pos + 1, &len);
ut_ad(len == DATA_ROLL_PTR_LEN);
trx_write_roll_ptr(field, roll_ptr);
}
@@ -361,8 +362,8 @@ row_upd_changes_field_size_or_external(
/* out: TRUE if the update changes the size of
some field in index or the field is external
in rec or update */
- rec_t* rec, /* in: record in index */
dict_index_t* index, /* in: index */
+ const ulint* offsets,/* in: rec_get_offsets(rec, index) */
upd_t* update) /* in: update vector */
{
upd_field_t* upd_field;
@@ -372,6 +373,7 @@ row_upd_changes_field_size_or_external(
ulint n_fields;
ulint i;
+ ut_ad(rec_offs_validate(NULL, index, offsets));
n_fields = upd_get_n_fields(update);
for (i = 0; i < n_fields; i++) {
@@ -380,19 +382,19 @@ row_upd_changes_field_size_or_external(
new_val = &(upd_field->new_val);
new_len = new_val->len;
- if (new_len == UNIV_SQL_NULL) {
+ if (new_len == UNIV_SQL_NULL && !rec_offs_comp(offsets)) {
new_len = dtype_get_sql_null_size(
dict_index_get_nth_type(index, i));
}
- old_len = rec_get_nth_field_size(rec, upd_field->field_no);
-
+ old_len = rec_offs_nth_size(offsets, upd_field->field_no);
+
if (old_len != new_len) {
return(TRUE);
}
- if (rec_get_nth_field_extern_bit(rec, upd_field->field_no)) {
+ if (rec_offs_nth_extern(offsets, upd_field->field_no)) {
return(TRUE);
}
@@ -414,15 +416,18 @@ a clustered index */
void
row_upd_rec_in_place(
/*=================*/
- rec_t* rec, /* in/out: record where replaced */
- upd_t* update) /* in: update vector */
+ rec_t* rec, /* in/out: record where replaced */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
+ upd_t* update) /* in: update vector */
{
upd_field_t* upd_field;
dfield_t* new_val;
ulint n_fields;
ulint i;
- rec_set_info_bits(rec, update->info_bits);
+ ut_ad(rec_offs_validate(rec, NULL, offsets));
+
+ rec_set_info_bits(rec, rec_offs_comp(offsets), update->info_bits);
n_fields = upd_get_n_fields(update);
@@ -430,7 +435,7 @@ row_upd_rec_in_place(
upd_field = upd_get_nth_field(update, i);
new_val = &(upd_field->new_val);
- rec_set_nth_field(rec, upd_field->field_no,
+ rec_set_nth_field(rec, offsets, upd_field->field_no,
dfield_get_data(new_val),
dfield_get_len(new_val));
}
@@ -695,6 +700,7 @@ row_upd_build_sec_rec_difference_binary(
upd_t* update;
ulint n_diff;
ulint i;
+ const ulint* offsets;
/* This function is used only for a secondary index */
ut_a(0 == (index->type & DICT_CLUSTERED));
@@ -702,10 +708,11 @@ row_upd_build_sec_rec_difference_binary(
update = upd_create(dtuple_get_n_fields(entry), heap);
n_diff = 0;
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
for (i = 0; i < dtuple_get_n_fields(entry); i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
dfield = dtuple_get_nth_field(entry, i);
@@ -768,6 +775,7 @@ row_upd_build_difference_binary(
ulint trx_id_pos;
ibool extern_bit;
ulint i;
+ const ulint* offsets;
/* This function is used only for a clustered index */
ut_a(index->type & DICT_CLUSTERED);
@@ -779,9 +787,11 @@ row_upd_build_difference_binary(
roll_ptr_pos = dict_index_get_sys_col_pos(index, DATA_ROLL_PTR);
trx_id_pos = dict_index_get_sys_col_pos(index, DATA_TRX_ID);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
for (i = 0; i < dtuple_get_n_fields(entry); i++) {
- data = rec_get_nth_field(rec, i, &len);
+ data = rec_get_nth_field(rec, offsets, i, &len);
dfield = dtuple_get_nth_field(entry, i);
@@ -793,7 +803,7 @@ row_upd_build_difference_binary(
goto skip_compare;
}
- extern_bit = rec_get_nth_field_extern_bit(rec, i);
+ extern_bit = rec_offs_nth_extern(offsets, i);
if (extern_bit != upd_ext_vec_contains(ext_vec, n_ext_vec, i)
|| !dfield_data_is_binary_equal(dfield, len, data)) {
@@ -1117,6 +1127,7 @@ void
row_upd_copy_columns(
/*=================*/
rec_t* rec, /* in: record in a clustered index */
+ const ulint* offsets,/* in: array returned by rec_get_offsets() */
sym_node_t* column) /* in: first column in a column list, or
NULL */
{
@@ -1124,7 +1135,7 @@ row_upd_copy_columns(
ulint len;
while (column) {
- data = rec_get_nth_field(rec,
+ data = rec_get_nth_field(rec, offsets,
column->field_nos[SYM_CLUST_FIELD_NO],
&len);
eval_node_copy_and_alloc_val(column, data, len);
@@ -1171,7 +1182,9 @@ row_upd_store_row(
dict_index_t* clust_index;
upd_t* update;
rec_t* rec;
-
+ mem_heap_t* heap;
+ const ulint* offsets;
+
ut_ad(node->pcur->latch_mode != BTR_NO_LATCHES);
if (node->row != NULL) {
@@ -1183,10 +1196,12 @@ row_upd_store_row(
rec = btr_pcur_get_rec(node->pcur);
- node->row = row_build(ROW_COPY_DATA, clust_index, rec, node->heap);
-
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, clust_index, ULINT_UNDEFINED, heap);
+ node->row = row_build(ROW_COPY_DATA, clust_index, rec, offsets,
+ node->heap);
node->ext_vec = mem_heap_alloc(node->heap, sizeof(ulint)
- * rec_get_n_fields(rec));
+ * rec_offs_n_fields(offsets));
if (node->is_delete) {
update = NULL;
} else {
@@ -1194,7 +1209,8 @@ row_upd_store_row(
}
node->n_ext_vec = btr_push_update_extern_fields(node->ext_vec,
- rec, update);
+ offsets, update);
+ mem_heap_free(heap);
}
/***************************************************************
@@ -1247,7 +1263,8 @@ row_upd_sec_index_entry(
dtuple_print(stderr, entry);
fputs("\n"
"InnoDB: record ", stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec,
+ rec_get_offsets(rec, index, ULINT_UNDEFINED, heap));
putc('\n', stderr);
trx_print(stderr, trx);
@@ -1259,7 +1276,7 @@ row_upd_sec_index_entry(
delete marked if we return after a lock wait in
row_ins_index_entry below */
- if (!rec_get_deleted_flag(rec)) {
+ if (!rec_get_deleted_flag(rec, index->table->comp)) {
err = btr_cur_del_mark_set_sec_rec(0, btr_cur, TRUE,
thr, &mtr);
if (err == DB_SUCCESS && check_ref) {
@@ -1362,6 +1379,7 @@ row_upd_clust_rec_by_insert(
table = node->table;
pcur = node->pcur;
btr_cur = btr_pcur_get_btr_cur(pcur);
+ heap = mem_heap_create(500);
if (node->state != UPD_NODE_INSERT_CLUSTERED) {
@@ -1369,7 +1387,7 @@ row_upd_clust_rec_by_insert(
btr_cur, TRUE, thr, mtr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
-
+ mem_heap_free(heap);
return(err);
}
@@ -1379,7 +1397,9 @@ row_upd_clust_rec_by_insert(
record is removed from the index tree, or updated. */
btr_cur_mark_extern_inherited_fields(btr_cur_get_rec(btr_cur),
- node->update, mtr);
+ rec_get_offsets(btr_cur_get_rec(btr_cur),
+ dict_table_get_first_index(table),
+ ULINT_UNDEFINED, heap), node->update, mtr);
if (check_ref) {
/* NOTE that the following call loses
the position of pcur ! */
@@ -1399,8 +1419,6 @@ row_upd_clust_rec_by_insert(
node->state = UPD_NODE_INSERT_CLUSTERED;
- heap = mem_heap_create(500);
-
entry = row_build_index_entry(node->row, index, heap);
row_upd_index_replace_new_col_vals(entry, index, node->update, NULL);
@@ -1452,7 +1470,8 @@ row_upd_clust_rec(
pcur = node->pcur;
btr_cur = btr_pcur_get_btr_cur(pcur);
- ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur)));
+ ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
+ index->table->comp));
/* Try optimistic updating of the record, keeping changes within
the page; we do not check locks because we assume the x-lock on the
@@ -1488,7 +1507,8 @@ row_upd_clust_rec(
ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
- ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur)));
+ ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
+ index->table->comp));
err = btr_cur_pessimistic_update(BTR_NO_LOCKING_FLAG, btr_cur,
&big_rec, node->update,
@@ -1496,12 +1516,17 @@ row_upd_clust_rec(
mtr_commit(mtr);
if (err == DB_SUCCESS && big_rec) {
+ mem_heap_t* heap;
+ rec_t* rec;
mtr_start(mtr);
+
+ heap = mem_heap_create(100);
+ rec = btr_cur_get_rec(btr_cur);
ut_a(btr_pcur_restore_position(BTR_MODIFY_TREE, pcur, mtr));
-
- err = btr_store_big_rec_extern_fields(index,
- btr_cur_get_rec(btr_cur),
- big_rec, mtr);
+ err = btr_store_big_rec_extern_fields(index, rec,
+ rec_get_offsets(rec, index, ULINT_UNDEFINED, heap),
+ big_rec, mtr);
+ mem_heap_free(heap);
mtr_commit(mtr);
}
@@ -1585,7 +1610,10 @@ row_upd_clust_step(
ulint err;
mtr_t* mtr;
mtr_t mtr_buf;
-
+ rec_t* rec;
+ mem_heap_t* heap;
+ const ulint* offsets;
+
index = dict_table_get_first_index(node->table);
check_ref = row_upd_index_is_referenced(index, thr_get_trx(thr));
@@ -1641,13 +1669,16 @@ row_upd_clust_step(
}
}
+ rec = btr_pcur_get_rec(pcur);
+ heap = mem_heap_create(100);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
if (!node->has_clust_rec_x_lock) {
err = lock_clust_rec_modify_check_and_lock(0,
- btr_pcur_get_rec(pcur),
- index, thr);
+ rec, index, offsets, thr);
if (err != DB_SUCCESS) {
mtr_commit(mtr);
-
+ mem_heap_free(heap);
return(err);
}
}
@@ -1655,6 +1686,7 @@ row_upd_clust_step(
/* NOTE: the following function calls will also commit mtr */
if (node->is_delete) {
+ mem_heap_free(heap);
err = row_upd_del_mark_clust_rec(node, index, thr, check_ref,
mtr);
if (err != DB_SUCCESS) {
@@ -1674,12 +1706,13 @@ row_upd_clust_step(
if (!node->in_mysql_interface) {
/* Copy the necessary columns from clust_rec and calculate the
new values to set */
-
- row_upd_copy_columns(btr_pcur_get_rec(pcur),
+ row_upd_copy_columns(rec, offsets,
UT_LIST_GET_FIRST(node->columns));
row_upd_eval_new_vals(node->update);
}
+ mem_heap_free(heap);
+
if (node->cmpl_info & UPD_NODE_NO_ORD_CHANGE) {
err = row_upd_clust_rec(node, index, thr, mtr);
@@ -1935,6 +1968,7 @@ row_upd_in_place_in_select(
btr_pcur_t* pcur;
btr_cur_t* btr_cur;
ulint err;
+ mem_heap_t* heap;
ut_ad(sel_node->select_will_do_update);
ut_ad(sel_node->latch_mode == BTR_MODIFY_LEAF);
@@ -1950,11 +1984,15 @@ row_upd_in_place_in_select(
/* Copy the necessary columns from clust_rec and calculate the new
values to set */
- row_upd_copy_columns(btr_pcur_get_rec(pcur),
- UT_LIST_GET_FIRST(node->columns));
+ heap = mem_heap_create(100);
+ row_upd_copy_columns(btr_pcur_get_rec(pcur), rec_get_offsets(
+ btr_pcur_get_rec(pcur), btr_cur->index, ULINT_UNDEFINED, heap),
+ UT_LIST_GET_FIRST(node->columns));
+ mem_heap_free(heap);
row_upd_eval_new_vals(node->update);
- ut_ad(FALSE == rec_get_deleted_flag(btr_pcur_get_rec(pcur)));
+ ut_ad(!rec_get_deleted_flag(btr_pcur_get_rec(pcur),
+ btr_cur->index->table->comp));
ut_ad(node->cmpl_info & UPD_NODE_NO_SIZE_CHANGE);
ut_ad(node->cmpl_info & UPD_NODE_NO_ORD_CHANGE);
diff --git a/innobase/row/row0vers.c b/innobase/row/row0vers.c
index bc17ede89e3..5281dbd67d7 100644
--- a/innobase/row/row0vers.c
+++ b/innobase/row/row0vers.c
@@ -41,10 +41,12 @@ row_vers_impl_x_locked_off_kernel(
transaction; NOTE that the kernel mutex is
temporarily released! */
rec_t* rec, /* in: record in a secondary index */
- dict_index_t* index) /* in: the secondary index */
+ dict_index_t* index, /* in: the secondary index */
+ const ulint* offsets)/* in: rec_get_offsets(rec, index) */
{
dict_index_t* clust_index;
rec_t* clust_rec;
+ ulint* clust_offsets;
rec_t* version;
rec_t* prev_version;
dulint trx_id;
@@ -59,6 +61,7 @@ row_vers_impl_x_locked_off_kernel(
ibool rec_del;
ulint err;
mtr_t mtr;
+ ibool comp;
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
@@ -96,7 +99,10 @@ row_vers_impl_x_locked_off_kernel(
return(NULL);
}
- trx_id = row_get_rec_trx_id(clust_rec, clust_index);
+ heap = mem_heap_create(1024);
+ clust_offsets = rec_get_offsets(clust_rec, clust_index,
+ ULINT_UNDEFINED, heap);
+ trx_id = row_get_rec_trx_id(clust_rec, clust_index, clust_offsets);
mtr_s_lock(&(purge_sys->latch), &mtr);
@@ -106,19 +112,27 @@ row_vers_impl_x_locked_off_kernel(
/* The transaction that modified or inserted clust_rec is no
longer active: no implicit lock on rec */
+ mem_heap_free(heap);
mtr_commit(&mtr);
return(NULL);
}
- if (!lock_check_trx_id_sanity(trx_id, clust_rec, clust_index, TRUE)) {
+ if (!lock_check_trx_id_sanity(trx_id, clust_rec, clust_index,
+ clust_offsets, TRUE)) {
/* Corruption noticed: try to avoid a crash by returning */
+ mem_heap_free(heap);
mtr_commit(&mtr);
return(NULL);
}
+ comp = index->table->comp;
+ ut_ad(index->table == clust_index->table);
+ ut_ad(comp == page_is_comp(buf_frame_align(rec)));
+ ut_ad(comp == page_is_comp(buf_frame_align(clust_rec)));
+
/* We look up if some earlier version, which was modified by the trx_id
transaction, of the clustered index record would require rec to be in
a different state (delete marked or unmarked, or have different field
@@ -128,11 +142,10 @@ row_vers_impl_x_locked_off_kernel(
different state, then the trx_id transaction has not yet had time to
modify rec, and does not necessarily have an implicit x-lock on rec. */
- rec_del = rec_get_deleted_flag(rec);
+ rec_del = rec_get_deleted_flag(rec, comp);
trx = NULL;
version = clust_rec;
- heap = NULL;
for (;;) {
mutex_exit(&kernel_mutex);
@@ -146,18 +159,16 @@ row_vers_impl_x_locked_off_kernel(
heap2 = heap;
heap = mem_heap_create(1024);
-
err = trx_undo_prev_version_build(clust_rec, &mtr, version,
- clust_index, heap,
- &prev_version);
- if (heap2) {
- mem_heap_free(heap2); /* version was stored in heap2,
- if heap2 != NULL */
- }
+ clust_index, clust_offsets, heap,
+ &prev_version);
+ mem_heap_free(heap2); /* free version and clust_offsets */
if (prev_version) {
+ clust_offsets = rec_get_offsets(prev_version,
+ clust_index, ULINT_UNDEFINED, heap);
row = row_build(ROW_COPY_POINTERS, clust_index,
- prev_version, heap);
+ prev_version, clust_offsets, heap);
entry = row_build_index_entry(row, index, heap);
}
@@ -189,11 +200,11 @@ row_vers_impl_x_locked_off_kernel(
if prev_version would require rec to be in a different
state. */
- vers_del = rec_get_deleted_flag(prev_version);
+ vers_del = rec_get_deleted_flag(prev_version, comp);
/* We check if entry and rec are identified in the alphabetical
ordering */
- if (0 == cmp_dtuple_rec(entry, rec)) {
+ if (0 == cmp_dtuple_rec(entry, rec, offsets)) {
/* The delete marks of rec and prev_version should be
equal for rec to be in the state required by
prev_version */
@@ -211,7 +222,7 @@ row_vers_impl_x_locked_off_kernel(
dtuple_set_types_binary(entry,
dtuple_get_n_fields(entry));
- if (0 != cmp_dtuple_rec(entry, rec)) {
+ if (0 != cmp_dtuple_rec(entry, rec, offsets)) {
trx = trx_get_on_id(trx_id);
@@ -226,7 +237,8 @@ row_vers_impl_x_locked_off_kernel(
break;
}
- prev_trx_id = row_get_rec_trx_id(prev_version, clust_index);
+ prev_trx_id = row_get_rec_trx_id(prev_version, clust_index,
+ clust_offsets);
if (0 != ut_dulint_cmp(trx_id, prev_trx_id)) {
/* The versions modified by the trx_id transaction end
@@ -297,12 +309,14 @@ row_vers_old_has_index_entry(
rec_t* version;
rec_t* prev_version;
dict_index_t* clust_index;
+ ulint* clust_offsets;
mem_heap_t* heap;
mem_heap_t* heap2;
dtuple_t* row;
dtuple_t* entry;
ulint err;
-
+ ibool comp;
+
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
|| mtr_memo_contains(mtr, buf_block_align(rec),
MTR_MEMO_PAGE_S_FIX));
@@ -313,10 +327,15 @@ row_vers_old_has_index_entry(
clust_index = dict_table_get_first_index(index->table);
- if (also_curr && !rec_get_deleted_flag(rec)) {
+ comp = index->table->comp;
+ ut_ad(comp == page_is_comp(buf_frame_align(rec)));
+ heap = mem_heap_create(1024);
+ clust_offsets = rec_get_offsets(rec, clust_index,
+ ULINT_UNDEFINED, heap);
- heap = mem_heap_create(1024);
- row = row_build(ROW_COPY_POINTERS, clust_index, rec, heap);
+ if (also_curr && !rec_get_deleted_flag(rec, comp)) {
+ row = row_build(ROW_COPY_POINTERS, clust_index,
+ rec, clust_offsets, heap);
entry = row_build_index_entry(row, index, heap);
/* NOTE that we cannot do the comparison as binary
@@ -331,24 +350,17 @@ row_vers_old_has_index_entry(
return(TRUE);
}
-
- mem_heap_free(heap);
}
version = rec;
- heap = NULL;
for (;;) {
heap2 = heap;
heap = mem_heap_create(1024);
-
err = trx_undo_prev_version_build(rec, mtr, version,
- clust_index, heap,
- &prev_version);
- if (heap2) {
- mem_heap_free(heap2); /* version was stored in heap2,
- if heap2 != NULL */
- }
+ clust_index, clust_offsets, heap,
+ &prev_version);
+ mem_heap_free(heap2); /* free version and clust_offsets */
if (err != DB_SUCCESS || !prev_version) {
/* Versions end here */
@@ -358,9 +370,12 @@ row_vers_old_has_index_entry(
return(FALSE);
}
- if (!rec_get_deleted_flag(prev_version)) {
+ clust_offsets = rec_get_offsets(prev_version, clust_index,
+ ULINT_UNDEFINED, heap);
+
+ if (!rec_get_deleted_flag(prev_version, comp)) {
row = row_build(ROW_COPY_POINTERS, clust_index,
- prev_version, heap);
+ prev_version, clust_offsets, heap);
entry = row_build_index_entry(row, index, heap);
/* NOTE that we cannot do the comparison as binary
@@ -412,6 +427,7 @@ row_vers_build_for_consistent_read(
mem_heap_t* heap2;
byte* buf;
ulint err;
+ ulint* offsets;
ut_ad(index->type & DICT_CLUSTERED);
ut_ad(mtr_memo_contains(mtr, buf_block_align(rec), MTR_MEMO_PAGE_X_FIX)
@@ -420,22 +436,23 @@ row_vers_build_for_consistent_read(
#ifdef UNIV_SYNC_DEBUG
ut_ad(!rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
- ut_ad(!read_view_sees_trx_id(view, row_get_rec_trx_id(rec, index)));
+
+ heap = mem_heap_create(1024);
+ offsets = rec_get_offsets(rec, index, ULINT_UNDEFINED, heap);
+
+ ut_ad(!read_view_sees_trx_id(view,
+ row_get_rec_trx_id(rec, index, offsets)));
rw_lock_s_lock(&(purge_sys->latch));
version = rec;
- heap = NULL;
for (;;) {
heap2 = heap;
heap = mem_heap_create(1024);
err = trx_undo_prev_version_build(rec, mtr, version, index,
- heap, &prev_version);
- if (heap2) {
- mem_heap_free(heap2); /* version was stored in heap2,
- if heap2 != NULL */
- }
+ offsets, heap, &prev_version);
+ mem_heap_free(heap2); /* free version and offsets */
if (err != DB_SUCCESS) {
break;
@@ -449,16 +466,17 @@ row_vers_build_for_consistent_read(
break;
}
- prev_trx_id = row_get_rec_trx_id(prev_version, index);
+ offsets = rec_get_offsets(prev_version, index,
+ ULINT_UNDEFINED, heap);
+ prev_trx_id = row_get_rec_trx_id(prev_version, index, offsets);
if (read_view_sees_trx_id(view, prev_trx_id)) {
/* The view already sees this version: we can copy
it to in_heap and return */
- buf = mem_heap_alloc(in_heap, rec_get_size(
- prev_version));
- *old_vers = rec_copy(buf, prev_version);
+ buf = mem_heap_alloc(in_heap, rec_offs_size(offsets));
+ *old_vers = rec_copy(buf, prev_version, offsets);
err = DB_SUCCESS;
break;
diff --git a/innobase/srv/srv0srv.c b/innobase/srv/srv0srv.c
index b8d03cfab5f..40befae424e 100644
--- a/innobase/srv/srv0srv.c
+++ b/innobase/srv/srv0srv.c
@@ -44,6 +44,7 @@ Created 10/8/1995 Heikki Tuuri
#include "buf0flu.h"
#include "btr0sea.h"
#include "dict0load.h"
+#include "dict0boot.h"
#include "srv0start.h"
#include "row0mysql.h"
@@ -186,6 +187,61 @@ that during a time of heavy update/insert activity. */
ulint srv_max_buf_pool_modified_pct = 90;
+/* variable counts amount of data read in total (in bytes) */
+ulint srv_data_read = 0;
+
+/* here we count the amount of data written in total (in bytes) */
+ulint srv_data_written = 0;
+
+/* the number of the log write requests done */
+ulint srv_log_write_requests = 0;
+
+/* the number of physical writes to the log performed */
+ulint srv_log_writes = 0;
+
+/* amount of data written to the log files in bytes */
+ulint srv_os_log_written = 0;
+
+/* amount of writes being done to the log files */
+ulint srv_os_log_pending_writes = 0;
+
+/* we increase this counter, when there we don't have enough space in the
+log buffer and have to flush it */
+ulint srv_log_waits = 0;
+
+/* this variable counts the amount of times, when the doublewrite buffer
+was flushed */
+ulint srv_dblwr_writes = 0;
+
+/* here we store the number of pages that have been flushed to the
+doublewrite buffer */
+ulint srv_dblwr_pages_written = 0;
+
+/* in this variable we store the number of write requests issued */
+ulint srv_buf_pool_write_requests = 0;
+
+/* here we store the number of times when we had to wait for a free page
+in the buffer pool. It happens when the buffer pool is full and we need
+to make a flush, in order to be able to read or create a page. */
+ulint srv_buf_pool_wait_free = 0;
+
+/* variable to count the number of pages that were written from buffer
+pool to the disk */
+ulint srv_buf_pool_flushed = 0;
+
+/* variable to count the number of buffer pool reads that led to the
+reading of a disk page */
+ulint srv_buf_pool_reads = 0;
+
+/* variable to count the number of sequential read-aheads */
+ulint srv_read_ahead_seq = 0;
+
+/* variable to count the number of random read-aheads */
+ulint srv_read_ahead_rnd = 0;
+
+/* structure to pass status variables to MySQL */
+export_struc export_vars;
+
/* If the following is != 0 we do not allow inserts etc. This protects
the user from forgetting the innodb_force_recovery keyword to my.cnf */
@@ -790,6 +846,7 @@ srv_init(void)
{
srv_conc_slot_t* conc_slot;
srv_slot_t* slot;
+ dict_table_t* table;
ulint i;
srv_sys = mem_alloc(sizeof(srv_sys_t));
@@ -839,6 +896,31 @@ srv_init(void)
UT_LIST_INIT(srv_sys->tasks);
+ /* create dummy table and index for old-style infimum and supremum */
+ table = dict_mem_table_create("SYS_DUMMY1",
+ DICT_HDR_SPACE, 1, FALSE);
+ dict_mem_table_add_col(table, "DUMMY", DATA_CHAR,
+ DATA_ENGLISH | DATA_NOT_NULL, 8, 0);
+
+ srv_sys->dummy_ind1 = dict_mem_index_create("SYS_DUMMY1",
+ "SYS_DUMMY1", DICT_HDR_SPACE, 0, 1);
+ dict_index_add_col(srv_sys->dummy_ind1,
+ dict_table_get_nth_col(table, 0), 0, 0);
+ srv_sys->dummy_ind1->table = table;
+ /* create dummy table and index for new-style infimum and supremum */
+ table = dict_mem_table_create("SYS_DUMMY2",
+ DICT_HDR_SPACE, 1, TRUE);
+ dict_mem_table_add_col(table, "DUMMY", DATA_CHAR,
+ DATA_ENGLISH | DATA_NOT_NULL, 8, 0);
+ srv_sys->dummy_ind2 = dict_mem_index_create("SYS_DUMMY2",
+ "SYS_DUMMY2", DICT_HDR_SPACE, 0, 1);
+ dict_index_add_col(srv_sys->dummy_ind2,
+ dict_table_get_nth_col(table, 0), 0, 0);
+ srv_sys->dummy_ind2->table = table;
+
+ /* avoid ut_ad(index->cached) in dict_index_get_n_unique_in_tree */
+ srv_sys->dummy_ind1->cached = srv_sys->dummy_ind2->cached = TRUE;
+
/* Init the server concurrency restriction data structures */
os_fast_mutex_init(&srv_conc_mutex);
@@ -1619,6 +1701,57 @@ srv_printf_innodb_monitor(
fflush(file);
}
+/**********************************************************************
+Function to pass InnoDB status variables to MySQL */
+
+void
+srv_export_innodb_status(void)
+{
+
+ mutex_enter(&srv_innodb_monitor_mutex);
+ export_vars.innodb_data_pending_reads= os_n_pending_reads;
+ export_vars.innodb_data_pending_writes= os_n_pending_writes;
+ export_vars.innodb_data_pending_fsyncs=
+ fil_n_pending_log_flushes + fil_n_pending_tablespace_flushes;
+ export_vars.innodb_data_fsyncs= os_n_fsyncs;
+ export_vars.innodb_data_read= srv_data_read;
+ export_vars.innodb_data_reads= os_n_file_reads;
+ export_vars.innodb_data_writes= os_n_file_writes;
+ export_vars.innodb_data_written= srv_data_written;
+ export_vars.innodb_buffer_pool_read_requests= buf_pool->n_page_gets;
+ export_vars.innodb_buffer_pool_write_requests= srv_buf_pool_write_requests;
+ export_vars.innodb_buffer_pool_wait_free= srv_buf_pool_wait_free;
+ export_vars.innodb_buffer_pool_pages_flushed= srv_buf_pool_flushed;
+ export_vars.innodb_buffer_pool_reads= srv_buf_pool_reads;
+ export_vars.innodb_buffer_pool_read_ahead_rnd= srv_read_ahead_rnd;
+ export_vars.innodb_buffer_pool_read_ahead_seq= srv_read_ahead_seq;
+ export_vars.innodb_buffer_pool_pages_data= UT_LIST_GET_LEN(buf_pool->LRU);
+ export_vars.innodb_buffer_pool_pages_dirty= UT_LIST_GET_LEN(buf_pool->flush_list);
+ export_vars.innodb_buffer_pool_pages_free= UT_LIST_GET_LEN(buf_pool->free);
+ export_vars.innodb_buffer_pool_pages_latched= buf_get_latched_pages_number();
+ export_vars.innodb_buffer_pool_pages_total= buf_pool->curr_size;
+ export_vars.innodb_buffer_pool_pages_misc= buf_pool->max_size -
+ UT_LIST_GET_LEN(buf_pool->LRU) - UT_LIST_GET_LEN(buf_pool->free);
+ export_vars.innodb_page_size= UNIV_PAGE_SIZE;
+ export_vars.innodb_log_waits= srv_log_waits;
+ export_vars.innodb_os_log_written= srv_os_log_written;
+ export_vars.innodb_os_log_fsyncs= fil_n_log_flushes;
+ export_vars.innodb_os_log_pending_fsyncs= fil_n_pending_log_flushes;
+ export_vars.innodb_os_log_pending_writes= srv_os_log_pending_writes;
+ export_vars.innodb_log_write_requests= srv_log_write_requests;
+ export_vars.innodb_log_writes= srv_log_writes;
+ export_vars.innodb_dblwr_pages_written= srv_dblwr_pages_written;
+ export_vars.innodb_dblwr_writes= srv_dblwr_writes;
+ export_vars.innodb_pages_created= buf_pool->n_pages_created;
+ export_vars.innodb_pages_read= buf_pool->n_pages_read;
+ export_vars.innodb_pages_written= buf_pool->n_pages_written;
+ export_vars.innodb_rows_read= srv_n_rows_read;
+ export_vars.innodb_rows_inserted= srv_n_rows_inserted;
+ export_vars.innodb_rows_updated= srv_n_rows_updated;
+ export_vars.innodb_rows_deleted= srv_n_rows_deleted;
+ mutex_exit(&srv_innodb_monitor_mutex);
+}
+
/*************************************************************************
A thread which wakes up threads whose lock wait may have lasted too long.
This also prints the info output by various InnoDB monitors. */
@@ -1677,11 +1810,13 @@ loop:
srv_printf_innodb_monitor(stderr);
}
- mutex_enter(&srv_monitor_file_mutex);
- rewind(srv_monitor_file);
- srv_printf_innodb_monitor(srv_monitor_file);
- os_file_set_eof(srv_monitor_file);
- mutex_exit(&srv_monitor_file_mutex);
+ if (srv_innodb_status) {
+ mutex_enter(&srv_monitor_file_mutex);
+ rewind(srv_monitor_file);
+ srv_printf_innodb_monitor(srv_monitor_file);
+ os_file_set_eof(srv_monitor_file);
+ mutex_exit(&srv_monitor_file_mutex);
+ }
if (srv_print_innodb_tablespace_monitor
&& difftime(current_time, last_table_monitor_time) > 60) {
diff --git a/innobase/srv/srv0start.c b/innobase/srv/srv0start.c
index 9709f5235de..69341a1d7d1 100644
--- a/innobase/srv/srv0start.c
+++ b/innobase/srv/srv0start.c
@@ -1172,6 +1172,9 @@ NetWare. */
}
if (ret == NULL) {
+ fprintf(stderr,
+"InnoDB: Fatal error: cannot allocate the memory for the buffer pool\n");
+
return(DB_ERROR);
}
diff --git a/innobase/trx/trx0purge.c b/innobase/trx/trx0purge.c
index 6726d7ca609..3df34111281 100644
--- a/innobase/trx/trx0purge.c
+++ b/innobase/trx/trx0purge.c
@@ -289,7 +289,7 @@ trx_purge_add_update_undo_to_history(
flst_get_len(seg_header + TRX_UNDO_PAGE_LIST, mtr));
mlog_write_ulint(rseg_header + TRX_RSEG_HISTORY_SIZE,
- hist_size + undo->size, MLOG_4BYTES, mtr);
+ hist_size + undo->size, MLOG_4BYTES, mtr);
}
/* Add the log as the first in the history list */
@@ -646,6 +646,27 @@ trx_purge_rseg_get_next_history_log(
mutex_exit(&(rseg->mutex));
mtr_commit(&mtr);
+ mutex_enter(&kernel_mutex);
+
+ /* Add debug code to track history list corruption reported
+ on the MySQL mailing list on Nov 9, 2004. The fut0lst.c
+ file-based list was corrupt. The prev node pointer was
+ FIL_NULL, even though the list length was over 8 million nodes!
+ We assume that purge truncates the history list in moderate
+ size pieces, and if we here reach the head of the list, the
+ list cannot be longer than 20 000 undo logs now. */
+
+ if (trx_sys->rseg_history_len > 20000) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Warning: purge reached the head of the history list,\n"
+"InnoDB: but its length is still reported as %lu! Make a detailed bug\n"
+"InnoDB: report, and post it to bugs.mysql.com\n",
+ (ulong)trx_sys->rseg_history_len);
+ }
+
+ mutex_exit(&kernel_mutex);
+
return;
}
@@ -1069,30 +1090,6 @@ trx_purge(void)
}
}
- /* Determine how much data manipulation language (DML) statements
- need to be delayed in order to reduce the lagging of the purge
- thread. */
- srv_dml_needed_delay = 0; /* in microseconds; default: no delay */
-
- /* If we cannot advance the 'purge view' because of an old
- 'consistent read view', then the DML statements cannot be delayed.
- Also, srv_max_purge_lag <= 0 means 'infinity'. */
- if (srv_max_purge_lag > 0
- && !UT_LIST_GET_LAST(trx_sys->view_list)) {
- float ratio = (float) trx_sys->rseg_history_len
- / srv_max_purge_lag;
- if (ratio > ULINT_MAX / 10000) {
- /* Avoid overflow: maximum delay is 4295 seconds */
- srv_dml_needed_delay = ULINT_MAX;
- } else if (ratio > 1) {
- /* If the history list length exceeds the
- innodb_max_purge_lag, the
- data manipulation statements are delayed
- by at least 5000 microseconds. */
- srv_dml_needed_delay = (ulint) ((ratio - .5) * 10000);
- }
- }
-
purge_sys->view = read_view_oldest_copy_or_open_new(NULL,
purge_sys->heap);
mutex_exit(&kernel_mutex);
diff --git a/innobase/trx/trx0rec.c b/innobase/trx/trx0rec.c
index fe429d1cc62..484d4f62744 100644
--- a/innobase/trx/trx0rec.c
+++ b/innobase/trx/trx0rec.c
@@ -38,16 +38,18 @@ trx_undof_page_add_undo_rec_log(
ulint new_free, /* in: end offset of the entry */
mtr_t* mtr) /* in: mtr */
{
- byte* log_ptr;
- ulint len;
+ byte* log_ptr;
+ const byte* log_end;
+ ulint len;
- log_ptr = mlog_open(mtr, 30 + MLOG_BUF_MARGIN);
+ log_ptr = mlog_open(mtr, 11 + 13 + MLOG_BUF_MARGIN);
if (log_ptr == NULL) {
return;
}
+ log_end = &log_ptr[11 + 13 + MLOG_BUF_MARGIN];
log_ptr = mlog_write_initial_log_record_fast(undo_page,
MLOG_UNDO_INSERT, log_ptr, mtr);
len = new_free - old_free - 4;
@@ -55,14 +57,11 @@ trx_undof_page_add_undo_rec_log(
mach_write_to_2(log_ptr, len);
log_ptr += 2;
- if (len < 256) {
- ut_memcpy(log_ptr, undo_page + old_free + 2, len);
- log_ptr += len;
- }
-
- mlog_close(mtr, log_ptr);
-
- if (len >= MLOG_BUF_MARGIN) {
+ if (log_ptr + len <= log_end) {
+ memcpy(log_ptr, undo_page + old_free + 2, len);
+ mlog_close(mtr, log_ptr + len);
+ } else {
+ mlog_close(mtr, log_ptr);
mlog_catenate_string(mtr, undo_page + old_free + 2, len);
}
}
@@ -404,6 +403,7 @@ trx_undo_page_report_modify(
delete marking is done */
rec_t* rec, /* in: clustered index record which
has NOT yet been modified */
+ const ulint* offsets, /* in: rec_get_offsets(rec, index) */
upd_t* update, /* in: update vector which tells the
columns to be updated; in the case of
a delete, this should be set to NULL */
@@ -430,6 +430,7 @@ trx_undo_page_report_modify(
ulint i;
ut_a(index->type & DICT_CLUSTERED);
+ ut_ad(rec_offs_validate(rec, index, offsets));
ut_ad(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_TYPE) == TRX_UNDO_UPDATE);
table = index->table;
@@ -454,7 +455,7 @@ trx_undo_page_report_modify(
/* Store first some general parameters to the undo log */
if (update) {
- if (rec_get_deleted_flag(rec)) {
+ if (rec_get_deleted_flag(rec, table->comp)) {
type_cmpl = TRX_UNDO_UPD_DEL_REC;
} else {
type_cmpl = TRX_UNDO_UPD_EXIST_REC;
@@ -479,14 +480,15 @@ trx_undo_page_report_modify(
/*----------------------------------------*/
/* Store the state of the info bits */
- bits = rec_get_info_bits(rec);
+ bits = rec_get_info_bits(rec, table->comp);
mach_write_to_1(ptr, bits);
ptr += 1;
/* Store the values of the system columns */
- trx_id = dict_index_rec_get_sys_col(index, DATA_TRX_ID, rec);
-
- roll_ptr = dict_index_rec_get_sys_col(index, DATA_ROLL_PTR, rec);
+ trx_id = dict_index_rec_get_sys_col(index, offsets,
+ DATA_TRX_ID, rec);
+ roll_ptr = dict_index_rec_get_sys_col(index, offsets,
+ DATA_ROLL_PTR, rec);
len = mach_dulint_write_compressed(ptr, trx_id);
ptr += len;
@@ -499,7 +501,7 @@ trx_undo_page_report_modify(
for (i = 0; i < dict_index_get_n_unique(index); i++) {
- field = rec_get_nth_field(rec, i, &flen);
+ field = rec_get_nth_field(rec, offsets, i, &flen);
if (trx_undo_left(undo_page, ptr) < 4) {
@@ -547,14 +549,14 @@ trx_undo_page_report_modify(
ptr += len;
/* Save the old value of field */
- field = rec_get_nth_field(rec, pos, &flen);
+ field = rec_get_nth_field(rec, offsets, pos, &flen);
if (trx_undo_left(undo_page, ptr) < 5) {
return(0);
}
- if (rec_get_nth_field_extern_bit(rec, pos)) {
+ if (rec_offs_nth_extern(offsets, pos)) {
/* If a field has external storage, we add to
flen the flag */
@@ -631,7 +633,7 @@ trx_undo_page_report_modify(
ptr += len;
/* Save the old value of field */
- field = rec_get_nth_field(rec, pos, &flen);
+ field = rec_get_nth_field(rec, offsets, pos, &flen);
if (trx_undo_left(undo_page, ptr) < 5) {
@@ -1008,7 +1010,9 @@ trx_undo_report_row_operation(
ibool is_insert;
trx_rseg_t* rseg;
mtr_t mtr;
-
+ mem_heap_t* heap;
+ ulint* offsets = NULL;
+
ut_a(index->type & DICT_CLUSTERED);
if (flags & BTR_NO_UNDO_LOG_FLAG) {
@@ -1019,7 +1023,6 @@ trx_undo_report_row_operation(
}
ut_ad(thr);
- ut_a(index->type & DICT_CLUSTERED);
ut_ad((op_type != TRX_UNDO_INSERT_OP)
|| (clust_entry && !update && !rec));
@@ -1063,6 +1066,8 @@ trx_undo_report_row_operation(
mtr_start(&mtr);
+ heap = mem_heap_create(100);
+
for (;;) {
undo_page = buf_page_get_gen(undo->space, page_no,
RW_X_LATCH, undo->guess_page,
@@ -1079,9 +1084,10 @@ trx_undo_report_row_operation(
index, clust_entry,
&mtr);
} else {
+ offsets = rec_reget_offsets(rec, index,
+ offsets, ULINT_UNDEFINED, heap);
offset = trx_undo_page_report_modify(undo_page, trx,
- index, rec, update,
- cmpl_info, &mtr);
+ index, rec, offsets, update, cmpl_info, &mtr);
}
if (offset == 0) {
@@ -1123,7 +1129,7 @@ trx_undo_report_row_operation(
mutex_exit(&(trx->undo_mutex));
mtr_commit(&mtr);
-
+ mem_heap_free(heap);
return(DB_OUT_OF_FILE_SPACE);
}
}
@@ -1140,6 +1146,7 @@ trx_undo_report_row_operation(
*roll_ptr = trx_undo_build_roll_ptr(is_insert, rseg->id, page_no,
offset);
+ mem_heap_free(heap);
return(DB_SUCCESS);
}
@@ -1236,6 +1243,7 @@ trx_undo_prev_version_build(
index_rec page and purge_view */
rec_t* rec, /* in: version of a clustered index record */
dict_index_t* index, /* in: clustered index */
+ ulint* offsets,/* in: rec_get_offsets(rec, index) */
mem_heap_t* heap, /* in: memory heap from which the memory
needed is allocated */
rec_t** old_vers)/* out, own: previous version, or NULL if
@@ -1258,7 +1266,7 @@ trx_undo_prev_version_build(
ibool dummy_extern;
byte* buf;
ulint err;
-
+ ulint* index_offsets = NULL;
#ifdef UNIV_SYNC_DEBUG
ut_ad(rw_lock_own(&(purge_sys->latch), RW_LOCK_SHARED));
#endif /* UNIV_SYNC_DEBUG */
@@ -1266,21 +1274,25 @@ trx_undo_prev_version_build(
MTR_MEMO_PAGE_S_FIX) ||
mtr_memo_contains(index_mtr, buf_block_align(index_rec),
MTR_MEMO_PAGE_X_FIX));
+ ut_ad(rec_offs_validate(rec, index, offsets));
+
if (!(index->type & DICT_CLUSTERED)) {
fprintf(stderr, "InnoDB: Error: trying to access"
" update undo rec for non-clustered index %s\n"
"InnoDB: Submit a detailed bug report to"
" http://bugs.mysql.com\n"
"InnoDB: index record ", index->name);
- rec_print(stderr, index_rec);
+ index_offsets = rec_get_offsets(index_rec, index,
+ ULINT_UNDEFINED, heap);
+ rec_print(stderr, index_rec, index_offsets);
fputs("\n"
"InnoDB: record version ", stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, offsets);
putc('\n', stderr);
return(DB_ERROR);
}
- roll_ptr = row_get_rec_roll_ptr(rec, index);
+ roll_ptr = row_get_rec_roll_ptr(rec, index, offsets);
old_roll_ptr = roll_ptr;
*old_vers = NULL;
@@ -1292,7 +1304,7 @@ trx_undo_prev_version_build(
return(DB_SUCCESS);
}
- rec_trx_id = row_get_rec_trx_id(rec, index);
+ rec_trx_id = row_get_rec_trx_id(rec, index, offsets);
err = trx_undo_get_undo_rec(roll_ptr, rec_trx_id, &undo_rec, heap);
@@ -1341,10 +1353,12 @@ trx_undo_prev_version_build(
ut_print_buf(stderr, undo_rec, 150);
fputs("\n"
"InnoDB: index record ", stderr);
- rec_print(stderr, index_rec);
+ index_offsets = rec_get_offsets(index_rec, index,
+ ULINT_UNDEFINED, heap);
+ rec_print(stderr, index_rec, index_offsets);
fputs("\n"
"InnoDB: record version ", stderr);
- rec_print(stderr, rec);
+ rec_print(stderr, rec, offsets);
fprintf(stderr, "\n"
"InnoDB: Record trx id %lu %lu, update rec trx id %lu %lu\n"
"InnoDB: Roll ptr in rec %lu %lu, in update rec %lu %lu\n",
@@ -1358,11 +1372,10 @@ trx_undo_prev_version_build(
(ulong) ut_dulint_get_low(roll_ptr));
trx_purge_sys_print();
-
return(DB_ERROR);
}
- if (row_upd_changes_field_size_or_external(rec, index, update)) {
+ if (row_upd_changes_field_size_or_external(index, offsets, update)) {
ulint* ext_vect;
ulint n_ext_vect;
@@ -1372,27 +1385,28 @@ trx_undo_prev_version_build(
those fields that update updates to become externally stored
fields. Store the info to ext_vect: */
- ext_vect = mem_alloc(sizeof(ulint) * rec_get_n_fields(rec));
- n_ext_vect = btr_push_update_extern_fields(ext_vect, rec,
+ ext_vect = mem_alloc(sizeof(ulint)
+ * rec_offs_n_fields(offsets));
+ n_ext_vect = btr_push_update_extern_fields(ext_vect, offsets,
update);
entry = row_rec_to_index_entry(ROW_COPY_DATA, index, rec,
heap);
row_upd_index_replace_new_col_vals(entry, index, update, heap);
- buf = mem_heap_alloc(heap, rec_get_converted_size(entry));
+ buf = mem_heap_alloc(heap,
+ rec_get_converted_size(index, entry));
- *old_vers = rec_convert_dtuple_to_rec(buf, entry);
+ *old_vers = rec_convert_dtuple_to_rec(buf, index, entry);
/* Now set the extern bits in the old version of the record */
- rec_set_field_extern_bits(*old_vers, ext_vect, n_ext_vect,
- NULL);
+ rec_set_field_extern_bits(*old_vers, index,
+ ext_vect, n_ext_vect, NULL);
mem_free(ext_vect);
} else {
- buf = mem_heap_alloc(heap, rec_get_size(rec));
-
- *old_vers = rec_copy(buf, rec);
-
- row_upd_rec_in_place(*old_vers, update);
+ buf = mem_heap_alloc(heap, rec_offs_size(offsets));
+ *old_vers = rec_copy(buf, rec, offsets);
+ rec_offs_make_valid(*old_vers, index, offsets);
+ row_upd_rec_in_place(*old_vers, offsets, update);
}
return(DB_SUCCESS);
diff --git a/innobase/trx/trx0roll.c b/innobase/trx/trx0roll.c
index eb7c7f43f03..db5e16c7778 100644
--- a/innobase/trx/trx0roll.c
+++ b/innobase/trx/trx0roll.c
@@ -331,10 +331,11 @@ trx_savept_take(
/***********************************************************************
Rollback or clean up transactions which have no user session. If the
transaction already was committed, then we clean up a possible insert
-undo log. If the transaction was not yet committed, then we roll it back. */
+undo log. If the transaction was not yet committed, then we roll it back.
+Note: this is done in a background thread */
-void
-trx_rollback_or_clean_all_without_sess(void)
+void *
+trx_rollback_or_clean_all_without_sess(void *i)
/*========================================*/
{
mem_heap_t* heap;
@@ -362,7 +363,7 @@ trx_rollback_or_clean_all_without_sess(void)
fprintf(stderr,
"InnoDB: Starting rollback of uncommitted transactions\n");
} else {
- return;
+ os_thread_exit(i);
}
loop:
heap = mem_heap_create(512);
@@ -371,9 +372,15 @@ loop:
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
- while (trx && (trx->sess || (trx->conc_state == TRX_NOT_STARTED))) {
+ while (trx) {
- trx = UT_LIST_GET_NEXT(trx_list, trx);
+ if ((trx->sess || (trx->conc_state == TRX_NOT_STARTED))) {
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+ } else if (trx->conc_state == TRX_PREPARED) {
+ trx->sess = trx_dummy_sess;
+ } else {
+ break;
+ }
}
mutex_exit(&kernel_mutex);
@@ -384,10 +391,11 @@ loop:
mem_heap_free(heap);
- return;
+ os_thread_exit(i);
}
trx->sess = trx_dummy_sess;
+
if (trx->conc_state == TRX_COMMITTED_IN_MEMORY) {
fprintf(stderr, "InnoDB: Cleaning up trx with id %lu %lu\n",
@@ -486,6 +494,8 @@ loop:
mem_heap_free(heap);
goto loop;
+
+ os_thread_exit(i); /* not reached */
}
/***********************************************************************
diff --git a/innobase/trx/trx0sys.c b/innobase/trx/trx0sys.c
index 54bd5be01a1..35e18064329 100644
--- a/innobase/trx/trx0sys.c
+++ b/innobase/trx/trx0sys.c
@@ -887,8 +887,12 @@ trx_sys_init_at_db_start(void)
trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
for (;;) {
- rows_to_undo +=
+
+ if ( trx->conc_state != TRX_PREPARED) {
+ rows_to_undo +=
ut_conv_dulint_to_longlong(trx->undo_no);
+ }
+
trx = UT_LIST_GET_NEXT(trx_list, trx);
if (!trx) {
diff --git a/innobase/trx/trx0trx.c b/innobase/trx/trx0trx.c
index f7497ac4090..ab8bd898dd6 100644
--- a/innobase/trx/trx0trx.c
+++ b/innobase/trx/trx0trx.c
@@ -24,6 +24,7 @@ Created 3/26/1996 Heikki Tuuri
#include "thr0loc.h"
#include "btr0sea.h"
#include "os0proc.h"
+#include "trx0xa.h"
/* Copy of the prototype for innobase_mysql_print_thd: this
copy MUST be equal to the one in mysql/sql/ha_innodb.cc ! */
@@ -156,6 +157,10 @@ trx_create(
trx->read_view_heap = mem_heap_create(256);
trx->read_view = NULL;
+ /* Set X/Open XA transaction identification to NULL */
+ memset(&trx->xid,0,sizeof(trx->xid));
+ trx->xid.formatID = -1;
+
return(trx);
}
@@ -408,13 +413,22 @@ trx_lists_init_at_db_start(void)
trx = trx_create(NULL);
trx->id = undo->trx_id;
-
+ trx->xid = undo->xid;
trx->insert_undo = undo;
trx->rseg = rseg;
if (undo->state != TRX_UNDO_ACTIVE) {
- trx->conc_state = TRX_COMMITTED_IN_MEMORY;
+ /* Prepared transactions are left in
+ the prepared state waiting for a
+ commit or abort decision from MySQL */
+
+ if (undo->state == TRX_UNDO_PREPARED) {
+ trx->conc_state = TRX_PREPARED;
+ } else {
+ trx->conc_state =
+ TRX_COMMITTED_IN_MEMORY;
+ }
/* We give a dummy value for the trx no;
this should have no relevance since purge
@@ -457,10 +471,22 @@ trx_lists_init_at_db_start(void)
trx = trx_create(NULL);
trx->id = undo->trx_id;
+ trx->xid = undo->xid;
if (undo->state != TRX_UNDO_ACTIVE) {
- trx->conc_state =
- TRX_COMMITTED_IN_MEMORY;
+
+ /* Prepared transactions are left in
+ the prepared state waiting for a
+ commit or abort decision from MySQL */
+
+ if (undo->state == TRX_UNDO_PREPARED) {
+ trx->conc_state =
+ TRX_PREPARED;
+ } else {
+ trx->conc_state =
+ TRX_COMMITTED_IN_MEMORY;
+ }
+
/* We give a dummy value for the trx
number */
@@ -726,7 +752,8 @@ trx_commit_off_kernel(
mutex_enter(&kernel_mutex);
}
- ut_ad(trx->conc_state == TRX_ACTIVE);
+ ut_ad(trx->conc_state == TRX_ACTIVE || trx->conc_state == TRX_PREPARED);
+
#ifdef UNIV_SYNC_DEBUG
ut_ad(mutex_own(&kernel_mutex));
#endif /* UNIV_SYNC_DEBUG */
@@ -1667,3 +1694,239 @@ trx_print(
innobase_mysql_print_thd(f, trx->mysql_thd);
}
}
+
+/********************************************************************
+Prepares a transaction. */
+
+void
+trx_prepare_off_kernel(
+/*==================*/
+ trx_t* trx) /* in: transaction */
+{
+ page_t* update_hdr_page;
+ dulint lsn;
+ trx_rseg_t* rseg;
+ trx_undo_t* undo;
+ ibool must_flush_log = FALSE;
+ mtr_t mtr;
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
+
+ rseg = trx->rseg;
+
+ if (trx->insert_undo != NULL || trx->update_undo != NULL) {
+
+ mutex_exit(&kernel_mutex);
+
+ mtr_start(&mtr);
+
+ must_flush_log = TRUE;
+
+ /* Change the undo log segment states from TRX_UNDO_ACTIVE
+ to some other state: these modifications to the file data
+ structure define the transaction as prepared in the file
+ based world, at the serialization point of the log sequence
+ number lsn obtained below. */
+
+ mutex_enter(&(rseg->mutex));
+
+ if (trx->insert_undo != NULL) {
+ trx_undo_set_state_at_prepare(trx, trx->insert_undo,
+ &mtr);
+ }
+
+ undo = trx->update_undo;
+
+ if (undo) {
+
+ /* It is not necessary to obtain trx->undo_mutex here
+ because only a single OS thread is allowed to do the
+ transaction prepare for this transaction. */
+
+ update_hdr_page = trx_undo_set_state_at_prepare(trx, undo, &mtr);
+ }
+
+ mutex_exit(&(rseg->mutex));
+
+ /*--------------*/
+ mtr_commit(&mtr);
+ /*--------------*/
+ lsn = mtr.end_lsn;
+
+ mutex_enter(&kernel_mutex);
+ }
+
+#ifdef UNIV_SYNC_DEBUG
+ ut_ad(mutex_own(&kernel_mutex));
+#endif /* UNIV_SYNC_DEBUG */
+
+ /*--------------------------------------*/
+ trx->conc_state = TRX_PREPARED;
+ /*--------------------------------------*/
+
+ if (trx->read_view) {
+ read_view_close(trx->read_view);
+
+ mem_heap_empty(trx->read_view_heap);
+ trx->read_view = NULL;
+ }
+
+ if (must_flush_log) {
+
+ mutex_exit(&kernel_mutex);
+
+ /* Write the log to the log files AND flush them to disk */
+
+ /*-------------------------------------*/
+
+ log_write_up_to(lsn, LOG_WAIT_ONE_GROUP, TRUE);
+
+ /*-------------------------------------*/
+
+ mutex_enter(&kernel_mutex);
+ }
+}
+
+/**************************************************************************
+Does the transaction prepare for MySQL. */
+
+ulint
+trx_prepare_for_mysql(
+/*=================*/
+ /* out: 0 or error number */
+ trx_t* trx) /* in: trx handle */
+{
+ /* Because we do not do the prepare by sending an Innobase
+ sig to the transaction, we must here make sure that trx has been
+ started. */
+
+ ut_a(trx);
+
+ trx->op_info = "preparing";
+
+ trx_start_if_not_started(trx);
+
+ mutex_enter(&kernel_mutex);
+
+ trx_prepare_off_kernel(trx);
+
+ mutex_exit(&kernel_mutex);
+
+ trx->op_info = "";
+
+ return(0);
+}
+
+/**************************************************************************
+This function is used to find number of prepared transactions and
+their transaction objects for a recovery. */
+
+int
+trx_recover_for_mysql(
+/*==================*/
+ /* out: number of prepared transactions
+ stored in xid_list */
+ XID* xid_list, /* in/out: prepared transactions */
+ uint len) /* in: number of slots in xid_list */
+{
+ trx_t* trx;
+ int num_of_transactions = 0;
+
+ ut_ad(xid_list);
+ ut_ad(len);
+
+ fprintf(stderr,
+ "InnoDB: Starting recovery for XA transactions...\n");
+
+
+ /* We should set those transactions which are in
+ the prepared state to the xid_list */
+
+ mutex_enter(&kernel_mutex);
+
+ trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
+
+ while (trx) {
+ if (trx->conc_state == TRX_PREPARED) {
+ xid_list[num_of_transactions] = trx->xid;
+
+ fprintf(stderr,
+"InnoDB: Transaction %lu %lu in prepared state after recovery\n",
+ (ulong) ut_dulint_get_high(trx->id),
+ (ulong) ut_dulint_get_low(trx->id));
+
+ fprintf(stderr,
+"InnoDB: Transaction contains changes to %lu rows\n",
+ (ulong)ut_conv_dulint_to_longlong(trx->undo_no));
+
+ num_of_transactions++;
+
+ if ((uint)num_of_transactions == len ) {
+ break;
+ }
+ }
+
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+ }
+
+ mutex_exit(&kernel_mutex);
+
+ fprintf(stderr,
+ "InnoDB: %d transactions in prepare state after recovery\n",
+ num_of_transactions);
+
+ return (num_of_transactions);
+}
+
+/***********************************************************************
+This function is used to find one X/Open XA distributed transaction
+which is in the prepared state */
+
+trx_t *
+trx_get_trx_by_xid(
+/*===============*/
+ /* out: trx or NULL */
+ XID* xid) /* in: X/Open XA Transaction Idenfication */
+{
+ trx_t* trx;
+
+ if (xid == NULL) {
+ return (NULL);
+ }
+
+ mutex_enter(&kernel_mutex);
+
+ trx = UT_LIST_GET_FIRST(trx_sys->trx_list);
+
+ while (trx) {
+ /* Compare two X/Open XA transaction id's: their
+ length should be the same and binary comparison
+ of gtrid_lenght+bqual_length bytes should be
+ the same */
+
+ if (xid->gtrid_length == trx->xid.gtrid_length &&
+ xid->bqual_length == trx->xid.bqual_length &&
+ memcmp(xid, &trx->xid,
+ xid->gtrid_length +
+ xid->bqual_length) == 0) {
+ break;
+ }
+
+ trx = UT_LIST_GET_NEXT(trx_list, trx);
+ }
+
+ mutex_exit(&kernel_mutex);
+
+ if (trx) {
+ if (trx->conc_state != TRX_PREPARED) {
+ return(NULL);
+ }
+
+ return(trx);
+ } else {
+ return(NULL);
+ }
+}
+
diff --git a/innobase/trx/trx0undo.c b/innobase/trx/trx0undo.c
index c1edc223cbc..4bfa9c20a54 100644
--- a/innobase/trx/trx0undo.c
+++ b/innobase/trx/trx0undo.c
@@ -19,6 +19,7 @@ Created 3/26/1996 Heikki Tuuri
#include "srv0srv.h"
#include "trx0rec.h"
#include "trx0purge.h"
+#include "trx0xa.h"
/* How should the old versions in the history list be managed?
----------------------------------------------------------
@@ -97,6 +98,7 @@ trx_undo_mem_create(
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
is created */
+ XID* xid, /* in: X/Open XA transaction identification*/
ulint page_no,/* in: undo log header page number */
ulint offset); /* in: undo log header byte offset on page */
/*******************************************************************
@@ -109,6 +111,7 @@ trx_undo_insert_header_reuse(
page_t* undo_page, /* in: insert undo log segment header page,
x-latched */
dulint trx_id, /* in: transaction id */
+ XID* xid, /* in: X/Open XA transaction identification*/
mtr_t* mtr); /* in: mtr */
/**************************************************************************
If an update undo log can be discarded immediately, this function frees the
@@ -484,6 +487,7 @@ trx_undo_header_create(
TRX_UNDO_LOG_HDR_SIZE bytes free space
on it */
dulint trx_id, /* in: transaction id */
+ XID* xid, /* in: X/Open XA XID */
mtr_t* mtr) /* in: mtr */
{
trx_upagef_t* page_hdr;
@@ -530,11 +534,25 @@ trx_undo_header_create(
mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
- mach_write_to_2(log_hdr + TRX_UNDO_DICT_OPERATION, FALSE);
-
+ /* If X/Open XID exits in the log header we store a
+ flag of it in upper byte of dict operation flag. */
+
+ if (xid != NULL || xid->formatID != -1) {
+ mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, TRUE);
+ } else {
+ mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
+ }
+
+ mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
mach_write_to_2(log_hdr + TRX_UNDO_NEXT_LOG, 0);
mach_write_to_2(log_hdr + TRX_UNDO_PREV_LOG, prev_log);
-
+
+ /* Write X/Open XA transaction identification if exists */
+
+ if (xid && xid->formatID != -1) {
+ trx_undo_write_xid(log_hdr, xid);
+ }
+
trx_undo_header_create_log(undo_page, trx_id, mtr);
return(free);
@@ -569,6 +587,11 @@ trx_undo_parse_page_header(
mtr_t* mtr) /* in: mtr or NULL */
{
dulint trx_id;
+ XID xid;
+
+ /* Set X/Open XA transaction identification to NULL */
+ memset(&xid, 0, sizeof(xid));
+ xid.formatID = -1;
ptr = mach_dulint_parse_compressed(ptr, end_ptr, &trx_id);
@@ -579,10 +602,10 @@ trx_undo_parse_page_header(
if (page) {
if (type == MLOG_UNDO_HDR_CREATE) {
- trx_undo_header_create(page, trx_id, mtr);
+ trx_undo_header_create(page, trx_id, &xid, mtr);
} else {
ut_ad(type == MLOG_UNDO_HDR_REUSE);
- trx_undo_insert_header_reuse(page, trx_id, mtr);
+ trx_undo_insert_header_reuse(page, trx_id, &xid, mtr);
}
}
@@ -599,6 +622,7 @@ trx_undo_insert_header_reuse(
page_t* undo_page, /* in: insert undo log segment header page,
x-latched */
dulint trx_id, /* in: transaction id */
+ XID* xid, /* in: X/Open XA transaction identification */
mtr_t* mtr) /* in: mtr */
{
trx_upagef_t* page_hdr;
@@ -636,8 +660,18 @@ trx_undo_insert_header_reuse(
mach_write_to_8(log_hdr + TRX_UNDO_TRX_ID, trx_id);
mach_write_to_2(log_hdr + TRX_UNDO_LOG_START, new_free);
- mach_write_to_2(log_hdr + TRX_UNDO_DICT_OPERATION, FALSE);
+ /* If X/Open XID exits in the log header we store it
+ to log header. */
+
+ if (xid && xid->formatID != -1) {
+ mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, TRUE);
+ trx_undo_write_xid(log_hdr, xid);
+ } else {
+ mach_write_to_1(log_hdr + TRX_UNDO_XID_EXISTS, FALSE);
+ }
+
+ mach_write_to_1(log_hdr + TRX_UNDO_DICT_TRANS, FALSE);
trx_undo_insert_header_reuse_log(undo_page, trx_id, mtr);
return(free);
@@ -718,6 +752,52 @@ trx_undo_discard_latest_update_undo(
}
/************************************************************************
+Write X/Open XA Transaction Identification (XID) to undo log header */
+
+void
+trx_undo_write_xid(
+/*===============*/
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ XID* xid) /* in: X/Open XA Transaction Identification */
+{
+ ulint i;
+
+ mach_write_to_4(log_hdr + TRX_UNDO_XA_FORMAT, xid->formatID);
+
+ mach_write_to_4(log_hdr + TRX_UNDO_XA_TRID_LEN, xid->gtrid_length);
+
+ mach_write_to_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN, xid->bqual_length);
+
+ for(i=0; i < XIDDATASIZE; i++) {
+ mach_write_to_1(log_hdr + TRX_UNDO_XA_XID + i,
+ (ulint)(xid->data[i]));
+ }
+}
+
+/************************************************************************
+Read X/Open XA Transaction Identification (XID) from undo log header */
+
+void
+trx_undo_read_xid(
+/*==============*/
+ trx_ulogf_t* log_hdr,/* in: undo log header */
+ XID* xid) /* out: X/Open XA Transaction Identification */
+{
+ ulint i;
+
+ xid->formatID = mach_read_from_4(log_hdr + TRX_UNDO_XA_FORMAT);
+
+ xid->gtrid_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_TRID_LEN);
+
+ xid->bqual_length = mach_read_from_4(log_hdr + TRX_UNDO_XA_BQUAL_LEN);
+
+ for(i=0; i < XIDDATASIZE; i++) {
+ xid->data[i] = (char)mach_read_from_1(log_hdr +
+ TRX_UNDO_XA_XID +i);
+ }
+}
+
+/************************************************************************
Tries to add a page to the undo log segment where the undo log is placed. */
ulint
@@ -800,7 +880,6 @@ trx_undo_free_page(
list */
ulint space, /* in: space */
ulint hdr_page_no, /* in: header page number */
- ulint hdr_offset, /* in: header offset */
ulint page_no, /* in: page number to free: must not be the
header page */
mtr_t* mtr) /* in: mtr which does not have a latch to any
@@ -813,7 +892,6 @@ trx_undo_free_page(
trx_rsegf_t* rseg_header;
ulint hist_size;
- UT_NOT_USED(hdr_offset);
ut_a(hdr_page_no != page_no);
#ifdef UNIV_SYNC_DEBUG
ut_ad(!mutex_own(&kernel_mutex));
@@ -870,8 +948,7 @@ trx_undo_free_page_in_rollback(
#endif /* UNIV_SYNC_DEBUG */
last_page_no = trx_undo_free_page(undo->rseg, FALSE, undo->space,
- undo->hdr_page_no, undo->hdr_offset,
- page_no, mtr);
+ undo->hdr_page_no, page_no, mtr);
undo->last_page_no = last_page_no;
undo->size--;
@@ -1039,7 +1116,7 @@ loop:
trx_undo_empty_header_page(space, hdr_page_no, hdr_offset,
&mtr);
} else {
- trx_undo_free_page(rseg, TRUE, space, hdr_page_no, hdr_offset,
+ trx_undo_free_page(rseg, TRUE, space, hdr_page_no,
page_no, &mtr);
}
@@ -1123,7 +1200,9 @@ trx_undo_mem_create_at_db_start(
fil_addr_t last_addr;
page_t* last_page;
trx_undo_rec_t* rec;
-
+ XID xid;
+ ibool xid_exists = FALSE;
+
if (id >= TRX_RSEG_N_SLOTS) {
fprintf(stderr,
"InnoDB: Error: undo->id is %lu\n", (ulong) id);
@@ -1145,15 +1224,31 @@ trx_undo_mem_create_at_db_start(
undo_header = undo_page + offset;
trx_id = mtr_read_dulint(undo_header + TRX_UNDO_TRX_ID, mtr);
+
+ xid_exists = mtr_read_ulint(undo_header + TRX_UNDO_XID_EXISTS,
+ MLOG_1BYTE, mtr);
+
+ /* Read X/Open XA transaction identification if exists or
+ set it to NULL. */
+
+ memset(&xid, 0, sizeof(xid));
+ xid.formatID = -1;
+
+ if (xid_exists == TRUE) {
+ trx_undo_read_xid(undo_header, &xid);
+ }
+
mutex_enter(&(rseg->mutex));
- undo = trx_undo_mem_create(rseg, id, type, trx_id, page_no, offset);
+ undo = trx_undo_mem_create(rseg, id, type, trx_id, &xid,
+ page_no, offset);
mutex_exit(&(rseg->mutex));
- undo->dict_operation = mtr_read_ulint(
- undo_header + TRX_UNDO_DICT_OPERATION,
- MLOG_2BYTES, mtr);
+ undo->dict_operation = mtr_read_ulint(
+ undo_header + TRX_UNDO_DICT_TRANS,
+ MLOG_1BYTE, mtr);
+
undo->table_id = mtr_read_dulint(undo_header + TRX_UNDO_TABLE_ID, mtr);
undo->state = state;
undo->size = flst_get_len(seg_header + TRX_UNDO_PAGE_LIST, mtr);
@@ -1241,7 +1336,7 @@ trx_undo_lists_init(
if (page_no != FIL_NULL
&& srv_force_recovery < SRV_FORCE_NO_UNDO_LOG_SCAN) {
-
+
undo = trx_undo_mem_create_at_db_start(rseg, i,
page_no, &mtr);
size += undo->size;
@@ -1272,7 +1367,8 @@ trx_undo_mem_create(
ulint type, /* in: type of the log: TRX_UNDO_INSERT or
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
- is created */
+ is created */
+ XID* xid, /* in: X/Open transaction identification */
ulint page_no,/* in: undo log header page number */
ulint offset) /* in: undo log header byte offset on page */
{
@@ -1295,6 +1391,7 @@ trx_undo_mem_create(
undo->state = TRX_UNDO_ACTIVE;
undo->del_marks = FALSE;
undo->trx_id = trx_id;
+ undo->xid = *xid;
undo->dict_operation = FALSE;
@@ -1322,6 +1419,7 @@ trx_undo_mem_init_for_reuse(
trx_undo_t* undo, /* in: undo log to init */
dulint trx_id, /* in: id of the trx for which the undo log
is created */
+ XID* xid, /* in: X/Open XA transaction identification*/
ulint offset) /* in: undo log header byte offset on page */
{
#ifdef UNIV_SYNC_DEBUG
@@ -1339,6 +1437,7 @@ trx_undo_mem_init_for_reuse(
undo->state = TRX_UNDO_ACTIVE;
undo->del_marks = FALSE;
undo->trx_id = trx_id;
+ undo->xid = *xid;
undo->dict_operation = FALSE;
@@ -1376,6 +1475,7 @@ trx_undo_create(
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
is created */
+ XID* xid, /* in: X/Open transaction identification*/
mtr_t* mtr) /* in: mtr */
{
trx_rsegf_t* rseg_header;
@@ -1410,9 +1510,10 @@ trx_undo_create(
page_no = buf_frame_get_page_no(undo_page);
- offset = trx_undo_header_create(undo_page, trx_id, mtr);
+ offset = trx_undo_header_create(undo_page, trx_id, xid, mtr);
- undo = trx_undo_mem_create(rseg, id, type, trx_id, page_no, offset);
+ undo = trx_undo_mem_create(rseg, id, type, trx_id, xid ,
+ page_no, offset);
return(undo);
}
@@ -1432,6 +1533,7 @@ trx_undo_reuse_cached(
TRX_UNDO_UPDATE */
dulint trx_id, /* in: id of the trx for which the undo log
is used */
+ XID* xid, /* in: X/Open XA transaction identification*/
mtr_t* mtr) /* in: mtr */
{
trx_undo_t* undo;
@@ -1475,16 +1577,17 @@ trx_undo_reuse_cached(
undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
if (type == TRX_UNDO_INSERT) {
- offset = trx_undo_insert_header_reuse(undo_page, trx_id, mtr);
+ offset = trx_undo_insert_header_reuse(undo_page, trx_id,
+ xid, mtr);
} else {
ut_a(mach_read_from_2(undo_page + TRX_UNDO_PAGE_HDR
+ TRX_UNDO_PAGE_TYPE)
== TRX_UNDO_UPDATE);
- offset = trx_undo_header_create(undo_page, trx_id, mtr);
+ offset = trx_undo_header_create(undo_page, trx_id, xid, mtr);
}
- trx_undo_mem_init_for_reuse(undo, trx_id, offset);
+ trx_undo_mem_init_for_reuse(undo, trx_id, xid, offset);
return(undo);
}
@@ -1506,9 +1609,10 @@ trx_undo_mark_as_dict_operation(
hdr_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
- mlog_write_ulint(hdr_page + undo->hdr_offset + TRX_UNDO_DICT_OPERATION,
- trx->dict_operation, MLOG_2BYTES, mtr);
-
+ mlog_write_ulint(hdr_page + undo->hdr_offset +
+ TRX_UNDO_DICT_TRANS,
+ trx->dict_operation, MLOG_1BYTE, mtr);
+
mlog_write_dulint(hdr_page + undo->hdr_offset + TRX_UNDO_TABLE_ID,
trx->table_id, mtr);
@@ -1548,10 +1652,10 @@ trx_undo_assign_undo(
#endif /* UNIV_SYNC_DEBUG */
mutex_enter(&(rseg->mutex));
- undo = trx_undo_reuse_cached(rseg, type, trx->id, &mtr);
+ undo = trx_undo_reuse_cached(rseg, type, trx->id, &trx->xid, &mtr);
if (undo == NULL) {
- undo = trx_undo_create(rseg, type, trx->id, &mtr);
+ undo = trx_undo_create(rseg, type, trx->id, &trx->xid, &mtr);
if (undo == NULL) {
/* Did not succeed */
@@ -1632,6 +1736,56 @@ trx_undo_set_state_at_finish(
return(undo_page);
}
+/**********************************************************************
+Sets the state of the undo log segment at a transaction prepare. */
+
+page_t*
+trx_undo_set_state_at_prepare(
+/*==========================*/
+ /* out: undo log segment header page,
+ x-latched */
+ trx_t* trx, /* in: transaction */
+ trx_undo_t* undo, /* in: undo log memory copy */
+ mtr_t* mtr) /* in: mtr */
+{
+ trx_usegf_t* seg_hdr;
+ trx_upagef_t* page_hdr;
+ trx_ulogf_t* undo_header;
+ page_t* undo_page;
+ ulint offset;
+
+ ut_ad(trx && undo && mtr);
+
+ if (undo->id >= TRX_RSEG_N_SLOTS) {
+ fprintf(stderr, "InnoDB: Error: undo->id is %lu\n",
+ (ulong) undo->id);
+ mem_analyze_corruption((byte*)undo);
+ ut_error;
+ }
+
+ undo_page = trx_undo_page_get(undo->space, undo->hdr_page_no, mtr);
+
+ seg_hdr = undo_page + TRX_UNDO_SEG_HDR;
+ page_hdr = undo_page + TRX_UNDO_PAGE_HDR;
+
+ /*------------------------------*/
+ undo->state = TRX_UNDO_PREPARED;
+ undo->xid = trx->xid;
+ /*------------------------------*/
+
+ mlog_write_ulint(seg_hdr + TRX_UNDO_STATE, undo->state,
+ MLOG_2BYTES, mtr);
+
+ offset = mach_read_from_2(seg_hdr + TRX_UNDO_LAST_LOG);
+ undo_header = undo_page + offset;
+
+ mlog_write_ulint(undo_header + TRX_UNDO_XID_EXISTS,
+ TRUE, MLOG_1BYTE, mtr);
+
+ trx_undo_write_xid(undo_header, &undo->xid);
+ return(undo_page);
+}
+
/**************************************************************************
Adds the update undo log header as the first in the history list, and
frees the memory object, or puts it to the list of cached update undo log
diff --git a/innobase/ut/ut0mem.c b/innobase/ut/ut0mem.c
index a6002d7fd83..6ed61b0b5de 100644
--- a/innobase/ut/ut0mem.c
+++ b/innobase/ut/ut0mem.c
@@ -61,8 +61,10 @@ ut_malloc_low(
/*==========*/
/* out, own: allocated memory */
ulint n, /* in: number of bytes to allocate */
- ibool set_to_zero) /* in: TRUE if allocated memory should be set
+ ibool set_to_zero, /* in: TRUE if allocated memory should be set
to zero if UNIV_SET_MEM_TO_ZERO is defined */
+ ibool assert_on_error) /* in: if TRUE, we crash mysqld if the memory
+ cannot be allocated */
{
void* ret;
@@ -86,9 +88,7 @@ ut_malloc_low(
"InnoDB: Check if you should increase the swap file or\n"
"InnoDB: ulimits of your operating system.\n"
"InnoDB: On FreeBSD check you have compiled the OS with\n"
- "InnoDB: a big enough maximum process size.\n"
- "InnoDB: We now intentionally generate a seg fault so that\n"
- "InnoDB: on Linux we get a stack trace.\n",
+ "InnoDB: a big enough maximum process size.\n",
(ulong) n, (ulong) ut_total_allocated_memory,
#ifdef __WIN__
(ulong) GetLastError()
@@ -110,7 +110,15 @@ ut_malloc_low(
/* Intentional segfault on NetWare causes an abend. Avoid this
by graceful exit handling in ut_a(). */
#if (!defined __NETWARE__)
- if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
+ if (assert_on_error) {
+ fprintf(stderr,
+ "InnoDB: We now intentionally generate a seg fault so that\n"
+ "InnoDB: on Linux we get a stack trace.\n");
+
+ if (*ut_mem_null_ptr) ut_mem_null_ptr = 0;
+ } else {
+ return(NULL);
+ }
#else
ut_a(0);
#endif
@@ -144,7 +152,7 @@ ut_malloc(
/* out, own: allocated memory */
ulint n) /* in: number of bytes to allocate */
{
- return(ut_malloc_low(n, TRUE));
+ return(ut_malloc_low(n, TRUE, TRUE));
}
/**************************************************************************
diff --git a/innobase/ut/ut0ut.c b/innobase/ut/ut0ut.c
index b67be77b29e..732380bcb1f 100644
--- a/innobase/ut/ut0ut.c
+++ b/innobase/ut/ut0ut.c
@@ -235,13 +235,18 @@ ut_get_year_month_day(
*month = (ulint)cal_tm.wMonth;
*day = (ulint)cal_tm.wDay;
#else
+ struct tm cal_tm;
struct tm* cal_tm_ptr;
time_t tm;
time(&tm);
+#ifdef HAVE_LOCALTIME_R
+ localtime_r(&tm, &cal_tm);
+ cal_tm_ptr = &cal_tm;
+#else
cal_tm_ptr = localtime(&tm);
-
+#endif
*year = (ulint)cal_tm_ptr->tm_year + 1900;
*month = (ulint)cal_tm_ptr->tm_mon + 1;
*day = (ulint)cal_tm_ptr->tm_mday;
diff --git a/isam/.cvsignore b/isam/.cvsignore
deleted file mode 100644
index dc55807a96b..00000000000
--- a/isam/.cvsignore
+++ /dev/null
@@ -1,10 +0,0 @@
-.deps
-.libs
-Makefile
-Makefile.in
-isamchk
-isamlog
-pack_isam
-test1
-test2
-test3
diff --git a/isam/ChangeLog b/isam/ChangeLog
deleted file mode 100644
index 4a9e3e03954..00000000000
--- a/isam/ChangeLog
+++ /dev/null
@@ -1,186 +0,0 @@
-2000-04-26 Michael Widenius <monty@mysql.com>
-
-* Fixed bug when doing read_next after a delete/insert which balanced key
- pages (In this case one internal buffer was wrongly reused)
-
-1999-11-23 Michael Widenius <monty@monty.pp.sci.fi>
-
-* Changed prefix from ni_ to nisam_ to avoid problems on MacOS X.
-
-1999-08-17 Michael Widenius <monty@tik.pp.sci.fi>
-
-* Changed last parameter to mi_open() to be a bit flag instead of an int.
-
-1998-10-01 Michael Widenius <monty@monty.pp.sci.fi>
-
-* Fixed bug in key packing when using some USE_STRCOLL character sets.
-
-Thu Aug 20 23:17:41 1998 Michael Widenius <monty@bitch.pp.sci.fi>
-
-* isamchk.c: Sometimes isamchk --sort-table caused isamchk to die.
-
-1998-06-28 Michael Widenius <monty@monty.pp.sci.fi>
-
-* Fixed some possible race conditions when using with MySQL and
- many reopen/close of the same tables under heavy load!
-* Changed isamchk to re-pack records when doing a repair to make it more safer.
-
-Thu Mar 12 21:44:08 1998 Michael Widenius <monty@monty.pp.sci.fi>
-
-* Added a safty test to _ni_rec_unpack.
-
-Wed Nov 26 01:52:55 1997 <monty@monty.pp.sci.fi>
-
-* Fixed small problem when reading delete-marked records with rkey, rnext and
- rprev. In normal applications this should never happen.
-
-Thu Nov 20 14:01:21 1997 <monty@monty.pp.sci.fi>
-
-* Fixed range key bug when using compressed key where the first part wasn't
- compressed.
-* Converted everything to use prototypes.
-
-Mon Sep 29 13:16:27 1997 <monty@monty.pp.sci.fi>
-
-* Fixed problem with isamchk and compressed records files with record_reflength
- < 4 (Gave wrong key when using isamchk -rq).
-
-Fri Sep 26 16:06:37 1997 <monty@monty.pp.sci.fi>
-
-* Fixed bug in range calculation.
-
-Thu Aug 14 14:44:33 1997 <monty@monty.pp.sci.fi>
-
-* Removed a couple of unnecessary seeks from 'delete static record'
-
-Tue Jul 1 22:04:16 1997 <monty@monty.pp.sci.fi>
-
-* Added checking of 'wrong packed records' when using 'isamchk -e' or
- isamchk -ro.
-
-Fri Feb 7 22:22:28 1997 Michael Widenius <monty@bitch.sci.fi>
-
-* Fixed use of packed tables with threads (One static variable left)
-
-Thu Jan 23 09:05:22 1997 Michael Widenius <monty@bitch.sci.fi>
-
-* Changed create to detect keys > 127 and not pack them. Now one can
- define keys with a length of up to (nisam_block_size-18)/2
- by changeing N_MAX_KEY_LENGTH.
-
-Fri Jan 10 21:01:44 1997 Michael Widenius <monty@bitch.sci.fi>
-
-* added signed chars as key type.
-
-Fri Apr 26 14:31:05 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* create.c: All keyfile blocks are now IO_SIZE big (for better keycashing).
-
-Tue Mar 12 22:42:52 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* isamchk.c: Changed to print info if system table
-* write.c: Don't allow more than 1 record in system table.
-
-Fri Feb 2 16:40:32 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* isamchk.c; Check that delete-link-chain is ok before trying to delete with 'q'.
-
-Thu Jan 11 13:21:23 1996 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* All same isam files now shares a structure to allow many opens off the same
- file
-
-Sat Nov 25 12:33:53 1995 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* All functions now used my_errno instead of errno
-
-Mon Oct 23 12:32:02 1995 Michael Widenius <monty@bitch.clinet.fi (Michael Widenius)>
-
-* isamchk.c: Don't print that database should be fixed on automatic rep.
-
-Sun Aug 27 20:13:56 1995 Michael Widenius <monty@bitch.analytikerna.se (Michael Widenius)>
-
-* _dynrec.c added flush_io_cash() if someone did a read when using
- WRITE CASHING.
-
-Thu Apr 20 01:41:24 1995 Michael Widenius (monty@bitch)
-
-* fixed errno when got error of 'key-not-found' when updateing or
- deleting record.
-
-Tue Jan 17 19:37:48 1995 Michael Widenius (monty@bitch)
-
-* isamchk can now unpack databases.
-* prolinted all files.
-
-Fri May 27 15:01:06 1994 Michael Widenius (monty@bitch)
-
-* Don't lock packed databases.
-
-Sat Apr 16 22:41:23 1994 Michael Widenius (monty@bitch)
-
-* Added new function read_rsame_with_pos.
-
-Wed Mar 30 15:52:19 1994 Michael Widenius (monty@bitch)
-
-* Added creation and recover date to indexfile and isamchk.
-
-Sat Mar 26 15:03:37 1994 Michael Widenius (monty@bitch)
-
-* change is_panic() to close all files on ha_panic(write) on systems
- (VMS) with can't open one file twice.
-
-Fri Feb 4 21:09:56 1994 Michael Widenius (monty@bitch)
-
-* READ_CASH on packed files now makes them mem-mapped if possibly
-
-Sat Sep 18 14:56:32 1993 Michael Widenius (monty at bitch)
-
-* changed _search to use pointer to buffer when reading keys.
-
-Mon Aug 16 19:45:29 1993 Michael Widenius (monty at bitch)
-
-* isamchk and packisam resolves symbolic links before file is used.
- This forces temp-files on same disk as orginal file and rename
- of temp-files dosen't destroy symbolic links.
-
-Mon May 31 18:26:08 1993 Michael Widenius (monty at bitch)
-
-* Added crc-check of records when packing for safe test if pack ok.
-
-Tue Mar 2 19:16:00 1993 Michael Widenius (monty@bitch)
-
-* Added logging of records with ni_log().
-
-Fri Jan 29 00:56:58 1993 Michael Widenius (monty@bitch)
-
-* Fixed bug in _read_rnd_static_record ; A lock was made for
- each record even if it was in cash.
-
-Sun Nov 15 12:51:36 1992 Michael Widenius (monty@bitch)
-
-* last change breaked _dynrec, when not compileing with dbug.
-
-Fri Nov 6 03:46:38 1992 Michael Widenius (monty@bitch)
-
-* Fixed bugg when using packed records and reclength < 8 byte.
-
-Wed Oct 28 22:23:32 1992 Michael Widenius (monty@bitch)
-
-* Changed _cash.c to use io_cash to allow use of aioread.
-
-Fri Oct 23 00:45:53 1992 Michael Widenius (monty@bitch)
-
-* Added MY_WAIT_IF_FULL to pack_isam.
-
-Sat Oct 17 14:51:15 1992 Michael Widenius (monty@bitch)
-
-* Added use of subset of keys (isamchk -k#)
-
-Mon Oct 5 21:53:18 1992 Michael Widenius (monty@bitch)
-
-* Remove reloc of database ; Gives only problems with isamchk.
-
-Mon Aug 17 03:17:09 1992 Michael Widenius (monty@bitch)
-
-* Changed isam to use io_cash instead of rec_cash
diff --git a/isam/Makefile.am b/isam/Makefile.am
deleted file mode 100644
index 6d9e4176d43..00000000000
--- a/isam/Makefile.am
+++ /dev/null
@@ -1,45 +0,0 @@
-# Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-#
-# 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; either version 2 of the License, or
-# (at your option) any later version.
-#
-# 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
-
-INCLUDES = @MT_INCLUDES@ -I$(top_srcdir)/include
-LDADD = @CLIENT_EXTRA_LDFLAGS@ libnisam.a ../mysys/libmysys.a \
- ../dbug/libdbug.a ../strings/libmystrings.a
-pkglib_LIBRARIES = libnisam.a
-bin_PROGRAMS = isamchk isamlog pack_isam
-isamchk_DEPENDENCIES= $(LIBRARIES)
-isamlog_DEPENDENCIES= $(LIBRARIES)
-pack_isam_DEPENDENCIES= $(LIBRARIES)
-noinst_PROGRAMS = test1 test2 test3
-noinst_HEADERS = isamdef.h
-test1_DEPENDENCIES= $(LIBRARIES)
-test2_DEPENDENCIES= $(LIBRARIES)
-test3_DEPENDENCIES= $(LIBRARIES)
-libnisam_a_SOURCES = open.c extra.c info.c rkey.c rnext.c \
- _search.c _page.c _key.c _locking.c \
- rrnd.c _cache.c _statrec.c _packrec.c \
- _dynrec.c update.c write.c delete.c \
- rprev.c rfirst.c rlast.c rsame.c rsamepos.c \
- panic.c close.c create.c range.c _dbug.c \
- log.c changed.c static.c
-isamchk_SOURCES = isamchk.c sort.c
-CLEANFILES = test?.IS? isam.log
-
-# Move to automake rules ?
-prolint:; plparse -b -u -hF1 "-width(0,0)" "-format=%f:%l:\s%t:%n\s%m" \
- "-elib(????)" "+elib(?3??)" my.lnt $(nisam_SOURCES)
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/isam/_cache.c b/isam/_cache.c
deleted file mode 100644
index bca9a699a85..00000000000
--- a/isam/_cache.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Functions for read record cacheing with nisam */
-/* Used instead of my_b_read() to allow for no-cacheed seeks */
-
-#include "isamdef.h"
-
-#define READING_NEXT 1
-#define READING_HEADER 2
-
- /* Copy block from cache if it`s in it. If re_read_if_possibly is */
- /* set read to cache (if after current file-position) else read to */
- /* buff */
-
-int _nisam_read_cache(IO_CACHE *info, byte *buff, ulong pos, uint length,
- int flag)
-{
- uint read_length,in_buff_length;
- ulong offset;
- char *in_buff_pos;
-
- if (pos < info->pos_in_file)
- {
- read_length= (uint) min((ulong) length,(ulong) (info->pos_in_file-pos));
- info->seek_not_done=1;
- VOID(my_seek(info->file,pos,MY_SEEK_SET,MYF(0)));
- if (my_read(info->file,buff,read_length,MYF(MY_NABP)))
- return 1;
- if (!(length-=read_length))
- return 0;
- pos+=read_length;
- buff+=read_length;
- }
- if ((offset=pos - (ulong) info->pos_in_file) <
- (ulong) (info->read_end - info->request_pos))
- {
- in_buff_pos=info->request_pos+(uint) offset;
- in_buff_length= min(length,(uint) (info->read_end-in_buff_pos));
- memcpy(buff,info->request_pos+(uint) offset,(size_t) in_buff_length);
- if (!(length-=in_buff_length))
- return 0;
- pos+=in_buff_length;
- buff+=in_buff_length;
- }
- else
- in_buff_length=0;
- if (flag & READING_NEXT)
- {
- if (pos != ((info)->pos_in_file +
- (uint) ((info)->read_end - (info)->request_pos)))
- {
- info->pos_in_file=pos; /* Force start here */
- info->read_pos=info->read_end=info->request_pos; /* Everything used */
- info->seek_not_done=1;
- }
- else
- info->read_pos=info->read_end; /* All block used */
- if (!(*info->read_function)(info,buff,length))
- return 0;
- if (!(flag & READING_HEADER) || info->error == -1 ||
- (uint) info->error+in_buff_length < 3)
- return 1;
- if (BLOCK_INFO_HEADER_LENGTH < in_buff_length + (uint) info->error)
- bzero(buff+info->error,BLOCK_INFO_HEADER_LENGTH - in_buff_length -
- (uint) info->error);
- return 0;
- }
- info->seek_not_done=1;
- VOID(my_seek(info->file,pos,MY_SEEK_SET,MYF(0)));
- if ((read_length=my_read(info->file,buff,length,MYF(0))) == length)
- return 0;
- if (!(flag & READING_HEADER) || (int) read_length == -1 ||
- read_length+in_buff_length < 3)
- return 1;
- bzero(buff+read_length,BLOCK_INFO_HEADER_LENGTH - in_buff_length -
- read_length);
- return 0;
-} /* _nisam_read_cache */
diff --git a/isam/_dbug.c b/isam/_dbug.c
deleted file mode 100644
index 0a52dbbc916..00000000000
--- a/isam/_dbug.c
+++ /dev/null
@@ -1,132 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Support rutiner with are using with dbug */
-
-#include "isamdef.h"
-
- /* Print a key in user understandable format */
-
-void _nisam_print_key(FILE *stream, register N_KEYSEG *keyseg, const uchar *key)
-{
- int flag;
- short int s_1;
- long int l_1;
- float f_1;
- double d_1;
- uchar *end;
-
- VOID(fputs("Key: \"",stream));
- flag=0;
- for (; keyseg->base.type ;keyseg++)
- {
- if (flag++)
- VOID(putc('-',stream));
- end= (uchar*) key+ keyseg->base.length;
- switch (keyseg->base.type) {
- case HA_KEYTYPE_BINARY:
- if (!(keyseg->base.flag & HA_SPACE_PACK) && keyseg->base.length == 1)
- { /* packed binary digit */
- VOID(fprintf(stream,"%d",(uint) *key++));
- break;
- }
- /* fall through */
- case HA_KEYTYPE_TEXT:
- case HA_KEYTYPE_NUM:
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- VOID(fprintf(stream,"%.*s",(int) *key,key+1));
- key+= (int) *key+1;
- }
- else
- {
- VOID(fprintf(stream,"%.*s",(int) keyseg->base.length,key));
- key=end;
- }
- break;
- case HA_KEYTYPE_INT8:
- VOID(fprintf(stream,"%d",(int) *((signed char*) key)));
- key=end;
- break;
- case HA_KEYTYPE_SHORT_INT:
- shortget(s_1,key);
- VOID(fprintf(stream,"%d",(int) s_1));
- key=end;
- break;
- case HA_KEYTYPE_USHORT_INT:
- {
- ushort u_1;
- ushortget(u_1,key);
- VOID(fprintf(stream,"%u",(uint) u_1));
- key=end;
- break;
- }
- case HA_KEYTYPE_LONG_INT:
- longget(l_1,key);
- VOID(fprintf(stream,"%ld",l_1));
- key=end;
- break;
- case HA_KEYTYPE_ULONG_INT:
- longget(l_1,key);
- VOID(fprintf(stream,"%lu",(ulong) l_1));
- key=end;
- break;
- case HA_KEYTYPE_INT24:
- VOID(fprintf(stream,"%ld",(long) sint3korr(key)));
- key=end;
- break;
- case HA_KEYTYPE_UINT24:
- VOID(fprintf(stream,"%ld",(long) uint3korr(key)));
- key=end;
- break;
- case HA_KEYTYPE_FLOAT:
- bmove((byte*) &f_1,(byte*) key,(int) sizeof(float));
- VOID(fprintf(stream,"%g",(double) f_1));
- key=end;
- break;
- case HA_KEYTYPE_DOUBLE:
- doubleget(d_1,key);
- VOID(fprintf(stream,"%g",d_1));
- key=end;
- break;
-#ifdef HAVE_LONG_LONG
- case HA_KEYTYPE_LONGLONG:
- {
- char buff[21];
- longlong tmp;
- longlongget(tmp,key);
- longlong2str(tmp,buff,-10);
- VOID(fprintf(stream,"%s",buff));
- key=end;
- break;
- }
- case HA_KEYTYPE_ULONGLONG:
- {
- char buff[21];
- longlong tmp;
- longlongget(tmp,key);
- longlong2str(tmp,buff,10);
- VOID(fprintf(stream,"%s",buff));
- key=end;
- break;
- }
-#endif
- default: break; /* This never happens */
- }
- }
- VOID(fputs("\n",stream));
- return;
-} /* print_key */
diff --git a/isam/_dynrec.c b/isam/_dynrec.c
deleted file mode 100644
index 25fe01e23f2..00000000000
--- a/isam/_dynrec.c
+++ /dev/null
@@ -1,1247 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
- /* Functions to handle space-packed-records and blobs */
-
-#include "isamdef.h"
-
-/* Enough for comparing if number is zero */
-static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-
-static int write_dynamic_record(N_INFO *info,const byte *record,
- uint reclength);
-static int _nisam_find_writepos(N_INFO *info,uint reclength,ulong *filepos,
- uint *length);
-static int update_dynamic_record(N_INFO *info,ulong filepos,byte *record,
- uint reclength);
-static int delete_dynamic_record(N_INFO *info,ulong filepos,
- uint second_read);
-static int _nisam_cmp_buffer(File file, const byte *buff, ulong filepos,
- uint length);
-
-#ifdef THREAD
-/* Play it safe; We have a small stack when using threads */
-#undef my_alloca
-#undef my_afree
-#define my_alloca(A) my_malloc((A),MYF(0))
-#define my_afree(A) my_free((A),MYF(0))
-#endif
-
- /* Interface function from N_INFO */
-
-int _nisam_write_dynamic_record(N_INFO *info, const byte *record)
-{
- uint reclength=_nisam_rec_pack(info,info->rec_buff,record);
- return (write_dynamic_record(info,info->rec_buff,reclength));
-}
-
-int _nisam_update_dynamic_record(N_INFO *info, ulong pos, const byte *record)
-{
- uint length=_nisam_rec_pack(info,info->rec_buff,record);
- return (update_dynamic_record(info,pos,info->rec_buff,length));
-}
-
-int _nisam_write_blob_record(N_INFO *info, const byte *record)
-{
- byte *rec_buff;
- int error;
- uint reclength,extra;
-
- extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (!(rec_buff=(byte*) my_alloca(info->s->base.pack_reclength+
- _calc_total_blob_length(info,record)+
- extra)))
- return(-1);
- reclength=_nisam_rec_pack(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
- record);
- error=write_dynamic_record(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
- reclength);
- my_afree(rec_buff);
- return(error);
-}
-
-
-int _nisam_update_blob_record(N_INFO *info, ulong pos, const byte *record)
-{
- byte *rec_buff;
- int error;
- uint reclength,extra;
-
- extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (!(rec_buff=(byte*) my_alloca(info->s->base.pack_reclength+
- _calc_total_blob_length(info,record)+
- extra)))
- return(-1);
- reclength=_nisam_rec_pack(info,rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
- record);
- error=update_dynamic_record(info,pos,
- rec_buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER),
- reclength);
- my_afree(rec_buff);
- return(error);
-}
-
-int _nisam_delete_dynamic_record(N_INFO *info)
-{
- return delete_dynamic_record(info,info->lastpos,0);
-}
-
-
- /* Write record to data-file */
-
-static int write_dynamic_record(N_INFO *info, const byte *record,
- uint reclength)
-{
- int flag;
- uint length;
- ulong filepos;
- DBUG_ENTER("write_dynamic_record");
-
- flag=0;
- while (reclength)
- {
- if (_nisam_find_writepos(info,reclength,&filepos,&length))
- goto err;
- if (_nisam_write_part_record(info,filepos,length,info->s->state.dellink,
- (byte**) &record,&reclength,&flag))
- goto err;
- }
-
- DBUG_RETURN(0);
- err:
- DBUG_RETURN(1);
-}
-
-
- /* Get a block for data ; The given data-area must be used !! */
-
-static int _nisam_find_writepos(N_INFO *info,
- uint reclength, /* record length */
- ulong *filepos, /* Return file pos */
- uint *length) /* length of block at filepos */
-{
- BLOCK_INFO block_info;
- DBUG_ENTER("_nisam_find_writepos");
-
- if (info->s->state.dellink != NI_POS_ERROR)
- {
- *filepos=info->s->state.dellink;
- block_info.second_read=0;
- info->rec_cache.seek_not_done=1;
-
- if (!(_nisam_get_block_info(&block_info,info->dfile,
- info->s->state.dellink) & BLOCK_DELETED))
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- DBUG_RETURN(-1);
- }
- info->s->state.dellink=block_info.next_filepos;
- info->s->state.del--;
- info->s->state.empty-= block_info.block_len;
- *length= block_info.block_len;
- }
- else
- {
- if (info->s->state.data_file_length > info->s->base.max_data_file_length)
- {
- my_errno=HA_ERR_RECORD_FILE_FULL;
- DBUG_RETURN(-1);
- }
- *filepos=info->s->state.data_file_length; /* New block last */
- if ((*length=reclength+3 + test(reclength > 65532)) <
- info->s->base.min_block_length)
- *length=info->s->base.min_block_length;
- info->s->state.data_file_length+= *length;
- info->s->state.splitt++;
- info->update|=HA_STATE_WRITE_AT_END;
- }
- DBUG_RETURN(0);
-} /* _nisam_find_writepos */
-
-
- /* Write a block to datafile */
-
-int _nisam_write_part_record(N_INFO *info,
- ulong filepos, /* points at empty block */
- uint length, /* length of block */
- ulong next_filepos, /* Next empty block */
- byte **record, /* pointer to record ptr */
- uint *reclength, /* length of *record */
- int *flag) /* *flag == 0 if header */
-{
- uint head_length,res_length,extra_length,long_block,del_length;
- byte *pos,*record_end;
- uchar temp[N_SPLITT_LENGTH+DYN_DELETE_BLOCK_HEADER];
- DBUG_ENTER("_nisam_write_part_record");
-
- res_length=extra_length=0;
- if (length > *reclength + N_SPLITT_LENGTH)
- { /* Splitt big block */
- res_length=length- *reclength - 3 - N_EXTEND_BLOCK_LENGTH;
- length-= res_length; /* Use this for first part */
- }
- long_block= (length < 65535L && *reclength < 65535L) ? 0 : 1;
- if (length-long_block == *reclength+3 || length == *reclength + 4)
- { /* Exact what we need */
- temp[0]=(uchar) (1+ *flag); /* 1, or 9 */
- if (long_block)
- {
- int3store(temp+1,*reclength);
- }
- else
- {
- int2store(temp+1,*reclength);
- }
- head_length=3+long_block;
- if (length-long_block == *reclength+4)
- {
- length--;
- temp[0]++; /* 2 or 10 */
- extra_length++; /* One empty */
- }
- }
- else if (length-long_block*2 < *reclength+5)
- { /* To short block */
- if (next_filepos == NI_POS_ERROR)
- next_filepos=info->s->state.dellink != NI_POS_ERROR ?
- info->s->state.dellink : info->s->state.data_file_length;
- if (*flag == 0) /* First block */
- {
- head_length=5+4+long_block*2;
- temp[0]=4;
- if (long_block)
- {
- int3store(temp+1,*reclength);
- int3store(temp+4,length-head_length);
- int4store((byte*) temp+7,next_filepos);
- }
- else
- {
- int2store(temp+1,*reclength);
- int2store(temp+3,length-head_length);
- int4store((byte*) temp+5,next_filepos);
- }
- }
- else
- {
- head_length=3+4+long_block;
- temp[0]=12;
- if (long_block)
- {
- int3store(temp+1,length-head_length);
- int4store((byte*) temp+4,next_filepos);
- }
- else
- {
- int2store(temp+1,length-head_length);
- int4store((byte*) temp+3,next_filepos);
- }
- }
- }
- else
- { /* Block with empty info last */
- head_length=5+long_block*2;
- temp[0]= (uchar) (3+ *flag); /* 3 or 11 */
- if (long_block)
- {
- int3store(temp+1,*reclength);
- int3store(temp+4,length-7);
- }
- else
- {
- int2store(temp+1,*reclength);
- int2store(temp+3,length-5);
- }
- extra_length= length- *reclength-head_length;
- length= *reclength+head_length; /* Write only what is needed */
- }
- temp[0]+=(uchar) (long_block*4);
- DBUG_DUMP("header",(byte*) temp,head_length);
-
- /* Make a long block for one write */
- record_end= *record+length-head_length;
- del_length=(res_length ? DYN_DELETE_BLOCK_HEADER : 0);
- bmove((byte*) (*record-head_length),(byte*) temp,head_length);
- memcpy(temp,record_end,(size_t) (extra_length+del_length));
- bzero((byte*) record_end,extra_length);
- if (res_length)
- {
- pos=record_end+extra_length;
- pos[0]= '\0';
- int3store(pos+1,res_length);
- int4store(pos+4,info->s->state.dellink);
- info->s->state.dellink= filepos+length+extra_length;
- info->s->state.del++;
- info->s->state.empty+=res_length;
- info->s->state.splitt++;
- }
- if (info->opt_flag & WRITE_CACHE_USED && info->update & HA_STATE_WRITE_AT_END)
- {
- if (my_b_write(&info->rec_cache,(byte*) *record-head_length,
- length+extra_length+del_length))
- goto err;
- }
- else
- {
- info->rec_cache.seek_not_done=1;
- if (my_pwrite(info->dfile,(byte*) *record-head_length,length+extra_length+
- del_length,filepos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
- goto err;
- }
- memcpy(record_end,temp,(size_t) (extra_length+del_length));
- *record=record_end;
- *reclength-=(length-head_length);
- *flag=8;
-
- DBUG_RETURN(0);
-err:
- DBUG_PRINT("exit",("errno: %d",my_errno));
- DBUG_RETURN(1);
-} /*_nisam_write_part_record */
-
-
- /* update record from datafile */
-
-static int update_dynamic_record(N_INFO *info, ulong filepos, byte *record, uint reclength)
-{
- int flag;
- uint error,length;
- BLOCK_INFO block_info;
- DBUG_ENTER("update_dynamic_record");
-
- flag=block_info.second_read=0;
- while (reclength > 0)
- {
- if (filepos != info->s->state.dellink)
- {
- block_info.next_filepos= NI_POS_ERROR;
- if ((error=_nisam_get_block_info(&block_info,info->dfile,filepos))
- & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if (!(error & BLOCK_FATAL_ERROR))
- my_errno=HA_ERR_WRONG_IN_RECORD;
- goto err;
- }
- length=(uint) (block_info.filepos-filepos) + block_info.block_len;
- }
- else
- {
- if (_nisam_find_writepos(info,reclength,&filepos,&length))
- goto err;
- }
- if (_nisam_write_part_record(info,filepos,length,block_info.next_filepos,
- &record,&reclength,&flag))
- goto err;
- if ((filepos=block_info.next_filepos) == NI_POS_ERROR)
- filepos=info->s->state.dellink;
- }
-
- if (block_info.next_filepos != NI_POS_ERROR)
- if (delete_dynamic_record(info,block_info.next_filepos,1))
- goto err;
- DBUG_RETURN(0);
-err:
- DBUG_RETURN(1);
-}
-
- /* Delete datarecord from database */
- /* info->rec_cache.seek_not_done is updated in cmp_record */
-
-static int delete_dynamic_record(N_INFO *info, ulong filepos, uint second_read)
-{
- uint length,b_type;
- BLOCK_INFO block_info;
- DBUG_ENTER("delete_dynamic_record");
-
- block_info.second_read=second_read;
- do
- {
- if ((b_type=_nisam_get_block_info(&block_info,info->dfile,filepos))
- & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR) ||
- (length=(uint) (block_info.filepos-filepos) +block_info.block_len) <
- N_MIN_BLOCK_LENGTH)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- DBUG_RETURN(1);
- }
- block_info.header[0]=0;
- length=(uint) (block_info.filepos-filepos) +block_info.block_len;
- int3store(block_info.header+1,length);
- int4store(block_info.header+4,info->s->state.dellink);
- if (my_pwrite(info->dfile,(byte*) block_info.header,8,filepos,
- MYF(MY_NABP)))
- DBUG_RETURN(1);
- info->s->state.dellink = filepos;
- info->s->state.del++;
- info->s->state.empty+=length;
- filepos=block_info.next_filepos;
- } while (!(b_type & BLOCK_LAST));
- DBUG_RETURN(0);
-}
-
-
- /* Pack a record. Return new reclength */
-
-uint _nisam_rec_pack(N_INFO *info, register byte *to, register const byte *from)
-{
- uint length,new_length,flag,bit,i;
- char *pos,*end,*startpos,*packpos;
- enum en_fieldtype type;
- reg3 N_RECINFO *rec;
- N_BLOB *blob;
- DBUG_ENTER("_nisam_rec_pack");
-
- flag=0 ; bit=1;
- startpos=packpos=to; to+= info->s->base.pack_bits; blob=info->blobs;
- rec=info->s->rec;
-
- for (i=info->s->base.fields ; i-- > 0; from+= (rec++)->base.length)
- {
- length=(uint) rec->base.length;
- if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
- {
- if (type == FIELD_BLOB)
- {
- if (!blob->length)
- flag|=bit;
- else
- {
- char *temp_pos;
- memcpy((byte*) to,from,(size_t) length);
- memcpy_fixed(&temp_pos,from+length,sizeof(char*));
- memcpy(to+length,temp_pos,(size_t) blob->length);
- to+=length+blob->length;
- }
- blob++;
- from+=sizeof(char*); /* Skip blob-pointer */
- }
- else if (type == FIELD_SKIP_ZERO)
- {
- if (memcmp((byte*) from,zero_string,length) == 0)
- flag|=bit;
- else
- {
- memcpy((byte*) to,from,(size_t) length); to+=length;
- }
- }
- else if (type == FIELD_SKIP_ENDSPACE ||
- type == FIELD_SKIP_PRESPACE)
- {
- pos= (byte*) from; end= (byte*) from + length;
- if (type == FIELD_SKIP_ENDSPACE)
- { /* Pack trailing spaces */
- while (end > from && *(end-1) == ' ')
- end--;
- }
- else
- { /* Pack pref-spaces */
- while (pos < end && *pos == ' ')
- pos++;
- }
- new_length=(uint) (end-pos);
- if (new_length +1 + test(rec->base.length > 255 && new_length > 127)
- < length)
- {
- if (rec->base.length > 255 && new_length > 127)
- {
- to[0]=(char) ((new_length & 127)+128);
- to[1]=(char) (new_length >> 7);
- to+=2;
- }
- else
- *to++= (char) new_length;
- memcpy((byte*) to,pos,(size_t) new_length); to+=new_length;
- flag|=bit;
- }
- else
- {
- memcpy(to,from,(size_t) length); to+=length;
- }
- }
- else if (type == FIELD_ZERO)
- continue; /* Don't store this */
- else
- {
- memcpy(to,from,(size_t) length); to+=length;
- continue; /* Normal field */
- }
- if ((bit= bit << 1) >= 256)
- {
- *packpos++ = (char) (uchar) flag;
- bit=1; flag=0;
- }
- }
- else
- {
- memcpy(to,from,(size_t) length); to+=length;
- }
- }
- if (bit != 1)
- *packpos= (char) (uchar) flag;
- DBUG_PRINT("exit",("packed length: %d",(int) (to-startpos)));
- DBUG_RETURN((uint) (to-startpos));
-} /* _nisam_rec_pack */
-
-
-
-/*
-** Check if a record was correctly packed. Used only by isamchk
-** Returns 0 if record is ok.
-*/
-
-my_bool _nisam_rec_check(N_INFO *info,const char *from)
-{
- uint length,new_length,flag,bit,i;
- char *pos,*end,*packpos,*to;
- enum en_fieldtype type;
- reg3 N_RECINFO *rec;
- DBUG_ENTER("_nisam_rec_check");
-
- packpos=info->rec_buff; to= info->rec_buff+info->s->base.pack_bits;
- rec=info->s->rec;
- flag= *packpos; bit=1;
-
- for (i=info->s->base.fields ; i-- > 0; from+= (rec++)->base.length)
- {
- length=(uint) rec->base.length;
- if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
- {
- if (type == FIELD_BLOB)
- {
- uint blob_length= _calc_blob_length(length,from);
- if (!blob_length && !(flag & bit))
- goto err;
- if (blob_length)
- to+=length+ blob_length;
- from+=sizeof(char*);
- }
- else if (type == FIELD_SKIP_ZERO)
- {
- if (memcmp((byte*) from,zero_string,length) == 0)
- {
- if (!(flag & bit))
- goto err;
- }
- else
- to+=length;
- }
- else if (type == FIELD_SKIP_ENDSPACE ||
- type == FIELD_SKIP_PRESPACE)
- {
- pos= (byte*) from; end= (byte*) from + length;
- if (type == FIELD_SKIP_ENDSPACE)
- { /* Pack trailing spaces */
- while (end > from && *(end-1) == ' ')
- end--;
- }
- else
- { /* Pack pre-spaces */
- while (pos < end && *pos == ' ')
- pos++;
- }
- new_length=(uint) (end-pos);
- if (new_length +1 + test(rec->base.length > 255 && new_length > 127)
- < length)
- {
- if (!(flag & bit))
- goto err;
- if (rec->base.length > 255 && new_length > 127)
- {
- if (to[0] != (char) ((new_length & 127)+128) ||
- to[1] != (char) (new_length >> 7))
- goto err;
- to+=2;
- }
- else if (*to++ != (char) new_length)
- goto err;
- to+=new_length;
- }
- else
- to+=length;
- }
- else
- {
- if (type != FIELD_ZERO)
- to+=length; /* Not packed field */
- continue;
- }
- if ((bit= bit << 1) >= 256)
- {
- flag= *++packpos;
- bit=1;
- }
- }
- else
- {
- to+=length;
- }
- }
- if (bit != 1)
- *packpos= (char) (uchar) flag;
- if (info->packed_length == (uint) (to - info->rec_buff) &&
- (bit == 1 || !(flag & ~(bit - 1))))
- DBUG_RETURN(0);
-
- err:
- DBUG_RETURN(1);
-}
-
-
-
- /* Unpacks a record */
- /* Returns -1 and my_errno =HA_ERR_RECORD_DELETED if reclength isn't */
- /* right. Returns reclength (>0) if ok */
-
-uint _nisam_rec_unpack(register N_INFO *info, register byte *to, byte *from,
- uint found_length)
-{
- uint flag,bit,length,rec_length,min_pack_length;
- enum en_fieldtype type;
- byte *from_end,*to_end,*packpos;
- reg3 N_RECINFO *rec,*end_field;
- DBUG_ENTER("_nisam_rec_unpack");
-
- to_end=to + info->s->base.reclength;
- from_end=from+found_length;
- flag= (uchar) *from; bit=1; packpos=from;
- if (found_length < info->s->base.min_pack_length)
- goto err;
- from+= info->s->base.pack_bits;
- min_pack_length=info->s->base.min_pack_length - info->s->base.pack_bits;
-
- for (rec=info->s->rec , end_field=rec+info->s->base.fields ;
- rec < end_field ; to+= rec_length, rec++)
- {
- rec_length=rec->base.length;
- if ((type = (enum en_fieldtype) rec->base.type) != FIELD_NORMAL)
- {
- if (type == FIELD_ZERO)
- continue; /* Skip this */
- if (flag & bit)
- {
- if (type == FIELD_BLOB)
- {
- bzero((byte*) to,rec_length+sizeof(char*));
- to+=sizeof(char*);
- }
- else if (type == FIELD_SKIP_ZERO)
- bzero((byte*) to,rec_length);
- else if (type == FIELD_SKIP_ENDSPACE ||
- type == FIELD_SKIP_PRESPACE)
- {
- if (rec->base.length > 255 && *from & 128)
- {
- if (from + 1 >= from_end)
- goto err;
- length= (*from & 127)+ ((uint) (uchar) *(from+1) << 7); from+=2;
- }
- else
- {
- if (from == from_end)
- goto err;
- length= (uchar) *from++;
- }
- min_pack_length--;
- if (length >= rec_length ||
- min_pack_length + length > (uint) (from_end - from))
- goto err;
- if (type == FIELD_SKIP_ENDSPACE)
- {
- memcpy(to,(byte*) from,(size_t) length);
- bfill((byte*) to+length,rec_length-length,' ');
- }
- else
- {
- bfill((byte*) to,rec_length-length,' ');
- memcpy(to+rec_length-length,(byte*) from,(size_t) length);
- }
- from+=length;
- }
- }
- else if (type == FIELD_BLOB)
- {
- ulong blob_length=_calc_blob_length(rec_length,from);
- if ((ulong) (from_end-from) - rec_length < blob_length ||
- min_pack_length > (uint) (from_end -(from+rec_length+blob_length)))
- goto err;
- memcpy((byte*) to,(byte*) from,(size_t) rec_length);
- from+=rec_length;
- /* memcpy crasches alpha egcs 1.1.2 */
- bmove((byte*) to+rec_length,(byte*) &from,sizeof(char*));
- from+=blob_length;
- to+=sizeof(char*);
- }
- else
- {
- if (type == FIELD_SKIP_ENDSPACE || type == FIELD_SKIP_PRESPACE)
- min_pack_length--;
- if (min_pack_length + rec_length > (uint) (from_end - from))
- goto err;
- memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
- }
- if ((bit= bit << 1) >= 256)
- {
- flag= (uchar) *++packpos; bit=1;
- }
- }
- else
- {
- if (min_pack_length > (uint) (from_end - from))
- goto err;
- min_pack_length-=rec_length;
- memcpy(to,(byte*) from,(size_t) rec_length); from+=rec_length;
- }
- }
- if (to == to_end && from == from_end && (bit == 1 || !(flag & ~(bit-1))))
- DBUG_RETURN((info->packed_length=found_length));
- err:
- my_errno=HA_ERR_RECORD_DELETED;
- DBUG_PRINT("error",("to_end: %lx -> %lx from_end: %lx -> %lx",
- to,to_end,from,from_end));
- DBUG_DUMP("from",(byte*) info->rec_buff,info->s->base.min_pack_length);
- DBUG_RETURN(MY_FILE_ERROR);
-} /* _nisam_rec_unpack */
-
-
- /* Calc length of blob. Update info in blobs->length */
-
-uint _calc_total_blob_length(N_INFO *info, const byte *record)
-{
- uint i,length;
- N_BLOB *blob;
-
- for (i=length=0, blob= info->blobs; i++ < info->s->base.blobs ; blob++)
- {
- blob->length=_calc_blob_length(blob->pack_length,record + blob->offset);
- length+=blob->length;
- }
- return length;
-}
-
-
-uint _calc_blob_length(uint length, const byte *pos)
-{
- switch (length) {
- case 1:
- return (uint) (uchar) *pos;
- case 2:
- {
- short j; shortget(j,pos);
- return (uint) (unsigned short) j;
- }
-#ifdef MSDOS
- break; /* skip microsoft warning */
-#endif
- case 3:
- return uint3korr(pos);
- case 4:
- {
- long j; longget(j,pos);
- return (uint) j;
- }
-#ifdef MSDOS
- break;
-#endif
- default:
- break;
- }
- return 0; /* Impossible */
-}
-
- /* Read record from datafile */
- /* Returns 0 if ok, -1 if error */
-
-int _nisam_read_dynamic_record(N_INFO *info, ulong filepos, byte *buf)
-{
- int flag;
- uint b_type,left_length;
- byte *to;
- BLOCK_INFO block_info;
- File file;
- DBUG_ENTER("ni_read_dynamic_record");
-
- if (filepos != NI_POS_ERROR)
- {
- LINT_INIT(to);
- LINT_INIT(left_length);
- file=info->dfile;
- block_info.next_filepos=filepos; /* for easyer loop */
- flag=block_info.second_read=0;
- do
- {
- if (info->opt_flag & WRITE_CACHE_USED &&
- info->rec_cache.pos_in_file <= block_info.next_filepos &&
- flush_io_cache(&info->rec_cache))
- goto err;
- info->rec_cache.seek_not_done=1;
- if ((b_type=_nisam_get_block_info(&block_info,file,
- block_info.next_filepos))
- & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
- my_errno=HA_ERR_RECORD_DELETED;
- goto err;
- }
- if (flag == 0) /* First block */
- {
- flag=1;
- if (block_info.rec_len > (uint) info->s->base.max_pack_length)
- goto panic;
- if (info->s->base.blobs)
- {
- if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
- goto err;
- }
- else
- to= info->rec_buff;
- left_length=block_info.rec_len;
- }
- if (left_length < block_info.data_len || ! block_info.data_len)
- goto panic; /* Wrong linked record */
- if (my_pread(file,(byte*) to,block_info.data_len,block_info.filepos,
- MYF(MY_NABP)))
- goto panic;
- left_length-=block_info.data_len;
- to+=block_info.data_len;
- } while (left_length);
-
- info->update|= HA_STATE_AKTIV; /* We have a aktive record */
- VOID(_nisam_writeinfo(info,0));
- DBUG_RETURN(_nisam_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
- MY_FILE_ERROR ? 0 : -1);
- }
- VOID(_nisam_writeinfo(info,0));
- DBUG_RETURN(-1); /* Wrong data to read */
-
-panic:
- my_errno=HA_ERR_WRONG_IN_RECORD;
-err:
- VOID(_nisam_writeinfo(info,0));
- DBUG_RETURN(-1);
-}
-
-
-byte *fix_rec_buff_for_blob(N_INFO *info, uint length)
-{
- uint extra;
- if (! info->rec_buff || length > info->alloced_rec_buff_length)
- {
- byte *newptr;
- extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (!(newptr=(byte*) my_realloc((gptr) info->rec_alloc,length+extra,
- MYF(MY_ALLOW_ZERO_PTR))))
- return newptr;
- info->rec_alloc=newptr;
- info->rec_buff=newptr+ALIGN_SIZE(DYN_DELETE_BLOCK_HEADER);
- info->alloced_rec_buff_length=length;
- }
- return info->rec_buff;
-}
-
-
- /* Compare of record one disk with packed record in memory */
-
-int _nisam_cmp_dynamic_record(register N_INFO *info, register const byte *record)
-{
- uint flag,reclength,b_type;
- ulong filepos;
- byte *buffer;
- BLOCK_INFO block_info;
- DBUG_ENTER("_nisam_cmp_dynamic_record");
-
- /* We are going to do changes; dont let anybody disturb */
- dont_break(); /* Dont allow SIGHUP or SIGINT */
-
- if (info->opt_flag & WRITE_CACHE_USED)
- {
- info->update&= ~HA_STATE_WRITE_AT_END;
- if (flush_io_cache(&info->rec_cache))
- DBUG_RETURN(-1);
- }
- info->rec_cache.seek_not_done=1;
-
- /* If nobody have touched the database we don't have to test rec */
-
- buffer=info->rec_buff;
- if ((info->opt_flag & READ_CHECK_USED))
- { /* If check isn't disabled */
- if (info->s->base.blobs)
- {
- if (!(buffer=(byte*) my_alloca(info->s->base.pack_reclength+
- _calc_total_blob_length(info,record))))
- DBUG_RETURN(-1);
- }
- reclength=_nisam_rec_pack(info,buffer,record);
- record= buffer;
-
- filepos=info->lastpos;
- flag=block_info.second_read=0;
- block_info.next_filepos=filepos;
- while (reclength > 0)
- {
- if ((b_type=_nisam_get_block_info(&block_info,info->dfile,
- block_info.next_filepos))
- & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if (b_type & (BLOCK_SYNC_ERROR | BLOCK_DELETED))
- my_errno=HA_ERR_RECORD_CHANGED;
- goto err;
- }
- if (flag == 0) /* First block */
- {
- flag=1;
- if (reclength != block_info.rec_len)
- {
- my_errno=HA_ERR_RECORD_CHANGED;
- goto err;
- }
- } else if (reclength < block_info.data_len)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- goto err;
- }
- reclength-=block_info.data_len;
- if (_nisam_cmp_buffer(info->dfile,record,block_info.filepos,
- block_info.data_len))
- {
- my_errno=HA_ERR_RECORD_CHANGED;
- goto err;
- }
- flag=1;
- record+=block_info.data_len;
- }
- }
- my_errno=0;
- err:
- if (buffer != info->rec_buff)
- my_afree((gptr) buffer);
- DBUG_RETURN(my_errno);
-}
-
-
- /* Compare file to buffert */
-
-static int _nisam_cmp_buffer(File file, const byte *buff, ulong filepos, uint length)
-{
- uint next_length;
- char temp_buff[IO_SIZE*2];
- DBUG_ENTER("_nisam_cmp_buffer");
-
- VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
- next_length= IO_SIZE*2 - (uint) (filepos & (IO_SIZE-1));
-
- while (length > IO_SIZE*2)
- {
- if (my_read(file,temp_buff,next_length,MYF(MY_NABP)))
- goto err;
- if (memcmp((byte*) buff,temp_buff,next_length))
- DBUG_RETURN(1);
- buff+=next_length;
- length-= next_length;
- next_length=IO_SIZE*2;
- }
- if (my_read(file,temp_buff,length,MYF(MY_NABP)))
- goto err;
- DBUG_RETURN(memcmp((byte*) buff,temp_buff,length));
-err:
- DBUG_RETURN(1);
-}
-
-
-int _nisam_read_rnd_dynamic_record(N_INFO *info, byte *buf, register ulong filepos, int skipp_deleted_blocks)
-{
- int flag,info_read,fatal_errcode;
- uint left_len,b_type;
- byte *to;
- BLOCK_INFO block_info;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_read_rnd_dynamic_record");
-
- info_read=0;
- fatal_errcode= -1;
- LINT_INIT(to);
-
-#ifndef NO_LOCKING
- if (info->lock_type == F_UNLCK)
- {
-#ifndef UNSAFE_LOCKING
- if (share->r_locks == 0 && share->w_locks == 0)
- {
- if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
- DBUG_RETURN(fatal_errcode);
- }
-#else
- info->tmp_lock_type=F_RDLCK;
-#endif
- }
- else
- info_read=1; /* memory-keyinfoblock is ok */
-#endif /* !NO_LOCKING */
-
- flag=block_info.second_read=0;
- left_len=1;
- do
- {
- if (filepos >= share->state.data_file_length)
- {
-#ifndef NO_LOCKING
- if (!info_read)
- { /* Check if changed */
- info_read=1;
- info->rec_cache.seek_not_done=1;
- if (my_pread(share->kfile,(char*) &share->state.header,
- share->state_length, 0L,MYF(MY_NABP)))
- goto err;
- }
- if (filepos >= share->state.data_file_length)
-#endif
- {
- my_errno= HA_ERR_END_OF_FILE;
- goto err;
- }
- }
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (_nisam_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
- sizeof(block_info.header),
- test(!flag && skipp_deleted_blocks) | 2))
- goto err;
- b_type=_nisam_get_block_info(&block_info,-1,filepos);
- }
- else
- {
- if (info->opt_flag & WRITE_CACHE_USED &&
- info->rec_cache.pos_in_file <= filepos &&
- flush_io_cache(&info->rec_cache))
- DBUG_RETURN(-1);
- info->rec_cache.seek_not_done=1;
- b_type=_nisam_get_block_info(&block_info,info->dfile,filepos);
- }
-
- if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if ((b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
- && skipp_deleted_blocks)
- {
- filepos=block_info.filepos+block_info.block_len;
- block_info.second_read=0;
- continue; /* Search after next_record */
- }
- if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
- {
- my_errno=HA_ERR_RECORD_DELETED;
- info->lastpos=block_info.filepos;
- info->nextpos=block_info.filepos+block_info.block_len;
- fatal_errcode=1;
- }
- goto err;
- }
- if (flag == 0) /* First block */
- {
- if (block_info.rec_len > (uint) share->base.max_pack_length)
- goto panic;
- info->lastpos=filepos;
- if (share->base.blobs)
- {
- if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
- goto err;
- }
- else
- to= info->rec_buff;
- left_len=block_info.rec_len;
- }
- if (left_len < block_info.data_len)
- goto panic; /* Wrong linked record */
-
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (_nisam_read_cache(&info->rec_cache,(byte*) to,block_info.filepos,
- block_info.data_len,
- test(!flag && skipp_deleted_blocks)))
- goto err;
- }
- else
- {
- VOID(my_seek(info->dfile,block_info.filepos,MY_SEEK_SET,MYF(0)));
- if (my_read(info->dfile,(byte*) to,block_info.data_len,MYF(MY_NABP)))
- goto err;
- }
- if (flag++ == 0)
- {
- info->nextpos=block_info.filepos+block_info.block_len;
- skipp_deleted_blocks=0;
- }
- left_len-=block_info.data_len;
- to+=block_info.data_len;
- filepos=block_info.next_filepos;
- } while (left_len);
-
- info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
- VOID(_nisam_writeinfo(info,0));
- if (_nisam_rec_unpack(info,buf,info->rec_buff,block_info.rec_len) !=
- MY_FILE_ERROR)
- DBUG_RETURN(0);
- DBUG_RETURN(fatal_errcode); /* Wrong record */
-
-panic:
- my_errno=HA_ERR_WRONG_IN_RECORD; /* Something is fatal wrong */
-err:
- VOID(_nisam_writeinfo(info,0));
- DBUG_RETURN(fatal_errcode);
-}
-
-
- /* Read and process header from a dynamic-record-file */
-
-uint _nisam_get_block_info(BLOCK_INFO *info, File file, ulong filepos)
-{
- uint return_val=0,length;
- uchar *header=info->header;
-
- if (file >= 0)
- {
- VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
- if ((length=my_read(file,(char*) header,BLOCK_INFO_HEADER_LENGTH,MYF(0)))
- == MY_FILE_ERROR)
- return BLOCK_FATAL_ERROR;
- if (length != BLOCK_INFO_HEADER_LENGTH)
- { /* Test if short block */
- if (length < 3)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */
- return BLOCK_FATAL_ERROR;
- }
- bzero((byte*) header+length,BLOCK_INFO_HEADER_LENGTH-length);
- }
- }
- DBUG_DUMP("header",(byte*) header,BLOCK_INFO_HEADER_LENGTH);
- if (info->second_read)
- {
- if (info->header[0] <= 8)
- return_val=BLOCK_SYNC_ERROR;
- }
- else
- {
- if (info->header[0] > 8)
- return_val=BLOCK_SYNC_ERROR;
- }
- info->next_filepos= (ulong) NI_POS_ERROR; /* Dummy ifall no next block */
-
- switch (info->header[0]) {
- case 0:
- if ((info->block_len=(uint) uint3korr(header+1)) < N_MIN_BLOCK_LENGTH)
- return BLOCK_FATAL_ERROR;
- info->filepos=filepos;
- info->next_filepos=uint4korr(header+4);
- if (info->next_filepos == (uint32) ~0) /* Fix for 64 bit long */
- info->next_filepos=NI_POS_ERROR;
- return return_val | BLOCK_DELETED; /* Deleted block */
- case 1:
- info->rec_len=info->data_len=info->block_len=uint2korr(header+1);
- info->filepos=filepos+3;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 2:
- info->block_len=(info->rec_len=info->data_len=uint2korr(header+1))+1;
- info->filepos=filepos+3;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 3:
- info->rec_len=info->data_len=uint2korr(header+1);
- info->block_len=uint2korr(header+3);
- info->filepos=filepos+5;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 4:
- info->rec_len=uint2korr(header+1);
- info->block_len=info->data_len=uint2korr(header+3);
- info->next_filepos=uint4korr(header+5);
- info->second_read=1;
- info->filepos=filepos+9;
- return return_val | BLOCK_FIRST;
-#if defined(_MSC_VER) || !defined(__WIN__)
- case 5:
- info->rec_len=info->data_len=info->block_len=uint3korr(header+1);
- info->filepos=filepos+4;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 6:
- info->block_len=(info->rec_len=info->data_len=uint3korr(header+1))+1;
- info->filepos=filepos+4;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 7:
- info->rec_len=info->data_len=uint3korr(header+1);
- info->block_len=uint3korr(header+4);
- info->filepos=filepos+7;
- return return_val | BLOCK_FIRST | BLOCK_LAST;
- case 8:
- info->rec_len=uint3korr(header+1);
- info->block_len=info->data_len=uint3korr(header+4);
- info->next_filepos=uint4korr(header+7);
- info->second_read=1;
- info->filepos=filepos+11;
- return return_val | BLOCK_FIRST;
-#endif
- case 9:
- info->data_len=info->block_len=uint2korr(header+1);
- info->filepos=filepos+3;
- return return_val | BLOCK_LAST;
- case 10:
- info->block_len=(info->data_len=uint2korr(header+1))+1;
- info->filepos=filepos+3;
- return return_val | BLOCK_LAST;
- case 11:
- info->data_len=uint2korr(header+1);
- info->block_len=uint2korr(header+3);
- info->filepos=filepos+5;
- return return_val | BLOCK_LAST;
- case 12:
- info->data_len=info->block_len=uint2korr(header+1);
- info->next_filepos=uint4korr(header+3);
- info->second_read=1;
- info->filepos=filepos+7;
- return return_val;
-#if defined(_MSC_VER) || !defined(__WIN__)
- case 13:
- info->data_len=info->block_len=uint3korr(header+1);
- info->filepos=filepos+4;
- return return_val | BLOCK_LAST;
- case 14:
- info->block_len=(info->data_len=uint3korr(header+1))+1;
- info->filepos=filepos+4;
- return return_val | BLOCK_LAST;
- case 15:
- info->data_len=uint3korr(header+1);
- info->block_len=uint3korr(header+4);
- info->filepos=filepos+7;
- return return_val | BLOCK_LAST;
- case 16:
- info->data_len=info->block_len=uint3korr(header+1);
- info->next_filepos=uint4korr(header+4);
- info->second_read=1;
- info->filepos=filepos+8;
- return return_val;
-#endif
- default:
- my_errno=HA_ERR_WRONG_IN_RECORD; /* Garbage */
- return BLOCK_ERROR;
- }
-}
diff --git a/isam/_key.c b/isam/_key.c
deleted file mode 100644
index 65d6885869e..00000000000
--- a/isam/_key.c
+++ /dev/null
@@ -1,238 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Functions to handle keys */
-
-#include "isamdef.h"
-#include "m_ctype.h"
-
-static void _nisam_put_key_in_record(N_INFO *info,uint keynr,byte *record);
-
- /* Make a intern key from a record */
- /* If ascii key convert according to sortorder */
- /* Ret: Length of key */
-
-uint _nisam_make_key(register N_INFO *info, uint keynr, uchar *key, const char *record, ulong filepos)
-{
- uint length;
- byte *pos,*end;
- uchar *start;
- reg1 N_KEYSEG *keyseg;
- enum ha_base_keytype type;
- DBUG_ENTER("_nisam_make_key");
-
- start=key;
- for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->base.type ;keyseg++)
- {
- type=(enum ha_base_keytype) keyseg->base.type;
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- pos= (byte*) record+keyseg->base.start; end=pos+keyseg->base.length;
- if (type != HA_KEYTYPE_NUM)
- {
- while (end > pos && end[-1] == ' ')
- end--;
- }
- else
- {
- while (pos < end && pos[0] == ' ')
- pos++;
- }
- *key++= (uchar) (length=(uint) (end-pos));
- memcpy((byte*) key,(byte*) pos,(size_t) length);
- if (!use_strnxfrm(default_charset_info))
- {
- if (type == HA_KEYTYPE_TEXT)
- my_strnxfrm(default_charset_info,(uchar*) key, length,
- (uchar*) key, length);
- }
- key+=length;
- }
- else
- {
- memcpy((byte*) key,(byte*) record+keyseg->base.start,
- (size_t) keyseg->base.length);
- if (!use_strnxfrm(default_charset_info))
- {
- if (type == HA_KEYTYPE_TEXT)
- my_strnxfrm(default_charset_info,(uchar*) key,
- (uint) keyseg->base.length,
- (uchar*) key,
- (uint) keyseg->base.length);
- }
-#ifdef NAN_TEST
- else if (type == HA_KEYTYPE_FLOAT)
- {
- float nr;
- bmove((byte*) &nr,(byte*) key,sizeof(float));
- if (nr == (float) FLT_MAX)
- {
- nr= (float) FLT_MAX;
- bmove((byte*) key,(byte*) &nr,sizeof(float));
- }
- }
- else if (type == HA_KEYTYPE_DOUBLE)
- {
- double nr;
- bmove((byte*) &nr,(byte*) key,sizeof(double));
- if (nr == DBL_MAX)
- {
- nr=DBL_MAX;
- bmove((byte*) key,(byte*) &nr,sizeof(double));
- }
- }
-#endif
- key+= keyseg->base.length;
- }
- }
- _nisam_dpointer(info,key,filepos);
- DBUG_PRINT("exit",("keynr: %d",keynr));
- DBUG_DUMP("key",(byte*) start,(uint) (key-start)+keyseg->base.length);
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,info->s->keyinfo[keynr].seg,start););
- DBUG_RETURN((uint) (key-start)); /* Return keylength */
-} /* _nisam_make_key */
-
-
- /* Pack a key to intern format from given format (c_rkey) */
- /* if key_length is set returns new length of key */
-
-uint _nisam_pack_key(register N_INFO *info, uint keynr, uchar *key, uchar *old, uint key_length)
-
-
-
- /* Length of used key */
-{
- int k_length;
- uint length;
- uchar *pos,*end;
- reg1 N_KEYSEG *keyseg;
- enum ha_base_keytype type;
- DBUG_ENTER("_nisam_pack_key");
-
- if ((k_length=(int) key_length) <= 0)
- k_length=N_MAX_KEY_BUFF;
-
- for (keyseg=info->s->keyinfo[keynr].seg ;
- keyseg->base.type && k_length >0;
- k_length-=keyseg->base.length, old+=keyseg->base.length, keyseg++)
- {
- length=min((uint) keyseg->base.length,(uint) k_length);
- type=(enum ha_base_keytype) keyseg->base.type;
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- pos=old; end=pos+length;
- if (type != HA_KEYTYPE_NUM)
- {
- while (end > pos && end[-1] == ' ')
- end--;
- }
- else
- {
- while (pos < end && pos[0] == ' ')
- pos++;
- }
- *key++ = (uchar) (length=(uint) (end-pos));
- memcpy((byte*) key,pos,(size_t) length);
- }
- else
- memcpy((byte*) key,old,(size_t) length);
- if (!use_strnxfrm(default_charset_info))
- {
- if (type == HA_KEYTYPE_TEXT)
- my_strnxfrm(default_charset_info,(uchar*) key,length,
- (uchar*) key,length);
- }
- key+= length;
- }
- if (!keyseg->base.type)
- {
- if (k_length >= 0) /* Hole key */
- key_length=0;
- }
- else
- { /* Part-key ; fill with null */
- length= (uint) -k_length; /* unused part of last key */
- do
- {
- length+= (keyseg->base.flag & HA_SPACE_PACK) ? 1 :
- keyseg->base.length;
- keyseg++;
- } while (keyseg->base.type);
- bzero((byte*) key,length);
- }
- DBUG_RETURN(key_length); /* Return part-keylength */
-} /* _nisam_pack_key */
-
-
- /* Put a key in record */
- /* Used when only-keyread is wanted */
-
-static void _nisam_put_key_in_record(register N_INFO *info, uint keynr, byte *record)
-{
- uint length;
- reg2 byte *key;
- byte *pos;
- reg1 N_KEYSEG *keyseg;
- DBUG_ENTER("_nisam_put_key_in_record");
-
- key=(byte*) info->lastkey;
- for (keyseg=info->s->keyinfo[keynr].seg ; keyseg->base.type ;keyseg++)
- {
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- length= (uint) (uchar) *key++;
- pos= record+keyseg->base.start;
- if (keyseg->base.type != (int) HA_KEYTYPE_NUM)
- {
- memcpy(pos,key,(size_t) length);
- bfill(pos+length,keyseg->base.length-length,' ');
- }
- else
- {
- bfill(pos,keyseg->base.length-length,' ');
- memcpy(pos+keyseg->base.length-length,key,(size_t) length);
- }
- key+=length;
- }
- else
- {
- memcpy(record+keyseg->base.start,(byte*) key,
- (size_t) keyseg->base.length);
- key+= keyseg->base.length;
- }
- }
- DBUG_VOID_RETURN;
-} /* _nisam_put_key_in_record */
-
-
- /* Here when key reads are used */
-
-int _nisam_read_key_record(N_INFO *info, ulong filepos, byte *buf)
-{
- VOID(_nisam_writeinfo(info,0));
- if (filepos != NI_POS_ERROR)
- {
- if (info->lastinx >= 0)
- { /* Read only key */
- _nisam_put_key_in_record(info,(uint) info->lastinx,buf);
- info->update|= HA_STATE_AKTIV; /* We should find a record */
- return 0;
- }
- my_errno=HA_ERR_WRONG_INDEX;
- return(-1);
- }
- return(-1); /* Wrong data to read */
-}
diff --git a/isam/_locking.c b/isam/_locking.c
deleted file mode 100644
index e19804549e5..00000000000
--- a/isam/_locking.c
+++ /dev/null
@@ -1,345 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- locking of isam-tables.
- reads info from a isam-table. Must be first request before doing any furter
- calls to any isamfunktion. Is used to allow many process use the same
- isamdatabase.
- */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* lock table by F_UNLCK, F_RDLCK or F_WRLCK */
-
-int nisam_lock_database(N_INFO *info, int lock_type)
-{
- int error;
- uint count;
- ISAM_SHARE *share;
- uint flag;
- DBUG_ENTER("nisam_lock_database");
-
- flag=error=0;
-#ifndef NO_LOCKING
- share=info->s;
- if (share->base.options & HA_OPTION_READ_ONLY_DATA ||
- info->lock_type == lock_type)
- DBUG_RETURN(0);
- pthread_mutex_lock(&share->intern_lock);
- switch (lock_type) {
- case F_UNLCK:
- if (info->lock_type == F_RDLCK)
- count= --share->r_locks;
- else
- count= --share->w_locks;
- if (info->lock_type == F_WRLCK && !share->w_locks &&
- flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_KEEP))
- error=my_errno;
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- if (end_io_cache(&info->rec_cache))
- error=my_errno;
-
- if (!count)
- {
- if (share->changed && !share->w_locks)
- {
- share->state.process= share->last_process=share->this_process;
- share->state.loop= info->last_loop= ++info->this_loop;
- share->state.uniq= info->last_uniq= info->this_uniq;
- if (my_pwrite(share->kfile,(char*) &share->state.header,
- share->state_length,0L,MYF(MY_NABP)))
- error=my_errno;
- share->changed=0;
-#ifdef __WIN__
- if (nisam_flush)
- {
- _commit(share->kfile);
- _commit(info->dfile);
- }
- else
- share->not_flushed=1;
-#endif
- }
- if (share->r_locks)
- { /* Only read locks left */
- flag=1;
- if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
- MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
- error=my_errno;
- }
- else if (!share->w_locks)
- { /* No more locks */
- flag=1;
- if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
- MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
- error=my_errno;
- }
- }
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- info->lock_type= F_UNLCK;
- break;
- case F_RDLCK:
- if (info->lock_type == F_WRLCK)
- { /* Change RW to READONLY */
- if (share->w_locks == 1)
- {
- flag=1;
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE)))
- {
- error=my_errno;
- break;
- }
- }
- share->w_locks--;
- share->r_locks++;
- info->lock_type=lock_type;
- break;
- }
- if (!share->r_locks && !share->w_locks)
- {
- flag=1;
-#ifdef HAVE_FCNTL
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
- {
- error=my_errno;
- break;
- }
- if (my_pread(share->kfile,
- (char*) &share->state.header,share->state_length,0L,
- MYF(MY_NABP)))
- {
- error=my_errno;
- VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
- my_errno=error;
- break;
- }
-#else
- VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
- {
- error=my_errno;
- break;
- }
- if (my_read(share->kfile,
- (char*) &share->state.header,share->state_length,
- MYF(MY_NABP)))
- {
- error=my_errno;
- VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
- my_errno=error;
- break;
- }
-#endif
- }
- VOID(_nisam_test_if_changed(info));
- share->r_locks++;
- info->lock_type=lock_type;
- break;
- case F_WRLCK:
- if (info->lock_type == F_RDLCK)
- { /* Change RW to READONLY */
- if (share->r_locks == 1)
- {
- flag=1;
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,
- MYF(info->lock_wait | MY_SEEK_NOT_DONE)))
- {
- error=my_errno;
- break;
- }
- share->r_locks--;
- share->w_locks++;
- info->lock_type=lock_type;
- break;
- }
- }
- if (!(share->base.options & HA_OPTION_READ_ONLY_DATA) && !share->w_locks)
- {
- flag=1;
- VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
- {
- error=my_errno;
- break;
- }
- if (!share->r_locks)
- {
- if (my_read(share->kfile,
- (char*) &share->state.header,share->state_length,
- MYF(MY_NABP)))
- {
- error=my_errno;
- VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,info->lock_wait));
- my_errno=error;
- break;
- }
- }
- }
- VOID(_nisam_test_if_changed(info));
- info->lock_type=lock_type;
- share->w_locks++;
- break;
- default:
- break; /* Impossible */
- }
- pthread_mutex_unlock(&share->intern_lock);
-#if defined(FULL_LOG) || defined(_lint)
- lock_type|=(int) (flag << 8); /* Set bit to set if real lock */
- nisam_log_command(LOG_LOCK,info,(byte*) &lock_type,sizeof(lock_type),
- error);
-#endif
-#endif
- DBUG_RETURN(error);
-} /* nisam_lock_database */
-
-
- /* Is used before access to database is granted */
-
-int _nisam_readinfo(register N_INFO *info, int lock_type, int check_keybuffer)
-{
- ISAM_SHARE *share;
- DBUG_ENTER("_nisam_readinfo");
-
- share=info->s;
- if (info->lock_type == F_UNLCK)
- {
- if (!share->r_locks && !share->w_locks)
- {
-#ifndef HAVE_FCNTL
- VOID(my_seek(share->kfile,0L,MY_SEEK_SET,MYF(0)));
-#endif
-#ifndef NO_LOCKING
-#ifdef UNSAFE_LOCKING
- if ((info->tmp_lock_type=lock_type) != F_RDLCK)
-#endif
- if (my_lock(share->kfile,lock_type,0L,F_TO_EOF,info->lock_wait))
- DBUG_RETURN(1);
-#endif
-#ifdef HAVE_FCNTL
- if (my_pread(share->kfile,
- (char*) &share->state.header,share->state_length,0L,
- MYF(MY_NABP)))
-#else
- if (my_read(share->kfile,
- (char*) &share->state.header,share->state_length,
- MYF(MY_NABP)))
-#endif
- {
-#ifndef NO_LOCKING
- int error=my_errno;
- VOID(my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE)));
- my_errno=error;
-#endif
- DBUG_RETURN(1);
- }
- }
- if (check_keybuffer)
- VOID(_nisam_test_if_changed(info));
- }
- else if (lock_type == F_WRLCK && info->lock_type == F_RDLCK)
- {
- my_errno=EACCES; /* Not allowed to change */
- DBUG_RETURN(-1); /* when have read_lock() */
- }
- DBUG_RETURN(0);
-} /* _nisam_readinfo */
-
-
- /* Every isam-function that uppdates the isam-database must! end */
- /* with this request */
- /* ARGSUSED */
-
-int _nisam_writeinfo(register N_INFO *info, uint flags)
-{
- int error,olderror;
- ISAM_SHARE *share;
- DBUG_ENTER("_nisam_writeinfo");
-
- error=0;
- share=info->s;
- if (share->r_locks == 0 && share->w_locks == 0)
- {
- olderror=my_errno; /* Remember last error */
- if (flags)
- { /* Two threads can't be here */
- share->state.process= share->last_process= share->this_process;
- share->state.loop= info->last_loop= ++info->this_loop;
- share->state.uniq= info->last_uniq= info->this_uniq;
- if ((error=my_pwrite(share->kfile,(char*) &share->state.header,
- share->state_length,0L,MYF(MY_NABP)) != 0))
- olderror=my_errno;
-#ifdef __WIN__
- if (nisam_flush)
- {
- _commit(share->kfile);
- _commit(info->dfile);
- }
-#endif
- }
- if (flags != 2)
- {
-#ifndef NO_LOCKING
-#ifdef UNSAFE_LOCKING
- if (info->tmp_lock_type != F_RDLCK)
-#endif
- {
- if (my_lock(share->kfile,F_UNLCK,0L,F_TO_EOF,
- MYF(MY_WME | MY_SEEK_NOT_DONE)) && !error)
- DBUG_RETURN(1);
- }
-#endif
- }
- my_errno=olderror;
- }
- else if (flags)
- share->changed= 1; /* Mark keyfile changed */
- DBUG_RETURN(error);
-} /* _nisam_writeinfo */
-
-
- /* Test if someone has changed the database */
- /* (Should be called after readinfo) */
-
-int _nisam_test_if_changed(register N_INFO *info)
-{
-#ifndef NO_LOCKING
- {
- ISAM_SHARE *share=info->s;
- if (share->state.process != share->last_process ||
- share->state.loop != info->last_loop ||
- share->state.uniq != info->last_uniq)
- { /* Keyfile has changed */
- if (share->state.process != share->this_process)
- VOID(flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_RELEASE));
- share->last_process=share->state.process;
- info->last_loop= share->state.loop;
- info->last_uniq= share->state.uniq;
- info->update|= HA_STATE_WRITTEN; /* Must use file on next */
- info->data_changed= 1; /* For nisam_is_changed */
- return 1;
- }
- }
-#endif
- return (!(info->update & HA_STATE_AKTIV) ||
- (info->update & (HA_STATE_WRITTEN | HA_STATE_DELETED |
- HA_STATE_KEY_CHANGED)));
-} /* _nisam_test_if_changed */
diff --git a/isam/_packrec.c b/isam/_packrec.c
deleted file mode 100644
index 74a45852e63..00000000000
--- a/isam/_packrec.c
+++ /dev/null
@@ -1,1184 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
- /* Functions to compressed records */
-
-#include "isamdef.h"
-
-#define IS_CHAR ((uint) 32768) /* Bit if char (not offset) in tree */
-
-#if INT_MAX > 65536L
-#define BITS_SAVED 32
-#define MAX_QUICK_TABLE_BITS 9 /* Because we may shift in 24 bits */
-#else
-#define BITS_SAVED 16
-#define MAX_QUICK_TABLE_BITS 6
-#endif
-
-#define get_bit(BU) ((BU)->bits ? \
- (BU)->current_byte & ((bit_type) 1 << --(BU)->bits) :\
- (fill_buffer(BU), (BU)->bits= BITS_SAVED-1,\
- (BU)->current_byte & ((bit_type) 1 << (BITS_SAVED-1))))
-#define skipp_to_next_byte(BU) ((BU)->bits&=~7)
-#define get_bits(BU,count) (((BU)->bits >= count) ? (((BU)->current_byte >> ((BU)->bits-=count)) & mask[count]) : fill_and_get_bits(BU,count))
-
-#define decode_bytes_test_bit(bit) \
- if (low_byte & (1 << (7-bit))) \
- pos++; \
- if (*pos & IS_CHAR) \
- { bits-=(bit+1); break; } \
- pos+= *pos
-
-
- static void read_huff_table(BIT_BUFF *bit_buff,DECODE_TREE *decode_tree,
- uint16 **decode_table,byte **intervall_buff,
- uint16 *tmp_buff);
-static void make_quick_table(uint16 *to_table,uint16 *decode_table,
- uint *next_free,uint value,uint bits,
- uint max_bits);
-static void fill_quick_table(uint16 *table,uint bits, uint max_bits,
- uint value);
-static uint copy_decode_table(uint16 *to_pos,uint offset,
- uint16 *decode_table);
-static uint find_longest_bitstream(uint16 *table);
-static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *field,
- BIT_BUFF *buff,
- uchar *to,
- uchar *end);
-static void uf_zerofill_skipp_zero(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_skipp_zero(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_normal(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_endspace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to, uchar *end);
-static void uf_endspace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_endspace(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_endspace(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_prespace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to, uchar *end);
-static void uf_prespace_selected(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_space_prespace(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_prespace(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_zerofill_normal(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_constant(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_intervall(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void uf_zero(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static void decode_bytes(N_RECINFO *rec,BIT_BUFF *bit_buff,
- uchar *to,uchar *end);
-static uint decode_pos(BIT_BUFF *bit_buff,DECODE_TREE *decode_tree);
-static void init_bit_buffer(BIT_BUFF *bit_buff,char *buffer,uint length);
-static uint fill_and_get_bits(BIT_BUFF *bit_buff,uint count);
-static void fill_buffer(BIT_BUFF *bit_buff);
-static uint max_bit(uint value);
-#ifdef HAVE_MMAP
-static void _nisam_mempack_get_block_info(BLOCK_INFO *info,uint ref_length,
- uchar *header);
-#endif
-
-static uint mask[]=
-{
- 0x00000000,
- 0x00000001, 0x00000003, 0x00000007, 0x0000000f,
- 0x0000001f, 0x0000003f, 0x0000007f, 0x000000ff,
- 0x000001ff, 0x000003ff, 0x000007ff, 0x00000fff,
- 0x00001fff, 0x00003fff, 0x00007fff, 0x0000ffff,
-#if BITS_SAVED > 16
- 0x0001ffff, 0x0003ffff, 0x0007ffff, 0x000fffff,
- 0x001fffff, 0x003fffff, 0x007fffff, 0x00ffffff,
- 0x01ffffff, 0x03ffffff, 0x07ffffff, 0x0fffffff,
- 0x1fffffff, 0x3fffffff, 0x7fffffff, 0xffffffff,
-#endif
- };
-
-
- /* Read all packed info, allocate memory and fix field structs */
-
-my_bool _nisam_read_pack_info(N_INFO *info, pbool fix_keys)
-{
- File file;
- int diff_length;
- uint i,trees,huff_tree_bits,rec_reflength,length;
- uint16 *decode_table,*tmp_buff;
- ulong elements,intervall_length;
- char *disk_cache,*intervall_buff;
- uchar header[32];
- ISAM_SHARE *share=info->s;
- BIT_BUFF bit_buff;
- DBUG_ENTER("_nisam_read_pack_info");
-
- if (nisam_quick_table_bits < 4)
- nisam_quick_table_bits=4;
- else if (nisam_quick_table_bits > MAX_QUICK_TABLE_BITS)
- nisam_quick_table_bits=MAX_QUICK_TABLE_BITS;
-
- file=info->dfile;
- my_errno=0;
- if (my_read(file,(byte*) header,sizeof(header),MYF(MY_NABP)))
- {
- if (!my_errno)
- my_errno=HA_ERR_END_OF_FILE;
- DBUG_RETURN(1);
- }
- if (memcmp((byte*) header,(byte*) nisam_pack_file_magic,4))
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- DBUG_RETURN(1);
- }
- share->pack.header_length=uint4korr(header+4);
- share->min_pack_length=(uint) uint4korr(header+8);
- share->max_pack_length=(uint) uint4korr(header+12);
- set_if_bigger(share->base.pack_reclength,share->max_pack_length);
- elements=uint4korr(header+16);
- intervall_length=uint4korr(header+20);
- trees=uint2korr(header+24);
- share->pack.ref_length=header[26];
- rec_reflength=header[27];
- diff_length=(int) rec_reflength - (int) share->base.rec_reflength;
- if (fix_keys)
- share->rec_reflength=rec_reflength;
- share->base.min_block_length=share->min_pack_length+share->pack.ref_length;
-
- if (!(share->decode_trees=(DECODE_TREE*)
- my_malloc((uint) (trees*sizeof(DECODE_TREE)+
- intervall_length*sizeof(byte)),
- MYF(MY_WME))))
- DBUG_RETURN(1);
- intervall_buff=(byte*) (share->decode_trees+trees);
-
- length=(uint) (elements*2+trees*(1 << nisam_quick_table_bits));
- if (!(share->decode_tables=(uint16*)
- my_malloc((length+512)*sizeof(uint16)+
- (uint) (share->pack.header_length+7),
- MYF(MY_WME | MY_ZEROFILL))))
- {
- my_free((gptr) share->decode_trees,MYF(0));
- DBUG_RETURN(1);
- }
- tmp_buff=share->decode_tables+length;
- disk_cache=(byte*) (tmp_buff+512);
-
- if (my_read(file,disk_cache,
- (uint) (share->pack.header_length-sizeof(header)),
- MYF(MY_NABP)))
- {
- my_free((gptr) share->decode_trees,MYF(0));
- my_free((gptr) share->decode_tables,MYF(0));
- DBUG_RETURN(1);
- }
-
- huff_tree_bits=max_bit(trees ? trees-1 : 0);
- init_bit_buffer(&bit_buff,disk_cache,
- (uint) (share->pack.header_length-sizeof(header)));
- /* Read new info for each field */
- for (i=0 ; i < share->base.fields ; i++)
- {
- share->rec[i].base_type=(enum en_fieldtype) get_bits(&bit_buff,4);
- share->rec[i].pack_type=(uint) get_bits(&bit_buff,4);
- share->rec[i].space_length_bits=get_bits(&bit_buff,4);
- share->rec[i].huff_tree=share->decode_trees+(uint) get_bits(&bit_buff,
- huff_tree_bits);
- share->rec[i].unpack=get_unpack_function(share->rec+i);
- }
- skipp_to_next_byte(&bit_buff);
- decode_table=share->decode_tables;
- for (i=0 ; i < trees ; i++)
- read_huff_table(&bit_buff,share->decode_trees+i,&decode_table,
- &intervall_buff,tmp_buff);
- decode_table=(uint16*)
- my_realloc((gptr) share->decode_tables,
- (uint) ((byte*) decode_table - (byte*) share->decode_tables),
- MYF(MY_HOLD_ON_ERROR));
- {
- my_ptrdiff_t diff=PTR_BYTE_DIFF(decode_table,share->decode_tables);
- share->decode_tables=decode_table;
- for (i=0 ; i < trees ; i++)
- share->decode_trees[i].table=ADD_TO_PTR(share->decode_trees[i].table,
- diff, uint16*);
- }
-
- /* Fix record-ref-length for keys */
- if (fix_keys)
- {
- for (i=0 ; i < share->base.keys ; i++)
- {
- share->keyinfo[i].base.keylength+=(uint16) diff_length;
- share->keyinfo[i].base.minlength+=(uint16) diff_length;
- share->keyinfo[i].base.maxlength+=(uint16) diff_length;
- share->keyinfo[i].seg[share->keyinfo[i].base.keysegs].base.length=
- (uint16) rec_reflength;
- }
- }
-
- if (bit_buff.error || bit_buff.pos < bit_buff.end)
- { /* info_length was wrong */
- my_errno=HA_ERR_WRONG_IN_RECORD;
- my_free((gptr) share->decode_trees,MYF(0));
- my_free((gptr) share->decode_tables,MYF(0));
- DBUG_RETURN(1);
- }
- DBUG_RETURN(0);
-}
-
-
- /* Read on huff-code-table from datafile */
-
-static void read_huff_table(BIT_BUFF *bit_buff, DECODE_TREE *decode_tree,
- uint16 **decode_table, byte **intervall_buff,
- uint16 *tmp_buff)
-{
- uint min_chr,elements,char_bits,offset_bits,size,intervall_length,table_bits,
- next_free_offset;
- uint16 *ptr,*end;
-
- LINT_INIT(ptr);
- if (!get_bits(bit_buff,1))
- {
- min_chr=get_bits(bit_buff,8);
- elements=get_bits(bit_buff,9);
- char_bits=get_bits(bit_buff,5);
- offset_bits=get_bits(bit_buff,5);
- intervall_length=0;
- ptr=tmp_buff;
- }
- else
- {
- min_chr=0;
- elements=get_bits(bit_buff,15);
- intervall_length=get_bits(bit_buff,16);
- char_bits=get_bits(bit_buff,5);
- offset_bits=get_bits(bit_buff,5);
- decode_tree->quick_table_bits=0;
- ptr= *decode_table;
- }
- size=elements*2-2;
-
- for (end=ptr+size ; ptr < end ; ptr++)
- {
- if (get_bit(bit_buff))
- *ptr= (uint16) get_bits(bit_buff,offset_bits);
- else
- *ptr= (uint16) (IS_CHAR + (get_bits(bit_buff,char_bits) + min_chr));
- }
- skipp_to_next_byte(bit_buff);
-
- decode_tree->table= *decode_table;
- decode_tree->intervalls= *intervall_buff;
- if (! intervall_length)
- {
- table_bits=find_longest_bitstream(tmp_buff);
- if (table_bits > nisam_quick_table_bits)
- table_bits=nisam_quick_table_bits;
- next_free_offset= (1 << table_bits);
- make_quick_table(*decode_table,tmp_buff,&next_free_offset,0,table_bits,
- table_bits);
- (*decode_table)+= next_free_offset;
- decode_tree->quick_table_bits=table_bits;
- }
- else
- {
- (*decode_table)=end;
- bit_buff->pos-= bit_buff->bits/8;
- memcpy(*intervall_buff,bit_buff->pos,(size_t) intervall_length);
- (*intervall_buff)+=intervall_length;
- bit_buff->pos+=intervall_length;
- bit_buff->bits=0;
- }
- return;
-}
-
-
-static void make_quick_table(uint16 *to_table, uint16 *decode_table, uint *next_free_offset, uint value, uint bits, uint max_bits)
-{
- if (!bits--)
- {
- to_table[value]= (uint16) *next_free_offset;
- *next_free_offset=copy_decode_table(to_table, *next_free_offset,
- decode_table);
- return;
- }
- if (!(*decode_table & IS_CHAR))
- {
- make_quick_table(to_table,decode_table+ *decode_table,
- next_free_offset,value,bits,max_bits);
- }
- else
- fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table);
- decode_table++;
- value|= (1 << bits);
- if (!(*decode_table & IS_CHAR))
- {
- make_quick_table(to_table,decode_table+ *decode_table,
- next_free_offset,value,bits,max_bits);
- }
- else
- fill_quick_table(to_table+value,bits,max_bits,(uint) *decode_table);
- return;
-}
-
-
-static void fill_quick_table(uint16 *table, uint bits, uint max_bits, uint value)
-{
- uint16 *end;
- value|=(max_bits-bits) << 8;
- for (end=table+ (1 << bits) ;
- table < end ;
- *table++ = (uint16) value | IS_CHAR) ;
-}
-
-
-static uint copy_decode_table(uint16 *to_pos, uint offset, uint16 *decode_table)
-{
- uint prev_offset;
- prev_offset= offset;
-
- if (!(*decode_table & IS_CHAR))
- {
- to_pos[offset]=2;
- offset=copy_decode_table(to_pos,offset+2,decode_table+ *decode_table);
- }
- else
- {
- to_pos[offset]= *decode_table;
- offset+=2;
- }
- decode_table++;
-
- if (!(*decode_table & IS_CHAR))
- {
- to_pos[prev_offset+1]=(uint16) (offset-prev_offset-1);
- offset=copy_decode_table(to_pos,offset,decode_table+ *decode_table);
- }
- else
- to_pos[prev_offset+1]= *decode_table;
- return offset;
-}
-
-
-static uint find_longest_bitstream(uint16 *table)
-{
- uint length=1,length2;
- if (!(*table & IS_CHAR))
- length=find_longest_bitstream(table+ *table)+1;
- table++;
- if (!(*table & IS_CHAR))
- {
- length2=find_longest_bitstream(table+ *table)+1;
- length=max(length,length2);
- }
- return length;
-}
-
-
- /* Read record from datafile */
- /* Returns length of packed record, -1 if error */
-
-int _nisam_read_pack_record(N_INFO *info, ulong filepos, byte *buf)
-{
- BLOCK_INFO block_info;
- File file;
- DBUG_ENTER("_nisam_read_pack_record");
-
- if (filepos == NI_POS_ERROR)
- DBUG_RETURN(-1); /* _search() didn't find record */
-
- file=info->dfile;
- if (_nisam_pack_get_block_info(&block_info,info->s->pack.ref_length,file,
- filepos))
- goto err;
- if (my_read(file,(byte*) info->rec_buff,block_info.rec_len,MYF(MY_NABP)))
- goto panic;
- info->update|= HA_STATE_AKTIV;
- DBUG_RETURN(_nisam_pack_rec_unpack(info,buf,info->rec_buff,
- block_info.rec_len));
-panic:
- my_errno=HA_ERR_WRONG_IN_RECORD;
-err:
- DBUG_RETURN(-1);
-}
-
-
-
-int _nisam_pack_rec_unpack(register N_INFO *info, register byte *to,
- byte *from, uint reclength)
-{
- byte *end_field;
- reg3 N_RECINFO *end;
- N_RECINFO *current_field;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_pack_rec_unpack");
-
- init_bit_buffer(&info->bit_buff,from,reclength);
-
- for (current_field=share->rec, end=current_field+share->base.fields ;
- current_field < end ;
- current_field++,to=end_field)
- {
- end_field=to+current_field->base.length;
- (*current_field->unpack)(current_field,&info->bit_buff,(uchar*) to,
- (uchar*) end_field);
- }
- if (! info->bit_buff.error &&
- info->bit_buff.pos - info->bit_buff.bits/8 == info->bit_buff.end)
- DBUG_RETURN(0);
- my_errno=HA_ERR_WRONG_IN_RECORD;
- info->update&= ~HA_STATE_AKTIV;
- DBUG_RETURN(-1);
-} /* _nisam_pack_rec_unpack */
-
-
- /* Return function to unpack field */
-
-static void (*get_unpack_function(N_RECINFO *rec))(N_RECINFO *, BIT_BUFF *, uchar *, uchar *)
-{
- switch (rec->base_type) {
- case FIELD_SKIP_ZERO:
- if (rec->pack_type & PACK_TYPE_ZERO_FILL)
- return &uf_zerofill_skipp_zero;
- return &uf_skipp_zero;
- case FIELD_NORMAL:
- if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
- return &uf_space_normal;
- if (rec->pack_type & PACK_TYPE_ZERO_FILL)
- return &uf_zerofill_normal;
- return &decode_bytes;
- case FIELD_SKIP_ENDSPACE:
- if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
- {
- if (rec->pack_type & PACK_TYPE_SELECTED)
- return &uf_space_endspace_selected;
- return &uf_space_endspace;
- }
- if (rec->pack_type & PACK_TYPE_SELECTED)
- return &uf_endspace_selected;
- return &uf_endspace;
- case FIELD_SKIP_PRESPACE:
- if (rec->pack_type & PACK_TYPE_SPACE_FIELDS)
- {
- if (rec->pack_type & PACK_TYPE_SELECTED)
- return &uf_space_prespace_selected;
- return &uf_space_prespace;
- }
- if (rec->pack_type & PACK_TYPE_SELECTED)
- return &uf_prespace_selected;
- return &uf_prespace;
- case FIELD_CONSTANT:
- return &uf_constant;
- case FIELD_INTERVALL:
- return &uf_intervall;
- case FIELD_ZERO:
- return &uf_zero;
- case FIELD_BLOB: /* Write this sometimes.. */
- case FIELD_LAST:
- default:
- return 0; /* This should never happend */
- }
-}
-
- /* De different functions to unpack a field */
-
-static void uf_zerofill_skipp_zero(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- if (get_bit(bit_buff))
- bzero((char*) to,(uint) (end-to));
- else
- {
-#ifdef WORDS_BIGENDIAN
- bzero((char*) to,rec->space_length_bits);
- decode_bytes(rec,bit_buff,to+rec->space_length_bits,end);
-#else
- end-=rec->space_length_bits;
- decode_bytes(rec,bit_buff,to,end);
- bzero((byte*) end,rec->space_length_bits);
-#endif
- }
-}
-
-static void uf_skipp_zero(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- if (get_bit(bit_buff))
- bzero((char*) to,(uint) (end-to));
- else
- decode_bytes(rec,bit_buff,to,end);
-}
-
-static void uf_space_normal(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- decode_bytes(rec,bit_buff,to,end);
-}
-
-static void uf_space_endspace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- {
- if (get_bit(bit_buff))
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to,end-spaces);
- bfill((byte*) end-spaces,spaces,' ');
- }
- else
- decode_bytes(rec,bit_buff,to,end);
- }
-}
-
-static void uf_endspace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to,end-spaces);
- bfill((byte*) end-spaces,spaces,' ');
- }
- else
- decode_bytes(rec,bit_buff,to,end);
-}
-
-static void uf_space_endspace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to,end-spaces);
- bfill((byte*) end-spaces,spaces,' ');
- }
-}
-
-static void uf_endspace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to,
- uchar *end)
-{
- uint spaces;
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to,end-spaces);
- bfill((byte*) end-spaces,spaces,' ');
-}
-
-static void uf_space_prespace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- {
- if (get_bit(bit_buff))
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- bfill((byte*) to,spaces,' ');
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to+spaces,end);
- }
- else
- decode_bytes(rec,bit_buff,to,end);
- }
-}
-
-
-static void uf_prespace_selected(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- bfill((byte*) to,spaces,' ');
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to+spaces,end);
- }
- else
- decode_bytes(rec,bit_buff,to,end);
-}
-
-
-static void uf_space_prespace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if (get_bit(bit_buff))
- bfill((byte*) to,(end-to),' ');
- else
- {
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- bfill((byte*) to,spaces,' ');
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to+spaces,end);
- }
-}
-
-static void uf_prespace(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- uint spaces;
- if ((spaces=get_bits(bit_buff,rec->space_length_bits))+to > end)
- {
- bit_buff->error=1;
- return;
- }
- bfill((byte*) to,spaces,' ');
- if (to+spaces != end)
- decode_bytes(rec,bit_buff,to+spaces,end);
-}
-
-static void uf_zerofill_normal(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
-#ifdef WORDS_BIGENDIAN
- bzero((char*) to,rec->space_length_bits);
- decode_bytes(rec,bit_buff,(uchar*) to+rec->space_length_bits,end);
-#else
- end-=rec->space_length_bits;
- decode_bytes(rec,bit_buff,(uchar*) to,end);
- bzero((byte*) end,rec->space_length_bits);
-#endif
-}
-
-static void uf_constant(N_RECINFO *rec,
- BIT_BUFF *bit_buff __attribute__((unused)),
- uchar *to, uchar *end)
-{
- memcpy(to,rec->huff_tree->intervalls,(size_t) (end-to));
-}
-
-static void uf_intervall(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- reg1 uint field_length=(uint) (end-to);
- memcpy(to,rec->huff_tree->intervalls+field_length*decode_pos(bit_buff,
- rec->huff_tree),
- (size_t) field_length);
-}
-
-
-/*ARGSUSED*/
-static void uf_zero(N_RECINFO *rec __attribute__((unused)),
- BIT_BUFF *bit_buff __attribute__((unused)),
- uchar *to, uchar *end)
-{
- bzero((char*) to,(uint) (end-to));
-}
-
-
- /* Functions to decode of buffer of bits */
-
-#if BITS_SAVED == 64
-
-static void decode_bytes(rec,bit_buff,to,end)
-N_RECINFO *rec;
-BIT_BUFF *bit_buff;
-uchar *to,*end;
-{
- reg1 uint bits,low_byte;
- reg3 uint16 *pos;
- reg4 uint table_bits,table_and;
- DECODE_TREE *decode_tree;
-
- decode_tree=rec->decode_tree;
- bits=bit_buff->bits; /* Save in reg for quicker access */
- table_bits=decode_tree->quick_table_bits;
- table_and= (1 << table_bits)-1;
-
- do
- {
- if (bits <= 32)
- {
- if (bit_buff->pos > bit_buff->end+4)
- return; /* Can't be right */
- bit_buff->current_byte= (bit_buff->current_byte << 32) +
- ((((uint) bit_buff->pos[3])) +
- (((uint) bit_buff->pos[2]) << 8) +
- (((uint) bit_buff->pos[1]) << 16) +
- (((uint) bit_buff->pos[0]) << 24));
- bit_buff->pos+=4;
- bits+=32;
- }
- /* First use info in quick_table */
- low_byte=(uint) (bit_buff->current_byte >> (bits - table_bits)) & table_and;
- low_byte=decode_tree->table[low_byte];
- if (low_byte & IS_CHAR)
- {
- *to++ = (low_byte & 255); /* Found char in quick table */
- bits-= ((low_byte >> 8) & 31); /* Remove bits used */
- }
- else
- { /* Map through rest of decode-table */
- pos=decode_tree->table+low_byte;
- bits-=table_bits;
- for (;;)
- {
- low_byte=(uint) (bit_buff->current_byte >> (bits-8));
- decode_bytes_test_bit(0);
- decode_bytes_test_bit(1);
- decode_bytes_test_bit(2);
- decode_bytes_test_bit(3);
- decode_bytes_test_bit(4);
- decode_bytes_test_bit(5);
- decode_bytes_test_bit(6);
- decode_bytes_test_bit(7);
- bits-=8;
- }
- *to++ = *pos;
- }
- } while (to != end);
-
- bit_buff->bits=bits;
- return;
-}
-
-#else
-
-static void decode_bytes(N_RECINFO *rec, BIT_BUFF *bit_buff, uchar *to, uchar *end)
-{
- reg1 uint bits,low_byte;
- reg3 uint16 *pos;
- reg4 uint table_bits,table_and;
- DECODE_TREE *decode_tree;
-
- decode_tree=rec->huff_tree;
- bits=bit_buff->bits; /* Save in reg for quicker access */
- table_bits=decode_tree->quick_table_bits;
- table_and= (1 << table_bits)-1;
-
- do
- {
- if (bits < table_bits)
- {
- if (bit_buff->pos > bit_buff->end+1)
- return; /* Can't be right */
-#if BITS_SAVED == 32
- bit_buff->current_byte= (bit_buff->current_byte << 24) +
- (((uint) ((uchar) bit_buff->pos[2]))) +
- (((uint) ((uchar) bit_buff->pos[1])) << 8) +
- (((uint) ((uchar) bit_buff->pos[0])) << 16);
- bit_buff->pos+=3;
- bits+=24;
-#else
- if (bits) /* We must have at leasts 9 bits */
- {
- bit_buff->current_byte= (bit_buff->current_byte << 8) +
- (uint) ((uchar) bit_buff->pos[0]);
- bit_buff->pos++;
- bits+=8;
- }
- else
- {
- bit_buff->current_byte= ((uint) ((uchar) bit_buff->pos[0]) << 8) +
- ((uint) ((uchar) bit_buff->pos[1]));
- bit_buff->pos+=2;
- bits+=16;
- }
-#endif
- }
- /* First use info in quick_table */
- low_byte=(bit_buff->current_byte >> (bits - table_bits)) & table_and;
- low_byte=decode_tree->table[low_byte];
- if (low_byte & IS_CHAR)
- {
- *to++ = (low_byte & 255); /* Found char in quick table */
- bits-= ((low_byte >> 8) & 31); /* Remove bits used */
- }
- else
- { /* Map through rest of decode-table */
- pos=decode_tree->table+low_byte;
- bits-=table_bits;
- for (;;)
- {
- if (bits < 8)
- { /* We don't need to check end */
-#if BITS_SAVED == 32
- bit_buff->current_byte= (bit_buff->current_byte << 24) +
- (((uint) ((uchar) bit_buff->pos[2]))) +
- (((uint) ((uchar) bit_buff->pos[1])) << 8) +
- (((uint) ((uchar) bit_buff->pos[0])) << 16);
- bit_buff->pos+=3;
- bits+=24;
-#else
- bit_buff->current_byte= (bit_buff->current_byte << 8) +
- (uint) ((uchar) bit_buff->pos[0]);
- bit_buff->pos+=1;
- bits+=8;
-#endif
- }
- low_byte=(uint) (bit_buff->current_byte >> (bits-8));
- decode_bytes_test_bit(0);
- decode_bytes_test_bit(1);
- decode_bytes_test_bit(2);
- decode_bytes_test_bit(3);
- decode_bytes_test_bit(4);
- decode_bytes_test_bit(5);
- decode_bytes_test_bit(6);
- decode_bytes_test_bit(7);
- bits-=8;
- }
- *to++ = (uchar) *pos;
- }
- } while (to != end);
-
- bit_buff->bits=bits;
- return;
-}
-#endif /* BIT_SAVED == 64 */
-
-
-static uint decode_pos(BIT_BUFF *bit_buff, DECODE_TREE *decode_tree)
-{
- uint16 *pos=decode_tree->table;
- for (;;)
- {
- if (get_bit(bit_buff))
- pos++;
- if (*pos & IS_CHAR)
- return (uint) (*pos & ~IS_CHAR);
- pos+= *pos;
- }
-}
-
-
-int _nisam_read_rnd_pack_record(N_INFO *info, byte *buf,
- register ulong filepos,
- int skipp_deleted_blocks)
-{
- uint b_type;
- BLOCK_INFO block_info;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_read_rnd_pack_record");
-
- if (filepos >= share->state.data_file_length)
- {
- my_errno= HA_ERR_END_OF_FILE;
- goto err;
- }
-
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (_nisam_read_cache(&info->rec_cache,(byte*) block_info.header,filepos,
- share->pack.ref_length, skipp_deleted_blocks))
- goto err;
- b_type=_nisam_pack_get_block_info(&block_info,share->pack.ref_length,-1,
- filepos);
- }
- else
- b_type=_nisam_pack_get_block_info(&block_info,share->pack.ref_length,
- info->dfile,filepos);
- if (b_type)
- goto err;
-#ifndef DBUG_OFF
- if (block_info.rec_len > share->max_pack_length)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- goto err;
- }
-#endif
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (_nisam_read_cache(&info->rec_cache,(byte*) info->rec_buff,
- block_info.filepos, block_info.rec_len,
- skipp_deleted_blocks))
- goto err;
- }
- else
- {
- if (my_read(info->dfile,(byte*) info->rec_buff,block_info.rec_len,
- MYF(MY_NABP)))
- goto err;
- }
- info->packed_length=block_info.rec_len;
- info->lastpos=filepos;
- info->nextpos=block_info.filepos+block_info.rec_len;
- info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
-
- DBUG_RETURN (_nisam_pack_rec_unpack(info,buf,info->rec_buff,
- block_info.rec_len));
-err:
- DBUG_RETURN(-1);
-}
-
-
- /* Read and process header from a huff-record-file */
-
-uint _nisam_pack_get_block_info(BLOCK_INFO *info, uint ref_length, File file,
- ulong filepos)
-{
- uchar *header=info->header;
-
- if (file >= 0)
- {
- VOID(my_seek(file,filepos,MY_SEEK_SET,MYF(0)));
- if (my_read(file,(char*) header,ref_length,MYF(MY_NABP)))
- return BLOCK_FATAL_ERROR;
- }
- DBUG_DUMP("header",(byte*) header,ref_length);
-
- switch (ref_length) {
- case 1:
- info->rec_len=header[0];
- info->filepos=filepos+1;
- break;
- case 2:
- info->rec_len=uint2korr(header);
- info->filepos=filepos+2;
- break;
- case 3:
- info->rec_len=(uint) (uint3korr(header));
- info->filepos=filepos+3;
- break;
- default: break;
- }
- return 0;
-}
-
-
- /* routines for bit buffer */
- /* Buffer must be 6 byte bigger */
-static void init_bit_buffer(BIT_BUFF *bit_buff, char *buffer, uint length)
-{
- bit_buff->pos=(uchar*) buffer;
- bit_buff->end=(uchar*) buffer+length;
- bit_buff->bits=bit_buff->error=0;
- bit_buff->current_byte=0; /* Avoid purify errors */
-}
-
-static uint fill_and_get_bits(BIT_BUFF *bit_buff, uint count)
-{
- uint tmp;
- count-=bit_buff->bits;
- tmp=(bit_buff->current_byte & mask[bit_buff->bits]) << count;
- fill_buffer(bit_buff);
- bit_buff->bits=BITS_SAVED - count;
- return tmp+(bit_buff->current_byte >> (BITS_SAVED - count));
-}
-
- /* Fill in empty bit_buff->current_byte from buffer */
- /* Sets bit_buff->error if buffer is exhausted */
-
-static void fill_buffer(BIT_BUFF *bit_buff)
-{
- if (bit_buff->pos >= bit_buff->end)
- {
- bit_buff->error= 1;
- bit_buff->current_byte=0;
- return;
- }
-#if BITS_SAVED == 64
- bit_buff->current_byte= ((((uint) ((uchar) bit_buff->pos[7]))) +
- (((uint) ((uchar) bit_buff->pos[6])) << 8) +
- (((uint) ((uchar) bit_buff->pos[5])) << 16) +
- (((uint) ((uchar) bit_buff->pos[4])) << 24) +
- ((ulonglong)
- ((((uint) ((uchar) bit_buff->pos[3]))) +
- (((uint) ((uchar) bit_buff->pos[2])) << 8) +
- (((uint) ((uchar) bit_buff->pos[1])) << 16) +
- (((uint) ((uchar) bit_buff->pos[0])) << 24)) << 32));
- bit_buff->pos+=8;
-#else
-#if BITS_SAVED == 32
- bit_buff->current_byte= (((uint) ((uchar) bit_buff->pos[3])) +
- (((uint) ((uchar) bit_buff->pos[2])) << 8) +
- (((uint) ((uchar) bit_buff->pos[1])) << 16) +
- (((uint) ((uchar) bit_buff->pos[0])) << 24));
- bit_buff->pos+=4;
-#else
- bit_buff->current_byte= (uint) (((uint) ((uchar) bit_buff->pos[1]))+
- (((uint) ((uchar) bit_buff->pos[0])) << 8));
- bit_buff->pos+=2;
-#endif
-#endif
-}
-
- /* Get number of bits neaded to represent value */
-
-static uint max_bit(register uint value)
-{
- reg2 uint power=1;
-
- while ((value>>=1))
- power++;
- return (power);
-}
-
-
-/*****************************************************************************
- Some redefined functions to handle files when we are using memmap
-*****************************************************************************/
-
-#ifdef HAVE_MMAP
-
-#include <sys/mman.h>
-
-static int _nisam_read_mempack_record(N_INFO *info,ulong filepos,byte *buf);
-static int _nisam_read_rnd_mempack_record(N_INFO*, byte *,ulong, int);
-
-#ifndef MAP_NORESERVE
-#define MAP_NORESERVE 0 /* For irix */
-#endif
-#ifndef MAP_FAILED
-#define MAP_FAILED -1
-#endif
-
-my_bool _nisam_memmap_file(N_INFO *info)
-{
- byte *file_map;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_memmap_file");
-
- if (!info->s->file_map)
- {
- if (my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) <
- share->state.data_file_length+MEMMAP_EXTRA_MARGIN)
- {
- DBUG_PRINT("warning",("File isn't extended for memmap"));
- DBUG_RETURN(0);
- }
- file_map=(byte*)
- mmap(0,share->state.data_file_length+MEMMAP_EXTRA_MARGIN,PROT_READ,
- MAP_SHARED | MAP_NORESERVE,info->dfile,0L);
- if (file_map == (byte*) MAP_FAILED)
- {
- DBUG_PRINT("warning",("mmap failed: errno: %d",errno));
- my_errno=errno;
- DBUG_RETURN(0);
- }
- info->s->file_map=file_map;
- }
- info->opt_flag|= MEMMAP_USED;
- info->read_record=share->read_record=_nisam_read_mempack_record;
- share->read_rnd=_nisam_read_rnd_mempack_record;
- DBUG_RETURN(1);
-}
-
-
-void _nisam_unmap_file(N_INFO *info)
-{
- if (info->s->file_map)
- (void) munmap((caddr_t) info->s->file_map,
- (size_t) info->s->state.data_file_length+
- MEMMAP_EXTRA_MARGIN);
-}
-
-
-static void _nisam_mempack_get_block_info(BLOCK_INFO *info, uint ref_length,
- uchar *header)
-{
- if (ref_length == 1) /* This is most usual */
- info->rec_len=header[0];
- else if (ref_length == 2)
- info->rec_len=uint2korr(header);
- else
- info->rec_len=(uint) (uint3korr(header));
-}
-
-
-static int _nisam_read_mempack_record(N_INFO *info, ulong filepos, byte *buf)
-{
- BLOCK_INFO block_info;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("ni_read_mempack_record");
-
- if (filepos == NI_POS_ERROR)
- DBUG_RETURN(-1); /* _search() didn't find record */
-
- _nisam_mempack_get_block_info(&block_info,share->pack.ref_length,
- (uchar*) share->file_map+filepos);
- DBUG_RETURN(_nisam_pack_rec_unpack(info,buf,share->file_map+
- share->pack.ref_length+filepos,
- block_info.rec_len));
-}
-
-
-/*ARGSUSED*/
-static int _nisam_read_rnd_mempack_record(N_INFO *info, byte *buf,
- register ulong filepos,
- int skipp_deleted_blocks
- __attribute__((unused)))
-{
- BLOCK_INFO block_info;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_read_rnd_mempack_record");
-
- if (filepos >= share->state.data_file_length)
- {
- my_errno=HA_ERR_END_OF_FILE;
- goto err;
- }
-
- _nisam_mempack_get_block_info(&block_info,share->pack.ref_length,
- (uchar*) share->file_map+filepos);
-#ifndef DBUG_OFF
- if (block_info.rec_len > info->s->max_pack_length)
- {
- my_errno=HA_ERR_WRONG_IN_RECORD;
- goto err;
- }
-#endif
- info->packed_length=block_info.rec_len;
- info->lastpos=filepos;
- info->nextpos=filepos+share->pack.ref_length+block_info.rec_len;
- info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
-
- DBUG_RETURN (_nisam_pack_rec_unpack(info,buf,share->file_map+
- share->pack.ref_length+filepos,
- block_info.rec_len));
-err:
- DBUG_RETURN(-1);
-}
-
-#endif /* HAVE_MMAP */
diff --git a/isam/_page.c b/isam/_page.c
deleted file mode 100644
index e31115e624f..00000000000
--- a/isam/_page.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser och skriver nyckelblock */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* Fetch a key-page in memory */
-
-uchar *_nisam_fetch_keypage(register N_INFO *info, N_KEYDEF *keyinfo,
- my_off_t page, uchar *buff, int return_buffer)
-{
- uchar *tmp;
- tmp=(uchar*) key_cache_read(dflt_key_cache,
- info->s->kfile,page,DFLT_INIT_HITS,(byte*) buff,
- (uint) keyinfo->base.block_length,
- (uint) keyinfo->base.block_length,
- return_buffer);
- if (tmp == info->buff)
- {
- info->update|=HA_STATE_BUFF_SAVED;
- info->int_pos=(ulong) page;
- info->buff_used=1;
- }
- else
- {
- info->update&= ~HA_STATE_BUFF_SAVED;
- if (tmp)
- info->int_pos=(ulong) page;
- else
- {
- info->int_pos=NI_POS_ERROR;
- DBUG_PRINT("error",("Got errno: %d from key_cache_read",my_errno));
- my_errno=HA_ERR_CRASHED;
- }
- }
- return tmp;
-} /* _nisam_fetch_keypage */
-
-
- /* Write a key-page on disk */
-
-int _nisam_write_keypage(register N_INFO *info, register N_KEYDEF *keyinfo,
- my_off_t page, uchar *buff)
-{
- reg3 uint length;
-#ifndef QQ /* Safety check */
- if (page < info->s->base.keystart ||
- page+keyinfo->base.block_length > info->s->state.key_file_length ||
- page & (nisam_block_size-1))
- {
- DBUG_PRINT("error",("Trying to write outside key region: %lu",
- (long) page));
- my_errno=EINVAL;
- return(-1);
- }
- DBUG_PRINT("page",("write page at: %lu",(long) page,buff));
- DBUG_DUMP("buff",(byte*) buff,getint(buff));
-#endif
-
- if ((length=keyinfo->base.block_length) > IO_SIZE*2 &&
- info->s->state.key_file_length != page+length)
- length= ((getint(buff)+IO_SIZE-1) & (uint) ~(IO_SIZE-1));
-#ifdef HAVE_purify
- {
- length=getint(buff);
- bzero((byte*) buff+length,keyinfo->base.block_length-length);
- length=keyinfo->base.block_length;
- }
-#endif
- return (key_cache_write(dflt_key_cache,
- info->s->kfile,page,DFLT_INIT_HITS,
- (byte*) buff,length,
- (uint) keyinfo->base.block_length,
- (int) (info->lock_type != F_UNLCK)));
-} /* nisam_write_keypage */
-
-
- /* Remove page from disk */
-
-int _nisam_dispose(register N_INFO *info, N_KEYDEF *keyinfo, my_off_t pos)
-{
- uint keynr= (uint) (keyinfo - info->s->keyinfo);
- ulong old_link; /* ulong is ok here */
- DBUG_ENTER("_nisam_dispose");
-
- old_link=info->s->state.key_del[keynr];
- info->s->state.key_del[keynr]=(ulong) pos;
- DBUG_RETURN(key_cache_write(dflt_key_cache,
- info->s->kfile,pos,DFLT_INIT_HITS,
- (byte*) &old_link,
- sizeof(long),
- (uint) keyinfo->base.block_length,
- (int) (info->lock_type != F_UNLCK)));
-} /* _nisam_dispose */
-
-
- /* Make new page on disk */
-
-ulong _nisam_new(register N_INFO *info, N_KEYDEF *keyinfo)
-{
- uint keynr= (uint) (keyinfo - info->s->keyinfo);
- ulong pos;
- DBUG_ENTER("_nisam_new");
-
- if ((pos=info->s->state.key_del[keynr]) == NI_POS_ERROR)
- {
- if (info->s->state.key_file_length >= info->s->base.max_key_file_length)
- {
- my_errno=HA_ERR_INDEX_FILE_FULL;
- DBUG_RETURN(NI_POS_ERROR);
- }
- pos=info->s->state.key_file_length;
- info->s->state.key_file_length+= keyinfo->base.block_length;
- }
- else
- {
- if (!key_cache_read(dflt_key_cache,
- info->s->kfile,pos,DFLT_INIT_HITS,
- (byte*) &info->s->state.key_del[keynr],
- (uint) sizeof(long),
- (uint) keyinfo->base.block_length,0))
- pos= NI_POS_ERROR;
- }
- DBUG_PRINT("exit",("Pos: %d",pos));
- DBUG_RETURN(pos);
-} /* _nisam_new */
diff --git a/isam/_search.c b/isam/_search.c
deleted file mode 100644
index fbffd6786e1..00000000000
--- a/isam/_search.c
+++ /dev/null
@@ -1,889 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* S|ker efter positionen f|r en nyckel samt d{rmedh|rande funktioner */
-
-#include "isamdef.h"
-#include "m_ctype.h"
-
-#define CMP(a,b) (a<b ? -1 : a == b ? 0 : 1)
-
- /* Check index */
-
-int _nisam_check_index(N_INFO *info, int inx)
-{
- if (inx == -1) /* Use last index */
- inx=info->lastinx;
- if (inx >= (int) info->s->state.keys || inx < 0)
- {
- my_errno=HA_ERR_WRONG_INDEX;
- return -1;
- }
- if (info->lastinx != inx) /* Index changed */
- {
- info->lastinx = inx;
- info->lastpos = NI_POS_ERROR;
- info->update= ((info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED)) |
- HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
- }
- if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
- return(-1);
- return(inx);
-} /* ni_check_index */
-
-
- /* S|ker reda p} positionen f|r ett record p} basen av en nyckel */
- /* Positionen l{ggs i info->lastpos */
- /* Returns -1 if not found and 1 if search at upper levels */
-
-int _nisam_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, uint key_len, uint nextflag, register ulong pos)
-{
- int error,flag;
- uint nod_flag;
- uchar *keypos,*maxpos;
- uchar lastkey[N_MAX_KEY_BUFF],*buff;
- DBUG_ENTER("_nisam_search");
- DBUG_PRINT("enter",("pos: %ld nextflag: %d lastpos: %ld",
- pos,nextflag,info->lastpos));
-
- if (pos == NI_POS_ERROR)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
- info->lastpos= NI_POS_ERROR;
- if (!(nextflag & (SEARCH_SMALLER | SEARCH_BIGGER | SEARCH_LAST)))
- DBUG_RETURN(-1); /* Not found ; return error */
- DBUG_RETURN(1); /* Search at upper levels */
- }
-
- if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,
- test(!(nextflag & SEARCH_SAVE_BUFF)))))
- goto err;
- DBUG_DUMP("page",(byte*) buff,getint(buff));
-
- flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
- &keypos,lastkey);
- nod_flag=test_if_nod(buff);
- maxpos=buff+getint(buff)-1;
-
- if (flag)
- {
- if ((error=_nisam_search(info,keyinfo,key,key_len,nextflag,
- _nisam_kpos(nod_flag,keypos))) <= 0)
- DBUG_RETURN(error);
-
- if (flag >0)
- {
- if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) &&
- keypos == buff+2+nod_flag)
- DBUG_RETURN(1); /* Bigger than key */
- }
- else if (nextflag & SEARCH_BIGGER && keypos >= maxpos)
- DBUG_RETURN(1); /* Smaller than key */
- }
- else
- {
- if (nextflag & SEARCH_FIND && (!(keyinfo->base.flag & HA_NOSAME)
- || key_len) && nod_flag)
- {
- if ((error=_nisam_search(info,keyinfo,key,key_len,SEARCH_FIND,
- _nisam_kpos(nod_flag,keypos))) >= 0 ||
- my_errno != HA_ERR_KEY_NOT_FOUND)
- DBUG_RETURN(error);
- info->int_pos= NI_POS_ERROR; /* Buffer not in memory */
- }
- }
- if (pos != info->int_pos)
- {
- uchar *old_buff=buff;
- if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,
- test(!(nextflag & SEARCH_SAVE_BUFF)))))
- goto err;
- keypos=buff+(keypos-old_buff);
- maxpos=buff+(maxpos-old_buff);
- }
-
- if ((nextflag & (SEARCH_SMALLER | SEARCH_LAST)) && flag != 0)
- {
- keypos=_nisam_get_last_key(info,keyinfo,buff,lastkey,keypos);
- if (!(nextflag & SEARCH_SMALLER) &&
- _nisam_key_cmp(keyinfo->seg, lastkey, key, key_len, SEARCH_FIND))
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
- goto err;
- }
- }
-
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey));
- VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey));
- info->lastpos=_nisam_dpos(info,nod_flag,keypos);
- info->int_keypos=info->buff+ (keypos-buff);
- info->int_maxpos=info->buff+ (maxpos-buff);
- info->page_changed=0;
- info->buff_used= (info->buff != buff);
- info->last_search_keypage=info->int_pos;
-
- DBUG_PRINT("exit",("found key at %ld",info->lastpos));
- DBUG_RETURN(0);
-err:
- DBUG_PRINT("exit",("Error: %d",my_errno));
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN (-1);
-} /* _nisam_search */
-
-
- /* Search after key in page-block */
- /* If packed key puts smaller or identical key in buff */
- /* ret_pos point to where find or bigger key starts */
- /* ARGSUSED */
-
-int _nisam_bin_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page,
- uchar *key, uint key_len, uint comp_flag, uchar **ret_pos,
- uchar *buff __attribute__((unused)))
-{
- reg4 int start,mid,end;
- int flag;
- uint totlength,nod_flag;
- DBUG_ENTER("_nisam_bin_search");
-
- LINT_INIT(flag);
- totlength=keyinfo->base.keylength+(nod_flag=test_if_nod(page));
- start=0; mid=1;
- end= (int) ((getint(page)-2-nod_flag)/totlength-1);
- DBUG_PRINT("test",("getint: %d end: %d",getint(page),end));
- page+=2+nod_flag;
-
- while (start != end)
- {
- mid= (start+end)/2;
- if ((flag=_nisam_key_cmp(keyinfo->seg,page+(uint) mid*totlength,key,key_len,
- comp_flag))
- >= 0)
- end=mid;
- else
- start=mid+1;
- }
- if (mid != start)
- flag=_nisam_key_cmp(keyinfo->seg,page+(uint) start*totlength,key,key_len,
- comp_flag);
- if (flag < 0)
- start++; /* point at next, bigger key */
- *ret_pos=page+(uint) start*totlength;
- DBUG_PRINT("exit",("flag: %d keypos: %d",flag,start));
- DBUG_RETURN(flag);
-} /* _nisam_bin_search */
-
-
- /* Used instead of _nisam_bin_search() when key is packed */
- /* Puts smaller or identical key in buff */
- /* Key is searched sequentially */
-
-int _nisam_seq_search(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, uchar *key, uint key_len, uint comp_flag, uchar **ret_pos, uchar *buff)
-{
- int flag;
- uint nod_flag,length;
- uchar t_buff[N_MAX_KEY_BUFF],*end;
- DBUG_ENTER("_nisam_seq_search");
-
- LINT_INIT(flag); LINT_INIT(length);
- end= page+getint(page);
- nod_flag=test_if_nod(page);
- page+=2+nod_flag;
- *ret_pos=page;
- while (page < end)
- {
- length=(*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff);
- if ((flag=_nisam_key_cmp(keyinfo->seg,t_buff,key,key_len,comp_flag)) >= 0)
- break;
-#ifdef EXTRA_DEBUG
- DBUG_PRINT("loop",("page: %lx key: '%s' flag: %d",page,t_buff,flag));
-#endif
- memcpy(buff,t_buff,length);
- *ret_pos=page;
- }
- if (flag == 0)
- memcpy(buff,t_buff,length); /* Result is first key */
- DBUG_PRINT("exit",("flag: %d ret_pos: %lx",flag,*ret_pos));
- DBUG_RETURN(flag);
-} /* _nisam_seq_search */
-
-
- /* Get pos to a key_block */
-
-ulong _nisam_kpos(uint nod_flag, uchar *after_key)
-{
- after_key-=nod_flag;
- switch (nod_flag) {
- case 3:
- return uint3korr(after_key)*512L;
- case 2:
- return uint2korr(after_key)*512L;
- case 1:
- return (uint) (*after_key)*512L;
- case 0: /* At leaf page */
- default: /* Impossible */
- return(NI_POS_ERROR);
- }
-} /* _kpos */
-
-
- /* Save pos to a key_block */
-
-void _nisam_kpointer(register N_INFO *info, register uchar *buff, ulong pos)
-{
- pos/=512L;
- switch (info->s->base.key_reflength) {
- case 3: int3store(buff,pos); break;
- case 2: int2store(buff,(uint) pos); break;
- case 1: buff[0]= (uchar) pos; break;
- default: abort(); /* impossible */
- }
-} /* _nisam_kpointer */
-
-
- /* Calc pos to a data-record */
-
-ulong _nisam_dpos(N_INFO *info, uint nod_flag, uchar *after_key)
-{
- ulong pos;
- after_key-=(nod_flag + info->s->rec_reflength);
- switch (info->s->rec_reflength) {
- case 4:
- pos= (ulong) uint4korr(after_key);
- break;
- case 3:
- pos= (ulong) uint3korr(after_key);
- break;
- case 2:
- pos= (ulong) uint2korr(after_key);
- break;
- default:
- pos=0L; /* Shut compiler up */
- }
- return (info->s->base.options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? pos :
- pos*info->s->base.reclength;
-}
-
- /* save pos to record */
-
-void _nisam_dpointer(N_INFO *info, uchar *buff, ulong pos)
-{
- if (!(info->s->base.options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
- pos/=info->s->base.reclength;
-
- switch (info->s->rec_reflength) {
- case 4: int4store(buff,pos); break;
- case 3: int3store(buff,pos); break;
- case 2: int2store(buff,(uint) pos); break;
- default: abort(); /* Impossible */
- }
-} /* _nisam_dpointer */
-
-
- /*
- ** Compare two keys with is bigger
- ** Returns <0, 0, >0 acording to with is bigger
- ** Key_length specifies length of key to use. Number-keys can't
- ** be splitted
- ** If flag <> SEARCH_FIND compare also position
- */
-int _nisam_key_cmp(register N_KEYSEG *keyseg, register uchar *a, register uchar *b, uint key_length, uint nextflag)
-{
- reg4 int flag,length_diff;
- int16 s_1,s_2;
- int32 l_1,l_2;
- uint32 u_1,u_2;
- float f_1,f_2;
- double d_1,d_2;
- reg5 uchar *end;
-
- if (!(nextflag & (SEARCH_FIND | SEARCH_NO_FIND | SEARCH_LAST))
- || key_length == 0)
- key_length=N_MAX_KEY_BUFF*2;
-
- for ( ; (int) key_length >0 ; key_length-= (keyseg++)->base.length)
- {
- end= a+ min(keyseg->base.length,key_length);
- switch ((enum ha_base_keytype) keyseg->base.type) {
- case HA_KEYTYPE_TEXT: /* Ascii; Key is converted */
- case HA_KEYTYPE_BINARY:
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- uchar *as, *bs;
- int length,b_length;
-
- as=a++; bs=b++;
- length= (length_diff= ((int) *as - (b_length= (int) *bs))) < 0 ?
- (int) *as : b_length;
- end= a+ min(key_length,(uint) length);
-
- if (use_strnxfrm(default_charset_info)) {
- if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
- {
- while (a < end)
- if ((flag= (int) *a++ - (int) *b++))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- }
- else
- {
- if ((flag = my_strnncoll(default_charset_info,
- a, (int) (end-a), b, b_length)))
- return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag;
- b+= (uint) (end-a);
- a=end;
- }
- }
- else
- {
- while (a < end)
- if ((flag= (int) *a++ - (int) *b++))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- }
- if (key_length < (uint) keyseg->base.length)
- { /* key_part */
- if (length_diff)
- {
- if (length_diff < 0 || (uint) *as <= key_length)
- return ((keyseg->base.flag & HA_REVERSE_SORT) ?
- -length_diff : length_diff);
- for (length= (int) key_length-b_length; length-- > 0 ;)
- {
- if (*a++ != ' ')
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -1 : 1);
- }
- }
- if (nextflag & SEARCH_NO_FIND) /* Find record after key */
- return (nextflag & SEARCH_BIGGER) ? -1 : 1;
- return 0;
- }
- else
- {
- if (length_diff)
- return ((keyseg->base.flag & HA_REVERSE_SORT) ?
- -length_diff : length_diff);
- }
- a=as+ (uint) *as+1 ; b= bs+ b_length+1; /* to next key */
- }
- else
- {
- if (use_strnxfrm(default_charset_info)) {
- if (((enum ha_base_keytype) keyseg->base.type) == HA_KEYTYPE_BINARY)
- {
- while (a < end)
- if ((flag= (int) *a++ - (int) *b++))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- }
- else
- {
- if ((flag = my_strnncoll(default_charset_info,
- a, (int) (end-a), b, (int) (end-a))))
- return (keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag;
- b+= (uint) (end-a);
- a=end;
- }
- }
- else
- {
- while (a < end)
- if ((flag= (int) *a++ - (int) *b++))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- }
- }
- break;
- case HA_KEYTYPE_INT8:
- {
- int i_1= (int) *((signed char*) a);
- int i_2= (int) *((signed char*) b);
- if ((flag = CMP(i_1,i_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b++;
- break;
- }
- case HA_KEYTYPE_SHORT_INT:
- shortget(s_1,a);
- shortget(s_2,b);
- if ((flag = CMP(s_1,s_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 2; /* sizeof(short int); */
- break;
- case HA_KEYTYPE_USHORT_INT:
- {
- uint16 us_1,us_2;
- ushortget(us_1,a);
- ushortget(us_2,b);
- if ((flag = CMP(us_1,us_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+=2; /* sizeof(short int); */
- break;
- }
- case HA_KEYTYPE_LONG_INT:
- longget(l_1,a);
- longget(l_2,b);
- if ((flag = CMP(l_1,l_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 4; /* sizeof(long int); */
- break;
- case HA_KEYTYPE_ULONG_INT:
- ulongget(u_1,a);
- ulongget(u_2,b);
- if ((flag = CMP(u_1,u_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 4; /* sizeof(long int); */
- break;
- case HA_KEYTYPE_INT24:
- l_1=sint3korr(a);
- l_2=sint3korr(b);
- if ((flag = CMP(l_1,l_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 3;
- break;
- case HA_KEYTYPE_UINT24:
- l_1=(long) uint3korr(a);
- l_2=(long) uint3korr(b);
- if ((flag = CMP(l_1,l_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= 3;
- break;
- case HA_KEYTYPE_FLOAT:
- bmove((byte*) &f_1,(byte*) a,(int) sizeof(float));
- bmove((byte*) &f_2,(byte*) b,(int) sizeof(float));
- if ((flag = CMP(f_1,f_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= sizeof(float);
- break;
- case HA_KEYTYPE_DOUBLE:
- doubleget(d_1,a);
- doubleget(d_2,b);
- if ((flag = CMP(d_1,d_2)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= sizeof(double);
- break;
- case HA_KEYTYPE_NUM: /* Numeric key */
- {
- int swap_flag=keyseg->base.flag & HA_REVERSE_SORT;
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- int alength,blength;
-
- if (swap_flag)
- swap_variables(uchar*, a, b);
- alength= *a++; blength= *b++;
- if ((flag=(int) (keyseg->base.length-key_length)) < 0)
- flag=0;
- if (alength != blength+flag)
- {
- if ((alength > blength+flag && *a != '-') ||
- (alength < blength+flag && *b == '-'))
- return 1;
- else
- return -1;
- }
- if (*a == '-' && *b == '-')
- {
- swap_flag=1;
- swap_variables(uchar*, a, b);
- }
- end=a+alength;
- while (a < end)
- if (*a++ != *b++)
- {
- a--; b--;
- if (my_isdigit(default_charset_info, (char) *a) &&
- my_isdigit(default_charset_info, (char) *b))
- return ((int) *a - (int) *b);
- if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
- return (-1);
- if (*b == '-' || *b++ == ' ' ||
- my_isdigit(default_charset_info,(char) *a))
- return (1);
- if (*a++ == ' ')
- return (-1);
- }
- }
- else
- {
- for ( ; a < end && *a == ' ' && *b == ' ' ; a++, b++) ;
- if (*a == '-' && *b == '-')
- swap_flag=1;
- if (swap_flag)
- {
- end=b+(int) (end-a);
- swap_variables(uchar*, a, b);
- }
- while (a < end)
- if (*a++ != *b++)
- {
- a--; b--;
- if (my_isdigit(default_charset_info,(char) *a) &&
- my_isdigit(default_charset_info,(char) *b))
- return ((int) *a - (int) *b);
- if (*a == '-' || my_isdigit(default_charset_info,(char) *b))
- return (-1);
- if (*b == '-' || *b++ == ' ' ||
- my_isdigit(default_charset_info,(char) *a))
- return (1);
- if (*a++ == ' ')
- return -1;
- }
- }
- if (swap_flag)
- swap_variables(uchar*, a, b);
- break;
- }
-#ifdef HAVE_LONG_LONG
- case HA_KEYTYPE_LONGLONG:
- {
- longlong ll_a,ll_b;
- longlongget(ll_a,a);
- longlongget(ll_b,b);
- if ((flag = CMP(ll_a,ll_b)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= sizeof(longlong);
- break;
- }
- case HA_KEYTYPE_ULONGLONG:
- {
- ulonglong ll_a,ll_b;
- longlongget(ll_a,a);
- longlongget(ll_b,b);
- if ((flag = CMP(ll_a,ll_b)))
- return ((keyseg->base.flag & HA_REVERSE_SORT) ? -flag : flag);
- a= end;
- b+= sizeof(ulonglong);
- break;
- }
-#endif
- case HA_KEYTYPE_END: /* Ready */
- case HA_KEYTYPE_VARTEXT: /* Impossible */
- case HA_KEYTYPE_VARBINARY: /* Impossible */
- goto end;
- }
- }
-end:
- if (!(nextflag & SEARCH_FIND))
- {
- if (nextflag & (SEARCH_NO_FIND | SEARCH_LAST)) /* Find record after key */
- return (nextflag & (SEARCH_BIGGER | SEARCH_LAST)) ? -1 : 1;
- LINT_INIT(l_1); LINT_INIT(l_2);
- switch (keyseg->base.length) {
- case 4:
- u_1= (ulong) uint4korr(a);
- u_2= (ulong) uint4korr(b);
- break;
- case 3:
- u_1= (ulong) uint3korr(a);
- u_2= (ulong) uint3korr(b);
- break;
- case 2:
- u_1= (ulong) uint2korr(a);
- u_2= (ulong) uint2korr(b);
- break;
- default: abort(); /* Impossible */
- }
- flag = CMP(u_1,u_2);
-
- if (nextflag & SEARCH_SAME)
- return (flag); /* read same */
- if (nextflag & SEARCH_BIGGER)
- return (flag <= 0 ? -1 : 1); /* read next */
- return (flag < 0 ? -1 : 1); /* read previous */
- }
- return 0;
-} /* _nisam_key_cmp */
-
-
- /* Get key from key-block */
- /* page points at previous key; its advanced to point at next key */
- /* key should contain previous key */
- /* Returns length of found key + pointers */
- /* nod_flag is a flag if we are on nod */
-
-uint _nisam_get_key(register N_KEYDEF *keyinfo, uint nod_flag,
- register uchar **page, register uchar *key)
-{
- reg1 N_KEYSEG *keyseg;
- uchar *start,*start_key;
- uint length,c_length;
-
- LINT_INIT(start);
- start_key=key; c_length=0;
- for (keyseg=keyinfo->seg ; keyseg->base.type ;keyseg++)
- {
- if (keyseg->base.flag & (HA_SPACE_PACK | HA_PACK_KEY))
- {
- start=key;
- if (keyseg->base.flag & HA_SPACE_PACK)
- key++;
- if ((length= *(*page)++) & 128)
- {
- key+= (c_length=(length & 127));
- if (c_length == 0) /* Same key */
- {
- key+= *start; /* Same diff_key as prev */
- length=0;
- }
- else
- {
- if (keyseg->base.flag & HA_SPACE_PACK)
- length= *(*page)++;
- else
- length=keyseg->base.length-length+128; /* Rest of key */
- /* Prevent core dumps if wrong data formats */
- if (length > keyseg->base.length)
- length=0;
- }
- }
- }
- else
- length=keyseg->base.length;
- memcpy((byte*) key,(byte*) *page,(size_t) length); key+=length;
- if (keyseg->base.flag & HA_SPACE_PACK)
- *start= (uchar) ((key-start)-1);
- *page+=length;
- }
- length=keyseg->base.length+nod_flag;
- bmove((byte*) key,(byte*) *page,length);
- *page+=length;
- return((uint) (key-start_key)+keyseg->base.length);
-} /* _nisam_get_key */
-
-
- /* same as _nisam_get_key but used with fixed length keys */
-
-uint _nisam_get_static_key(register N_KEYDEF *keyinfo, uint nod_flag, register uchar **page, register uchar *key)
-{
- memcpy((byte*) key,(byte*) *page,
- (size_t) (keyinfo->base.keylength+nod_flag));
- *page+=keyinfo->base.keylength+nod_flag;
- return(keyinfo->base.keylength);
-} /* _nisam_get_static_key */
-
-
- /* Get last key from key-block, starting from keypos */
- /* Return pointer to where keystarts */
-
-uchar *_nisam_get_last_key(N_INFO *info, N_KEYDEF *keyinfo, uchar *keypos, uchar *lastkey, uchar *endpos)
-{
- uint nod_flag;
- uchar *lastpos;
-
- nod_flag=test_if_nod(keypos);
- if (! (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
- {
- lastpos=endpos-keyinfo->base.keylength-nod_flag;
- if (lastpos > keypos)
- bmove((byte*) lastkey,(byte*) lastpos,keyinfo->base.keylength+nod_flag);
- }
- else
- {
- lastpos=0 ; keypos+=2+nod_flag;
- lastkey[0]=0;
- while (keypos < endpos)
- {
- lastpos=keypos;
- VOID(_nisam_get_key(keyinfo,nod_flag,&keypos,lastkey));
- }
- }
- return lastpos;
-} /* _nisam_get_last_key */
-
-
- /* Calculate length of key */
-
-uint _nisam_keylength(N_KEYDEF *keyinfo, register uchar *key)
-{
- reg1 N_KEYSEG *keyseg;
- uchar *start;
-
- if (! (keyinfo->base.flag & HA_SPACE_PACK_USED))
- return (keyinfo->base.keylength);
-
- start=key;
- for (keyseg=keyinfo->seg ; keyseg->base.type ; keyseg++)
- {
- if (keyseg->base.flag & HA_SPACE_PACK)
- key+= *key+1;
- else
- key+= keyseg->base.length;
- }
- return((uint) (key-start)+keyseg->base.length);
-} /* _nisam_keylength */
-
-
- /* Move a key */
-
-uchar *_nisam_move_key(N_KEYDEF *keyinfo, uchar *to, uchar *from)
-{
- reg1 uint length;
- memcpy((byte*) to, (byte*) from,
- (size_t) (length=_nisam_keylength(keyinfo,from)));
- return to+length;
-}
-
- /* Find next/previous record with same key */
- /* This can't be used when database is touched after last read */
-
-int _nisam_search_next(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, uint nextflag, ulong pos)
-{
- int error;
- uint nod_flag;
- uchar lastkey[N_MAX_KEY_BUFF];
- DBUG_ENTER("_nisam_search_next");
- DBUG_PRINT("enter",("nextflag: %d lastpos: %d int_keypos: %lx",
- nextflag,info->lastpos,info->int_keypos));
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,key););
-
- if ((nextflag & SEARCH_BIGGER && info->int_keypos >= info->int_maxpos) ||
- info->int_pos == NI_POS_ERROR || info->page_changed)
- DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
- pos));
-
- if (info->buff_used)
- {
- if (!_nisam_fetch_keypage(info,keyinfo,info->last_search_keypage,
- info->buff,0))
- {
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
- info->buff_used=0;
- }
-
- /* Last used buffer is in info->buff */
-
- nod_flag=test_if_nod(info->buff);
- VOID(_nisam_move_key(keyinfo,lastkey,key));
-
- if (nextflag & SEARCH_BIGGER) /* Next key */
- {
- ulong tmp_pos=_nisam_kpos(nod_flag,info->int_keypos);
- if (tmp_pos != NI_POS_ERROR)
- {
- if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
- tmp_pos)) <=0)
- DBUG_RETURN(error);
- }
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,lastkey));
- }
- else /* Previous key */
- {
- info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey,
- info->int_keypos);
- if (info->int_keypos == info->buff+2)
- DBUG_RETURN(_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
- pos));
- if ((error=_nisam_search(info,keyinfo,key,0,nextflag | SEARCH_SAVE_BUFF,
- _nisam_kpos(nod_flag,info->int_keypos))) <= 0)
- DBUG_RETURN(error);
- }
-
- info->int_keypos=_nisam_get_last_key(info,keyinfo,info->buff,lastkey,
- info->int_keypos);
- VOID(_nisam_move_key(keyinfo,info->lastkey,lastkey));
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&info->int_keypos,info->lastkey));
- info->lastpos=_nisam_dpos(info,nod_flag,info->int_keypos);
- DBUG_PRINT("exit",("found key at %d",info->lastpos));
- DBUG_RETURN(0);
-} /* _nisam_search_next */
-
-
- /* S|ker reda p} positionen f|r f|rsta recordet i ett index */
- /* Positionen l{ggs i info->lastpos */
-
-int _nisam_search_first(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos)
-{
- uint nod_flag;
- uchar *page;
- DBUG_ENTER("_nisam_search_first");
-
- if (pos == NI_POS_ERROR)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND;
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
-
- do
- {
- if (!_nisam_fetch_keypage(info,keyinfo,pos,info->buff,0))
- {
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
- nod_flag=test_if_nod(info->buff);
- page=info->buff+2+nod_flag;
- } while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR);
-
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,info->lastkey));
- info->int_keypos=page; info->int_maxpos=info->buff+getint(info->buff)-1;
- info->lastpos=_nisam_dpos(info,nod_flag,page);
- info->page_changed=info->buff_used=0;
- info->last_search_keypage=info->int_pos;
-
- DBUG_PRINT("exit",("found key at %d",info->lastpos));
- DBUG_RETURN(0);
-} /* _nisam_search_first */
-
-
- /* S|ker reda p} positionen f|r sista recordet i ett index */
- /* Positionen l{ggs i info->lastpos */
-
-int _nisam_search_last(register N_INFO *info, register N_KEYDEF *keyinfo, register ulong pos)
-{
- uint nod_flag;
- uchar *buff,*page;
- DBUG_ENTER("_nisam_search_last");
-
- if (pos == NI_POS_ERROR)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* Didn't find key */
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
-
- buff=info->buff;
- do
- {
- if (!_nisam_fetch_keypage(info,keyinfo,pos,buff,0))
- {
- info->lastpos= NI_POS_ERROR;
- DBUG_RETURN(-1);
- }
- page= buff+getint(buff);
- nod_flag=test_if_nod(buff);
- } while ((pos=_nisam_kpos(nod_flag,page)) != NI_POS_ERROR);
-
- VOID(_nisam_get_last_key(info,keyinfo,buff,info->lastkey,page));
- info->lastpos=_nisam_dpos(info,nod_flag,page);
- info->int_keypos=info->int_maxpos=page;
- info->page_changed=info->buff_used=0;
- info->last_search_keypage=info->int_pos;
-
- DBUG_PRINT("exit",("found key at %d",info->lastpos));
- DBUG_RETURN(0);
-} /* _nisam_search_last */
diff --git a/isam/_statrec.c b/isam/_statrec.c
deleted file mode 100644
index 9dbc948440f..00000000000
--- a/isam/_statrec.c
+++ /dev/null
@@ -1,265 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
- /* Functions to handle fixed-length-records */
-
-#include "isamdef.h"
-
-
-int _nisam_write_static_record(N_INFO *info, const byte *record)
-{
- uchar temp[4]; /* Not sizeof(long) */
-
- if (info->s->state.dellink != NI_POS_ERROR)
- {
- ulong filepos=info->s->state.dellink;
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,info->s->state.dellink+1,MY_SEEK_SET,MYF(0)));
-
- if (my_read(info->dfile,(char*) &temp[0],sizeof(temp), MYF(MY_NABP)))
- goto err;
- info->s->state.dellink=uint4korr(temp);
- if (info->s->state.dellink == (uint32) ~0) /* Fix for 64 bit long */
- info->s->state.dellink=NI_POS_ERROR;
- info->s->state.del--;
- info->s->state.empty-=info->s->base.reclength;
- VOID(my_seek(info->dfile,filepos,MY_SEEK_SET,MYF(0)));
- if (my_write(info->dfile, (char*) record, info->s->base.reclength,
- MYF(MY_NABP)))
- goto err;
- }
- else
- {
- if (info->s->state.data_file_length > info->s->base.max_data_file_length)
- {
- my_errno=HA_ERR_RECORD_FILE_FULL;
- return(2);
- }
- if (info->opt_flag & WRITE_CACHE_USED)
- { /* Cash in use */
- if (my_b_write(&info->rec_cache, (byte*) record, info->s->base.reclength))
- goto err;
- }
- else
- {
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,info->s->state.data_file_length,
- MY_SEEK_SET,MYF(0)));
- if (my_write(info->dfile,(char*) record,info->s->base.reclength,
- MYF(MY_NABP | MY_WAIT_IF_FULL)))
- goto err;
- }
- info->s->state.data_file_length+=info->s->base.reclength;
- info->s->state.splitt++;
- }
- return 0;
- err:
- return 1;
-}
-
-int _nisam_update_static_record(N_INFO *info, ulong pos, const byte *record)
-{
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,pos,MY_SEEK_SET,MYF(0)));
- return (my_write(info->dfile,(char*) record,info->s->base.reclength,
- MYF(MY_NABP)) != 0);
-}
-
-
-int _nisam_delete_static_record(N_INFO *info)
-{
- uchar temp[5]; /* 1+sizeof(uint32) */
-
- info->s->state.del++;
- info->s->state.empty+=info->s->base.reclength;
- temp[0]= '\0'; /* Mark that record is deleted */
- int4store(temp+1,info->s->state.dellink);
- info->s->state.dellink = info->lastpos;
- info->rec_cache.seek_not_done=1;
- VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0)));
- return (my_write(info->dfile,(byte*) temp,(uint) sizeof(temp),
- MYF(MY_NABP)) != 0);
-}
-
-
-int _nisam_cmp_static_record(register N_INFO *info, register const byte *old)
-{
- DBUG_ENTER("_nisam_rectest");
-
- /* We are going to do changes; dont let anybody disturb */
- dont_break(); /* Dont allow SIGHUP or SIGINT */
-
- if (info->opt_flag & WRITE_CACHE_USED)
- {
- if (flush_io_cache(&info->rec_cache))
- {
- DBUG_RETURN(-1);
- }
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- }
-
- if ((info->opt_flag & READ_CHECK_USED))
- { /* If check isn't disabled */
- info->rec_cache.seek_not_done=1; /* We have done a seek */
- VOID(my_seek(info->dfile,info->lastpos,MY_SEEK_SET,MYF(0)));
- if (my_read(info->dfile, (char*) info->rec_buff, info->s->base.reclength,
- MYF(MY_NABP)))
- DBUG_RETURN(-1);
- if (memcmp((byte*) info->rec_buff, (byte*) old,
- (uint) info->s->base.reclength))
- {
- DBUG_DUMP("read",old,info->s->base.reclength);
- DBUG_DUMP("disk",info->rec_buff,info->s->base.reclength);
- my_errno=HA_ERR_RECORD_CHANGED; /* Record have changed */
- DBUG_RETURN(1);
- }
- }
- DBUG_RETURN(0);
-}
-
- /* Read a fixed-length-record */
- /* Returns 0 if Ok. */
- /* 1 if record is deleted */
- /* MY_FILE_ERROR on read-error or locking-error */
-
-int _nisam_read_static_record(register N_INFO *info, register ulong pos,
- register byte *record)
-{
- int error;
-
- if (pos != NI_POS_ERROR)
- {
- if (info->opt_flag & WRITE_CACHE_USED &&
- info->rec_cache.pos_in_file <= pos &&
- flush_io_cache(&info->rec_cache))
- return(-1);
- info->rec_cache.seek_not_done=1; /* We have done a seek */
-
- error=my_pread(info->dfile,(char*) record,info->s->base.reclength,
- pos,MYF(MY_NABP)) != 0;
- if (info->s->r_locks == 0 && info->s->w_locks == 0)
- VOID(_nisam_writeinfo(info,0));
- if (! error)
- {
- if (!*record) return(1); /* Record is deleted */
- info->update|= HA_STATE_AKTIV; /* Record is read */
- my_errno=HA_ERR_RECORD_DELETED;
- return(0);
- }
- return(-1); /* Error on read */
- }
- VOID(_nisam_writeinfo(info,0)); /* No such record */
- return(-1);
-} /* _nisam_read_record */
-
-
-int _nisam_read_rnd_static_record(N_INFO *info, byte *buf,
- register ulong filepos,
- int skipp_deleted_blocks)
-{
- int locked,error,cache_read;
- uint cache_length;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_read_rnd_static_record");
-
- cache_read=0;
- LINT_INIT(cache_length);
- if (info->opt_flag & WRITE_CACHE_USED &&
- (info->rec_cache.pos_in_file <= filepos || skipp_deleted_blocks) &&
- flush_io_cache(&info->rec_cache))
- DBUG_RETURN(-1);
- if (info->opt_flag & READ_CACHE_USED)
- { /* Cash in use */
- if (filepos == my_b_tell(&info->rec_cache) &&
- (skipp_deleted_blocks || !filepos))
- {
- cache_read=1; /* Read record using cache */
- cache_length=(uint) (info->rec_cache.read_end - info->rec_cache.read_pos);
- }
- else
- info->rec_cache.seek_not_done=1; /* Filepos is changed */
- }
-#ifndef NO_LOCKING
- locked=0;
- if (info->lock_type == F_UNLCK)
- {
- if (filepos >= share->state.data_file_length)
- { /* Test if new records */
- if (_nisam_readinfo(info,F_RDLCK,0))
- DBUG_RETURN(-1);
- locked=1;
- }
- else
- { /* We don't nead new info */
-#ifndef UNSAFE_LOCKING
- if ((! cache_read || share->base.reclength > cache_length) &&
- share->r_locks == 0 && share->w_locks == 0)
- { /* record not in cache */
- if (my_lock(share->kfile,F_RDLCK,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
- DBUG_RETURN(-1);
- locked=1;
- }
-#else
- info->tmp_lock_type=F_RDLCK;
-#endif
- }
- }
-#endif
- if (filepos >= share->state.data_file_length)
- {
-#ifndef NO_LOCKING
- DBUG_PRINT("test",("filepos: %ld (%ld) records: %ld del: %ld",
- filepos/share->base.reclength,filepos,
- share->state.records, share->state.del));
- VOID(_nisam_writeinfo(info,0));
-#endif
- my_errno=HA_ERR_END_OF_FILE;
- DBUG_RETURN(-1);
- }
- info->lastpos= filepos;
- info->nextpos= filepos+share->base.reclength;
-
- if (! cache_read) /* No cacheing */
- {
- error=_nisam_read_static_record(info,filepos,buf);
- if (error > 0)
- my_errno=HA_ERR_RECORD_DELETED;
- DBUG_RETURN(error);
- }
-
- /* Read record with cacheing */
- error=my_b_read(&info->rec_cache,(byte*) buf,share->base.reclength);
-
-#ifndef NO_LOCKING
- if (locked)
- VOID(_nisam_writeinfo(info,0)); /* Unlock keyfile */
-#endif
- if (!error)
- {
- if (!buf[0])
- { /* Record is removed */
- my_errno=HA_ERR_RECORD_DELETED;
- DBUG_RETURN(1);
- }
- /* Found and may be updated */
- info->update|= HA_STATE_AKTIV | HA_STATE_KEY_CHANGED;
- DBUG_RETURN(0);
- }
- if (info->rec_cache.error != -1 || my_errno == 0)
- my_errno=HA_ERR_WRONG_IN_RECORD;
- DBUG_RETURN(-1); /* Something wrong (EOF?) */
-}
diff --git a/isam/changed.c b/isam/changed.c
deleted file mode 100644
index b8132538b86..00000000000
--- a/isam/changed.c
+++ /dev/null
@@ -1,35 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Check if somebody has changed table since last check. */
-
-#include "isamdef.h"
-
- /* Return 0 if table isn't changed */
-
-int nisam_is_changed(N_INFO *info)
-{
- int result;
- DBUG_ENTER("nisam_is_changed");
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1);
- VOID(_nisam_writeinfo(info,0));
-#endif
- result=(int) info->data_changed;
- info->data_changed=0;
- DBUG_PRINT("exit",("result: %d",result));
- DBUG_RETURN(result);
-}
diff --git a/isam/close.c b/isam/close.c
deleted file mode 100644
index 37425653a5d..00000000000
--- a/isam/close.c
+++ /dev/null
@@ -1,92 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* close a isam-database */
-
-#include "isamdef.h"
-
-int nisam_close(register N_INFO *info)
-{
- int error=0,flag;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("nisam_close");
- DBUG_PRINT("enter",("base: %lx reopen: %u locks: %u",
- info,(uint) share->reopen,
- (uint) (share->w_locks+share->r_locks)));
-
- pthread_mutex_lock(&THR_LOCK_isam);
- if (info->lock_type == F_EXTRA_LCK)
- info->lock_type=F_UNLCK; /* HA_EXTRA_NO_USER_CHANGE */
-
-#ifndef NO_LOCKING
- if (info->lock_type != F_UNLCK)
- VOID(nisam_lock_database(info,F_UNLCK));
-#else
- info->lock_type=F_UNLCK;
- share->w_locks--;
- if (_nisam_writeinfo(info,test(share->changed)))
- error=my_errno;
-#endif
- pthread_mutex_lock(&share->intern_lock);
-
- if (share->base.options & HA_OPTION_READ_ONLY_DATA)
- share->r_locks--;
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- {
- if (end_io_cache(&info->rec_cache))
- error=my_errno;
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- }
- flag= !--share->reopen;
- nisam_open_list=list_delete(nisam_open_list,&info->open_list);
- pthread_mutex_unlock(&share->intern_lock);
-
- if (flag)
- {
- if (share->kfile >= 0 &&
- flush_key_blocks(dflt_key_cache,share->kfile,FLUSH_RELEASE))
- error=my_errno;
- if (share->kfile >= 0 && my_close(share->kfile,MYF(0)))
- error = my_errno;
-#ifdef HAVE_MMAP
- _nisam_unmap_file(info);
-#endif
- if (share->decode_trees)
- {
- my_free((gptr) share->decode_trees,MYF(0));
- my_free((gptr) share->decode_tables,MYF(0));
- }
-#ifdef THREAD
- thr_lock_delete(&share->lock);
- VOID(pthread_mutex_destroy(&share->intern_lock));
-#endif
- my_free((gptr) info->s,MYF(0));
- }
- pthread_mutex_unlock(&THR_LOCK_isam);
- if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))
- error = my_errno;
-
- nisam_log_command(LOG_CLOSE,info,NULL,0,error);
- my_free((gptr) info->rec_alloc,MYF(0));
- my_free((gptr) info,MYF(0));
-
- if (error)
- {
- my_errno=error;
- DBUG_RETURN(-1);
- }
- DBUG_RETURN(0);
-} /* nisam_close */
diff --git a/isam/create.c b/isam/create.c
deleted file mode 100644
index 4c23f3edd11..00000000000
--- a/isam/create.c
+++ /dev/null
@@ -1,328 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Skapar en isam-databas */
-
-#include "isamdef.h"
-#if defined(MSDOS) || defined(__WIN__)
-#ifdef __WIN__
-#include <fcntl.h>
-#else
-#include <process.h> /* Prototype for getpid */
-#endif
-#endif
-
- /*
- ** Old options is used when recreating database, from isamchk
- ** Note that the minimun reclength that MySQL allows for static rows
- ** are 5. (Will be fixed in the next generation)
- */
-
-int nisam_create(const char *name,uint keys,N_KEYDEF *keyinfo,
- N_RECINFO *recinfo,
- ulong records,ulong reloc, uint flags,uint old_options,
- ulong data_file_length)
-{
- register uint i,j;
- File dfile,file;
- int errpos,save_errno;
- uint fields,length,max_key_length,packed,pointer,reclength,min_pack_length,
- key_length,info_length,key_segs,options,min_key_length_skipp,max_block,
- base_pos;
- char buff[max(FN_REFLEN,512)];
- ulong tot_length,pack_reclength;
- enum en_fieldtype type;
- ISAM_SHARE share;
- N_KEYDEF *keydef;
- N_KEYSEG *keyseg;
- N_RECINFO *rec;
- DBUG_ENTER("nisam_create");
-
- LINT_INIT(dfile);
- pthread_mutex_lock(&THR_LOCK_isam);
- errpos=0;
- options=0;
- base_pos=512; /* Enough for N_STATE_INFO */
- bzero((byte*) &share,sizeof(share));
- if ((file = my_create(fn_format(buff,name,"",N_NAME_IEXT,4),0,
- O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
- goto err;
- errpos=1;
- VOID(fn_format(buff,name,"",N_NAME_DEXT,2+4));
- if (!(flags & HA_DONT_TOUCH_DATA))
- {
- if ((dfile = my_create(buff,0,O_RDWR | O_TRUNC,MYF(MY_WME))) < 0)
- goto err;
- errpos=2;
- }
- else if (!(old_options & HA_OPTION_TEMP_COMPRESS_RECORD))
- options=old_options & (HA_OPTION_COMPRESS_RECORD |
- HA_OPTION_READ_ONLY_DATA | HA_OPTION_PACK_RECORD);
- if (reloc > records)
- reloc=records; /* Check if wrong parameter */
-
- /* Start by checking fields and field-types used */
- reclength=0;
- for (rec=recinfo, fields=packed=min_pack_length=0, pack_reclength=0L;
- rec->base.type != (int) FIELD_LAST;
- rec++,fields++)
- {
- reclength+=rec->base.length;
- if ((type=(enum en_fieldtype) rec->base.type))
- {
- packed++;
- if (type == FIELD_BLOB)
- {
- share.base.blobs++;
- rec->base.length-= sizeof(char*); /* Don't calc pointer */
- if (pack_reclength != NI_POS_ERROR)
- {
- if (rec->base.length == 4)
- pack_reclength= (ulong) NI_POS_ERROR;
- else
- pack_reclength+=sizeof(char*)+(1 << (rec->base.length*8));
- }
- }
- else if (type == FIELD_SKIP_PRESPACE ||
- type == FIELD_SKIP_ENDSPACE)
- {
- if (pack_reclength != NI_POS_ERROR)
- pack_reclength+= rec->base.length > 255 ? 2 : 1;
- min_pack_length++;
- }
- else if (type == FIELD_ZERO)
- packed--;
- else if (type != FIELD_SKIP_ZERO)
- {
- min_pack_length+=rec->base.length;
- packed--; /* Not a pack record type */
- }
- }
- else
- min_pack_length+=rec->base.length;
- }
- if ((packed & 7) == 1)
- { /* Bad packing, try to remove a zero-field */
- while (rec != recinfo)
- {
- rec--;
- if (rec->base.type == (int) FIELD_SKIP_ZERO && rec->base.length == 1)
- {
- rec->base.type=(int) FIELD_NORMAL;
- packed--;
- min_pack_length++;
- break;
- }
- }
- }
- if (packed && !(options & HA_OPTION_COMPRESS_RECORD))
- options|=HA_OPTION_PACK_RECORD; /* Must use packed records */
-
- packed=(packed+7)/8;
- if (pack_reclength != NI_POS_ERROR)
- pack_reclength+= reclength+packed;
- min_pack_length+=packed;
-
- if (options & HA_OPTION_COMPRESS_RECORD)
- {
- if (data_file_length >= (1L << 24))
- pointer=4;
- else if (data_file_length >= (1L << 16))
- pointer=3;
- else
- pointer=2;
- }
- else if (((records == 0L && pack_reclength < 255) ||
- options & HA_OPTION_PACK_RECORD) ||
- records >= (ulong) 16000000L ||
- pack_reclength == (ulong) NI_POS_ERROR ||
- ((options & HA_OPTION_PACK_RECORD) &&
- pack_reclength+4 >= (ulong) 14000000L/records))
- pointer=4;
- else if (records == 0L || records >= (ulong) 65000L ||
- ((options & HA_OPTION_PACK_RECORD) &&
- pack_reclength+4 >= (ulong) 60000L/records))
- pointer=3;
- else
- pointer=2;
-
- max_block=max_key_length=0; tot_length=key_segs=0;
- for (i=0, keydef=keyinfo ; i < keys ; i++ , keydef++)
- {
- share.state.key_root[i]= share.state.key_del[i]= NI_POS_ERROR;
- share.base.rec_per_key[i]= (keydef->base.flag & HA_NOSAME) ? 1L : 0L;
- min_key_length_skipp=length=0;
- key_length=pointer;
-
- if (keydef->base.flag & HA_PACK_KEY &&
- keydef->seg[0].base.length > 127)
- keydef->base.flag&= ~HA_PACK_KEY; /* Can't pack long keys */
- if (keydef->base.flag & HA_PACK_KEY)
- {
- if ((keydef->seg[0].base.flag & HA_SPACE_PACK) &&
- keydef->seg[0].base.type == (int) HA_KEYTYPE_NUM)
- keydef->seg[0].base.flag&= ~HA_SPACE_PACK;
- if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
- length++;
- keydef->seg[0].base.flag|=HA_PACK_KEY; /* for easyer intern test */
- options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
- if (!(keydef->seg[0].base.flag & HA_SPACE_PACK))
- min_key_length_skipp+=keydef->seg[0].base.length;
- }
- keydef->base.keysegs=0;
- for (keyseg=keydef->seg ; keyseg->base.type ; keyseg++)
- {
- keydef->base.keysegs++;
- if (keyseg->base.length > 127)
- keyseg->base.flag&= ~(HA_SPACE_PACK | HA_PACK_KEY);
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- keydef->base.flag |= HA_SPACE_PACK_USED;
- options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
- length++;
- min_key_length_skipp+=keyseg->base.length;
- }
- key_length+= keyseg->base.length;
- }
- bzero((gptr) keyseg,sizeof(keyseg[0]));
- keyseg->base.length=(uint16) pointer; /* Last key part is pointer */
- key_segs+=keydef->base.keysegs;
- length+=key_length;
- keydef->base.block_length=nisam_block_size;
- keydef->base.keylength= (uint16) key_length;
- keydef->base.minlength= (uint16) (length-min_key_length_skipp);
- keydef->base.maxlength= (uint16) length;
-
- if ((uint) keydef->base.block_length > max_block)
- max_block=(uint) keydef->base.block_length;
- if (length > max_key_length)
- max_key_length= length;
- tot_length+= (records/(ulong) (((uint) keydef->base.block_length-5)/
- (length*2)))*
- (ulong) keydef->base.block_length;
- }
- info_length=(uint) (base_pos+sizeof(N_BASE_INFO)+keys*sizeof(N_SAVE_KEYDEF)+
- (keys+key_segs)*sizeof(N_SAVE_KEYSEG)+
- fields*sizeof(N_SAVE_RECINFO));
-
- bmove(share.state.header.file_version,(byte*) nisam_file_magic,4);
- old_options=options| (old_options & HA_OPTION_TEMP_COMPRESS_RECORD ?
- HA_OPTION_COMPRESS_RECORD |
- HA_OPTION_TEMP_COMPRESS_RECORD: 0);
- int2store(share.state.header.options,old_options);
- int2store(share.state.header.header_length,info_length);
- int2store(share.state.header.state_info_length,sizeof(N_STATE_INFO));
- int2store(share.state.header.base_info_length,sizeof(N_BASE_INFO));
- int2store(share.state.header.base_pos,base_pos);
-
- share.state.dellink = NI_POS_ERROR;
- share.state.process= (ulong) getpid();
- share.state.uniq= (ulong) file;
- share.state.loop= 0;
- share.state.version= (ulong) time((time_t*) 0);
- share.base.options=options;
- share.base.rec_reflength=pointer;
- share.base.key_reflength=((!tot_length || tot_length > 30000000L) ? 3 :
- tot_length > 120000L ? 2 : 1);
- share.base.keys= share.state.keys = keys;
- share.base.keystart = share.state.key_file_length=MY_ALIGN(info_length,
- nisam_block_size);
- share.base.max_block=max_block;
- share.base.max_key_length=(uint) ALIGN_SIZE(max_key_length+4);
- share.base.records=records;
- share.base.reloc=reloc;
- share.base.reclength=reclength;
- share.base.pack_reclength=
- (uint) (reclength+packed-share.base.blobs*sizeof(char*));
- share.base.max_pack_length=pack_reclength;
- share.base.min_pack_length=min_pack_length;
- share.base.pack_bits=packed;
- share.base.fields=fields;
- share.base.pack_fields=packed;
- share.base.sortkey= (ushort) ~0;
- share.base.max_data_file_length= (pointer == 4) ? (ulong) ~0L :
- (options & (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ?
- (ulong) (1L << (pointer*8)) :
- (pointer == 3 && reclength >= 256L) ? (ulong) NI_POS_ERROR :
- ((ulong) reclength * (1L << (pointer*8)));
- share.base.max_key_file_length= (share.base.key_reflength == 3 ?
- NI_POS_ERROR :
- (ulong)
- (1L << (share.base.key_reflength*8))*512);
- share.base.min_block_length=
- (share.base.pack_reclength+3 < N_EXTEND_BLOCK_LENGTH &&
- ! share.base.blobs) ?
- max(share.base.pack_reclength,N_MIN_BLOCK_LENGTH) :
- N_EXTEND_BLOCK_LENGTH;
- if (! (flags & HA_DONT_TOUCH_DATA))
- share.base.create_time= (long) time((time_t*) 0);
-
- bzero(buff,base_pos);
- if (my_write(file,(char*) &share.state,sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
- my_write(file,buff,base_pos-sizeof(N_STATE_INFO),MYF(MY_NABP)) ||
- my_write(file,(char*) &share.base,sizeof(N_BASE_INFO),MYF(MY_NABP)))
- goto err;
-
- for (i=0 ; i < share.base.keys ; i++)
- {
- if (my_write(file,(char*) &keyinfo[i].base,sizeof(N_SAVE_KEYDEF),
- MYF(MY_NABP)))
- goto err;
- for (j=0 ; j <= keyinfo[i].base.keysegs ; j++)
- {
- if (my_write(file,(char*) &keyinfo[i].seg[j].base,sizeof(N_SAVE_KEYSEG),
- MYF(MY_NABP)))
- goto err;
- }
- }
- for (i=0 ; i < share.base.fields ; i++)
- if (my_write(file,(char*) &recinfo[i].base, (uint) sizeof(N_SAVE_RECINFO),
- MYF(MY_NABP)))
- goto err;
-
- /* Enlarge files */
- if (my_chsize(file, (ulong) share.base.keystart, 0, MYF(0)))
- goto err;
-
- if (! (flags & HA_DONT_TOUCH_DATA))
- {
-#ifdef USE_RELOC
- if (my_chsize(dfile, share.base.min_pack_length*reloc, 0, MYF(0)))
- goto err;
-#endif
- errpos=1;
- if (my_close(dfile,MYF(0)))
- goto err;
- }
- errpos=0;
- pthread_mutex_unlock(&THR_LOCK_isam);
- if (my_close(file,MYF(0)))
- goto err;
- DBUG_RETURN(0);
-
-err:
- pthread_mutex_unlock(&THR_LOCK_isam);
- save_errno=my_errno;
- switch (errpos) {
- case 2:
- VOID(my_close(dfile,MYF(0)));
- /* fall through */
- case 1:
- VOID(my_close(file,MYF(0)));
- }
- my_errno=save_errno; /* R{tt felkod tillbaka */
- DBUG_RETURN(-1);
-} /* nisam_create */
diff --git a/isam/delete.c b/isam/delete.c
deleted file mode 100644
index 5aa542561c1..00000000000
--- a/isam/delete.c
+++ /dev/null
@@ -1,615 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Tar bort ett record fr}n en isam-databas */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-#include <assert.h>
-
-static int d_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,ulong page,
- uchar *anc_buff);
-static int del(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uchar *anc_buff,
- ulong leaf_page,uchar *leaf_buff,uchar *keypos,
- ulong next_block,uchar *ret_key);
-static int underflow(N_INFO *info,N_KEYDEF *keyinfo,uchar *anc_buff,
- ulong leaf_page, uchar *leaf_buff,uchar *keypos);
-static uint remove_key(N_KEYDEF *keyinfo,uint nod_flag,uchar *keypos,
- uchar *lastkey,uchar *page_end);
-
-
-int nisam_delete(N_INFO *info,const byte *record)
-{
- uint i;
- uchar *old_key;
- int save_errno;
- uint32 lastpos;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("nisam_delete");
-
- /* Test if record is in datafile */
-
- if (!(info->update & HA_STATE_AKTIV))
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* No database read */
- DBUG_RETURN(-1);
- }
- if (share->base.options & HA_OPTION_READ_ONLY_DATA)
- {
- my_errno=EACCES;
- DBUG_RETURN(-1);
- }
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
-#endif
- if ((*share->compare_record)(info,record))
- goto err; /* Fel vid kontroll-l{sning */
-
- /* Remove all keys from the .ISAM file */
-
- old_key=info->lastkey+share->base.max_key_length;
- for (i=0 ; i < share->state.keys ; i++ )
- {
- VOID(_nisam_make_key(info,i,old_key,record,info->lastpos));
- if (_nisam_ck_delete(info,i,old_key)) goto err;
- }
-
- if ((*share->delete_record)(info))
- goto err; /* Remove record from database */
-
- info->update= HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_DELETED;
- share->state.records--;
-
- lastpos= (uint32) info->lastpos;
- nisam_log_command(LOG_DELETE,info,(byte*) &lastpos,sizeof(lastpos),0);
- VOID(_nisam_writeinfo(info,1));
- allow_break(); /* Allow SIGHUP & SIGINT */
- DBUG_RETURN(0);
-
-err:
- save_errno=my_errno;
- lastpos= (uint32) info->lastpos;
- nisam_log_command(LOG_DELETE,info,(byte*) &lastpos, sizeof(lastpos),0);
- VOID(_nisam_writeinfo(info,1));
- info->update|=HA_STATE_WRITTEN; /* Buffer changed */
- allow_break(); /* Allow SIGHUP & SIGINT */
- my_errno=save_errno;
- if (save_errno == HA_ERR_KEY_NOT_FOUND)
- my_errno=HA_ERR_CRASHED;
-
- DBUG_RETURN(-1);
-} /* nisam_delete */
-
-
- /* Tar bort en nyckel till isam-nyckelfilen */
-
-int _nisam_ck_delete(register N_INFO *info, uint keynr, uchar *key)
-{
- int error;
- uint nod_flag;
- ulong old_root;
- uchar *root_buff;
- N_KEYDEF *keyinfo;
- DBUG_ENTER("_nisam_ck_delete");
-
- if ((old_root=info->s->state.key_root[keynr]) == NI_POS_ERROR)
- {
- my_errno=HA_ERR_CRASHED;
- DBUG_RETURN(-1);
- }
- keyinfo=info->s->keyinfo+keynr;
- if (!(root_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
- N_MAX_KEY_BUFF*2)))
- DBUG_RETURN(-1);
- if (!_nisam_fetch_keypage(info,keyinfo,old_root,root_buff,0))
- {
- error= -1;
- goto err;
- }
- if ((error=d_search(info,keyinfo,key,old_root,root_buff)) >0)
- {
- if (error == 2)
- {
- DBUG_PRINT("test",("Enlarging of root when deleting"));
- error=_nisam_enlarge_root(info,keynr,key);
- }
- else
- {
- error=0;
- if (getint(root_buff) <= (nod_flag=test_if_nod(root_buff))+3)
- {
- if (nod_flag)
- info->s->state.key_root[keynr]=_nisam_kpos(nod_flag,
- root_buff+2+nod_flag);
- else
- info->s->state.key_root[keynr]= NI_POS_ERROR;
- if (_nisam_dispose(info,keyinfo,old_root))
- error= -1;
- }
- }
- }
-err:
- my_afree((gptr) root_buff);
- DBUG_RETURN(error);
-} /* _nisam_ck_delete */
-
-
- /* Tar bort en nyckel under root */
- /* Returnerar 1 om nuvarande buffert minskade */
- /* Returnerar 2 om nuvarande buffert |kar */
-
-static int d_search(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key, ulong page, uchar *anc_buff)
-{
- int flag,ret_value,save_flag;
- uint length,nod_flag;
- uchar *leaf_buff,*keypos,*next_keypos;
- ulong leaf_page,next_block;
- uchar lastkey[N_MAX_KEY_BUFF];
- DBUG_ENTER("d_search");
- DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff));
-
- flag=(*keyinfo->bin_search)(info,keyinfo,anc_buff,key,0,SEARCH_SAME,&keypos,
- lastkey);
- nod_flag=test_if_nod(anc_buff);
-
- leaf_buff=0;
- LINT_INIT(leaf_page);
- if (nod_flag)
- {
- leaf_page=_nisam_kpos(nod_flag,keypos);
- if (!(leaf_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
- N_MAX_KEY_BUFF*2)))
- {
- my_errno=ENOMEM;
- DBUG_RETURN(-1);
- }
- if (!_nisam_fetch_keypage(info,keyinfo,leaf_page,leaf_buff,0))
- goto err;
- }
-
- if (flag != 0)
- {
- if (!nod_flag)
- {
- my_errno=HA_ERR_CRASHED; /* This should newer happend */
- goto err;
- }
- save_flag=0;
- ret_value=d_search(info,keyinfo,key,leaf_page,leaf_buff);
- }
- else
- { /* Found key */
- next_keypos=keypos; /* Find where next block is */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&next_keypos,lastkey));
- next_block=_nisam_kpos(nod_flag,next_keypos);
- length=getint(anc_buff);
- length-= remove_key(keyinfo,nod_flag,keypos,lastkey,anc_buff+length);
- putint(anc_buff,length,nod_flag);
- if (!nod_flag)
- { /* On leaf page */
- if (_nisam_write_keypage(info,keyinfo,page,anc_buff))
- DBUG_RETURN(-1);
- DBUG_RETURN(length <= (uint) keyinfo->base.block_length/2);
- }
- save_flag=1;
- ret_value=del(info,keyinfo,key,anc_buff,leaf_page,leaf_buff,keypos,
- next_block,lastkey);
- }
- if (ret_value >0)
- {
- save_flag=1;
- if (ret_value == 1)
- ret_value= underflow(info,keyinfo,anc_buff,leaf_page,leaf_buff,keypos);
- else
- { /* This happens only with packed keys */
- DBUG_PRINT("test",("Enlarging of key when deleting"));
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,lastkey,keypos));
- ret_value=_nisam_insert(info,keyinfo,key,anc_buff,keypos,lastkey,
- (uchar*) 0,(uchar*) 0,0L);
- }
- }
- if (ret_value == 0 && getint(anc_buff) > keyinfo->base.block_length)
- {
- save_flag=1;
- ret_value=_nisam_splitt_page(info,keyinfo,key,anc_buff,lastkey) | 2;
- }
- if (save_flag)
- ret_value|=_nisam_write_keypage(info,keyinfo,page,anc_buff);
- else
- {
- DBUG_DUMP("page",(byte*) anc_buff,getint(anc_buff));
- }
- my_afree((byte*) leaf_buff);
- DBUG_RETURN(ret_value);
-err:
- my_afree((byte*) leaf_buff);
- DBUG_PRINT("exit",("Error: %d",my_errno));
- DBUG_RETURN (-1);
-} /* d_search */
-
-
- /* Remove a key that has a page-reference */
-
-static int del(register N_INFO *info, register N_KEYDEF *keyinfo, uchar *key,
- uchar *anc_buff, ulong leaf_page, uchar *leaf_buff,
- uchar *keypos, /* Pos to where deleted key was */
- ulong next_block,
- uchar *ret_key) /* key before keypos in anc_buff */
-{
- int ret_value,length;
- uint a_length,nod_flag;
- ulong next_page;
- uchar keybuff[N_MAX_KEY_BUFF],*endpos,*next_buff,*key_start;
- ISAM_SHARE *share=info->s;
- S_PARAM s_temp;
- DBUG_ENTER("del");
- DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",leaf_page,keypos));
- DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff));
-
- endpos=leaf_buff+getint(leaf_buff);
- key_start=_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos);
-
- if ((nod_flag=test_if_nod(leaf_buff)))
- {
- next_page= _nisam_kpos(nod_flag,endpos);
- if (!(next_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
- N_MAX_KEY_BUFF)))
- DBUG_RETURN(-1);
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,next_buff,0))
- ret_value= -1;
- else
- {
- DBUG_DUMP("next_page",(byte*) next_buff,getint(next_buff));
- if ((ret_value=del(info,keyinfo,key,anc_buff,next_page,next_buff,
- keypos,next_block,ret_key)) >0)
- {
- endpos=leaf_buff+getint(leaf_buff);
- if (ret_value == 1)
- {
- ret_value=underflow(info,keyinfo,leaf_buff,next_page,
- next_buff,endpos);
- if (ret_value == 0 && getint(leaf_buff) > keyinfo->base.block_length)
- {
- ret_value=_nisam_splitt_page(info,keyinfo,key,leaf_buff,ret_key) | 2;
- }
- }
- else
- {
- DBUG_PRINT("test",("Inserting of key when deleting"));
- VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,keybuff,endpos));
- ret_value=_nisam_insert(info,keyinfo,key,leaf_buff,endpos,keybuff,
- (uchar*) 0,(uchar*) 0,0L);
- }
- }
- if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
- goto err;
- }
- my_afree((byte*) next_buff);
- DBUG_RETURN(ret_value);
- }
-
- /* Remove last key from leaf page */
-
- putint(leaf_buff,key_start-leaf_buff,nod_flag);
- if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
- goto err;
-
- /* Place last key in ancestor page on deleted key position */
-
- a_length=getint(anc_buff);
- endpos=anc_buff+a_length;
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,ret_key,keypos));
- length=_nisam_get_pack_key_length(keyinfo,share->base.key_reflength,
- keypos == endpos ? (uchar*) 0 : keypos,
- ret_key,keybuff,&s_temp);
- if (length > 0)
- bmove_upp((byte*) endpos+length,(byte*) endpos,(uint) (endpos-keypos));
- else
- bmove(keypos,keypos-length, (int) (endpos-keypos)+length);
- _nisam_store_key(keyinfo,keypos,&s_temp);
- /* Save pointer to next leaf */
- VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&keypos,ret_key));
- _nisam_kpointer(info,keypos - share->base.key_reflength,next_block);
- putint(anc_buff,a_length+length,share->base.key_reflength);
-
- DBUG_RETURN( getint(leaf_buff) <= (uint) keyinfo->base.block_length/2 );
-err:
- DBUG_RETURN(-1);
-} /* del */
-
-
- /* Balances adjacent pages if underflow occours */
-
-static int underflow(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *anc_buff,
- ulong leaf_page, /* Ancestor page and underflow page */
- uchar *leaf_buff,
- uchar *keypos) /* Position to pos after key */
-{
- int t_length;
- uint length,anc_length,buff_length,leaf_length,p_length,s_length,nod_flag;
- ulong next_page;
- uchar anc_key[N_MAX_KEY_BUFF],leaf_key[N_MAX_KEY_BUFF],
- *buff,*endpos,*next_keypos,*half_pos,*temp_pos;
- S_PARAM s_temp;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("underflow");
- DBUG_PRINT("enter",("leaf_page: %ld keypos: %lx",leaf_page,keypos));
- DBUG_DUMP("anc_buff",(byte*) anc_buff,getint(anc_buff));
- DBUG_DUMP("leaf_buff",(byte*) leaf_buff,getint(leaf_buff));
-
- buff=info->buff;
- next_keypos=keypos;
- nod_flag=test_if_nod(leaf_buff);
- p_length=2+nod_flag;
- anc_length=getint(anc_buff);
- leaf_length=getint(leaf_buff);
- info->page_changed=1;
-
- if ((keypos < anc_buff+anc_length && (share->rnd++ & 1)) ||
- keypos == anc_buff+2+share->base.key_reflength)
- { /* Use page right of anc-page */
- DBUG_PRINT("test",("use right page"));
-
- VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos,
- buff));
- next_page= _nisam_kpos(share->base.key_reflength,next_keypos);
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0))
- goto err;
- buff_length=getint(buff);
- DBUG_DUMP("next",(byte*) buff,buff_length);
-
- /* find keys to make a big key-page */
- bmove((byte*) next_keypos-share->base.key_reflength,(byte*) buff+2,
- share->base.key_reflength);
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,next_keypos));
- VOID(_nisam_get_last_key(info,keyinfo,leaf_buff,leaf_key,
- leaf_buff+leaf_length));
-
- /* merge pages and put parting key from anc_buff between */
- t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,buff+p_length,
- (leaf_length == nod_flag+2 ?
- (uchar*) 0 : leaf_key),
- anc_key,&s_temp);
- length=buff_length-p_length;
- endpos=buff+length+leaf_length+t_length;
- bmove_upp((byte*) endpos, (byte*) buff+buff_length,length);
- memcpy((byte*) buff, (byte*) leaf_buff,(size_t) leaf_length);
- _nisam_store_key(keyinfo,buff+leaf_length,&s_temp);
- buff_length=(uint) (endpos-buff);
- putint(buff,buff_length,nod_flag);
-
- /* remove key from anc_buff */
-
- s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key,
- anc_buff+anc_length);
- putint(anc_buff,(anc_length-=s_length),share->base.key_reflength);
-
- if (buff_length <= keyinfo->base.block_length)
- { /* Keys in one page */
- memcpy((byte*) leaf_buff,(byte*) buff,(size_t) buff_length);
- if (_nisam_dispose(info,keyinfo,next_page))
- goto err;
- }
- else
- { /* Page is full */
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos));
- half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key);
- length=(uint) (half_pos-buff);
- memcpy((byte*) leaf_buff,(byte*) buff,(size_t) length);
- putint(leaf_buff,length,nod_flag);
- endpos=anc_buff+anc_length;
-
- /* Correct new keypointer to leaf_page */
- length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key);
- _nisam_kpointer(info,leaf_key+length,next_page);
- /* Save key in anc_buff */
- t_length=(int) _nisam_get_pack_key_length(keyinfo,
- share->base.key_reflength,
- keypos == endpos ?
- (uchar*) 0 : keypos,
- anc_key,leaf_key,&s_temp);
- if (t_length >= 0)
- bmove_upp((byte*) endpos+t_length,(byte*) endpos,
- (uint) (endpos-keypos));
- else
- bmove(keypos,keypos-t_length,(uint) (endpos-keypos)+t_length);
- _nisam_store_key(keyinfo,keypos,&s_temp);
- putint(anc_buff,(anc_length+=t_length),share->base.key_reflength);
-
- /* Store new page */
- if (nod_flag)
- bmove((byte*) buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag);
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key));
- t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,(uchar*) 0,
- (uchar*) 0, leaf_key,&s_temp);
- s_temp.n_length= *half_pos; /* For _nisam_store_key */
- length=(uint) ((buff+getint(buff))-half_pos);
- bmove((byte*) buff+p_length+t_length,(byte*) half_pos,(size_t) length);
- _nisam_store_key(keyinfo,buff+p_length,&s_temp);
- putint(buff,length+t_length+p_length,nod_flag);
-
- if (_nisam_write_keypage(info,keyinfo,next_page,buff))
- goto err;
- }
- if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
- goto err;
- DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2);
- }
-
- DBUG_PRINT("test",("use left page"));
-
- keypos=_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos);
- next_page= _nisam_kpos(share->base.key_reflength,keypos);
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,buff,0))
- goto err;
- buff_length=getint(buff);
- endpos=buff+buff_length;
- DBUG_DUMP("prev",(byte*) buff,buff_length);
-
- /* find keys to make a big key-page */
- bmove((byte*) next_keypos - share->base.key_reflength,(byte*) leaf_buff+2,
- share->base.key_reflength);
- next_keypos=keypos;
- VOID((*keyinfo->get_key)(keyinfo,share->base.key_reflength,&next_keypos,
- anc_key));
- VOID(_nisam_get_last_key(info,keyinfo,buff,leaf_key,endpos));
-
- /* merge pages and put parting key from anc_buff between */
- t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag,
- leaf_buff+p_length,
- (leaf_length == nod_flag+2 ?
- (uchar*) 0 : leaf_key),
- anc_key,&s_temp);
- if (t_length >= 0)
- bmove((byte*) endpos+t_length,(byte*) leaf_buff+p_length,
- (size_t) (leaf_length-p_length));
- else /* We gained space */
- bmove((byte*) endpos,(byte*) leaf_buff+((int) p_length-t_length),
- (size_t) (leaf_length-p_length+t_length));
-
- _nisam_store_key(keyinfo,endpos,&s_temp);
- buff_length=buff_length+leaf_length-p_length+t_length;
- putint(buff,buff_length,nod_flag);
-
- /* remove key from anc_buff */
- s_length=remove_key(keyinfo,share->base.key_reflength,keypos,anc_key,
- anc_buff+anc_length);
- putint(anc_buff,(anc_length-=s_length),share->base.key_reflength);
-
- if (buff_length <= keyinfo->base.block_length)
- { /* Keys in one page */
- if (_nisam_dispose(info,keyinfo,leaf_page))
- goto err;
- }
- else
- { /* Page is full */
- VOID(_nisam_get_last_key(info,keyinfo,anc_buff,anc_key,keypos));
- endpos=half_pos=_nisam_find_half_pos(info,keyinfo,buff,leaf_key);
-
- /* Correct new keypointer to leaf_page */
- length=(*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key);
- _nisam_kpointer(info,leaf_key+length,leaf_page);
- /* Save key in anc_buff */
- DBUG_DUMP("anc_buff",(byte*) anc_buff,anc_length);
- DBUG_DUMP("key",(byte*) leaf_key,16);
-
- temp_pos=anc_buff+anc_length;
- t_length=(int) _nisam_get_pack_key_length(keyinfo,
- share->base.key_reflength,
- keypos == temp_pos ? (uchar*) 0
- : keypos,
- anc_key,leaf_key,&s_temp);
- if (t_length > 0)
- bmove_upp((byte*) temp_pos+t_length,(byte*) temp_pos,
- (uint) (temp_pos-keypos));
- else
- bmove(keypos,keypos-t_length,(uint) (temp_pos-keypos)+t_length);
- _nisam_store_key(keyinfo,keypos,&s_temp);
- putint(anc_buff,(anc_length+=t_length),share->base.key_reflength);
-
- /* Store new page */
- if (nod_flag)
- bmove((byte*) leaf_buff+2,(byte*) half_pos-nod_flag,(size_t) nod_flag);
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&half_pos,leaf_key));
- t_length=(int) _nisam_get_pack_key_length(keyinfo,nod_flag, (uchar*) 0,
- (uchar*) 0, leaf_key, &s_temp);
- s_temp.n_length= *half_pos; /* For _nisam_store_key */
- length=(uint) ((buff+buff_length)-half_pos);
- bmove((byte*) leaf_buff+p_length+t_length,(byte*) half_pos,
- (size_t) length);
- _nisam_store_key(keyinfo,leaf_buff+p_length,&s_temp);
- putint(leaf_buff,length+t_length+p_length,nod_flag);
- putint(buff,endpos-buff,nod_flag);
- if (_nisam_write_keypage(info,keyinfo,leaf_page,leaf_buff))
- goto err;
- }
- if (_nisam_write_keypage(info,keyinfo,next_page,buff))
- goto err;
- DBUG_RETURN(anc_length <= (uint) keyinfo->base.block_length/2);
-err:
- DBUG_RETURN(-1);
-} /* underflow */
-
-
- /* remove a key from packed buffert */
- /* returns how many chars was removed */
-
-static uint remove_key(N_KEYDEF *keyinfo, uint nod_flag,
- uchar *keypos, /* Where key starts */
- uchar *lastkey, /* key to be removed */
- uchar *page_end) /* End of page */
-{
- int r_length,s_length,first,diff_flag;
- uchar *start;
- DBUG_ENTER("remove_key");
- DBUG_PRINT("enter",("keypos: %lx page_end: %lx",keypos,page_end));
-
- start=keypos;
- if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
- s_length=(int) (keyinfo->base.keylength+nod_flag);
- else
- { /* Let keypos point at next key */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey));
- s_length=(uint) (keypos-start);
- if (keyinfo->base.flag & HA_PACK_KEY)
- {
- diff_flag= (keyinfo->seg[0].base.flag & HA_SPACE_PACK);
- first= *start;
- if (keypos != page_end && *keypos & 128 && first != 128)
- { /* Referens length */
- if ((r_length= *keypos++ & 127) == 0)
- { /* Same key after */
- if (first & 128)
- start++; /* Skip ref length */
- if (diff_flag)
- start+= *start+1; /* Skip key length */
- else
- start+=keyinfo->seg[0].base.length- (first & 127);
- s_length=(uint)(keypos-start); /* Remove pntrs and next-key-flag */
- }
- else if (! (first & 128))
- { /* Deleted key was not compressed */
- if (diff_flag)
- {
- *start= (uchar) (r_length+ *keypos);
- start+=r_length+1; /* Let ref-part remain */
- s_length=(uint) (keypos-start)+1; /* Skip everything between */
- }
- else
- {
- start+=r_length+1; /* Let ref-part remain */
- s_length=(uint) (keypos-start); /* Skip everything between */
- }
- }
- else if ((first & 127) < r_length)
- { /* mid-part of key is used */
- r_length-=(first & 127);
- start++; /* Ref remains the same */
- if (diff_flag)
- *start++= (uchar) (*keypos++ + r_length);
- start+= r_length;
- s_length=(uint) (keypos-start); /* Skip everything between */
- }
- }
- }
- }
- bmove((byte*) start,(byte*) start+s_length,
- (uint) (page_end-start-s_length));
- DBUG_RETURN((uint) s_length);
-} /* remove_key */
diff --git a/isam/extra.c b/isam/extra.c
deleted file mode 100644
index 421404311c8..00000000000
--- a/isam/extra.c
+++ /dev/null
@@ -1,271 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Extra functions we want to do with a database */
-/* - Set flags for quicker databasehandler */
-/* - Set databasehandler to normal */
-/* - Reset recordpointers as after open database */
-
-#include "isamdef.h"
-#ifdef HAVE_MMAP
-#include <sys/mman.h>
-#endif
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* set extra flags for database */
-
-int nisam_extra(N_INFO *info, enum ha_extra_function function)
-{
- int error=0;
- DBUG_ENTER("nisam_extra");
-
- switch (function) {
- case HA_EXTRA_RESET:
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- {
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- error=end_io_cache(&info->rec_cache);
- }
- info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
-
- case HA_EXTRA_RESET_STATE:
- info->lastinx= 0; /* Use first index as def */
- info->int_pos=info->lastpos= NI_POS_ERROR;
- info->page_changed=1;
- /* Next/prev gives first/last */
- if (info->opt_flag & READ_CACHE_USED)
- {
- VOID(flush_io_cache(&info->rec_cache));
- reinit_io_cache(&info->rec_cache,READ_CACHE,0,
- (pbool) (info->lock_type != F_UNLCK),
- (pbool) test(info->update & HA_STATE_ROW_CHANGED));
- }
- info->update=((info->update & HA_STATE_CHANGED) |
- HA_STATE_NEXT_FOUND | HA_STATE_PREV_FOUND);
- break;
- case HA_EXTRA_CACHE:
-#ifndef NO_LOCKING
- if (info->lock_type == F_UNLCK && (info->options & HA_OPTION_PACK_RECORD))
- {
- error=1; /* Not possibly if not locked */
- my_errno=EACCES;
- break;
- }
-#endif
-#if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
- if ((info->options & HA_OPTION_COMPRESS_RECORD))
- {
- pthread_mutex_lock(&info->s->intern_lock);
- if (_nisam_memmap_file(info))
- {
- /* We don't nead MADV_SEQUENTIAL if small file */
- madvise(info->s->file_map,info->s->state.data_file_length,
- info->s->state.data_file_length <= RECORD_CACHE_SIZE*16 ?
- MADV_RANDOM : MADV_SEQUENTIAL);
- pthread_mutex_unlock(&info->s->intern_lock);
- break;
- }
- pthread_mutex_unlock(&info->s->intern_lock);
- }
-#endif
- if (info->opt_flag & WRITE_CACHE_USED)
- {
- info->opt_flag&= ~WRITE_CACHE_USED;
- if ((error=end_io_cache(&info->rec_cache)))
- break;
- }
- if (!(info->opt_flag &
- (READ_CACHE_USED | WRITE_CACHE_USED | MEMMAP_USED)))
- {
- if (!(init_io_cache(&info->rec_cache,info->dfile,
- (uint) min(info->s->state.data_file_length+1,
- my_default_record_cache_size),
- READ_CACHE,0L,(pbool) (info->lock_type != F_UNLCK),
- MYF(MY_WAIT_IF_FULL))))
- {
- info->opt_flag|=READ_CACHE_USED;
- info->update&= ~HA_STATE_ROW_CHANGED;
- }
- /* info->rec_cache.end_of_file=info->s->state.data_file_length; */
- }
- break;
- case HA_EXTRA_REINIT_CACHE:
- if (info->opt_flag & READ_CACHE_USED)
- {
- reinit_io_cache(&info->rec_cache,READ_CACHE,info->nextpos,
- (pbool) (info->lock_type != F_UNLCK),
- (pbool) test(info->update & HA_STATE_ROW_CHANGED));
- info->update&= ~HA_STATE_ROW_CHANGED;
- /* info->rec_cache.end_of_file=info->s->state.data_file_length; */
- }
- break;
- case HA_EXTRA_WRITE_CACHE:
-#ifndef NO_LOCKING
- if (info->lock_type == F_UNLCK)
- {
- error=1; /* Not possibly if not locked */
- break;
- }
-#endif
- if (!(info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED)))
- {
- if (!(init_io_cache(&info->rec_cache,info->dfile,0,
- WRITE_CACHE,info->s->state.data_file_length,
- (pbool) (info->lock_type != F_UNLCK),
- MYF(MY_WAIT_IF_FULL))))
- {
- info->opt_flag|=WRITE_CACHE_USED;
- info->update&= ~HA_STATE_ROW_CHANGED;
- }
- }
- break;
- case HA_EXTRA_PREPARE_FOR_UPDATE:
- if (info->s->data_file_type != DYNAMIC_RECORD)
- break;
- /* Remove read/write cache if dynamic rows */
- case HA_EXTRA_NO_CACHE:
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- {
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- error=end_io_cache(&info->rec_cache);
- }
-#if defined(HAVE_MMAP) && defined(HAVE_MADVICE)
- if (info->opt_flag & MEMMAP_USED)
- madvise(info->s->file_map,info->s->state.data_file_length,MADV_RANDOM);
-#endif
- break;
- case HA_EXTRA_FLUSH_CACHE:
- if (info->opt_flag & WRITE_CACHE_USED)
- error=flush_io_cache(&info->rec_cache);
- break;
- case HA_EXTRA_NO_READCHECK:
- info->opt_flag&= ~READ_CHECK_USED; /* No readcheck */
- break;
- case HA_EXTRA_READCHECK:
- info->opt_flag|= READ_CHECK_USED;
- break;
- case HA_EXTRA_KEYREAD: /* Read only keys to record */
- case HA_EXTRA_REMEMBER_POS:
- info->opt_flag |= REMEMBER_OLD_POS;
- bmove((byte*) info->lastkey+info->s->base.max_key_length*2,
- (byte*) info->lastkey,info->s->base.max_key_length);
- info->save_update= info->update;
- info->save_lastinx= info->lastinx;
- info->save_lastpos= info->lastpos;
- if (function == HA_EXTRA_REMEMBER_POS)
- break;
- /* fall through */
- case HA_EXTRA_KEYREAD_CHANGE_POS:
- info->opt_flag |= KEY_READ_USED;
- info->read_record=_nisam_read_key_record;
- break;
- case HA_EXTRA_NO_KEYREAD:
- case HA_EXTRA_RESTORE_POS:
- if (info->opt_flag & REMEMBER_OLD_POS)
- {
- bmove((byte*) info->lastkey,
- (byte*) info->lastkey+info->s->base.max_key_length*2,
- info->s->base.max_key_length);
- info->update= info->save_update | HA_STATE_WRITTEN;
- info->lastinx= info->save_lastinx;
- info->lastpos= info->save_lastpos;
- }
- info->read_record= info->s->read_record;
- info->opt_flag&= ~(KEY_READ_USED | REMEMBER_OLD_POS);
- break;
- case HA_EXTRA_NO_USER_CHANGE: /* Database is somehow locked agains changes */
- info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
- break;
- case HA_EXTRA_WAIT_LOCK:
- info->lock_wait=0;
- break;
- case HA_EXTRA_NO_WAIT_LOCK:
- info->lock_wait=MY_DONT_WAIT;
- break;
- case HA_EXTRA_NO_KEYS:
-#ifndef NO_LOCKING
- if (info->lock_type == F_UNLCK)
- {
- error=1; /* Not possibly if not lock */
- break;
- }
-#endif
- info->s->state.keys=0;
- info->s->state.key_file_length=info->s->base.keystart;
- info->s->changed=1; /* Update on close */
- break;
- case HA_EXTRA_FORCE_REOPEN:
- case HA_EXTRA_PREPARE_FOR_DELETE:
- pthread_mutex_lock(&THR_LOCK_isam);
- info->s->last_version= 0L; /* Impossible version */
-#ifdef __WIN__
- /* Close the isam and data files as Win32 can't drop an open table */
- if (flush_key_blocks(dflt_key_cache, info->s->kfile, FLUSH_RELEASE))
- error=my_errno;
- if (info->opt_flag & (READ_CACHE_USED | WRITE_CACHE_USED))
- {
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- error=end_io_cache(&info->rec_cache);
- }
- if (info->lock_type != F_UNLCK && ! info->was_locked)
- {
- info->was_locked=info->lock_type;
- if (nisam_lock_database(info,F_UNLCK))
- error=my_errno;
- }
- if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0)))
- error=my_errno;
- {
- LIST *list_element ;
- for (list_element=nisam_open_list ;
- list_element ;
- list_element=list_element->next)
- {
- N_INFO *tmpinfo=(N_INFO*) list_element->data;
- if (tmpinfo->s == info->s)
- {
- if (tmpinfo->dfile >= 0 && my_close(tmpinfo->dfile,MYF(0)))
- error = my_errno;
- tmpinfo->dfile=-1;
- }
- }
- }
- info->s->kfile=-1; /* Files aren't open anymore */
-#endif
- pthread_mutex_unlock(&THR_LOCK_isam);
- break;
- case HA_EXTRA_FLUSH:
- if (info->s->not_flushed)
- {
- info->s->not_flushed=0;
- if (my_sync(info->s->kfile, MYF(0)))
- error= my_errno;
- if (my_sync(info->dfile, MYF(0)))
- error= my_errno;
- }
- break;
- case HA_EXTRA_NORMAL: /* Theese isn't in use */
- case HA_EXTRA_QUICK:
- case HA_EXTRA_KEY_CACHE:
- case HA_EXTRA_NO_KEY_CACHE:
- default:
- break;
- }
- nisam_log_command(LOG_EXTRA,info,(byte*) &function,sizeof(function),error);
- DBUG_RETURN(error);
-} /* nisam_extra */
diff --git a/isam/info.c b/isam/info.c
deleted file mode 100644
index a23494e4876..00000000000
--- a/isam/info.c
+++ /dev/null
@@ -1,77 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Ger tillbaka en struct med information om isam-filen */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <sys/stat.h>
-#endif
-
-ulong nisam_position(N_INFO *info)
-{
- return info->lastpos;
-}
-
- /* If flag == 1 one only gets pos of last record */
- /* if flag == 2 one get current info (no sync from database */
-
-int nisam_info(N_INFO *info, register N_ISAMINFO *x, int flag)
-{
- struct stat state;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("nisam_info");
-
- x->recpos = info->lastpos;
- if (flag & (HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE |
- HA_STATUS_ERRKEY | HA_STATUS_NO_LOCK))
- {
-#ifndef NO_LOCKING
- if (!(flag & HA_STATUS_NO_LOCK))
- {
- pthread_mutex_lock(&share->intern_lock);
- VOID(_nisam_readinfo(info,F_RDLCK,0));
- VOID(_nisam_writeinfo(info,0));
- pthread_mutex_unlock(&share->intern_lock);
- }
-#endif
- x->records = share->state.records;
- x->deleted = share->state.del;
- x->delete_length= share->state.empty;
- x->keys = share->state.keys;
- x->reclength = share->base.reclength;
- x->mean_reclength= share->state.records ?
- (share->state.data_file_length-share->state.empty)/share->state.records :
- share->min_pack_length;
- x->data_file_length=share->state.data_file_length;
- x->max_data_file_length=share->base.max_data_file_length;
- x->index_file_length=share->state.key_file_length;
- x->max_index_file_length=share->base.max_key_file_length;
- x->filenr = info->dfile;
- x->errkey = info->errkey;
- x->dupp_key_pos= info->dupp_key_pos;
- x->options = share->base.options;
- x->create_time=share->base.create_time;
- x->isamchk_time=share->base.isamchk_time;
- x->rec_per_key=share->base.rec_per_key;
- if ((flag & HA_STATUS_TIME) && !fstat(info->dfile,&state))
- x->update_time=state.st_mtime;
- else
- x->update_time=0;
- x->sortkey= -1; /* No clustering */
- }
- DBUG_RETURN(0);
-} /* nisam_info */
diff --git a/isam/isamchk.c b/isam/isamchk.c
deleted file mode 100644
index 5dd20c14063..00000000000
--- a/isam/isamchk.c
+++ /dev/null
@@ -1,3424 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Descript, check and repair of ISAM tables */
-
-#include "isamdef.h"
-
-#include <m_ctype.h>
-#include <stdarg.h>
-#include <my_getopt.h>
-#ifdef HAVE_SYS_VADVICE_H
-#include <sys/vadvise.h>
-#endif
-#ifdef HAVE_SYS_MMAN_H
-#include <sys/mman.h>
-#endif
-SET_STACK_SIZE(9000) /* Minimum stack size for program */
-
-#define T_VERBOSE 1
-#define T_SILENT 2
-#define T_DESCRIPT 4
-#define T_EXTEND 8
-#define T_INFO 16
-#define T_REP 32
-#define T_OPT 64 /* Not currently used */
-#define T_FORCE_CREATE 128
-#define T_WRITE_LOOP 256
-#define T_UNPACK 512
-#define T_STATISTICS 1024
-#define T_VERY_SILENT 2048
-#define T_SORT_RECORDS 4096
-#define T_SORT_INDEX 8192
-#define T_WAIT_FOREVER 16384
-#define T_REP_BY_SORT 32768L
-
-
-#define O_NEW_INDEX 1 /* Bits set in out_flag */
-#define O_NEW_DATA 2
-
-#if defined(_MSC_VER) && !defined(__WIN__)
-#define USE_BUFFER_INIT 250L*1024L
-#define READ_BUFFER_INIT ((uint) 32768-MALLOC_OVERHEAD)
-#define SORT_BUFFER_INIT (uint) (65536L-MALLOC_OVERHEAD)
-#define MIN_SORT_BUFFER (1024*16-MALLOC_OVERHEAD)
-#else
-#define USE_BUFFER_INIT (((1024L*512L-MALLOC_OVERHEAD)/IO_SIZE)*IO_SIZE)
-#define READ_BUFFER_INIT (1024L*256L-MALLOC_OVERHEAD)
-#define SORT_BUFFER_INIT (2048L*1024L-MALLOC_OVERHEAD)
-#define MIN_SORT_BUFFER (4096-MALLOC_OVERHEAD)
-#endif
-
-#define NEED_MEM ((uint) 10*4*(IO_SIZE+32)+32) /* Nead for recursion */
-#define MAXERR 20
-#define BUFFERS_WHEN_SORTING 16 /* Alloc for sort-key-tree */
-#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE
-#define INDEX_TMP_EXT ".TMM"
-#define DATA_TMP_EXT ".TMD"
-#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
-
-#define UPDATE_TIME 1
-#define UPDATE_STAT 2
-#define UPDATE_SORT 4
-
-typedef struct st_isam_sort_key_blocks { /* Used when sorting */
- uchar *buff,*end_pos;
- uchar lastkey[N_MAX_POSSIBLE_KEY_BUFF];
- uint last_length;
- int inited;
-} ISAM_SORT_KEY_BLOCKS;
-
-typedef struct st_isam_sort_info {
- N_INFO *info;
- enum data_file_type new_data_file_type;
- ISAM_SORT_KEY_BLOCKS *key_block,*key_block_end;
- uint key,find_length;
- ulong pos,max_pos,filepos,start_recpos,filelength,dupp,max_records,unique,
- buff_length;
- my_bool fix_datafile;
- char *record,*buff;
- N_KEYDEF *keyinfo;
- N_KEYSEG *keyseg;
-} ISAM_SORT_INFO;
-
-enum ic_options {OPT_CHARSETS_DIR_IC=256, OPT_KEY_BUFFER_SIZE,
- OPT_READ_BUFFER_SIZE, OPT_WRITE_BUFFER_SIZE,
- OPT_SORT_BUFFER_SIZE, OPT_SORT_KEY_BLOCKS,
- OPT_DECODE_BITS};
-
-static ulong use_buffers=0,read_buffer_length=0,write_buffer_length=0,
- sort_buffer_length=0,sort_key_blocks=0,crc=0,unique_count=0;
-static uint testflag=0,out_flag=0,warning_printed=0,error_printed=0,
- verbose=0,opt_follow_links=1;
-static my_bool rep_quick= 0;
-static uint opt_sort_key=0,total_files=0,max_level=0,max_key=N_MAXKEY;
-static ulong keydata=0,totaldata=0,key_blocks=0;
-static ulong new_file_pos=0,record_checksum=0,key_file_blocks=0,decode_bits;
-static ulong total_records=0,total_deleted=0;
-static ulong search_after_block=NI_POS_ERROR;
-static byte *record_buff;
-static char **defaults_alloc;
-static const char *type_names[]=
-{ "?","text","binary", "short", "long", "float",
- "double","number","unsigned short",
- "unsigned long","longlong","ulonglong","int24",
- "uint24","int8","?",},
- *packed_txt="packed ",
- *diff_txt="stripped ",
- *field_pack[]={"","no endspace", "no prespace",
- "no zeros", "blob", "constant", "table-lookup",
- "always zero","?","?",};
-
-static char temp_filename[FN_REFLEN], *isam_file_name, *default_charset;
-static IO_CACHE read_cache;
-static ISAM_SORT_INFO sort_info;
-static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
-
-static const char *load_default_groups[]= { "isamchk",0 };
-
- /* Functions defined in this file */
-
-extern int main(int argc,char * *argv);
-extern void print_error _VARARGS((const char *fmt,...));
-static void print_warning _VARARGS((const char *fmt,...));
-static void print_info _VARARGS((const char *fmt,...));
-static int nisamchk(char *filename);
-static void get_options(int *argc,char * * *argv);
-static int chk_del(N_INFO *info,uint testflag);
-static int check_k_link(N_INFO *info,uint nr);
-static int chk_size(N_INFO *info);
-static int chk_key(N_INFO *info);
-static int chk_index(N_INFO *info, N_KEYDEF *keyinfo, ulong page, uchar *buff,
- ulong *keys, uint level);
-static uint isam_key_length(N_INFO *info,N_KEYDEF *keyinfo);
-static unsigned long calc_checksum(ulong count);
-static int chk_data_link(N_INFO *info,int extend);
-static int rep(N_INFO *info,char *name);
-static int writekeys(N_INFO *info,byte *buff,ulong filepos);
-static void descript(N_INFO *info,char *name);
-static int movepoint(N_INFO *info,byte *record,ulong oldpos,ulong newpos,
- uint prot_key);
-static void lock_memory(void);
-static int flush_blocks(File file);
-static int sort_records(N_INFO *,my_string,uint,int);
-static int sort_index(N_INFO *info,my_string name);
-static int sort_record_index(N_INFO *info,N_KEYDEF *keyinfo,ulong page,
- uchar *buff,uint sortkey,File new_file);
-static int sort_one_index(N_INFO *info,N_KEYDEF *keyinfo,uchar *buff,
- File new_file);
-static int change_to_newfile(const char * filename,const char * old_ext,
- const char * new_ext);
-static int lock_file(File file,ulong start,int lock_type,const char* filetype,
- const char *filename);
-static int filecopy(File to,File from,ulong start,ulong length,
- const char * type);
-
-static void print_version(void);
-static int rep_by_sort(N_INFO *info,my_string name);
-static int sort_key_read(void *key);
-static int sort_get_next_record(void);
-static int sort_write_record(void);
-static int sort_key_cmp(const void *not_used, const void *a,const void *b);
-static int sort_key_write(const void *a);
-static ulong get_record_for_key(N_INFO *info,N_KEYDEF *keyinfo,
- uchar *key);
-static int sort_insert_key(reg1 ISAM_SORT_KEY_BLOCKS *key_block,uchar *key,
- ulong prev_block);
-static int sort_delete_record(void);
-static void usage(void);
-static int flush_pending_blocks(void);
-static ISAM_SORT_KEY_BLOCKS *alloc_key_blocks(uint blocks,uint buffer_length);
-static int test_if_almost_full(N_INFO *info);
-static int recreate_database(N_INFO **info,char *filename);
-static void save_integer(byte *pos,uint pack_length,ulong value);
-static int write_data_suffix(N_INFO *info);
-static int update_state_info(N_INFO *info,uint update);
-
-
- /* Main program */
-
-int main( int argc, char **argv)
-{
- int error;
- MY_INIT(argv[0]);
-
-#ifdef __EMX__
- _wildcard (&argc, &argv);
-#endif
-
- get_options(&argc,(char***) &argv);
- nisam_quick_table_bits=(uint) decode_bits;
- error=0;
- while (--argc >= 0)
- {
- error|= nisamchk(*(argv++));
- VOID(fflush(stdout));
- VOID(fflush(stderr));
- if ((error_printed | warning_printed) && (testflag & T_FORCE_CREATE) &&
- (!(testflag & (T_REP | T_REP_BY_SORT | T_SORT_RECORDS |
- T_SORT_INDEX))))
- {
- testflag|=T_REP;
- error|=nisamchk(argv[-1]);
- testflag&= ~T_REP;
- VOID(fflush(stdout));
- VOID(fflush(stderr));
- }
- if (argc && (!(testflag & T_SILENT) || testflag & T_INFO))
- {
- puts("\n---------\n");
- VOID(fflush(stdout));
- }
- }
- if (total_files > 1)
- { /* Only if descript */
- if (!(testflag & T_SILENT) || testflag & T_INFO)
- puts("\n---------\n");
- printf("\nTotal of all %d ISAM-files:\nData records: %8lu Deleted blocks: %8lu\n",total_files,total_records,total_deleted);
- }
- free_defaults(defaults_alloc);
- my_end(testflag & T_INFO ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
- exit(error);
-#ifndef _lint
- return 0; /* No compiler warning */
-#endif
-} /* main */
-
-
-static struct my_option my_long_options[] =
-{
- {"analyze", 'a',
- "Analyze distribution of keys. Will make some joins in MySQL faster.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"character-sets-dir", OPT_CHARSETS_DIR_IC,
- "Directory where character sets are", (gptr*) &charsets_dir,
- (gptr*) &charsets_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#ifndef DBUG_OFF
- {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
-#endif
- {"default-character-set", 'C', "Set the default character set",
- (gptr*) &default_charset, (gptr*) &default_charset, 0, GET_STR,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"description", 'd', "Prints some information about table.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"extend-check", 'e',
- "Check the table VERY thoroughly. One need to use this only in extreme cases, because isamchk should normally find all errors even without this switch.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"information", 'i', "Print statistics information about the table",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"force", 'f',
- "Overwrite old temporary files. If one uses -f when checking tables (running isamchk without -r), isamchk will automatically restart with -r on any wrong table.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"help", '?', "Display this help and exit.", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
- 0, 0, 0, 0, 0},
- {"keys-used", 'k',
- "Used with '-r'. Tell ISAM to update only the first # keys. This can be used to get faster inserts!",
- (gptr*) &max_key, (gptr*) &max_key, 0, GET_UINT, REQUIRED_ARG, N_MAXKEY, 0,
- 0, 0, 0, 0},
- {"no-symlinks", 'l',
- "Do not follow symbolic links when repairing. Normally isamchk repairs the table a symlink points at.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"quick", 'q',
- "Used with -r to get a faster repair. (The data file isn't touched.) One can give a second '-q' to force isamchk to modify the original datafile.",
- (gptr*) &rep_quick, (gptr*) &rep_quick, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0,
- 0},
- {"recover", 'r',
- "Can fix almost anything except unique keys that aren't unique.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"safe-recover", 'o',
- "Uses old recovery method; slower than '-r' but can handle a couple of cases that '-r' cannot handle.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"set-variable", 'O',
- "Change the value of a variable. Please note that this option is deprecated; you can set variables directly with --variable-name=value.",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"block-search", 'b', "For debugging.", (gptr*) &search_after_block,
- (gptr*) &search_after_block, 0, GET_ULONG, REQUIRED_ARG,
- (longlong) NI_POS_ERROR, 0, 0, 0, 0, 0},
- {"silent", 's',
- "Only print errors. One can use two -s to make isamchk very silent.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"sort-index", 'S',
- "Sort index blocks. This speeds up 'read-next' in applications.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"sort-records", 'R',
- "Sort records according to an index. This makes your data much more localized and may speed up things (It may be VERY slow to do a sort the first time!)",
- (gptr*) &opt_sort_key, (gptr*) &opt_sort_key, 0, GET_UINT, REQUIRED_ARG,
- 0, 0, (N_MAXKEY - 1), 1, 0, 0},
- {"unpack", 'u', "Unpack file packed with pack_isam.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"verbose", 'v',
- "Print more information. This can be used with -d and -e. Use many -v for more verbosity!",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"version", 'V', "Print version and exit.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"wait", 'w', "Wait if table is locked.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"key_buffer_size", OPT_KEY_BUFFER_SIZE, "", (gptr*) &use_buffers,
- (gptr*) &use_buffers, 0, GET_ULONG, REQUIRED_ARG, (long) USE_BUFFER_INIT,
- (long) MALLOC_OVERHEAD, (long) ~0L, (long) MALLOC_OVERHEAD, (long) IO_SIZE,
- 0},
- {"read_buffer_size", OPT_READ_BUFFER_SIZE, "",
- (gptr*) &read_buffer_length, (gptr*) &read_buffer_length, 0, GET_ULONG,
- REQUIRED_ARG, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD,
- (long) ~0L, (long) MALLOC_OVERHEAD, (long) 1L, 0},
- {"write_buffer_size", OPT_WRITE_BUFFER_SIZE, "",
- (gptr*) &write_buffer_length, (gptr*) &write_buffer_length, 0, GET_ULONG,
- REQUIRED_ARG, (long) READ_BUFFER_INIT, (long) MALLOC_OVERHEAD, (long) ~0L,
- (long) MALLOC_OVERHEAD, (long) 1L, 0},
- {"sort_buffer_size", OPT_SORT_BUFFER_SIZE, "",
- (gptr*) &sort_buffer_length, (gptr*) &sort_buffer_length, 0, GET_ULONG,
- REQUIRED_ARG, (long) SORT_BUFFER_INIT,
- (long) (MIN_SORT_BUFFER + MALLOC_OVERHEAD), (long) ~0L,
- (long) MALLOC_OVERHEAD, (long) 1L, 0},
- {"sort_key_blocks", OPT_SORT_KEY_BLOCKS, "",
- (gptr*) &sort_key_blocks, (gptr*) &sort_key_blocks, 0, GET_ULONG,
- REQUIRED_ARG, BUFFERS_WHEN_SORTING, 4L, 100L, 0L, 1L, 0},
- {"decode_bits", OPT_DECODE_BITS, "",
- (gptr*) &decode_bits, (gptr*) &decode_bits, 0, GET_ULONG, REQUIRED_ARG,
- 9L, 4L, 17L, 0L, 1L, 0},
- {0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
-};
-
-#include <help_start.h>
-
-static void print_version(void)
-{
- printf("%s Ver 6.01 for %s at %s\n", my_progname, SYSTEM_TYPE,
- MACHINE_TYPE);
- NETWARE_SET_SCREEN_MODE(1);
-}
-
-
-static void usage(void)
-{
- print_version();
- puts("MySQL AB, by Monty, for your professional use");
- puts("This software comes with NO WARRANTY: see the PUBLIC for details.\n");
- puts("Description, check and repair of ISAM tables.");
- puts("Used without options all tables on the command will be checked for errors");
- printf("Usage: %s [OPTIONS] tables[.ISM]\n", my_progname);
- my_print_help(my_long_options);
- print_defaults("my", load_default_groups);
- my_print_variables(my_long_options);
-}
-
-#include <help_end.h>
-
- /* Check table */
-
-static int nisamchk(my_string filename)
-{
- int error,lock_type,recreate;
- N_INFO *info;
- File datafile;
- char fixed_name[FN_REFLEN];
- ISAM_SHARE *share;
- DBUG_ENTER("nisamchk");
-
- out_flag=error=warning_printed=error_printed=recreate=0;
- datafile=0;
- isam_file_name=filename; /* For error messages */
- if (!(info=nisam_open(filename,
- (testflag & T_DESCRIPT) ? O_RDONLY : O_RDWR,
- (testflag & T_WAIT_FOREVER) ? HA_OPEN_WAIT_IF_LOCKED :
- (testflag & T_DESCRIPT) ? HA_OPEN_IGNORE_IF_LOCKED :
- HA_OPEN_ABORT_IF_LOCKED)))
- {
- /* Avoid twice printing of isam file name */
- error_printed=1;
- switch (my_errno) {
- case HA_ERR_CRASHED:
- print_error("'%s' is not a ISAM-table",filename);
- break;
- case HA_ERR_OLD_FILE:
- print_error("'%s' is a old type of ISAM-table", filename);
- break;
- case HA_ERR_END_OF_FILE:
- print_error("Couldn't read compleat header from '%s'", filename);
- break;
- case EAGAIN:
- print_error("'%s' is locked. Use -w to wait until unlocked",filename);
- break;
- case ENOENT:
- print_error("File '%s' doesn't exist",filename);
- break;
- case EACCES:
- print_error("You don't have permission to use '%s'",filename);
- break;
- default:
- print_error("%d when opening ISAM-table '%s'",
- my_errno,filename);
- break;
- }
- DBUG_RETURN(1);
- }
- share=info->s;
- share->base.options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */
- share->r_locks=0;
- if ((testflag & (T_REP_BY_SORT | T_REP | T_STATISTICS |
- T_SORT_RECORDS | T_SORT_INDEX)) &&
- ((testflag & T_UNPACK && share->data_file_type == COMPRESSED_RECORD) ||
- share->state_length != sizeof(share->state) ||
- uint2korr(share->state.header.base_info_length) !=
- sizeof(share->base) ||
- (max_key && ! share->state.keys && share->base.keys) ||
- test_if_almost_full(info) ||
- info->s->state.header.file_version[3] != nisam_file_magic[3]))
- {
- if (recreate_database(&info,filename))
- {
- VOID(fprintf(stderr,
- "ISAM-table '%s' is not fixed because of errors\n",
- filename));
- return(-1);
- }
- recreate=1;
- if (!(testflag & (T_REP | T_REP_BY_SORT)))
- {
- testflag|=T_REP_BY_SORT; /* if only STATISTICS */
- if (!(testflag & T_SILENT))
- printf("- '%s' has old table-format. Recreating index\n",filename);
- if (!rep_quick)
- rep_quick=1;
- }
- share=info->s;
- share->r_locks=0;
- }
-
- if (testflag & T_DESCRIPT)
- {
- total_files++;
- total_records+=share->state.records; total_deleted+=share->state.del;
- descript(info,filename);
- }
- else
- {
- if (testflag & (T_REP+T_REP_BY_SORT+T_OPT+T_SORT_RECORDS+T_SORT_INDEX))
- lock_type = F_WRLCK; /* table is changed */
- else
- lock_type= F_RDLCK;
- if (info->lock_type == F_RDLCK)
- info->lock_type=F_UNLCK; /* Read only table */
- if (_nisam_readinfo(info,lock_type,0))
- {
- print_error("Can't lock indexfile of '%s', error: %d",
- filename,my_errno);
- error_printed=0;
- goto end2;
- }
- share->w_locks++; /* Mark (for writeinfo) */
- if (lock_file(info->dfile,0L,lock_type,"datafile of",filename))
- goto end;
- info->lock_type= F_EXTRA_LCK; /* Simulate as locked */
- info->tmp_lock_type=lock_type;
- datafile=info->dfile;
- if (testflag & (T_REP+T_REP_BY_SORT+T_SORT_RECORDS+T_SORT_INDEX))
- {
- if (testflag & (T_REP+T_REP_BY_SORT))
- share->state.keys=min(share->base.keys,max_key);
- VOID(fn_format(fixed_name,filename,"",N_NAME_IEXT,
- 4+ (opt_follow_links ? 16 : 0)));
-
- if (rep_quick && (error=chk_del(info,testflag & ~T_VERBOSE)))
- print_error("Quick-recover aborted; Run recovery without switch 'q'");
- else
- {
- if (testflag & T_REP_BY_SORT &&
- (share->state.keys || (rep_quick && !max_key && ! recreate)))
- error=rep_by_sort(info,fixed_name);
- else if (testflag & (T_REP | T_REP_BY_SORT))
- error=rep(info,fixed_name);
- }
- if (!error && testflag & T_SORT_RECORDS)
- {
- if (out_flag & O_NEW_DATA)
- { /* Change temp file to org file */
- VOID(lock_file(datafile,0L,F_UNLCK,"datafile of",filename));
- VOID(my_close(datafile,MYF(MY_WME))); /* Close old file */
- VOID(my_close(info->dfile,MYF(MY_WME))); /* Close new file */
- error|=change_to_newfile(fixed_name,N_NAME_DEXT,DATA_TMP_EXT);
- if ((info->dfile=my_open(fn_format(temp_filename,fixed_name,"",
- N_NAME_DEXT,2+4),
- O_RDWR | O_SHARE,
- MYF(MY_WME))) <= 0 ||
- lock_file(info->dfile,0L,F_WRLCK,"datafile",temp_filename))
- error=1;
- out_flag&= ~O_NEW_DATA; /* We are using new datafile */
- read_cache.file=info->dfile;
- }
- if (! error)
- error=sort_records(info,fixed_name,opt_sort_key,
- test(!(testflag & T_REP)));
- datafile=info->dfile; /* This is now locked */
- }
- if (!error && testflag & T_SORT_INDEX)
- error=sort_index(info,fixed_name);
- }
- else
- {
- if (!(testflag & T_SILENT) || testflag & T_INFO)
- printf("Checking ISAM file: %s\n",filename);
- if (!(testflag & T_SILENT))
- printf("Data records: %7ld Deleted blocks: %7ld\n",
- share->state.records,share->state.del);
- share->state.keys=min(share->state.keys,max_key);
- error =chk_size(info);
- error|=chk_del(info,testflag);
- error|=chk_key(info);
- if (!rep_quick)
- {
- if (testflag & T_EXTEND)
- VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,
- use_buffers,0,0));
- VOID(init_io_cache(&read_cache,datafile,(uint) read_buffer_length,
- READ_CACHE,share->pack.header_length,1,
- MYF(MY_WME)));
- lock_memory();
- error|=chk_data_link(info,testflag & T_EXTEND);
- error|=flush_blocks(share->kfile);
- VOID(end_io_cache(&read_cache));
- }
- }
- }
-end:
- if (!(testflag & T_DESCRIPT))
- {
- if (info->update & (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED))
- error|=update_state_info(info,
- ((testflag & (T_REP | T_REP_BY_SORT)) ?
- UPDATE_TIME | UPDATE_STAT : 0) |
- ((testflag & T_SORT_RECORDS) ?
- UPDATE_SORT : 0));
- VOID(lock_file(share->kfile,0L,F_UNLCK,"indexfile",filename));
- if (datafile > 0)
- VOID(lock_file(datafile,0L,F_UNLCK,"datafile of",filename));
- info->update&= ~(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- }
- share->w_locks--;
-end2:
- if (datafile && datafile != info->dfile)
- VOID(my_close(datafile,MYF(MY_WME)));
- if (nisam_close(info))
- {
- print_error("%d when closing ISAM-table '%s'",my_errno,filename);
- DBUG_RETURN(1);
- }
- if (error == 0)
- {
- if (out_flag & O_NEW_DATA)
- error|=change_to_newfile(fixed_name,N_NAME_DEXT,DATA_TMP_EXT);
- if (out_flag & O_NEW_INDEX)
- error|=change_to_newfile(fixed_name,N_NAME_IEXT,INDEX_TMP_EXT);
- }
- VOID(fflush(stdout)); VOID(fflush(stderr));
- if (error_printed)
- {
- if (testflag & (T_REP+T_REP_BY_SORT+T_SORT_RECORDS+T_SORT_INDEX))
- VOID(fprintf(stderr,
- "ISAM-table '%s' is not fixed because of errors\n",
- filename));
- else if (! (error_printed & 2) && !(testflag & T_FORCE_CREATE))
- VOID(fprintf(stderr,
- "ISAM-table '%s' is corrupted\nFix it using switch \"-r\" or \"-o\"\n",
- filename));
- }
- else if (warning_printed &&
- ! (testflag & (T_REP+T_REP_BY_SORT+T_SORT_RECORDS+T_SORT_INDEX+
- T_FORCE_CREATE)))
- VOID(fprintf(stderr, "ISAM-table '%s' is useable but should be fixed\n",
- filename));
- VOID(fflush(stderr));
- DBUG_RETURN(error);
-} /* nisamchk */
-
-
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-
-{
- switch(optid) {
- case 'a':
- testflag|= T_STATISTICS;
- break;
- case 's': /* silent */
- if (testflag & T_SILENT)
- testflag|=T_VERY_SILENT;
- testflag|= T_SILENT;
- testflag&= ~T_WRITE_LOOP;
- break;
- case 'w':
- testflag|= T_WAIT_FOREVER;
- break;
- case 'd': /* description if isam-file */
- testflag|= T_DESCRIPT;
- break;
- case 'e': /* extend check */
- testflag|= T_EXTEND;
- break;
- case 'i':
- testflag|= T_INFO;
- break;
- case 'f':
- tmpfile_createflag= O_RDWR | O_TRUNC;
- testflag|=T_FORCE_CREATE;
- break;
- case 'l':
- opt_follow_links=0;
- break;
- case 'r': /* Repair table */
- testflag= (testflag & ~T_REP) | T_REP_BY_SORT;
- break;
- case 'o':
- testflag= (testflag & ~T_REP_BY_SORT) | T_REP;
- my_disable_async_io=1; /* More safety */
- break;
- case 'u':
- testflag|= T_UNPACK | T_REP_BY_SORT;
- break;
- case 'v': /* Verbose */
- testflag|= T_VERBOSE;
- verbose++;
- break;
- case 'R': /* Sort records */
- testflag|= T_SORT_RECORDS;
- if (opt_sort_key >= N_MAXKEY)
- {
- fprintf(stderr,
- "The value of the sort key is bigger than max key: %d.\n",
- N_MAXKEY);
- exit(1);
- }
- break;
- case 'S': /* Sort index */
- testflag|= T_SORT_INDEX;
- break;
- case '#':
- DBUG_PUSH(argument ? argument : "d:t:o,/tmp/isamchk.trace");
- break;
- case 'V':
- print_version();
- exit(0);
- case '?':
- usage();
- exit(0);
- }
- return 0;
-}
-
- /* Read options */
-
-static void get_options(register int *argc, register char ***argv)
-{
- int ho_error;
-
- load_defaults("my",load_default_groups,argc,argv);
- defaults_alloc= *argv;
- if (isatty(fileno(stdout)))
- testflag|=T_WRITE_LOOP;
-
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
- exit(ho_error);
-
- if (*argc == 0)
- {
- usage();
- exit(-1);
- }
- if ((testflag & T_UNPACK) && (rep_quick || (testflag & T_SORT_RECORDS)))
- {
- VOID(fprintf(stderr,
- "%s: --unpack can't be used with --quick or --sort-records\n",
- my_progname));
- exit(1);
- }
- if (default_charset)
- {
- if (!(default_charset_info= get_charset_by_name(default_charset, MYF(MY_WME))))
- exit(1);
- }
- return;
-} /* get options */
-
-
- /* Check delete links */
-
-static int chk_del( reg1 N_INFO *info, uint test_flag)
-{
- reg2 ulong i;
- uint j,delete_link_length;
- ulong empty,next_link;
- uchar buff[8];
- DBUG_ENTER("chk_del");
- if (!(test_flag & T_SILENT)) puts("- check delete-chain");
-
- record_checksum=0L;
- key_file_blocks=info->s->base.keystart;
- for (j =0 ; j < info->s->state.keys ; j++)
- if (check_k_link(info,j))
- goto wrong;
- delete_link_length=(info->s->base.options & HA_OPTION_PACK_RECORD) ? 8 : 5;
-
- next_link=info->s->state.dellink;
- if (info->s->state.del == 0)
- {
- if (test_flag & T_VERBOSE)
- {
- puts("No recordlinks");
- }
- }
- else
- {
- if (test_flag & T_VERBOSE)
- printf("Recordlinks: ");
- empty=0;
- for (i= info->s->state.del ; i > 0L && next_link != NI_POS_ERROR ; i--)
- {
- if (test_flag & T_VERBOSE) printf("%10lu",next_link);
- if (next_link >= info->s->state.data_file_length)
- goto wrong;
- if (my_pread(info->dfile,(char*) buff,delete_link_length,
- next_link,MYF(MY_NABP)))
- {
- if (test_flag & T_VERBOSE) puts("");
- print_error("Can't read delete-link at filepos: %lu",
- (ulong) next_link);
- DBUG_RETURN(1);
- }
- if (*buff != '\0')
- {
- if (test_flag & T_VERBOSE) puts("");
- print_error("Record at pos: %lu is not remove-marked",
- (ulong) next_link);
- goto wrong;
- }
- if (info->s->base.options & HA_OPTION_PACK_RECORD)
- {
- next_link=uint4korr(buff+4);
- empty+=uint3korr(buff+1);
- }
- else
- {
- record_checksum+=next_link;
- next_link=uint4korr(buff+1);
- empty+=info->s->base.reclength;
- }
- if (next_link == (uint32) ~0) /* Fix for 64 bit long */
- next_link=NI_POS_ERROR;
- }
- if (empty != info->s->state.empty)
- {
- if (test_flag & T_VERBOSE) puts("");
- print_warning("Not used space is supposed to be: %lu but is: %lu",
- (ulong) info->s->state.empty,(ulong) empty);
- info->s->state.empty=empty;
- }
- if (i != 0 || next_link != NI_POS_ERROR)
- goto wrong;
-
- if (test_flag & T_VERBOSE) puts("\n");
- }
- DBUG_RETURN(0);
-wrong:
- if (test_flag & T_VERBOSE) puts("");
- print_error("delete-link-chain corrupted");
- DBUG_RETURN(1);
-} /* chk_del */
-
-
- /* Kontrollerar l{nkarna i nyckelfilen */
-
-static int check_k_link( register N_INFO *info, uint nr)
-{
- ulong next_link,records;
- DBUG_ENTER("check_k_link");
-
- if (testflag & T_VERBOSE)
- printf("index %2d: ",nr+1);
-
- next_link=info->s->state.key_del[nr];
- records= (info->s->state.key_file_length /
- info->s->keyinfo[nr].base.block_length);
- while (next_link != NI_POS_ERROR && records > 0)
- {
- if (testflag & T_VERBOSE) printf("%10lu",next_link);
- if (next_link > info->s->state.key_file_length ||
- next_link & (info->s->blocksize-1))
- DBUG_RETURN(1);
- if (my_pread(info->s->kfile,(char*) &next_link,sizeof(long),next_link,
- MYF(MY_NABP)))
- DBUG_RETURN(1);
- records--;
- key_file_blocks+=info->s->keyinfo[nr].base.block_length;
- }
- if (testflag & T_VERBOSE)
- {
- if (next_link != NI_POS_ERROR)
- printf("%10lu\n",next_link);
- else
- puts("");
- }
- DBUG_RETURN (next_link != NI_POS_ERROR);
-} /* check_k_link */
-
-
- /* Kontrollerar storleken p} filerna */
-
-static int chk_size(register N_INFO *info)
-{
- int error=0;
- register my_off_t skr,size;
- DBUG_ENTER("chk_size");
-
- if (!(testflag & T_SILENT)) puts("- check file-size");
-
- size=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
- if ((skr=(my_off_t) info->s->state.key_file_length) != size)
- {
- if (skr > size)
- {
- error=1;
- print_error("Size of indexfile is: %-8lu Should be: %lu",
- (ulong) size, (ulong) skr);
- }
- else
- print_warning("Size of indexfile is: %-8lu Should be: %lu",
- (ulong) size,(ulong) skr);
- }
- if (!(testflag & T_VERY_SILENT) &&
- ! (info->s->base.options & HA_OPTION_COMPRESS_RECORD) &&
- info->s->state.key_file_length >
- (ulong) (ulong_to_double(info->s->base.max_key_file_length)*0.9))
- print_warning("Keyfile is almost full, %10lu of %10lu used",
- info->s->state.key_file_length,
- info->s->base.max_key_file_length-1);
-
- size=my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
- skr=(my_off_t) info->s->state.data_file_length;
- if (info->s->base.options & HA_OPTION_COMPRESS_RECORD)
- skr+= MEMMAP_EXTRA_MARGIN;
-#ifdef USE_RELOC
- if (info->data_file_type == STATIC_RECORD &&
- skr < (my_off_t) info->s->base.reloc*info->s->base.min_pack_length)
- skr=(my_off_t) info->s->base.reloc*info->s->base.min_pack_length;
-#endif
- if (skr != size)
- {
- info->s->state.data_file_length=(ulong) size; /* Skip other errors */
- if (skr > size && skr != size + MEMMAP_EXTRA_MARGIN)
- {
- error=1;
- print_error("Size of datafile is: %-8lu Should be: %lu",
- (ulong) size,(ulong) skr);
- }
- else
- {
- print_warning("Size of datafile is: %-8lu Should be: %lu",
- (ulong) size,(ulong) skr);
-
- }
- }
- if (!(testflag & T_VERY_SILENT) &&
- !(info->s->base.options & HA_OPTION_COMPRESS_RECORD) &&
- info->s->state.data_file_length >
- (ulong) (ulong_to_double(info->s->base.max_data_file_length)*0.9))
- print_warning("Datafile is almost full, %10lu of %10lu used",
- info->s->state.data_file_length,
- info->s->base.max_data_file_length-1);
- DBUG_RETURN(error);
-} /* chk_size */
-
-
- /* Kontrollerar nycklarna */
-
-static int chk_key( register N_INFO *info)
-{
- uint key;
- ulong keys,all_keydata,all_totaldata,key_totlength,length,
- init_checksum,old_record_checksum;
- ISAM_SHARE *share=info->s;
- N_KEYDEF *keyinfo;
- DBUG_ENTER("chk_key");
-
- if (!(testflag & T_SILENT)) puts("- check index reference");
-
- all_keydata=all_totaldata=key_totlength=old_record_checksum=0;
- init_checksum=record_checksum;
- if (!(share->base.options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
- old_record_checksum=calc_checksum(share->state.records+share->state.del-1)*
- share->base.reclength;
- for (key= 0,keyinfo= &share->keyinfo[0]; key < share->state.keys ;
- key++,keyinfo++)
- {
- record_checksum=init_checksum;
- unique_count=0L;
- if ((!(testflag & T_SILENT)) && share->state.keys >1)
- printf ("- check data record references index: %d\n",key+1);
- if (share->state.key_root[key] == NI_POS_ERROR &&
- share->state.records == 0)
- continue;
- if (!_nisam_fetch_keypage(info,keyinfo,share->state.key_root[key],info->buff,
- 0))
- {
- print_error("Can't read indexpage from filepos: %lu",
- (ulong) share->state.key_root[key]);
- DBUG_RETURN(-1);
- }
- key_file_blocks+=keyinfo->base.block_length;
- keys=keydata=totaldata=key_blocks=0; max_level=0;
- if (chk_index(info,keyinfo,share->state.key_root[key],info->buff,&keys,1))
- DBUG_RETURN(-1);
- if (keys != share->state.records)
- {
- print_error("Found %lu keys of %lu",(ulong) keys,
- (ulong) share->state.records);
- DBUG_RETURN(-1);
- }
- if (!key && (share->base.options &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)))
- old_record_checksum=record_checksum;
- else if (old_record_checksum != record_checksum)
- {
- if (key)
- print_error("Key %u doesn't point at same records that key 1",
- key+1);
- else
- print_error("Key 1 doesn't point at all records");
- DBUG_RETURN(-1);
- }
- length=(ulong) isam_key_length(info,keyinfo)*keys + key_blocks*2;
- if (testflag & T_INFO && totaldata != 0L && keys != 0L)
- printf("Key: %2d: Keyblocks used: %3d%% Packed: %4d%% Max levels: %2d\n",
- key+1,
- (int) (keydata*100.0/totaldata),
- (int) ((long) (length-keydata)*100.0/(double) length),
- max_level);
- all_keydata+=keydata; all_totaldata+=totaldata; key_totlength+=length;
- share->base.rec_per_key[key]=
- unique_count ? ((share->state.records+unique_count/2)/
- unique_count) : 1L;
- }
- if (testflag & T_INFO)
- {
- if (all_totaldata != 0L && share->state.keys != 1)
- printf("Total: Keyblocks used: %3d%% Packed: %4d%%\n\n",
- (int) (all_keydata*100.0/all_totaldata),
- (int) ((long) (key_totlength-all_keydata)*100.0/
- (double) key_totlength));
- else if (all_totaldata != 0L && share->state.keys)
- puts("");
- }
- if (key_file_blocks != share->state.key_file_length)
- print_warning("Some data are unreferenced in keyfile");
- record_checksum-=init_checksum; /* Remove delete links */
- if (testflag & T_STATISTICS)
- DBUG_RETURN(update_state_info(info,UPDATE_STAT));
- DBUG_RETURN(0);
-} /* chk_key */
-
-
- /* Check if index is ok */
-
-static int chk_index(N_INFO *info, N_KEYDEF *keyinfo, ulong page, uchar *buff,
- ulong *keys,uint level)
-{
- int flag;
- uint used_length,comp_flag,nod_flag;
- uchar key[N_MAX_POSSIBLE_KEY_BUFF],*temp_buff,*keypos,*endpos;
- ulong next_page,record;
- DBUG_ENTER("chk_index");
- DBUG_DUMP("buff",(byte*) buff,getint(buff));
-
- if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length)))
- {
- print_error("Not Enough memory");
- DBUG_RETURN(-1);
- }
-
- if (keyinfo->base.flag & HA_NOSAME)
- comp_flag=SEARCH_FIND; /* Not dupplicates */
- else
- comp_flag=SEARCH_SAME; /* Keys in positionorder */
- nod_flag=test_if_nod(buff);
- used_length=getint(buff);
- keypos=buff+2+nod_flag;
- endpos=buff+used_length;
-
- keydata+=used_length; totaldata+=keyinfo->base.block_length; /* INFO */
- key_blocks++;
- if (level > max_level)
- max_level=level;
-
- if (used_length > keyinfo->base.block_length)
- {
- print_error("Wrong pageinfo at page: %lu",(ulong) page);
- goto err;
- }
- for ( ;; )
- {
- if (nod_flag)
- {
- next_page=_nisam_kpos(nod_flag,keypos);
- if (next_page > info->s->state.key_file_length ||
- (nod_flag && (next_page & (info->s->blocksize -1))))
- {
- my_off_t max_length=my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0));
- print_error("Wrong pagepointer: %lu at page: %lu",
- (ulong) next_page,(ulong) page);
-
- if (next_page+info->s->blocksize > max_length)
- goto err;
- info->s->state.key_file_length=(ulong) (max_length &
- ~ (my_off_t)
- (info->s->blocksize-1));
- }
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,temp_buff,0))
- {
- print_error("Can't read key from filepos: %lu",(ulong) next_page);
- goto err;
- }
- key_file_blocks+=keyinfo->base.block_length;
- if (chk_index(info,keyinfo,next_page,temp_buff,keys,level+1))
- goto err;
- }
- if (keypos >= endpos ||
- (*keyinfo->get_key)(keyinfo,nod_flag,&keypos,key) == 0)
- break;
- if ((*keys)++ &&
- (flag=_nisam_key_cmp(keyinfo->seg,info->lastkey,key,0,comp_flag)) >=0)
- {
- DBUG_DUMP("old",(byte*) info->lastkey,
- _nisam_keylength(keyinfo,info->lastkey));
- DBUG_DUMP("new",(byte*) key,_nisam_keylength(keyinfo,key));
-
- if (comp_flag == SEARCH_FIND && flag == 0)
- print_error("Found dupplicated key at page %lu",(ulong) page);
- else
- print_error("Key in wrong position at page %lu",(ulong) page);
- goto err;
- }
- if (testflag & T_STATISTICS)
- {
- if (*keys == 1L ||
- _nisam_key_cmp(keyinfo->seg,info->lastkey,key,0,SEARCH_FIND))
- unique_count++;
- }
- VOID(_nisam_move_key(keyinfo,(uchar*) info->lastkey,key));
- record= _nisam_dpos(info,nod_flag,keypos);
- if (record >= info->s->state.data_file_length)
- {
- print_error("Found key at page %lu that points to record outside datafile",page);
- DBUG_PRINT("test",("page: %lu record: %lu filelength: %lu",
- (ulong) page,(ulong) record,
- (ulong) info->s->state.data_file_length));
- DBUG_DUMP("key",(byte*) info->lastkey,info->s->base.max_key_length);
- goto err;
- }
- record_checksum+=record;
- }
- if (keypos != endpos)
- {
- print_error("Keyblock size at page %lu is not correct. Block length: %d key length: %d",(ulong) page, used_length, (keypos - buff));
- goto err;
- }
- my_afree((byte*) temp_buff);
- DBUG_RETURN(0);
- err:
- my_afree((byte*) temp_buff);
- DBUG_RETURN(1);
-} /* chk_index */
-
-
- /* Calculate a checksum of 1+2+3+4...N = N*(N+1)/2 without overflow */
-
-static ulong calc_checksum(count)
-ulong count;
-{
- ulong sum,a,b;
- DBUG_ENTER("calc_checksum");
-
- sum=0;
- a=count; b=count+1;
- if (a & 1)
- b>>=1;
- else
- a>>=1;
- while (b)
- {
- if (b & 1)
- sum+=a;
- a<<=1; b>>=1;
- }
- DBUG_PRINT("exit",("sum: %lx",sum));
- DBUG_RETURN(sum);
-} /* calc_checksum */
-
-
- /* Calc length of key in normal isam */
-
-static uint isam_key_length( N_INFO *info, reg1 N_KEYDEF *keyinfo)
-{
- uint length;
- N_KEYSEG *keyseg;
- DBUG_ENTER("isam_key_length");
-
- length= info->s->rec_reflength;
- for (keyseg=keyinfo->seg ; keyseg->base.type ; keyseg++)
- length+= keyseg->base.length;
-
- DBUG_PRINT("exit",("length: %d",length));
- DBUG_RETURN(length);
-} /* key_length */
-
-
- /* Check that record-link is ok */
-
-static int chk_data_link(info,extend)
-reg1 N_INFO *info;
-int extend;
-{
- int error,got_error,flag;
- uint key,left_length,b_type;
- ulong records,del_blocks,used,empty,pos,splitts,start_recpos,
- del_length,link_used,intern_record_checksum,start_block;
- byte *record,*to;
- N_KEYDEF *keyinfo;
- BLOCK_INFO block_info;
- DBUG_ENTER("chk_data_link");
-
- if (! (info->s->base.options & (HA_OPTION_PACK_RECORD |
- HA_OPTION_COMPRESS_RECORD)) &&
- ! extend)
- DBUG_RETURN(0);
-
- if (!(testflag & T_SILENT))
- {
- if (extend)
- puts("- check records and index references");
- else
- puts("- check record links");
- }
-
- if (!(record= (byte*) my_alloca(info->s->base.reclength)))
- {
- print_error("Not Enough memory");
- DBUG_RETURN(-1);
- }
- records=used=link_used=splitts=del_blocks=del_length=
- intern_record_checksum=crc=0L;
- LINT_INIT(left_length); LINT_INIT(start_recpos); LINT_INIT(to);
- got_error=error=0;
- empty=pos=info->s->pack.header_length;
-
- while (pos < info->s->state.data_file_length)
- {
- switch (info->s->data_file_type) {
- case STATIC_RECORD:
- if (my_b_read(&read_cache,(byte*) record,info->s->base.reclength))
- goto err;
- start_recpos=pos;
- pos+=info->s->base.reclength;
- splitts++;
- if (*record == '\0')
- {
- del_blocks++;
- del_length+=info->s->base.reclength;
- continue; /* Record removed */
- }
- used+=info->s->base.reclength;
- break;
- case DYNAMIC_RECORD:
- flag=block_info.second_read=0;
- block_info.next_filepos=pos;
- do
- {
- if (_nisam_read_cache(&read_cache,(byte*) block_info.header,
- (start_block=block_info.next_filepos),
- sizeof(block_info.header),test(! flag) | 2))
- goto err;
- b_type=_nisam_get_block_info(&block_info,-1,start_block);
- if (b_type & (BLOCK_DELETED | BLOCK_ERROR | BLOCK_SYNC_ERROR |
- BLOCK_FATAL_ERROR))
- {
- if (b_type & BLOCK_SYNC_ERROR)
- {
- if (flag)
- {
- print_error("Unexpected byte: %d at link: %lu",
- (int) block_info.header[0],(ulong) start_block);
- goto err2;
- }
- pos=block_info.filepos+block_info.block_len;
- goto next;
- }
- if (b_type & BLOCK_DELETED)
- {
- if (block_info.block_len < info->s->base.min_block_length ||
- block_info.block_len-4 > (uint) info->s->base.max_pack_length)
- {
- print_error("Deleted block with impossible length %u at %lu",
- block_info.block_len,(ulong) pos);
- goto err2;
- }
- del_blocks++;
- del_length+=block_info.block_len;
- pos=block_info.filepos+block_info.block_len;
- splitts++;
- goto next;
- }
- print_error("Wrong bytesec: %d-%d-%d at linkstart: %lu",
- block_info.header[0],block_info.header[1],
- block_info.header[2],(ulong) start_block);
- goto err2;
- }
- if (info->s->state.data_file_length < block_info.filepos+
- block_info.block_len)
- {
- print_error("Recordlink that points outside datafile at %lu",
- (ulong) pos);
- got_error=1;
- break;
- }
- splitts++;
- if (!flag++) /* First block */
- {
- start_recpos=pos;
- pos=block_info.filepos+block_info.block_len;
- if (block_info.rec_len > (uint) info->s->base.max_pack_length)
- {
- print_error("Found too long record at %lu",(ulong) start_recpos);
- got_error=1;
- break;
- }
- if (info->s->base.blobs)
- {
- if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
- {
- print_error("Not enough memory for blob at %lu",
- (ulong) start_recpos);
- got_error=1;
- break;
- }
- }
- else
- to= info->rec_buff;
- left_length=block_info.rec_len;
- }
- if (left_length < block_info.data_len)
- {
- print_error("Found too long record at %lu",(ulong) start_recpos);
- got_error=1; break;
- }
- if (_nisam_read_cache(&read_cache,(byte*) to,block_info.filepos,
- (uint) block_info.data_len, test(flag == 1)))
- goto err;
- to+=block_info.data_len;
- link_used+= block_info.filepos-start_block;
- used+= block_info.filepos - start_block + block_info.data_len;
- empty+=block_info.block_len-block_info.data_len;
- left_length-=block_info.data_len;
- if (left_length)
- {
- if (b_type & BLOCK_LAST)
- {
- print_error("Record link to short for record at %lu",
- (ulong) start_recpos);
- got_error=1;
- break;
- }
- if (info->s->state.data_file_length < block_info.next_filepos)
- {
- print_error("Found next-recordlink that points outside datafile at %lu",
- (ulong) block_info.filepos);
- got_error=1;
- break;
- }
- }
- } while (left_length);
- if (! got_error)
- {
- if (_nisam_rec_unpack(info,record,info->rec_buff,block_info.rec_len) ==
- MY_FILE_ERROR)
- {
- print_error("Found wrong record at %lu",(ulong) start_recpos);
- got_error=1;
- }
- if (testflag & (T_EXTEND | T_VERBOSE))
- {
- if (_nisam_rec_check(info,record))
- {
- print_error("Found wrong packed record at %lu",
- (ulong) start_recpos);
- got_error=1;
- }
- }
- }
- else if (!flag)
- pos=block_info.filepos+block_info.block_len;
- break;
- case COMPRESSED_RECORD:
- if (_nisam_read_cache(&read_cache,(byte*) block_info.header,pos, 3,1))
- goto err;
- start_recpos=pos;
- splitts++;
- VOID(_nisam_pack_get_block_info(&block_info,info->s->pack.ref_length,-1,
- start_recpos));
- pos=start_recpos+info->s->pack.ref_length+block_info.rec_len;
- if (block_info.rec_len < (uint) info->s->min_pack_length ||
- block_info.rec_len > (uint) info->s->max_pack_length)
- {
- print_error("Found block with wrong recordlength: %d at %lu",
- block_info.rec_len,(ulong) start_recpos);
- got_error=1;
- break;
- }
- if (_nisam_read_cache(&read_cache,(byte*) info->rec_buff,
- block_info.filepos, block_info.rec_len,1))
- goto err;
- if (_nisam_pack_rec_unpack(info,record,info->rec_buff,block_info.rec_len))
- {
- print_error("Found wrong record at %lu",(ulong) start_recpos);
- got_error=1;
- }
- crc^=_nisam_checksum(record,info->s->base.reclength);
- link_used+=info->s->pack.ref_length;
- used+=block_info.rec_len+info->s->pack.ref_length;
- }
- if (! got_error)
- {
- intern_record_checksum+=start_recpos;
- records++;
- if (testflag & T_WRITE_LOOP && records % WRITE_COUNT == 0)
- {
- printf("%lu\r",(ulong) records); VOID(fflush(stdout));
- }
-
- if (extend)
- {
- for (key=0,keyinfo= info->s->keyinfo; key<info->s->state.keys;
- key++,keyinfo++)
- {
- VOID(_nisam_make_key(info,key,info->lastkey,record,start_recpos));
- if (_nisam_search(info,keyinfo,info->lastkey,0,SEARCH_SAME,
- info->s->state.key_root[key]))
- {
- print_error("Record at: %10lu Can't find key for index: %2d",
- start_recpos,key+1);
- if (error++ > MAXERR || !(testflag & T_VERBOSE))
- goto err2;
- }
- }
- }
- }
- else
- {
- got_error=0;
- if (error++ > MAXERR || !(testflag & T_VERBOSE))
- goto err2;
- }
- next:; /* Next record */
- }
- if (testflag & T_WRITE_LOOP)
- {
- VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
- }
- if (records != info->s->state.records)
- {
- print_error("Record-count is not ok; is %-10lu Should be: %lu",
- (ulong) records,(ulong) info->s->state.records);
- error=1;
- }
- else if (record_checksum != intern_record_checksum && info->s->state.keys)
- {
- print_error("Keypointers and records don't match");
- error=1;
- }
- if (used+empty+del_length != info->s->state.data_file_length)
- {
- print_warning("Found %lu record-data and %lu unused data and %lu deleted-data\nTotal %lu, Should be: %lu",
- (ulong) used,(ulong) empty,(ulong) del_length,
- (ulong) (used+empty+del_length),
- (ulong) info->s->state.data_file_length);
- }
- if (del_blocks != info->s->state.del)
- {
- print_warning("Found %10lu deleted blocks Should be: %lu",
- (ulong) del_blocks,(ulong) info->s->state.del);
- }
- if (splitts != info->s->state.splitt)
- {
- print_warning("Found %10lu parts Should be: %lu parts",
- (ulong) splitts,(ulong) info->s->state.splitt);
- }
- if ((info->s->base.options & HA_OPTION_COMPRESS_RECORD) &&
- crc != info->s->state.uniq)
- print_warning("Wrong checksum for records; Restore uncompressed table");
-
- if (testflag & T_INFO)
- {
- if (warning_printed || error_printed)
- puts("");
- if (used != 0 && ! error_printed)
- {
- printf("Records:%17lu M.recordlength:%8lu Packed:%14.0f%%\n",
- records, (used-link_used)/records,
- (info->s->base.blobs ? 0 :
- (ulong_to_double(info->s->base.reclength*records)-used)/
- ulong_to_double(info->s->base.reclength*records)*100.0));
- printf("Recordspace used:%8.0f%% Empty space:%11d%% Blocks/Record: %6.2f\n",
- (ulong_to_double(used-link_used)/ulong_to_double(used-link_used+empty)*100.0),
- (!records ? 100 : (int) (ulong_to_double(del_length+empty)/used*100.0)),
- ulong_to_double(splitts - del_blocks) / records);
- }
- printf("Record blocks:%12lu Delete blocks:%10lu\n",
- splitts-del_blocks,del_blocks);
- printf("Record data: %12lu Deleted data :%10lu\n",
- used-link_used,del_length);
- printf("Lost space: %12lu Linkdata: %10lu\n",
- empty,link_used);
- }
- my_afree((gptr) record);
- DBUG_RETURN (error);
- err:
- print_error("got error: %d when reading datafile",my_errno);
- err2:
- my_afree((gptr) record);
- DBUG_RETURN(1);
-} /* chk_data_link */
-
-
- /* Recover old table by reading each record and writing all keys */
- /* Save new datafile-name in temp_filename */
-
-static int rep(info,name)
-reg1 N_INFO *info;
-my_string name;
-{
- int error,got_error;
- uint i;
- ulong start_records,new_header_length,del;
- File new_file;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("rep");
-
- start_records=share->state.records;
- new_header_length=(testflag & T_UNPACK) ? 0L : share->pack.header_length;
- got_error=1;
- new_file= -1;
- if (!(testflag & T_SILENT))
- {
- printf("- recovering ISAM-table '%s'\n",name);
- printf("Data records: %lu\n",(ulong) share->state.records);
- }
-
- VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,use_buffers,0,0));
- if (init_io_cache(&read_cache,info->dfile,(uint) read_buffer_length,
- READ_CACHE,share->pack.header_length,1,MYF(MY_WME)))
- goto err;
- if (!rep_quick)
- if (init_io_cache(&info->rec_cache,-1,(uint) write_buffer_length,
- WRITE_CACHE, new_header_length, 1,
- MYF(MY_WME | MY_WAIT_IF_FULL)))
- goto err;
- info->opt_flag|=WRITE_CACHE_USED;
- sort_info.start_recpos=0;
- sort_info.buff=0; sort_info.buff_length=0;
- if (!(sort_info.record=(byte*) my_alloca((uint) share->base.reclength)))
- {
- print_error("Not Enough memory");
- goto err;
- }
-
- if (!rep_quick)
- {
- if ((new_file=my_create(fn_format(temp_filename,name,"",DATA_TMP_EXT,
- 2+4),
- 0,tmpfile_createflag,MYF(0))) < 0)
- {
- print_error("Can't create new tempfile: '%s'",temp_filename);
- goto err;
- }
- if (filecopy(new_file,info->dfile,0L,new_header_length,"datafile-header"))
- goto err;
- share->state.dellink= NI_POS_ERROR;
- info->rec_cache.file=new_file;
- if (testflag & T_UNPACK)
- share->base.options&= ~HA_OPTION_COMPRESS_RECORD;
- }
-
- sort_info.info=info;
- sort_info.pos=sort_info.max_pos=share->pack.header_length;
- sort_info.filepos=new_header_length;
- read_cache.end_of_file=sort_info.filelength=(ulong)
- my_seek(info->dfile,0L,MY_SEEK_END,MYF(0));
- sort_info.dupp=0;
- sort_info.fix_datafile= (my_bool) (! rep_quick);
- sort_info.max_records=LONG_MAX;
- if ((sort_info.new_data_file_type=share->data_file_type) ==
- COMPRESSED_RECORD && testflag & T_UNPACK)
- {
- if (share->base.options & HA_OPTION_PACK_RECORD)
- sort_info.new_data_file_type = DYNAMIC_RECORD;
- else
- sort_info.new_data_file_type = STATIC_RECORD;
- }
-
- del=share->state.del;
- share->state.records=share->state.del=share->state.empty=
- share->state.splitt=0;
- info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- for (i=0 ; i < N_MAXKEY ; i++)
- share->state.key_del[i]=share->state.key_root[i]= NI_POS_ERROR;
- share->state.key_file_length=share->base.keystart;
-
- lock_memory(); /* Everything is alloced */
- while (!(error=sort_get_next_record()))
- {
- if (writekeys(info,(byte*) sort_info.record,sort_info.filepos))
- {
- if (my_errno != HA_ERR_FOUND_DUPP_KEY) goto err;
- DBUG_DUMP("record",(byte*) sort_info.record,share->base.pack_reclength);
- print_info("Dupplicate key %2d for record at %10lu against new record at %10lu",info->errkey+1,sort_info.start_recpos,info->int_pos);
- if (testflag & T_VERBOSE)
- {
- VOID(_nisam_make_key(info,(uint) info->errkey,info->lastkey,
- sort_info.record,0L));
- _nisam_print_key(stdout,share->keyinfo[info->errkey].seg,info->lastkey);
- }
- sort_info.dupp++;
- if (rep_quick == 1)
- {
- error_printed=1;
- goto err;
- }
- continue;
- }
- if (sort_write_record())
- goto err;
- }
- if (error > 0 || write_data_suffix(info) ||
- flush_io_cache(&info->rec_cache) || read_cache.error < 0)
- goto err;
-
- if (testflag & T_WRITE_LOOP)
- {
- VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
- }
- if (my_chsize(share->kfile, share->state.key_file_length, 0, MYF(0)))
- {
- print_warning("Can't change size of indexfile, error: %d",my_errno);
- goto err;
- }
-
- if (rep_quick && del+sort_info.dupp != share->state.del)
- {
- print_error("Couldn't fix table with quick recovery: Found wrong number of deleted records");
- print_error("Run recovery again without -q");
- got_error=1;
- goto err;
- }
-
- if (!rep_quick)
- {
- info->dfile=new_file;
- share->state.data_file_length=sort_info.filepos;
- share->state.splitt=share->state.records; /* Only hole records */
- out_flag|=O_NEW_DATA; /* Data in new file */
- share->state.version=(ulong) time((time_t*) 0); /* Force reopen */
- }
- else
- share->state.data_file_length=sort_info.max_pos;
-
- if (!(testflag & T_SILENT))
- {
- if (start_records != share->state.records)
- printf("Data records: %lu\n",(ulong) share->state.records);
- if (sort_info.dupp)
- print_warning("%lu records have been removed",(ulong) sort_info.dupp);
- }
-
- got_error=0;
-err:
- if (got_error)
- {
- if (! error_printed)
- print_error("%d for record at pos %lu",my_errno,
- (ulong) sort_info.start_recpos);
- if (new_file >= 0)
- {
- VOID(my_close(new_file,MYF(0)));
- VOID(my_delete(temp_filename,MYF(MY_WME)));
- }
- }
- if (sort_info.record)
- {
- my_afree(sort_info.record);
- }
- my_free(sort_info.buff,MYF(MY_ALLOW_ZERO_PTR));
- VOID(end_io_cache(&read_cache));
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- VOID(end_io_cache(&info->rec_cache));
- got_error|=flush_blocks(share->kfile);
- if (!got_error && testflag & T_UNPACK)
- {
- share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
- share->pack.header_length=0;
- share->data_file_type=sort_info.new_data_file_type;
- }
- DBUG_RETURN(got_error);
-} /* rep */
-
-
- /* Uppdaterar nyckelfilen i samband med reparation */
-
-static int writekeys(register N_INFO *info,byte *buff,ulong filepos)
-{
- register uint i;
- uchar *key;
- DBUG_ENTER("writekeys");
-
- key=info->lastkey+info->s->base.max_key_length;
- for (i=0 ; i < info->s->state.keys ; i++)
- {
- VOID(_nisam_make_key(info,i,key,buff,filepos));
- if (_nisam_ck_write(info,i,key)) goto err;
- }
- DBUG_RETURN(0);
-
- err:
- if (my_errno == HA_ERR_FOUND_DUPP_KEY)
- {
- info->errkey=(int) i; /* This key was found */
- while ( i-- > 0 )
- {
- VOID(_nisam_make_key(info,i,key,buff,filepos));
- if (_nisam_ck_delete(info,i,key)) break;
- }
- }
- DBUG_PRINT("error",("errno: %d",my_errno));
- DBUG_RETURN(-1);
-} /* writekeys */
-
-
- /* Write info about table */
-
-static void descript(info,name)
-reg1 N_INFO *info;
-my_string name;
-{
- uint key,field,start,len;
- reg3 N_KEYDEF *keyinfo;
- reg2 N_KEYSEG *keyseg;
- reg4 const char *text;
- char buff[40],length[10],*pos,*end;
- enum en_fieldtype type;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("describe");
-
- printf("\nISAM file: %s\n",name);
- if (testflag & T_VERBOSE)
- {
- printf("Isam-version: %d\n",(int) share->state.header.file_version[3]);
- if (share->base.create_time)
- {
- get_date(buff,1,share->base.create_time);
- printf("Creation time: %s\n",buff);
- }
- if (share->base.isamchk_time)
- {
- get_date(buff,1,share->base.isamchk_time);
- printf("Recover time: %s\n",buff);
- }
- }
- printf("Data records: %10lu Deleted blocks: %10lu\n",
- share->state.records,share->state.del);
- if (testflag & T_SILENT)
- DBUG_VOID_RETURN; /* This is enough */
-
- if (testflag & T_VERBOSE)
- {
-#ifdef USE_RELOC
- printf("Init-relocation: %10lu\n",share->base.reloc);
-#endif
- printf("Datafile Parts: %10lu Deleted data: %10lu\n",
- share->state.splitt,share->state.empty);
- printf("Datafile pointer (bytes):%6d Keyfile pointer (bytes):%6d\n",
- share->rec_reflength,share->base.key_reflength);
- if (info->s->base.reloc == 1L && info->s->base.records == 1L)
- puts("This is a one-record table");
- else
- {
- if (share->base.max_data_file_length != NI_POS_ERROR ||
- share->base.max_key_file_length != NI_POS_ERROR)
- printf("Max datafile length: %10lu Max keyfile length: %10lu\n",
- share->base.max_data_file_length-1,
- share->base.max_key_file_length-1);
- }
- }
-
- printf("Recordlength: %10d\n",(int) share->base.reclength);
- VOID(fputs("Record format: ",stdout));
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- puts("Compressed");
- else if (share->base.options & HA_OPTION_PACK_RECORD)
- puts("Packed");
- else
- puts("Fixed length");
- if (share->state.keys != share->base.keys)
- printf("Using only %d keys of %d possibly keys\n",share->state.keys,
- share->base.keys);
-
- puts("\ntable description:");
- printf("Key Start Len Index Type");
- if (testflag & T_VERBOSE)
- printf(" Root Blocksize Rec/key");
- VOID(putchar('\n'));
-
- for (key=0, keyinfo= &share->keyinfo[0] ; key < share->base.keys;
- key++,keyinfo++)
- {
- keyseg=keyinfo->seg;
- if (keyinfo->base.flag & HA_NOSAME) text="unique ";
- else text="multip.";
-
- pos=buff;
- if (keyseg->base.flag & HA_REVERSE_SORT)
- *pos++ = '-';
- pos=strmov(pos,type_names[keyseg->base.type]);
- *pos++ = ' ';
- *pos=0;
- if (keyinfo->base.flag & HA_PACK_KEY)
- pos=strmov(pos,packed_txt);
- if (keyseg->base.flag & HA_SPACE_PACK)
- pos=strmov(pos,diff_txt);
- printf("%-4d%-6d%-3d %-8s%-21s",
- key+1,keyseg->base.start+1,keyseg->base.length,text,buff);
- if (testflag & T_VERBOSE)
- printf(" %9ld %9d %9ld",
- share->state.key_root[key],keyinfo->base.block_length,
- share->base.rec_per_key[key]);
- VOID(putchar('\n'));
- while ((++keyseg)->base.type)
- {
- pos=buff;
- if (keyseg->base.flag & HA_REVERSE_SORT)
- *pos++ = '-';
- pos=strmov(pos,type_names[keyseg->base.type]);
- *pos++= ' ';
- if (keyseg->base.flag & HA_SPACE_PACK)
- pos=strmov(pos,diff_txt);
- *pos=0;
- printf(" %-6d%-3d %-24s\n",
- keyseg->base.start+1,keyseg->base.length,buff);
- }
- }
- if (verbose > 1)
- {
- printf("\nField Start Length Type");
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- printf(" Huff tree Bits");
- VOID(putchar('\n'));
- if (verbose > 2 && share->base.pack_bits)
- printf("- %-7d%-35s\n",share->base.pack_bits,"bit field");
-
- start=1;
- for (field=0 ; field < share->base.fields ; field++)
- {
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- type=share->rec[field].base_type;
- else
- type=(enum en_fieldtype) share->rec[field].base.type;
- end=strmov(buff,field_pack[type]);
-#ifndef NOT_PACKED_DATABASES
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- if (share->rec[field].pack_type & PACK_TYPE_SELECTED)
- end=strmov(end,", not_always");
- if (share->rec[field].pack_type & PACK_TYPE_SPACE_FIELDS)
- end=strmov(end,", no empty");
- if (share->rec[field].pack_type & PACK_TYPE_ZERO_FILL)
- {
- sprintf(end,", zerofill(%d)",share->rec[field].space_length_bits);
- end=strend(end);
- }
- }
- if (buff[0] == ',')
- strmov(buff,buff+2);
-#endif
- len=(uint) (int10_to_str((long) share->rec[field].base.length,length,10) -
- length);
- if (type == FIELD_BLOB)
- {
- length[len]='+';
- VOID(int10_to_str((long) sizeof(char*),length+len+1,10));
- }
- printf("%-6d%-6d%-7s%-35s",field+1,start,length,buff);
-#ifndef NOT_PACKED_DATABASES
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- if (share->rec[field].huff_tree)
- printf("%3d %2d",
- (uint) (share->rec[field].huff_tree-share->decode_trees)+1,
- share->rec[field].huff_tree->quick_table_bits);
- }
-#endif
- VOID(putchar('\n'));
- start+=share->rec[field].base.length;
- if (type == FIELD_BLOB)
- start+=sizeof(char*);
- }
- }
- DBUG_VOID_RETURN;
-} /* describe */
-
-
- /* Change all key-pointers that points to a records */
-
-static int movepoint(info,record,oldpos,newpos,prot_key)
-register N_INFO *info;
-byte *record;
-ulong oldpos,newpos;
-uint prot_key;
-{
- register uint i;
- uchar *key;
- DBUG_ENTER("movepoint");
-
- key=info->lastkey+info->s->base.max_key_length;
- for (i=0 ; i < info->s->state.keys; i++)
- {
- if (i != prot_key)
- {
- VOID(_nisam_make_key(info,i,key,record,oldpos));
- if (info->s->keyinfo[i].base.flag & HA_NOSAME)
- { /* Change pointer direct */
- uint nod_flag;
- N_KEYDEF *keyinfo;
- keyinfo=info->s->keyinfo+i;
- if (_nisam_search(info,keyinfo,key,USE_HOLE_KEY,
- (uint) (SEARCH_SAME | SEARCH_SAVE_BUFF),
- info->s->state.key_root[i]))
- DBUG_RETURN(-1);
- nod_flag=test_if_nod(info->buff);
- _nisam_dpointer(info,info->int_keypos-nod_flag-
- info->s->rec_reflength,newpos);
- if (_nisam_write_keypage(info,keyinfo,info->int_pos,info->buff))
- DBUG_RETURN(-1);
- }
- else
- { /* Change old key to new */
- if (_nisam_ck_delete(info,i,key))
- DBUG_RETURN(-1);
- VOID(_nisam_make_key(info,i,key,record,newpos));
- if (_nisam_ck_write(info,i,key))
- DBUG_RETURN(-1);
- }
- }
- }
- DBUG_RETURN(0);
-} /* movepoint */
-
-
- /* Tell system that we want all memory for our cache */
-
-static void lock_memory(void)
-{
-#ifdef SUN_OS /* Key-cacheing thrases on sun 4.1 */
- int success;
-
- success = mlockall(MCL_CURRENT); /* or plock(DATLOCK); */
-
- if (geteuid() == 0 && success != 0)
- print_warning("Failed to lock memory. errno %d",my_errno);
-#endif
-} /* lock_memory */
-
-
- /* Flush all changed blocks to disk */
-
-static int flush_blocks(file)
-File file;
-{
- if (flush_key_blocks(dflt_key_cache,file,FLUSH_RELEASE))
- {
- print_error("%d when trying to write bufferts",my_errno);
- return(1);
- }
- end_key_cache(dflt_key_cache,1);
- return 0;
-} /* flush_blocks */
-
-
- /* Sort records according to one key */
-
-static int sort_records(info,name,sort_key,write_info)
-register N_INFO *info;
-my_string name;
-uint sort_key;
-int write_info;
-{
- int got_error;
- uint key;
- N_KEYDEF *keyinfo;
- File new_file;
- uchar *temp_buff;
- ulong old_record_count;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("sort_records");
-
- keyinfo= &share->keyinfo[sort_key];
- got_error=1;
- temp_buff=0; record_buff=0;
- new_file= -1;
-
- if (sort_key >= share->state.keys)
- {
- print_error("Can't sort table '%s' on key %d. It has only %d keys",
- name,sort_key+1,share->state.keys);
- error_printed=0;
- DBUG_RETURN(-1);
- }
- if (!(testflag & T_SILENT))
- {
- printf("- Sorting records in ISAM-table '%s'\n",name);
- if (write_info)
- printf("Data records: %7lu Deleted: %7lu\n",
- share->state.records,share->state.del);
- }
- if (share->state.key_root[sort_key] == NI_POS_ERROR)
- DBUG_RETURN(0); /* Nothing to do */
-
- init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,use_buffers, 0, 0);
- if (init_io_cache(&info->rec_cache,-1,(uint) write_buffer_length,
- WRITE_CACHE,share->pack.header_length,1,
- MYF(MY_WME | MY_WAIT_IF_FULL)))
- goto err;
- info->opt_flag|=WRITE_CACHE_USED;
-
- if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length)))
- {
- print_error("Not Enough memory");
- goto err;
- }
- if (!(record_buff=(byte*) my_alloca((uint) share->base.reclength)))
- {
- print_error("Not Enough memory");
- goto err;
- }
- if ((new_file=my_create(fn_format(temp_filename,name,"",DATA_TMP_EXT,2+4),
- 0,tmpfile_createflag,MYF(0))) <= 0)
- {
- print_error("Can't create new tempfile: '%s'",temp_filename);
- goto err;
- }
- if (filecopy(new_file,info->dfile,0L,share->pack.header_length,
- "datafile-header"))
- goto err;
- info->rec_cache.file=new_file; /* Use this file for cacheing*/
-
- lock_memory();
- for (key=0 ; key < share->state.keys ; key++)
- share->keyinfo[key].base.flag|= HA_SORT_ALLOWS_SAME;
-
- if (my_pread(share->kfile,(byte*) temp_buff,
- (uint) keyinfo->base.block_length,
- share->state.key_root[sort_key],
- MYF(MY_NABP+MY_WME)))
- {
- print_error("Can't read indexpage from filepos: %lu",
- (ulong) share->state.key_root[sort_key]);
- goto err;
- }
-
- /* Setup param for sort_write_record */
- bzero((char*) &sort_info,sizeof(sort_info));
- sort_info.info=info;
- sort_info.new_data_file_type=share->data_file_type;
- sort_info.fix_datafile=1;
- sort_info.filepos=share->pack.header_length;
- sort_info.record=record_buff;
- old_record_count=share->state.records;
- share->state.records=0;
-
- if (sort_record_index(info,keyinfo,share->state.key_root[sort_key],temp_buff,
- sort_key,new_file) ||
- write_data_suffix(info) ||
- flush_io_cache(&info->rec_cache))
- goto err;
-
- if (share->state.records != old_record_count)
- {
- print_error("found %lu of %lu records",
- (ulong) share->state.records,(ulong) old_record_count);
- goto err;
- }
-
- /* Put same locks as old file */
- if (lock_file(new_file,0L,F_WRLCK,"tempfile",temp_filename))
- goto err;
- VOID(lock_file(info->dfile,0L,F_UNLCK,"datafile of",name));
- VOID(my_close(info->dfile,MYF(MY_WME)));
- out_flag|=O_NEW_DATA; /* Data in new file */
-
- info->dfile=new_file; /* Use new indexfile */
- share->state.del=share->state.empty=0;
- share->state.dellink= NI_POS_ERROR;
- share->state.data_file_length=sort_info.filepos;
- share->state.splitt=share->state.records; /* Only hole records */
- share->state.version=(ulong) time((time_t*) 0);
-
- info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
-
- if (testflag & T_WRITE_LOOP)
- {
- VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
- }
- got_error=0;
-
-err:
- if (got_error && new_file >= 0)
- {
- VOID(my_close(new_file,MYF(MY_WME)));
- VOID(my_delete(temp_filename,MYF(MY_WME)));
- }
- if (temp_buff)
- {
- my_afree((gptr) temp_buff);
- }
- if (record_buff)
- {
- my_afree(record_buff);
- }
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- VOID(end_io_cache(&info->rec_cache));
- share->base.sortkey=sort_key;
- DBUG_RETURN(flush_blocks(share->kfile) | got_error);
-} /* sort_records */
-
-
- /* Sort records recursive using one index */
-
-static int sort_record_index(info,keyinfo,page,buff,sort_key,new_file)
-N_INFO *info;
-N_KEYDEF *keyinfo;
-ulong page;
-uchar *buff;
-uint sort_key;
-File new_file;
-{
- uint nod_flag,used_length;
- uchar *temp_buff,*keypos,*endpos;
- ulong next_page,rec_pos;
- uchar lastkey[N_MAX_KEY_BUFF];
- DBUG_ENTER("sort_record_index");
-
- nod_flag=test_if_nod(buff);
- temp_buff=0;
-
- if (nod_flag)
- {
- if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length)))
- {
- print_error("Not Enough memory");
- DBUG_RETURN(-1);
- }
- }
- used_length=getint(buff);
- keypos=buff+2+nod_flag;
- endpos=buff+used_length;
- for ( ;; )
- {
- _sanity(__FILE__,__LINE__);
- if (nod_flag)
- {
- next_page=_nisam_kpos(nod_flag,keypos);
- if (my_pread(info->s->kfile,(byte*) temp_buff,
- (uint) keyinfo->base.block_length, next_page,
- MYF(MY_NABP+MY_WME)))
- {
- print_error("Can't read keys from filepos: %lu",(ulong) next_page);
- goto err;
- }
- if (sort_record_index(info,keyinfo,next_page,temp_buff,sort_key,
- new_file))
- goto err;
- }
- _sanity(__FILE__,__LINE__);
- if (keypos >= endpos ||
- (*keyinfo->get_key)(keyinfo,nod_flag,&keypos,lastkey) == 0)
- break;
- rec_pos= _nisam_dpos(info,nod_flag,keypos);
-
- if ((*info->s->read_rnd)(info,record_buff,rec_pos,0))
- {
- print_error("%d when reading datafile",my_errno);
- goto err;
- }
- if (rec_pos != sort_info.filepos)
- {
- _nisam_dpointer(info,keypos-nod_flag-info->s->rec_reflength,
- sort_info.filepos);
- if (movepoint(info,record_buff,rec_pos,sort_info.filepos,sort_key))
- {
- print_error("%d when updating key-pointers",my_errno);
- goto err;
- }
- }
- if (sort_write_record())
- goto err;
- }
- bzero((byte*) buff+used_length,keyinfo->base.block_length-used_length);
- if (my_pwrite(info->s->kfile,(byte*) buff,(uint) keyinfo->base.block_length,
- page,MYF_RW))
- {
- print_error("%d when updating keyblock",my_errno);
- goto err;
- }
- if (temp_buff)
- my_afree((gptr) temp_buff);
- DBUG_RETURN(0);
-err:
- if (temp_buff)
- my_afree((gptr) temp_buff);
- DBUG_RETURN(1);
-} /* sort_record_index */
-
-
- /* Sort index for more efficent reads */
-
-static int sort_index(info,name)
-register N_INFO *info;
-my_string name;
-{
- reg2 uint key;
- reg1 N_KEYDEF *keyinfo;
- File new_file;
- ulong index_pos[N_MAXKEY];
- DBUG_ENTER("sort_index");
-
- if (!(testflag & T_SILENT))
- printf("- Sorting index for ISAM-table '%s'\n",name);
-
- if ((new_file=my_create(fn_format(temp_filename,name,"",INDEX_TMP_EXT,2+4),
- 0,tmpfile_createflag,MYF(0))) <= 0)
- {
- print_error("Can't create new tempfile: '%s'",temp_filename);
- DBUG_RETURN(-1);
- }
- if (filecopy(new_file,info->s->kfile,0L,(ulong) info->s->base.keystart,
- "headerblock"))
- goto err;
-
- new_file_pos=info->s->base.keystart;
- for (key= 0,keyinfo= &info->s->keyinfo[0]; key < info->s->state.keys ;
- key++,keyinfo++)
- {
- if (info->s->state.key_root[key] != NI_POS_ERROR)
- {
- index_pos[key]=new_file_pos; /* Write first block here */
- if (!_nisam_fetch_keypage(info,keyinfo,info->s->state.key_root[key],
- info->buff,0))
- {
- print_error("Can't read indexpage from filepos: %lu",
- (ulong) info->s->state.key_root[key]);
- goto err;
- }
- if (sort_one_index(info,keyinfo,info->buff,new_file))
- goto err;
- }
- else
- index_pos[key]= NI_POS_ERROR; /* No blocks */
- }
-
- /* Put same locks as old file */
- if (lock_file(new_file,0L,F_WRLCK,"tempfile",temp_filename))
- goto err;
- info->s->state.version=(ulong) time((time_t*) 0);
- VOID(_nisam_writeinfo(info,1)); /* This unlocks table */
- VOID(my_close(info->s->kfile,MYF(MY_WME)));
- out_flag|=O_NEW_INDEX; /* Data in new file */
-
- info->s->kfile=new_file;
- info->s->state.key_file_length=new_file_pos;
- info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- for (key=0 ; key < info->s->state.keys ; key++)
- {
- info->s->state.key_root[key]=index_pos[key];
- info->s->state.key_del[key]= NI_POS_ERROR;
- }
- DBUG_RETURN(0);
-
-err:
- VOID(my_close(new_file,MYF(MY_WME)));
- VOID(my_delete(temp_filename,MYF(MY_WME)));
- DBUG_RETURN(-1);
-} /* sort_index */
-
-
- /* Sort records recursive using one index */
-
-static int sort_one_index(info,keyinfo,buff,new_file)
-N_INFO *info;
-N_KEYDEF *keyinfo;
-uchar *buff;
-File new_file;
-{
- uint length,nod_flag,used_length;
- uchar *temp_buff,*keypos,*endpos;
- ulong new_page_pos,next_page;
- DBUG_ENTER("sort_one_index");
-
- temp_buff=0;
- new_page_pos=new_file_pos;
- new_file_pos+=keyinfo->base.block_length;
-
- if ((nod_flag=test_if_nod(buff)))
- {
- if (!(temp_buff=(uchar*) my_alloca((uint) keyinfo->base.block_length)))
- {
- print_error("Not Enough memory");
- DBUG_RETURN(-1);
- }
-
- used_length=getint(buff);
- keypos=buff+2+nod_flag;
- endpos=buff+used_length;
- for ( ;; )
- {
- if (nod_flag)
- {
- next_page=_nisam_kpos(nod_flag,keypos);
- _nisam_kpointer(info,keypos-nod_flag,new_file_pos); /* Save new pos */
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,temp_buff,0))
- {
- print_error("Can't read keys from filepos: %lu",
- (ulong) next_page);
- goto err;
- }
- if (sort_one_index(info,keyinfo,temp_buff,new_file))
- goto err;
- }
- if (keypos >= endpos ||
- ((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,info->lastkey)) == 0)
- break;
- }
- my_afree((gptr) temp_buff);
- }
-
- /* Fill block with zero and write it to new file */
-
- length=getint(buff);
- bzero((byte*) buff+length,keyinfo->base.block_length-length);
- if (my_pwrite(new_file,(byte*) buff,(uint) keyinfo->base.block_length,
- new_page_pos,MYF(MY_NABP | MY_WAIT_IF_FULL)))
- {
- print_error("Can't write indexblock, error: %d",my_errno);
- goto err;
- }
- DBUG_RETURN(0);
-err:
- if (temp_buff)
- my_afree((gptr) temp_buff);
- DBUG_RETURN(1);
-} /* sort_one_index */
-
-
- /* Change to use new file */
- /* Copy stats from old file to new file, deletes orginal and */
- /* changes new file name to old file name */
-
-static int change_to_newfile(filename,old_ext,new_ext)
-const char *filename,*old_ext,*new_ext;
-{
- char old_filename[FN_REFLEN],new_filename[FN_REFLEN];
-
- return my_redel(fn_format(old_filename,filename,"",old_ext,2+4),
- fn_format(new_filename,filename,"",new_ext,2+4),
- MYF(MY_WME+MY_LINK_WARNING));
-} /* change_to_newfile */
-
-
- /* Locks a hole file */
- /* Gives error-message if file can't be locked */
-
-static int lock_file(file,start,lock_type,filetype,filename)
-File file;
-ulong start;
-int lock_type;
-const char *filetype,*filename;
-{
-#ifndef NO_LOCKING
- if (my_lock(file,lock_type,start,F_TO_EOF,
- testflag & T_WAIT_FOREVER ? MYF(MY_SEEK_NOT_DONE) :
- MYF(MY_SEEK_NOT_DONE | MY_DONT_WAIT)))
- {
- print_error(" %d when %s %s '%s'",my_errno,
- lock_type == F_UNLCK ? "unlocking": "locking",
- filetype,filename);
- error_printed=2; /* Don't give that data is crashed */
- return 1;
- }
-#endif
- return 0;
-} /* lock_file */
-
-
- /* Copy a block between two files */
-
-static int filecopy(File to,File from,ulong start,ulong length,
- const char *type)
-{
- char tmp_buff[IO_SIZE],*buff;
- ulong buff_length;
- DBUG_ENTER("filecopy");
-
- buff_length=min(write_buffer_length,length);
- if (!(buff=my_malloc(buff_length,MYF(0))))
- {
- buff=tmp_buff; buff_length=IO_SIZE;
- }
-
- VOID(my_seek(from,start,MY_SEEK_SET,MYF(0)));
- while (length > buff_length)
- {
- if (my_read(from,(byte*) buff,buff_length,MYF(MY_NABP)) ||
- my_write(to,(byte*) buff,buff_length,MYF(MY_NABP | MY_WAIT_IF_FULL)))
- goto err;
- length-= buff_length;
- }
- if (my_read(from,(byte*) buff,(uint) length,MYF(MY_NABP)) ||
- my_write(to,(byte*) buff,(uint) length,MYF(MY_NABP | MY_WAIT_IF_FULL)))
- goto err;
- if (buff != tmp_buff)
- my_free(buff,MYF(0));
- DBUG_RETURN(0);
-err:
- if (buff != tmp_buff)
- my_free(buff,MYF(0));
- print_error("Can't copy %s to tempfile, error %d",type,my_errno);
- DBUG_RETURN(1);
-}
-
-
- /* Fix table using sorting */
- /* saves new table in temp_filename */
-
-static int rep_by_sort(info,name)
-reg1 N_INFO *info;
-my_string name;
-{
- int got_error;
- uint i,length;
- ulong start_records,new_header_length,del;
- File new_file;
- SORT_PARAM sort_param;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("rep_by_sort");
-
- start_records=share->state.records;
- got_error=1;
- new_file= -1;
- new_header_length=(testflag & T_UNPACK) ? 0 : share->pack.header_length;
- if (!(testflag & T_SILENT))
- {
- printf("- recovering ISAM-table '%s'\n",name);
- printf("Data records: %lu\n",(ulong) start_records);
- }
- bzero((char*) &sort_info,sizeof(sort_info));
- if (!(sort_info.key_block=alloc_key_blocks((uint) sort_key_blocks,
- share->base.max_block))
- || init_io_cache(&read_cache,info->dfile,(uint) read_buffer_length,
- READ_CACHE,share->pack.header_length,1,MYF(MY_WME)) ||
- (! rep_quick &&
- init_io_cache(&info->rec_cache,info->dfile,(uint) write_buffer_length,
- WRITE_CACHE,new_header_length,1,
- MYF(MY_WME | MY_WAIT_IF_FULL))))
- goto err;
- sort_info.key_block_end=sort_info.key_block+sort_key_blocks;
- info->opt_flag|=WRITE_CACHE_USED;
- info->rec_cache.file=info->dfile; /* for sort_delete_record */
-
- if (!(sort_info.record=(byte*) my_alloca((uint) share->base.reclength)))
- {
- print_error("Not enough memory for extra record");
- goto err;
- }
- if (!rep_quick)
- {
- if ((new_file=my_create(fn_format(temp_filename,name,"",DATA_TMP_EXT,
- 2+4),
- 0,tmpfile_createflag,MYF(0))) < 0)
- {
- print_error("Can't create new tempfile: '%s'",temp_filename);
- goto err;
- }
- if (filecopy(new_file,info->dfile,0L,new_header_length,"datafile-header"))
- goto err;
- if (testflag & T_UNPACK)
- share->base.options&= ~HA_OPTION_COMPRESS_RECORD;
- share->state.dellink= NI_POS_ERROR;
- info->rec_cache.file=new_file;
- }
-
- info->update= (short) (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- for (i=0 ; i < N_MAXKEY ; i++)
- share->state.key_del[i]=share->state.key_root[i]= NI_POS_ERROR;
- share->state.key_file_length=share->base.keystart;
-
- sort_info.info=info;
- if ((sort_info.new_data_file_type=share->data_file_type) ==
- COMPRESSED_RECORD && testflag & T_UNPACK)
- {
- if (share->base.options & HA_OPTION_PACK_RECORD)
- sort_info.new_data_file_type = DYNAMIC_RECORD;
- else
- sort_info.new_data_file_type = STATIC_RECORD;
- }
-
- sort_info.filepos=new_header_length;
- sort_info.dupp=0;
- read_cache.end_of_file=sort_info.filelength=
- (ulong) my_seek(read_cache.file,0L,MY_SEEK_END,MYF(0));
-
- if (share->data_file_type == DYNAMIC_RECORD)
- length=max(share->base.min_pack_length+1,share->base.min_block_length);
- else if (share->data_file_type == COMPRESSED_RECORD)
- length=share->base.min_block_length;
- else
- length=share->base.reclength;
- sort_param.max_records=sort_info.max_records=sort_info.filelength/length+1;
- sort_param.key_cmp=sort_key_cmp;
- sort_param.key_write=sort_key_write;
- sort_param.key_read=sort_key_read;
- sort_param.lock_in_memory=lock_memory;
- del=share->state.del;
-
- for (sort_info.key=0 ; sort_info.key < share->state.keys ; sort_info.key++)
- {
- if ((!(testflag & T_SILENT)))
- printf ("- Fixing index %d\n",sort_info.key+1);
- sort_info.max_pos=sort_info.pos=share->pack.header_length;
- sort_info.keyinfo=share->keyinfo+sort_info.key;
- sort_info.keyseg=sort_info.keyinfo->seg;
- sort_info.fix_datafile= (my_bool) (sort_info.key == 0 && ! rep_quick);
- sort_info.unique=0;
- sort_param.key_length=share->rec_reflength;
- for (i=0 ; sort_info.keyseg[i].base.type ; i++)
- sort_param.key_length+=sort_info.keyseg[i].base.length+
- (sort_info.keyseg[i].base.flag & HA_SPACE_PACK ? 1 : 0);
- share->state.records=share->state.del=share->state.empty=share->state.splitt=0;
-
- if (_create_index_by_sort(&sort_param,
- (pbool) (!(testflag & T_VERBOSE)),
- (uint) sort_buffer_length))
- goto err;
- /* Set for next loop */
- sort_param.max_records=sort_info.max_records=share->state.records;
- share->base.rec_per_key[sort_info.key]=
- sort_info.unique ? ((sort_info.max_records+sort_info.unique/2)/
- sort_info.unique)
- : 1L;
-
- if (sort_info.fix_datafile)
- {
- info->dfile=new_file;
- share->state.data_file_length=sort_info.filepos;
- share->state.splitt=share->state.records; /* Only hole records */
- share->state.version=(ulong) time((time_t*) 0);
- out_flag|=O_NEW_DATA; /* Data in new file */
- read_cache.end_of_file=sort_info.filepos;
- if (write_data_suffix(info) || end_io_cache(&info->rec_cache))
- goto err;
- share->data_file_type=sort_info.new_data_file_type;
- share->pack.header_length=new_header_length;
- }
- else
- share->state.data_file_length=sort_info.max_pos;
-
- if (flush_pending_blocks())
- goto err;
-
- read_cache.file=info->dfile; /* re-init read cache */
- reinit_io_cache(&read_cache,READ_CACHE,share->pack.header_length,1,1);
- }
-
- if (testflag & T_WRITE_LOOP)
- {
- VOID(fputs(" \r",stdout)); VOID(fflush(stdout));
- }
-
- if (rep_quick && del+sort_info.dupp != share->state.del)
- {
- print_error("Couldn't fix table with quick recovery: Found wrong number of deleted records");
- print_error("Run recovery again without -q");
- got_error=1;
- goto err;
- }
-
- if (rep_quick != 1)
- {
- ulong skr=share->state.data_file_length+
- (share->base.options & HA_OPTION_COMPRESS_RECORD ?
- MEMMAP_EXTRA_MARGIN : 0);
-#ifdef USE_RELOC
- if (share->data_file_type == STATIC_RECORD &&
- skr < share->base.reloc*share->base.min_pack_length)
- skr=share->base.reloc*share->base.min_pack_length;
-#endif
- if (skr != sort_info.filelength)
- if (my_chsize(info->dfile, skr, 0, MYF(0)))
- print_warning("Can't change size of datafile, error: %d",my_errno);
- }
- if (my_chsize(share->kfile, share->state.key_file_length, 0, MYF(0)))
- print_warning("Can't change size of indexfile, error: %d",my_errno);
-
- if (!(testflag & T_SILENT))
- {
- if (start_records != share->state.records)
- printf("Data records: %lu\n",(ulong) share->state.records);
- if (sort_info.dupp)
- print_warning("%lu records have been removed",(ulong) sort_info.dupp);
- }
- got_error=0;
-
-err:
- if (got_error)
- {
- if (! error_printed)
- print_error("%d when fixing table",my_errno);
- if (new_file >= 0)
- {
- VOID(end_io_cache(&info->rec_cache));
- VOID(my_close(new_file,MYF(0)));
- VOID(my_delete(temp_filename,MYF(MY_WME)));
- }
- }
- if (sort_info.key_block)
- my_free((gptr) sort_info.key_block,MYF(0));
- if (sort_info.record)
- {
- my_afree(sort_info.record);
- }
- VOID(end_io_cache(&read_cache));
- VOID(end_io_cache(&info->rec_cache));
- info->opt_flag&= ~(READ_CACHE_USED | WRITE_CACHE_USED);
- if (!got_error && testflag & T_UNPACK)
- {
- share->state.header.options[0]&= (uchar) ~HA_OPTION_COMPRESS_RECORD;
- share->pack.header_length=0;
- }
- DBUG_RETURN(got_error);
-} /* rep_by_sort */
-
-
- /* Read next record and return next key */
-
-static int sort_key_read(key)
-void *key;
-{
- int error;
- N_INFO *info;
- DBUG_ENTER("sort_key_read");
-
- info=sort_info.info;
-
- if ((error=sort_get_next_record()))
- DBUG_RETURN(error);
- if (info->s->state.records == sort_info.max_records)
- {
- print_error("Found too many records; Can`t continue");
- DBUG_RETURN(1);
- }
- VOID(_nisam_make_key(info,sort_info.key,key,sort_info.record,
- sort_info.filepos));
- DBUG_RETURN(sort_write_record());
-} /* sort_key_read */
-
-
- /* Read next record from file using parameters in sort_info */
- /* Return -1 if end of file, 0 if ok and > 0 if error */
-
-static int sort_get_next_record()
-{
- int searching;
- uint found_record,b_type,left_length;
- ulong pos;
- byte *to;
- BLOCK_INFO block_info;
- N_INFO *info;
- ISAM_SHARE *share;
- DBUG_ENTER("sort_get_next_record");
-
- info=sort_info.info;
- share=info->s;
- switch (share->data_file_type) {
- case STATIC_RECORD:
- for (;;)
- {
- if (my_b_read(&read_cache,sort_info.record,share->base.reclength))
- DBUG_RETURN(-1);
- sort_info.start_recpos=sort_info.pos;
- if (!sort_info.fix_datafile)
- sort_info.filepos=sort_info.pos;
- sort_info.max_pos=(sort_info.pos+=share->base.reclength);
- share->state.splitt++;
- if (*sort_info.record)
- DBUG_RETURN(0);
- if (!sort_info.fix_datafile)
- {
- share->state.del++;
- share->state.empty+=share->base.reclength;
- }
- }
- case DYNAMIC_RECORD:
- LINT_INIT(to);
- pos=sort_info.pos;
- searching=(sort_info.fix_datafile && (testflag & T_EXTEND));
- for (;;)
- {
- found_record=block_info.second_read= 0;
- left_length=1;
- do
- {
- if (pos > sort_info.max_pos)
- sort_info.max_pos=pos;
- if (found_record && pos == search_after_block)
- print_info("Block: %lu used by record at %lu",
- search_after_block,
- sort_info.start_recpos);
- if (_nisam_read_cache(&read_cache,(byte*) block_info.header,pos,
- BLOCK_INFO_HEADER_LENGTH, test(! found_record) | 2))
- {
- if (found_record)
- {
- print_info("Can't read whole record at %lu (errno: %d)",
- (ulong) sort_info.start_recpos,errno);
- goto try_next;
- }
- DBUG_RETURN(-1);
- }
- if (searching && ! sort_info.fix_datafile)
- {
- error_printed=1;
- DBUG_RETURN(1); /* Something wrong with data */
- }
- if (((b_type=_nisam_get_block_info(&block_info,-1,pos)) &
- (BLOCK_ERROR | BLOCK_FATAL_ERROR)) ||
- ((b_type & BLOCK_FIRST) &&
- (block_info.rec_len < (uint) share->base.min_pack_length ||
- block_info.rec_len > (uint) share->base.max_pack_length)))
- {
- uint i;
- if (testflag & T_VERBOSE || searching == 0)
- print_info("Wrong bytesec: %3d-%3d-%3d at %10lu; Skipped",
- block_info.header[0],block_info.header[1],
- block_info.header[2],pos);
- if (found_record)
- goto try_next;
- block_info.second_read=0;
- searching=1;
- for (i=1 ; i < 11 ; i++) /* Skip from read string */
- if (block_info.header[i] >= 1 && block_info.header[i] <= 16)
- break;
- pos+=(ulong) i;
- continue;
- }
- if (block_info.block_len+ (uint) (block_info.filepos-pos) <
- share->base.min_block_length ||
- block_info.block_len-4 > (uint) share->base.max_pack_length)
- {
- if (!searching)
- print_info("Found block with impossible length %u at %lu; Skipped",
- block_info.block_len+ (uint) (block_info.filepos-pos),
- (ulong) pos);
- if (found_record)
- goto try_next;
- searching=1;
- pos++;
- block_info.second_read=0;
- continue;
- }
- if (b_type & (BLOCK_DELETED | BLOCK_SYNC_ERROR))
- {
- if (!sort_info.fix_datafile && (b_type & BLOCK_DELETED))
- {
- share->state.empty+=block_info.block_len;
- share->state.del++;
- share->state.splitt++;
- }
- if (found_record)
- goto try_next;
- /* Check if impossible big deleted block */
- if (block_info.block_len > share->base.max_pack_length +4)
- searching=1;
- if (searching)
- pos++;
- else
- pos=block_info.filepos+block_info.block_len;
- block_info.second_read=0;
- continue;
- }
-
- share->state.splitt++;
- if (! found_record++)
- {
- sort_info.find_length=left_length=block_info.rec_len;
- sort_info.start_recpos=pos;
- if (!sort_info.fix_datafile)
- sort_info.filepos=sort_info.start_recpos;
- if (sort_info.fix_datafile && (testflag & T_EXTEND))
- sort_info.pos=block_info.filepos+1;
- else
- sort_info.pos=block_info.filepos+block_info.block_len;
- if (share->base.blobs)
- {
- if (!(to=fix_rec_buff_for_blob(info,block_info.rec_len)))
- {
- print_error("Not enough memory for blob at %lu",
- (ulong) sort_info.start_recpos);
- DBUG_RETURN(-1);
- }
- }
- else
- to= info->rec_buff;
- }
- if (left_length < block_info.data_len || ! block_info.data_len)
- {
- print_info("Found block with too small length at %lu; Skipped",
- (ulong) sort_info.start_recpos);
- goto try_next;
- }
- if (block_info.filepos + block_info.data_len > read_cache.end_of_file)
- {
- print_info("Found block that points outside data file at %lu",
- (ulong) sort_info.start_recpos);
- goto try_next;
- }
- if (_nisam_read_cache(&read_cache,to,block_info.filepos,
- block_info.data_len, test(found_record == 1)))
- {
- print_info("Read error for block at: %lu (error: %d); Skipped",
- (ulong) block_info.filepos,my_errno);
- goto try_next;
- }
- left_length-=block_info.data_len;
- to+=block_info.data_len;
- pos=block_info.next_filepos;
- if (pos == NI_POS_ERROR && left_length)
- {
- print_info("Wrong block with wrong total length starting at %lu",
- (ulong) sort_info.start_recpos);
- goto try_next;
- }
- if (pos + BLOCK_INFO_HEADER_LENGTH > read_cache.end_of_file)
- {
- print_info("Found link that points at %lu (outside data file) at %lu",
- (ulong) pos,(ulong) sort_info.start_recpos);
- goto try_next;
- }
- } while (left_length);
-
- if (_nisam_rec_unpack(info,sort_info.record,info->rec_buff,
- sort_info.find_length) != MY_FILE_ERROR)
- {
- if (read_cache.error < 0)
- DBUG_RETURN(1);
- if ((testflag & (T_EXTEND | T_REP)) || searching)
- {
- if (_nisam_rec_check(info, sort_info.record))
- {
- print_info("Found wrong packed record at %lu",
- (ulong) sort_info.start_recpos);
- goto try_next;
- }
- }
- DBUG_RETURN(0);
- }
- if (!searching)
- {
- print_info("Found wrong packed record at %lu",
- (ulong) sort_info.start_recpos);
- }
- try_next:
- pos=sort_info.start_recpos+1;
- searching=1;
- }
- case COMPRESSED_RECORD:
- for (searching=0 ;; searching=1, sort_info.pos++)
- {
- if (_nisam_read_cache(&read_cache,(byte*) block_info.header,sort_info.pos,
- share->pack.ref_length,1))
- DBUG_RETURN(-1);
- if (searching && ! sort_info.fix_datafile)
- {
- error_printed=1;
- DBUG_RETURN(1); /* Something wrong with data */
- }
- sort_info.start_recpos=sort_info.pos;
- VOID(_nisam_pack_get_block_info(&block_info,share->pack.ref_length,-1,
- sort_info.pos));
- if (!block_info.rec_len &&
- sort_info.pos + MEMMAP_EXTRA_MARGIN == read_cache.end_of_file)
- DBUG_RETURN(-1);
- if (block_info.rec_len < (uint) share->min_pack_length ||
- block_info.rec_len > (uint) share->max_pack_length)
- {
- if (! searching)
- print_info("Found block with wrong recordlength: %d at %lu\n",
- block_info.rec_len, (ulong) sort_info.pos);
- continue;
- }
- if (_nisam_read_cache(&read_cache,(byte*) info->rec_buff,
- block_info.filepos, block_info.rec_len,1))
- {
- if (! searching)
- print_info("Couldn't read hole record from %lu",
- (ulong) sort_info.pos);
- continue;
- }
- if (_nisam_pack_rec_unpack(info,sort_info.record,info->rec_buff,
- block_info.rec_len))
- {
- if (! searching)
- print_info("Found wrong record at %lu",(ulong) sort_info.pos);
- continue;
- }
- if (!sort_info.fix_datafile)
- sort_info.filepos=sort_info.pos;
- sort_info.max_pos=(sort_info.pos+=share->pack.ref_length+
- block_info.rec_len);
- share->state.splitt++;
- info->packed_length=block_info.rec_len;
- DBUG_RETURN(0);
- }
- }
- DBUG_RETURN(1); /* Impossible */
-}
-
-
- /* Write record to new file */
-
-static int sort_write_record()
-{
- int flag;
- uint block_length,reclength;
- byte *from;
- uchar *block_buff[3];
- N_INFO *info;
- ISAM_SHARE *share;
- DBUG_ENTER("sort_write_record");
-
- info=sort_info.info;
- share=info->s;
- if (sort_info.fix_datafile)
- {
- switch (sort_info.new_data_file_type) {
- case STATIC_RECORD:
- if (my_b_write(&info->rec_cache,sort_info.record, share->base.reclength))
- {
- print_error("%d when writing to datafile",my_errno);
- DBUG_RETURN(1);
- }
- sort_info.filepos+=share->base.reclength;
- break;
- case DYNAMIC_RECORD:
- if (! info->blobs)
- from=info->rec_buff;
- else
- {
- /* must be sure that local buffer is big enough */
- reclength=info->s->base.pack_reclength+
- _calc_total_blob_length(info,sort_info.record)+
- ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (sort_info.buff_length < reclength)
- {
- if (!(sort_info.buff=my_realloc(sort_info.buff, (uint) reclength,
- MYF(MY_FREE_ON_ERROR |
- MY_ALLOW_ZERO_PTR))))
- DBUG_RETURN(1);
- sort_info.buff_length=reclength;
- }
- from=sort_info.buff+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER);
- }
- reclength=_nisam_rec_pack(info,from,sort_info.record);
- block_length=reclength+ 3 +test(reclength > 65532L);
- if (block_length < share->base.min_block_length)
- block_length=share->base.min_block_length;
- flag=0;
- info->update|=HA_STATE_WRITE_AT_END;
- if (_nisam_write_part_record(info,0L,block_length,NI_POS_ERROR,
- &from,&reclength,&flag))
- {
- print_error("%d when writing to datafile",my_errno);
- DBUG_RETURN(1);
- }
- sort_info.filepos+=block_length;
- break;
- case COMPRESSED_RECORD:
- reclength=info->packed_length;
- save_integer((byte*) block_buff,share->pack.ref_length,reclength);
- if (my_b_write(&info->rec_cache,(byte*) block_buff,share->pack.ref_length)
- || my_b_write(&info->rec_cache,(byte*) info->rec_buff,reclength))
- {
- print_error("%d when writing to datafile",my_errno);
- DBUG_RETURN(1);
- }
- sort_info.filepos+=reclength+share->pack.ref_length;
- break;
- }
- }
- share->state.records++;
- if (testflag & T_WRITE_LOOP && share->state.records % WRITE_COUNT == 0)
- {
- printf("%lu\r",(ulong) share->state.records); VOID(fflush(stdout));
- }
- DBUG_RETURN(0);
-} /* sort_write_record */
-
-
- /* Compare two keys from _create_index_by_sort */
-
-static int sort_key_cmp(const void *not_used __attribute__((unused)),
- const void *a,const void *b)
-{
- return (_nisam_key_cmp(sort_info.keyseg,*((uchar**) a),*((uchar**) b),0,
- SEARCH_SAME));
-} /* sort_key_cmp */
-
-
-static int sort_key_write( const void *a)
-{
- int cmp=sort_info.key_block->inited ?
- _nisam_key_cmp(sort_info.keyseg,sort_info.key_block->lastkey,(uchar*) a,
- 0,SEARCH_FIND) : -1L;
- if ((sort_info.keyinfo->base.flag & HA_NOSAME) &&
- cmp == 0)
- {
- sort_info.dupp++;
- print_warning("Dupplicate key for record at %10lu against record at %10lu",
- sort_info.info->lastpos=get_record_for_key(sort_info.info,
- sort_info.keyinfo,
- (uchar*) a),
- get_record_for_key(sort_info.info,sort_info.keyinfo,
- sort_info.key_block->lastkey));
- if (testflag & T_VERBOSE)
- _nisam_print_key(stdout,sort_info.keyseg,(uchar*) a);
- return(sort_delete_record());
- }
- if (cmp)
- sort_info.unique++;
-#ifndef DBUG_OFF
- if (cmp > 0)
- {
- print_error("Fatal intern error: Keys are not in order from sort");
- return(1);
- }
-#endif
- return (sort_insert_key(sort_info.key_block,(uchar*) a,NI_POS_ERROR));
-} /* sort_key_write */
-
-
- /* get pointer to record from a key */
-
-static ulong get_record_for_key( N_INFO *info, N_KEYDEF *keyinfo, uchar *key)
-{
- return _nisam_dpos(info,0,key+_nisam_keylength(keyinfo,key));
-} /* get_record_for_key */
-
-
- /* Insert a key in sort-key-blocks */
-
-static int sort_insert_key(reg1 ISAM_SORT_KEY_BLOCKS *key_block,
- uchar *key, ulong prev_block)
-{
- uint a_length,t_length,nod_flag;
- ulong filepos;
- uchar *anc_buff,*lastkey;
- S_PARAM s_temp;
- N_INFO *info;
- DBUG_ENTER("sort_insert_key");
-
- anc_buff=key_block->buff;
- info=sort_info.info;
- lastkey=key_block->lastkey;
- nod_flag= (key_block == sort_info.key_block ? 0 :
- sort_info.info->s->base.key_reflength);
-
- if (!key_block->inited)
- {
- key_block->inited=1;
- if (key_block == sort_info.key_block_end)
- {
- print_error("To many keyblocklevels; Try increasing sort_key_blocks");
- DBUG_RETURN(1);
- }
- a_length=2+nod_flag;
- key_block->end_pos=anc_buff+2;
- lastkey=0; /* No previous key in block */
- }
- else
- a_length=getint(anc_buff);
-
- /* Save pointer to previous block */
- if (nod_flag)
- _nisam_kpointer(info,key_block->end_pos,prev_block);
-
- t_length=_nisam_get_pack_key_length(sort_info.keyinfo,nod_flag,
- (uchar*) 0,lastkey,key,&s_temp);
- _nisam_store_key(sort_info.keyinfo,key_block->end_pos+nod_flag,&s_temp);
- a_length+=t_length;
- putint(anc_buff,a_length,nod_flag);
- key_block->end_pos+=t_length;
- if (a_length <= sort_info.keyinfo->base.block_length)
- {
- VOID(_nisam_move_key(sort_info.keyinfo,key_block->lastkey,key));
- key_block->last_length=a_length-t_length;
- DBUG_RETURN(0);
- }
-
- /* Fill block with end-zero and write filled block */
- putint(anc_buff,key_block->last_length,nod_flag);
- bzero((byte*) anc_buff+key_block->last_length,
- sort_info.keyinfo->base.block_length- key_block->last_length);
- if ((filepos=_nisam_new(info,sort_info.keyinfo)) == NI_POS_ERROR)
- return 1;
- if (my_pwrite(info->s->kfile,(byte*) anc_buff,
- (uint) sort_info.keyinfo->base.block_length,filepos,MYF_RW))
- DBUG_RETURN(1);
- DBUG_DUMP("buff",(byte*) anc_buff,getint(anc_buff));
-
- /* Write separator-key to block in next level */
- if (sort_insert_key(key_block+1,key_block->lastkey,filepos))
- DBUG_RETURN(1);
-
- /* clear old block and write new key in it */
- key_block->inited=0;
- DBUG_RETURN(sort_insert_key(key_block,key,prev_block));
-} /* sort_insert_key */
-
-
- /* Delete record when we found a dupplicated key */
-
-static int sort_delete_record()
-{
- uint i;
- int old_file,error;
- uchar *key;
- N_INFO *info;
- DBUG_ENTER("sort_delete_record");
-
- if (rep_quick == 1)
- {
- VOID(fputs("Quick-recover aborted; Run recovery without switch 'q' or with switch -qq\n",stderr));
- error_printed=1;
- DBUG_RETURN(1);
- }
- info=sort_info.info;
- if (info->s->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- VOID(fputs("Recover aborted; Can't run standard recovery on compressed tables\nwith errors in data-file\nUse switch '--safe-recover' to fix it\n",stderr));
- error_printed=1;
- DBUG_RETURN(1);
- }
-
- old_file=info->dfile;
- info->dfile=info->rec_cache.file;
- if (sort_info.key)
- {
- key=info->lastkey+info->s->base.max_key_length;
- if ((*info->s->read_rnd)(info,sort_info.record,info->lastpos,0) < 0)
- {
- print_error("Can't read record to be removed");
- info->dfile=old_file;
- DBUG_RETURN(1);
- }
-
- for (i=0 ; i < sort_info.key ; i++)
- {
- VOID(_nisam_make_key(info,i,key,sort_info.record,info->lastpos));
- if (_nisam_ck_delete(info,i,key))
- {
- print_error("Can't delete key %d from record to be removed",i+1);
- info->dfile=old_file;
- DBUG_RETURN(1);
- }
- }
- }
- error=flush_io_cache(&info->rec_cache) || (*info->s->delete_record)(info);
- info->dfile=old_file; /* restore actual value */
- info->s->state.records--;
- DBUG_RETURN(error);
-} /* sort_delete_record */
-
-
- /* Fix all pending blocks and flush everything to disk */
-
-static int flush_pending_blocks()
-{
- uint nod_flag,length;
- ulong filepos;
- N_INFO *info;
- ISAM_SORT_KEY_BLOCKS *key_block;
- DBUG_ENTER("flush_pending_blocks");
-
- filepos= NI_POS_ERROR; /* if empty file */
- info=sort_info.info;
- nod_flag=0;
- for (key_block=sort_info.key_block ; key_block->inited ; key_block++)
- {
- key_block->inited=0;
- length=getint(key_block->buff);
- if (nod_flag)
- _nisam_kpointer(info,key_block->end_pos,filepos);
- if ((filepos=_nisam_new(info,sort_info.keyinfo)) == NI_POS_ERROR)
- DBUG_RETURN(1);
- bzero((byte*) key_block->buff+length,
- sort_info.keyinfo->base.block_length-length);
- if (my_pwrite(info->s->kfile,(byte*) key_block->buff,
- (uint) sort_info.keyinfo->base.block_length,filepos,MYF_RW))
- DBUG_RETURN(1);
- DBUG_DUMP("buff",(byte*) key_block->buff,length);
- nod_flag=1;
- }
- info->s->state.key_root[sort_info.key]=filepos; /* Last is root for tree */
- DBUG_RETURN(0);
-} /* flush_pending_blocks */
-
-
- /* alloc space and pointers for key_blocks */
-
-static ISAM_SORT_KEY_BLOCKS *alloc_key_blocks(uint blocks, uint buffer_length)
-{
- reg1 uint i;
- ISAM_SORT_KEY_BLOCKS *block;
- DBUG_ENTER("alloc_key_blocks");
-
- if (!(block=(ISAM_SORT_KEY_BLOCKS*) my_malloc((sizeof(ISAM_SORT_KEY_BLOCKS)+
- buffer_length+IO_SIZE)*blocks,
- MYF(0))))
- {
- print_error("Not Enough memory for sort-key-blocks");
- return(0);
- }
- for (i=0 ; i < blocks ; i++)
- {
- block[i].inited=0;
- block[i].buff=(uchar*) (block+blocks)+(buffer_length+IO_SIZE)*i;
- }
- DBUG_RETURN(block);
-} /* alloc_key_blocks */
-
-
- /* print warnings and errors */
- /* VARARGS */
-
-static void print_info(const char * fmt,...)
-{
- va_list args;
-
- va_start(args,fmt);
- VOID(vfprintf(stdout, fmt, args));
- VOID(fputc('\n',stdout));
- va_end(args);
- return;
-}
-
-/* VARARGS */
-
-static void print_warning(const char * fmt,...)
-{
- va_list args;
- DBUG_ENTER("print_warning");
-
- if (!warning_printed && !error_printed)
- {
- fflush(stdout);
- if (testflag & T_SILENT)
- fprintf(stderr,"%s: ISAM file %s\n",my_progname,isam_file_name);
- }
- warning_printed=1;
- va_start(args,fmt);
- fprintf(stderr,"%s: warning: ",my_progname);
- VOID(vfprintf(stderr, fmt, args));
- VOID(fputc('\n',stderr));
- va_end(args);
- DBUG_VOID_RETURN;
-}
-
-/* VARARGS */
-
-void print_error(const char *fmt,...)
-{
- va_list args;
- DBUG_ENTER("print_error");
- DBUG_PRINT("enter",("format: %s",fmt));
-
- if (!warning_printed && !error_printed)
- {
- fflush(stdout);
- if (testflag & T_SILENT)
- fprintf(stderr,"%s: ISAM file %s\n",my_progname,isam_file_name);
- }
- error_printed|=1;
- va_start(args,fmt);
- fprintf(stderr,"%s: error: ",my_progname);
- VOID(vfprintf(stderr, fmt, args));
- VOID(fputc('\n',stderr));
- va_end(args);
- DBUG_VOID_RETURN;
-}
-
- /* Check if file is almost full */
-
-static int test_if_almost_full(N_INFO *info)
-{
- double diff= 0.9;
- if (info->s->base.options & HA_OPTION_COMPRESS_RECORD)
- { /* Fix problem with pack_isam */
- diff=1.0;
- if (info->s->base.rec_reflength == 4)
- info->s->base.max_data_file_length= (uint32) ~0L;
- else
- info->s->base.max_data_file_length=
- 1L << (info->s->base.rec_reflength);
- }
- return (my_seek(info->s->kfile,0L,MY_SEEK_END,MYF(0)) >
- (ulong) (info->s->base.max_key_file_length*diff) ||
- my_seek(info->dfile,0L,MY_SEEK_END,MYF(0)) >
- (ulong) (info->s->base.max_data_file_length*diff));
-}
-
- /* Recreate table with bigger more alloced record-data */
-
-static int recreate_database(N_INFO **org_info, char *filename)
-{
- int error;
- N_INFO info;
- ISAM_SHARE share;
- N_KEYDEF *keyinfo;
- N_RECINFO *recinfo,*rec,*end;
- uint unpack;
- ulong max_records;
- char name[FN_REFLEN];
-
- error=1; /* Default error */
- info= **org_info;
- share= *(*org_info)->s;
- unpack= (share.base.options & HA_OPTION_COMPRESS_RECORD) &&
- (testflag & T_UNPACK);
- if (!(keyinfo=(N_KEYDEF*) my_alloca(sizeof(N_KEYDEF)*share.base.keys)))
- return 0;
- memcpy((byte*) keyinfo,(byte*) share.keyinfo,
- (size_t) (sizeof(N_KEYDEF)*share.base.keys));
- if (!(recinfo=(N_RECINFO*)
- my_alloca(sizeof(N_RECINFO)*(share.base.fields+1))))
- {
- my_afree((gptr) keyinfo);
- return 1;
- }
- memcpy((byte*) recinfo,(byte*) share.rec,
- (size_t) (sizeof(N_RECINFO)*(share.base.fields+1)));
- for (rec=recinfo,end=recinfo+share.base.fields; rec != end ; rec++)
- {
- if (rec->base.type == (int) FIELD_BLOB)
- rec->base.length+=sizeof(char*);
- else if (unpack && !(share.base.options & HA_OPTION_PACK_RECORD))
- rec->base.type=(int) FIELD_NORMAL;
- }
-
- if (share.base.options & HA_OPTION_COMPRESS_RECORD)
- share.base.records=max_records=share.state.records;
- else if (share.base.min_pack_length)
- max_records=(ulong) (my_seek(info.dfile,0L,MY_SEEK_END,MYF(0)) /
- (ulong) share.base.min_pack_length);
- else
- max_records=0;
- unpack= (share.base.options & HA_OPTION_COMPRESS_RECORD) &&
- (testflag & T_UNPACK);
- share.base.options&= ~HA_OPTION_TEMP_COMPRESS_RECORD;
- VOID(nisam_close(*org_info));
- if (nisam_create(fn_format(name,filename,"",N_NAME_IEXT,
- 4+ (opt_follow_links ? 16 : 0)),
- share.base.keys,keyinfo,recinfo,
- max(max_records,share.base.records),share.base.reloc,
- HA_DONT_TOUCH_DATA,
- share.base.options |
- (unpack ? HA_OPTION_TEMP_COMPRESS_RECORD
- : 0),
- (ulong) my_seek(info.dfile,0L,MY_SEEK_END,MYF(0))))
- {
- print_error("Got error %d when trying to recreate indexfile",my_errno);
- goto end;
- }
- *org_info=nisam_open(name,O_RDWR,
- (testflag & T_WAIT_FOREVER) ? HA_OPEN_WAIT_IF_LOCKED :
- (testflag & T_DESCRIPT) ? HA_OPEN_IGNORE_IF_LOCKED :
- HA_OPEN_ABORT_IF_LOCKED);
- if (!*org_info)
- {
- print_error("Got error %d when trying to open re-created indexfile",
- my_errno);
- goto end;
- }
- /* We are modifing */
- (*org_info)->s->base.options&= ~HA_OPTION_READ_ONLY_DATA;
- VOID(_nisam_readinfo(*org_info,F_WRLCK,0));
- (*org_info)->s->state.records=share.state.records;
- if (share.base.create_time)
- (*org_info)->s->base.create_time=share.base.create_time;
- (*org_info)->s->state.uniq=(*org_info)->this_uniq=
- share.state.uniq;
- (*org_info)->s->state.del=share.state.del;
- (*org_info)->s->state.dellink=share.state.dellink;
- (*org_info)->s->state.empty=share.state.empty;
- (*org_info)->s->state.data_file_length=share.state.data_file_length;
- if (update_state_info(*org_info,UPDATE_TIME | UPDATE_STAT))
- goto end;
- error=0;
-end:
- my_afree((gptr) keyinfo);
- my_afree((gptr) recinfo);
- return error;
-}
-
- /* Store long in 1,2,3 or 4 bytes */
-
-static void save_integer( byte *pos, uint pack_length, ulong value)
-{
- switch (pack_length) {
- case 4: int4store(pos,value); break;
- case 3: int3store(pos,value); break;
- case 2: int2store(pos,(uint) value); break;
- case 1: pos[0]= (char) (uchar) value; break;
- default: break;
- }
- return;
-}
-
- /* write suffix to data file if neaded */
-
-static int write_data_suffix( N_INFO *info)
-{
- if (info->s->base.options & HA_OPTION_COMPRESS_RECORD &&
- sort_info.fix_datafile)
- {
- char buff[MEMMAP_EXTRA_MARGIN];
- bzero(buff,sizeof(buff));
- if (my_b_write(&info->rec_cache,buff,sizeof(buff)))
- {
- print_error("%d when writing to datafile",my_errno);
- return 1;
- }
- read_cache.end_of_file+=sizeof(buff);
- }
- return 0;
-}
-
-
- /* Update state and isamchk_time of indexfile */
-
-static int update_state_info( N_INFO *info, uint update)
-{
- ISAM_SHARE *share=info->s;
- uint base_pos=uint2korr(info->s->state.header.base_pos);
-
- if (update & (UPDATE_STAT | UPDATE_SORT | UPDATE_TIME))
- {
- if (offsetof(N_BASE_INFO,rec_per_key) >
- uint2korr(share->state.header.base_info_length))
- {
- VOID(fputs("Internal error: Trying to change base of old table\n",
- stderr));
- }
- else
- {
- if (update & UPDATE_TIME)
- {
- share->base.isamchk_time= (long) time((time_t*) 0);
- if (!share->base.create_time)
- share->base.create_time=share->base.isamchk_time;
- if (my_pwrite(share->kfile,(gptr) &share->base.create_time,
- sizeof(long)*2,
- base_pos+offsetof(N_BASE_INFO,create_time),
- MYF(MY_NABP)))
- goto err;
- }
- if (update & (UPDATE_STAT | UPDATE_SORT))
- {
- if (my_pwrite(share->kfile,(gptr) share->base.rec_per_key,
- sizeof(long)*share->state.keys+sizeof(uint),
- base_pos+offsetof(N_BASE_INFO,rec_per_key),
- MYF(MY_NABP)))
- goto err;
- }
- }
- }
- { /* Force update of status */
- int error;
- uint r_locks=share->r_locks,w_locks=share->w_locks;
- share->r_locks=share->w_locks=0;
- error=_nisam_writeinfo(info,2);
- share->r_locks=r_locks; share->w_locks=w_locks;
- if (!error)
- return 0;
- }
-err:
- print_error("%d when updating keyfile",my_errno);
- return 1;
-}
diff --git a/isam/isamdef.h b/isam/isamdef.h
deleted file mode 100644
index 7d89730fe32..00000000000
--- a/isam/isamdef.h
+++ /dev/null
@@ -1,418 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Denna fil includeras i alla isam-filer */
-
-#define ISAM_LIBRARY
-#include <nisam.h> /* Structs & some defines */
-#ifdef THREAD
-#include <my_pthread.h>
-#include <thr_lock.h>
-#else
-#include <my_no_pthread.h>
-#endif
-#include <keycache.h>
-
-#ifdef my_write
-#undef my_write /* We want test if disk full */
-#endif
-#undef HA_SORT_ALLOWS_SAME
-#define HA_SORT_ALLOWS_SAME 128 /* Can't be > 128 in NISAM */
-
-#ifdef __WATCOMC__
-#pragma pack(2)
-#define uint uint16 /* Same format as in MSDOS */
-#endif
-#ifdef __ZTC__
-#pragma ZTC align 2
-#define uint uint16 /* Same format as in MSDOS */
-#endif
-#if defined(__WIN__) && defined(_MSC_VER)
-#pragma pack(push,isamdef,2)
-#define uint uint16
-#endif
-
-typedef struct st_state_info
-{
- struct { /* Fileheader */
- uchar file_version[4];
- uchar options[2];
- uchar header_length[2];
- uchar state_info_length[2];
- uchar base_info_length[2];
- uchar base_pos[2];
- uchar not_used[2];
- } header;
-
- ulong records; /* Antal record i databasen */
- ulong del; /* Antalet borttagna poster */
- ulong dellink; /* L{nk till n{sta borttagna */
- ulong key_file_length;
- ulong data_file_length;
- ulong splitt; /* Antal splittrade delar */
- ulong empty; /* Outnyttjat utrymme */
- ulong process; /* Vem som senast uppdatera */
- ulong loop; /* not used anymore */
- ulong uniq; /* Unik nr i denna process */
- ulong key_root[N_MAXKEY]; /* Pekare till rootblocken */
- ulong key_del[N_MAXKEY]; /* Del-l{nkar f|r n-block */
- ulong sec_index_changed; /* Updated when new sec_index */
- ulong sec_index_used; /* 1 bit for each sec index in use */
- ulong version; /* timestamp of create */
- uint keys; /* Keys in use for database */
-} N_STATE_INFO;
-
-
-typedef struct st_base_info
-{
- ulong keystart; /* Var nycklarna b|rjar */
- ulong records,reloc; /* Parameter vid skapandet */
- ulong max_pack_length; /* Max possibly length of packed rec.*/
- ulong max_data_file_length;
- ulong max_key_file_length;
- uint reclength; /* length of unpacked record */
- uint options; /* Options used */
- uint pack_reclength; /* Length of full packed rec. */
- uint min_pack_length;
- uint min_block_length;
- uint rec_reflength; /* = 2 or 3 or 4 */
- uint key_reflength; /* = 2 or 3 or 4 */
- uint keys; /* Keys defined for database */
- uint blobs; /* Number of blobs */
- uint max_block; /* Max blockl{ngd anv{nd */
- uint max_key_length; /* L{ngsta nyckel-l{ngden */
- uint fields, /* Antal f{lt i databasen */
- pack_fields, /* Packade f{lt i databasen */
- pack_bits; /* Length of packed bits */
- time_t create_time; /* Time when created database */
- time_t isamchk_time; /* Time for last recover */
- ulong rec_per_key[N_MAXKEY]; /* for sql optimizing */
- uint sortkey; /* sorted by this key */
-} N_BASE_INFO;
-
-
-#ifdef __ZTC__
-#pragma ZTC align
-#undef uint
-#endif
-#ifdef __WATCOMC__
-#pragma pack()
-#undef uint
-#endif
-#if defined(__WIN__) && defined(_MSC_VER)
-#pragma pack(pop,isamdef)
-#undef uint
-#endif
-
- /* Structs used intern in database */
-
-typedef struct st_n_blob /* Info of record */
-{
- uint offset; /* Offset to blob in record */
- uint pack_length; /* Type of packed length */
- uint length; /* Calc:ed for each record */
-} N_BLOB;
-
-
-typedef struct st_isam_pack {
- ulong header_length;
- uint ref_length;
-} N_PACK;
-
-
-typedef struct st_isam_share { /* Shared between opens */
- N_STATE_INFO state;
- N_BASE_INFO base;
- N_KEYDEF *keyinfo; /* Nyckelinfo */
- N_RECINFO *rec; /* Pointer till recdata */
- N_PACK pack; /* Data about packed records */
- N_BLOB *blobs; /* Pointer to blobs */
- char *filename; /* Name of indexfile */
- byte *file_map; /* mem-map of file if possible */
- ulong this_process; /* processid */
- ulong last_process; /* For table-change-check */
- ulong last_version; /* Version on start */
- uint rec_reflength; /* rec_reflength in use now */
- int kfile; /* Shared keyfile */
- int mode; /* mode of file on open */
- int reopen; /* How many times reopened */
- uint state_length;
- uint w_locks,r_locks; /* Number of read/write locks */
- uint min_pack_length; /* Theese is used by packed data */
- uint max_pack_length;
- uint blocksize; /* blocksize of keyfile */
- my_bool changed,not_flushed; /* If changed since lock */
- int rnd; /* rnd-counter */
- DECODE_TREE *decode_trees;
- uint16 *decode_tables;
- enum data_file_type data_file_type;
- int (*read_record)(struct st_isam_info*, ulong, byte*);
- int (*write_record)(struct st_isam_info*, const byte*);
- int (*update_record)(struct st_isam_info*, ulong, const byte*);
- int (*delete_record)(struct st_isam_info*);
- int (*read_rnd)(struct st_isam_info*, byte*, ulong, int);
- int (*compare_record)(struct st_isam_info*, const byte *);
-#ifdef THREAD
- THR_LOCK lock;
- pthread_mutex_t intern_lock; /* Locking for use with _locking */
-#endif
-} ISAM_SHARE;
-
-
-typedef uint bit_type;
-
-typedef struct st_bit_buff { /* Used for packing of record */
- bit_type current_byte;
- uint bits;
- uchar *pos,*end;
- uint error;
-} BIT_BUFF;
-
-
-typedef struct st_isam_info {
- ISAM_SHARE *s; /* Shared between open:s */
- N_BLOB *blobs; /* Pointer to blobs */
- int dfile; /* The datafile */
- BIT_BUFF bit_buff;
- uint options;
- uint opt_flag; /* Optim. for space/speed */
- uint update; /* If file changed since open */
- char *filename; /* parameter to open filename */
- ulong this_uniq; /* uniq filenumber or thread */
- ulong last_uniq; /* last uniq number */
- ulong this_loop; /* counter for this open */
- ulong last_loop; /* last used counter */
- ulong lastpos, /* Last record position */
- nextpos; /* Position to next record */
- ulong int_pos; /* Intern variabel */
- ulong dupp_key_pos; /* Position to record with dupp key */
- ulong last_search_keypage;
- ulong save_lastpos;
- uint packed_length; /* Length of found, packed record */
- uint alloced_rec_buff_length; /* Max recordlength malloced */
- uchar *buff, /* Temp area for key */
- *lastkey; /* Last used search key */
- byte *rec_buff, /* Tempbuff for recordpack */
- *rec_alloc; /* Malloced area for record */
- uchar *int_keypos, /* Intern variabel */
- *int_maxpos; /* Intern variabel */
- int lastinx; /* Last used index */
- int errkey; /* Got last error on this key */
- uint data_changed; /* Somebody has changed data */
- int lock_type; /* How database was locked */
- int tmp_lock_type; /* When locked by readinfo */
- int was_locked; /* Was locked in panic */
- myf lock_wait; /* is 0 or MY_DONT_WAIT */
- my_bool page_changed;
- my_bool buff_used;
- uint save_update; /* When using KEY_READ */
- int save_lastinx;
- int (*read_record)(struct st_isam_info*, ulong, byte*);
- LIST open_list;
- IO_CACHE rec_cache; /* When cacheing records */
-#ifdef THREAD
- THR_LOCK_DATA lock;
-#endif
-} N_INFO;
-
-
- /* Some defines used by isam-funktions */
-
-#define USE_HOLE_KEY 0 /* Use hole key in _nisam_search() */
-#define F_EXTRA_LCK -1
-
- /* bits in opt_flag */
-#define MEMMAP_USED 32
-#define REMEMBER_OLD_POS 64
-
-#define getint(x) ((uint) (uint16) *((int16*) (x)) & 32767)
-#define putint(x,y,nod) (*((uint16*) (x))= ((nod ? (uint16) 32768 : 0)+(uint16) (y)))
-#ifdef WORDS_BIGENDIAN
-#define test_if_nod(x) (x[0] & 128 ? info->s->base.key_reflength : 0)
-#else
-#define test_if_nod(x) (x[1] & 128 ? info->s->base.key_reflength : 0)
-#endif
-
-#define N_MIN_BLOCK_LENGTH 8 /* Because of delete-link */
-#define N_EXTEND_BLOCK_LENGTH 20 /* Don't use to small record-blocks */
-#define N_SPLITT_LENGTH ((N_EXTEND_BLOCK_LENGTH+3)*2)
-#define MAX_DYN_BLOCK_HEADER 11 /* Max prefix of record-block */
-#define DYN_DELETE_BLOCK_HEADER 8 /* length of delete-block-header */
-#define MEMMAP_EXTRA_MARGIN 7 /* Write this as a suffix for file */
-#define INDEX_BLOCK_MARGIN 16 /* Safety margin for .ISM tables */
-
-#define PACK_TYPE_SELECTED 1 /* Bits in field->pack_type */
-#define PACK_TYPE_SPACE_FIELDS 2
-#define PACK_TYPE_ZERO_FILL 4
-
-#ifdef THREAD
-extern pthread_mutex_t THR_LOCK_isam;
-#endif
-
- /* Some extern variables */
-
-extern LIST *nisam_open_list;
-extern uchar NEAR nisam_file_magic[],NEAR nisam_pack_file_magic[];
-extern uint NEAR nisam_read_vec[],nisam_quick_table_bits;
-extern File nisam_log_file;
-
- /* This is used by _nisam_get_pack_key_length och _nisam_store_key */
-
-typedef struct st_s_param
-{
- uint ref_length,key_length,
- n_ref_length,
- n_length,
- totlength,
- part_of_prev_key,prev_length;
- uchar *key, *prev_key;
-} S_PARAM;
-
- /* Prototypes for intern functions */
-
-extern int _nisam_read_dynamic_record(N_INFO *info,ulong filepos,byte *buf);
-extern int _nisam_write_dynamic_record(N_INFO*, const byte*);
-extern int _nisam_update_dynamic_record(N_INFO*, ulong, const byte*);
-extern int _nisam_delete_dynamic_record(N_INFO *info);
-extern int _nisam_cmp_dynamic_record(N_INFO *info,const byte *record);
-extern int _nisam_read_rnd_dynamic_record(N_INFO *, byte *,ulong, int);
-extern int _nisam_write_blob_record(N_INFO*, const byte*);
-extern int _nisam_update_blob_record(N_INFO*, ulong, const byte*);
-extern int _nisam_read_static_record(N_INFO *info,ulong filepos,byte *buf);
-extern int _nisam_write_static_record(N_INFO*, const byte*);
-extern int _nisam_update_static_record(N_INFO*, ulong, const byte*);
-extern int _nisam_delete_static_record(N_INFO *info);
-extern int _nisam_cmp_static_record(N_INFO *info,const byte *record);
-extern int _nisam_read_rnd_static_record(N_INFO*, byte *,ulong, int);
-extern int _nisam_ck_write(N_INFO *info,uint keynr,uchar *key);
-extern int _nisam_enlarge_root(N_INFO *info,uint keynr,uchar *key);
-extern int _nisam_insert(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- uchar *anc_buff,uchar *key_pos,uchar *key_buff,
- uchar *father_buff, uchar *father_keypos,
- ulong father_page);
-extern int _nisam_splitt_page(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- uchar *buff,uchar *key_buff);
-extern uchar *_nisam_find_half_pos(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,
- uchar *key);
-extern uint _nisam_get_pack_key_length(N_KEYDEF *keyinfo,uint nod_flag,
- uchar *key_pos,uchar *key_buff,
- uchar *key, S_PARAM *s_temp);
-extern void _nisam_store_key(N_KEYDEF *keyinfo,uchar *key_pos,
- S_PARAM *s_temp);
-extern int _nisam_ck_delete(N_INFO *info,uint keynr,uchar *key);
-extern int _nisam_readinfo(N_INFO *info,int lock_flag,int check_keybuffer);
-extern int _nisam_writeinfo(N_INFO *info, uint flag);
-extern int _nisam_test_if_changed(N_INFO *info);
-extern int _nisam_check_index(N_INFO *info,int inx);
-extern int _nisam_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uint key_len,uint nextflag,ulong pos);
-extern int _nisam_bin_search(struct st_isam_info *info,N_KEYDEF *keyinfo,uchar *page,uchar *key,uint key_len,uint comp_flag,uchar * *ret_pos,uchar *buff);
-extern int _nisam_seq_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,uchar *key,uint key_len,uint comp_flag,uchar * *ret_pos,uchar *buff);
-extern ulong _nisam_kpos(uint nod_flag,uchar *after_key);
-extern void _nisam_kpointer(N_INFO *info,uchar *buff,ulong pos);
-extern ulong _nisam_dpos(N_INFO *info, uint nod_flag,uchar *after_key);
-extern void _nisam_dpointer(N_INFO *info, uchar *buff,ulong pos);
-extern int _nisam_key_cmp(N_KEYSEG *keyseg,uchar *a,uchar *b,
- uint key_length,uint nextflag);
-extern uint _nisam_get_key(N_KEYDEF *keyinfo,uint nod_flag,uchar * *page,uchar *key);
-extern uint _nisam_get_static_key(N_KEYDEF *keyinfo,uint nod_flag,uchar * *page,uchar *key);
-extern uchar *_nisam_get_last_key(N_INFO *info,N_KEYDEF *keyinfo,uchar *keypos,uchar *lastkey,uchar *endpos);
-extern uint _nisam_keylength(N_KEYDEF *keyinfo,uchar *key);
-extern uchar *_nisam_move_key(N_KEYDEF *keyinfo,uchar *to,uchar *from);
-extern int _nisam_search_next(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,uint nextflag,ulong pos);
-extern int _nisam_search_first(N_INFO *info,N_KEYDEF *keyinfo,ulong pos);
-extern int _nisam_search_last(N_INFO *info,N_KEYDEF *keyinfo,ulong pos);
-extern uchar *_nisam_fetch_keypage(N_INFO *info,N_KEYDEF *keyinfo,my_off_t page,
- uchar *buff,int return_buffer);
-extern int _nisam_write_keypage(N_INFO *info,N_KEYDEF *keyinfo,my_off_t page,
- uchar *buff);
-extern int _nisam_dispose(N_INFO *info,N_KEYDEF *keyinfo,my_off_t pos);
-extern ulong _nisam_new(N_INFO *info,N_KEYDEF *keyinfo);
-extern uint _nisam_make_key(N_INFO *info,uint keynr,uchar *key,
- const char *record,ulong filepos);
-extern uint _nisam_pack_key(N_INFO *info,uint keynr,uchar *key,uchar *old,uint key_length);
-extern int _nisam_read_key_record(N_INFO *info,ulong filepos,byte *buf);
-extern int _nisam_read_cache(IO_CACHE *info,byte *buff,ulong pos,
- uint length,int re_read_if_possibly);
-extern byte *fix_rec_buff_for_blob(N_INFO *info,uint blob_length);
-extern uint _nisam_rec_unpack(N_INFO *info,byte *to,byte *from,
- uint reclength);
-my_bool _nisam_rec_check(N_INFO *info,const char *from);
-extern int _nisam_write_part_record(N_INFO *info,ulong filepos,uint length,
- ulong next_filepos,byte **record,
- uint *reclength,int *flag);
-extern void _nisam_print_key(FILE *stream,N_KEYSEG *keyseg,const uchar *key);
-extern my_bool _nisam_read_pack_info(N_INFO *info,pbool fix_keys);
-extern int _nisam_read_pack_record(N_INFO *info,ulong filepos,byte *buf);
-extern int _nisam_read_rnd_pack_record(N_INFO*, byte *,ulong, int);
-extern int _nisam_pack_rec_unpack(N_INFO *info,byte *to,byte *from,
- uint reclength);
-extern ulong _nisam_checksum(const byte *mem, uint count);
-
-typedef struct st_sortinfo {
- uint key_length;
- ulong max_records;
- int (*key_cmp)(const void *, const void *, const void *);
- int (*key_read)(void *buff);
- int (*key_write)(const void *buff);
- void (*lock_in_memory)(void);
-} SORT_PARAM;
-
-int _create_index_by_sort(SORT_PARAM *info,pbool no_messages,
- uint sortbuff_size);
-
-#define BLOCK_INFO_HEADER_LENGTH 11
-
-typedef struct st_block_info { /* Parameter to _nisam_get_block_info */
- uchar header[BLOCK_INFO_HEADER_LENGTH];
- uint rec_len;
- uint data_len;
- uint block_len;
- ulong filepos; /* Must be ulong on Alpha! */
- ulong next_filepos;
- uint second_read;
-} BLOCK_INFO;
-
- /* bits in return from _nisam_get_block_info */
-
-#define BLOCK_FIRST 1
-#define BLOCK_LAST 2
-#define BLOCK_DELETED 4
-#define BLOCK_ERROR 8 /* Wrong data */
-#define BLOCK_SYNC_ERROR 16 /* Right data at wrong place */
-#define BLOCK_FATAL_ERROR 32 /* hardware-error */
-
-enum nisam_log_commands {
- LOG_OPEN,LOG_WRITE,LOG_UPDATE,LOG_DELETE,LOG_CLOSE,LOG_EXTRA,LOG_LOCK
-};
-
-#define nisam_log_simple(a,b,c,d) if (nisam_log_file >= 0) _nisam_log(a,b,c,d)
-#define nisam_log_command(a,b,c,d,e) if (nisam_log_file >= 0) _nisam_log_command(a,b,c,d,e)
-#define nisam_log_record(a,b,c,d,e) if (nisam_log_file >= 0) _nisam_log_record(a,b,c,d,e)
-
-extern uint _nisam_get_block_info(BLOCK_INFO *,File, ulong);
-extern uint _nisam_rec_pack(N_INFO *info,byte *to,const byte *from);
-extern uint _nisam_pack_get_block_info(BLOCK_INFO *, uint, File, ulong);
-extern uint _calc_total_blob_length(N_INFO *info,const byte *record);
-extern void _nisam_log(enum nisam_log_commands command,N_INFO *info,
- const byte *buffert,uint length);
-extern void _nisam_log_command(enum nisam_log_commands command,
- N_INFO *info, const byte *buffert,
- uint length, int result);
-extern void _nisam_log_record(enum nisam_log_commands command,N_INFO *info,
- const byte *record,ulong filepos,
- int result);
-extern my_bool _nisam_memmap_file(N_INFO *info);
-extern void _nisam_unmap_file(N_INFO *info);
diff --git a/isam/isamlog.c b/isam/isamlog.c
deleted file mode 100644
index 5cc204b26aa..00000000000
--- a/isam/isamlog.c
+++ /dev/null
@@ -1,853 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* write whats in isam.log */
-
-#ifndef USE_MY_FUNC
-#define USE_MY_FUNC
-#endif
-
-#include "isamdef.h"
-#include <my_tree.h>
-#include <stdarg.h>
-#ifdef HAVE_GETRUSAGE
-#include <sys/resource.h>
-#endif
-
-#define FILENAME(A) (A ? A->show_name : "Unknown")
-
-struct isamlog_file_info {
- long process;
- int filenr,id;
- my_string name,show_name,record;
- N_INFO *isam;
- bool closed,used;
- ulong accessed;
-};
-
-struct test_if_open_param {
- my_string name;
- int max_id;
-};
-
-struct st_access_param
-{
- ulong min_accessed;
- struct isamlog_file_info *found;
-};
-
-#define NO_FILEPOS (ulong) ~0L
-
-extern int main(int argc,char * *argv);
-static void get_options(int *argc,char ***argv);
-static int examine_log(my_string file_name,char **table_names);
-static int read_string(IO_CACHE *file,gptr *to,uint length);
-static int file_info_compare(void *a,void *b);
-static int test_if_open(struct isamlog_file_info *key,element_count count,
- struct test_if_open_param *param);
-static void fix_blob_pointers(N_INFO *isam,byte *record);
-static uint set_maximum_open_files(uint);
-static int test_when_accessed(struct isamlog_file_info *key,element_count count,
- struct st_access_param *access_param);
-static void file_info_free(struct isamlog_file_info *info);
-static int close_some_file(TREE *tree);
-static int reopen_closed_file(TREE *tree,struct isamlog_file_info *file_info);
-static int find_record_with_key(struct isamlog_file_info *file_info,
- byte *record);
-static void printf_log(const char *str,...);
-static bool cmp_filename(struct isamlog_file_info *file_info,my_string name);
-
-static uint verbose=0,update=0,test_info=0,max_files=0,re_open_count=0,
- recover=0,prefix_remove=0,opt_processes=0;
-static my_string log_filename=0,filepath=0,write_filename=0,record_pos_file=0;
-static ulong com_count[10][3],number_of_commands=(ulong) ~0L,start_offset=0,
- record_pos= NO_FILEPOS,isamlog_filepos,isamlog_process;
-static const char *command_name[]=
-{"open","write","update","delete","close","extra","lock","re-open",NullS};
-
-
-int main(int argc, char **argv)
-{
- int error,i,first;
- ulong total_count,total_error,total_recover;
- MY_INIT(argv[0]);
-
- log_filename=nisam_log_filename;
- get_options(&argc,&argv);
- /* Nr of isam-files */
- max_files=(set_maximum_open_files(min(max_files,8))-6)/2;
-
- if (update)
- printf("Trying to %s ISAM files according to log '%s'\n",
- (recover ? "recover" : "update"),log_filename);
- error= examine_log(log_filename,argv);
- if (update && ! error)
- puts("Tables updated successfully");
- total_count=total_error=total_recover=0;
- for (i=first=0 ; command_name[i] ; i++)
- {
- if (com_count[i][0])
- {
- if (!first++)
- {
- if (verbose || update)
- puts("");
- puts("Commands Used count Errors Recover errors");
- }
- printf("%-12s%9ld%10ld%17ld\n",command_name[i],com_count[i][0],
- com_count[i][1],com_count[i][2]);
- total_count+=com_count[i][0];
- total_error+=com_count[i][1];
- total_recover+=com_count[i][2];
- }
- }
- if (total_count)
- printf("%-12s%9ld%10ld%17ld\n","Total",total_count,total_error,
- total_recover);
- if (re_open_count)
- printf("Had to do %d re-open because of too few possibly open files\n",
- re_open_count);
- VOID(nisam_panic(HA_PANIC_CLOSE));
- my_end(test_info ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
- exit(error);
- return 0; /* No compiler warning */
-} /* main */
-
-
-static void get_options(register int *argc, register char ***argv)
-{
- int help,version;
- const char *pos,*usage;
- char option;
-
- help=0;
- usage="Usage: %s [-?iruvIPV] [-c #] [-f #] [-F filepath/] [-o #] [-R file recordpos] [-w write_file] [log-filename [table ...]] \n";
- pos= "";
-
- while (--*argc > 0 && *(pos = *(++*argv)) == '-' ) {
- while (*++pos)
- {
- version=0;
- switch((option=*pos)) {
- case '#':
- DBUG_PUSH (++pos);
- pos=" "; /* Skip rest of arg */
- break;
- case 'c':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- number_of_commands=(ulong) atol(pos);
- pos=" ";
- break;
- case 'u':
- update=1;
- break;
- case 'f':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- max_files=(uint) atoi(pos);
- pos=" ";
- break;
- case 'i':
- test_info=1;
- break;
- case 'o':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- start_offset=(ulong) atol(pos);
- pos=" ";
- break;
- case 'p':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- prefix_remove=atoi(pos);
- break;
- case 'r':
- update=1;
- recover++;
- break;
- case 'P':
- opt_processes=1;
- break;
- case 'R':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- record_pos_file=(char*) pos;
- if (!--*argc)
- goto err;
- record_pos=(ulong) atol(*(++*argv));
- pos= " ";
- break;
- case 'v':
- verbose++;
- break;
- case 'w':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- write_filename=(char*) pos;
- pos=" ";
- break;
- case 'F':
- if (! *++pos)
- {
- if (!--*argc)
- goto err;
- else
- pos= *(++*argv);
- }
- filepath= (char*) pos;
- pos=" ";
- break;
- case 'V':
- version=1;
- /* Fall through */
- case 'I':
- case '?':
- printf("%s Ver 3.3 for %s at %s\n",my_progname,SYSTEM_TYPE,
- MACHINE_TYPE);
- puts("By Monty, for your professional use\n");
- if (version)
- break;
- puts("Write info about whats in a ISAM log file.");
- printf("If no file name is given %s is used\n",log_filename);
- puts("");
- printf(usage,my_progname);
- puts("");
- puts("Options: -? or -I \"Info\" -V \"version\" -c \"do only # commands\"");
- puts(" -f \"max open files\" -F \"filepath\" -i \"extra info\"");
- puts(" -o \"offset\" -p # \"remove # components from path\"");
- puts(" -r \"recover\" -R \"file recordposition\"");
- puts(" -u \"update\" -v \"verbose\" -w \"write file\"");
- puts(" -P \"processes\"");
- puts("\nOne can give a second and a third '-v' for more verbose.");
- puts("Normaly one does a update (-u).");
- puts("If a recover is done all writes and all possibly updates and deletes is done\nand errors are only counted.");
- puts("If one gives table names as arguments only these tables will be updated\n");
- help=1;
- break;
- default:
- printf("illegal option: \"-%c\"\n",*pos);
- break;
- }
- }
- }
- if (! *argc)
- {
- if (help)
- exit(0);
- (*argv)++;
- }
- if (*argc >= 1)
- {
- log_filename=(char*) pos;
- (*argc)--;
- (*argv)++;
- }
- return;
- err:
- VOID(fprintf(stderr,"option \"%c\" used without or with wrong argument\n",
- option));
- exit(1);
-}
-
-
-static int examine_log(my_string file_name, char **table_names)
-{
- uint command,result,files_open;
- ulong access_time,length;
- uint32 filepos;
- int lock_command,ni_result;
- char isam_file_name[FN_REFLEN];
- uchar head[20];
- gptr buff;
- struct test_if_open_param open_param;
- IO_CACHE cache;
- File file;
- FILE *write_file;
- enum ha_extra_function extra_command;
- TREE tree;
- struct isamlog_file_info file_info,*curr_file_info;
- char llbuff[22],llbuff2[22];
- DBUG_ENTER("examine_log");
-
- if ((file=my_open(file_name,O_RDONLY,MYF(MY_WME))) < 0)
- DBUG_RETURN(1);
- write_file=0;
- if (write_filename)
- {
- if (!(write_file=my_fopen(write_filename,O_WRONLY,MYF(MY_WME))))
- {
- my_close(file,MYF(0));
- DBUG_RETURN(1);
- }
- }
-
- init_io_cache(&cache,file,0,READ_CACHE,start_offset,0,MYF(0));
- bzero((gptr) com_count,sizeof(com_count));
- init_tree(&tree,0,0,sizeof(file_info),(qsort_cmp2) file_info_compare,1,
- (tree_element_free) file_info_free, NULL);
- VOID(init_key_cache(dflt_key_cache,KEY_CACHE_BLOCK_SIZE,KEY_CACHE_SIZE,
- 0,0));
- files_open=0; access_time=0;
- while (access_time++ != number_of_commands &&
- !my_b_read(&cache,(byte*) head,9))
- {
- isamlog_filepos=my_b_tell(&cache)-9L;
- file_info.filenr=uint2korr(head+1);
- isamlog_process=file_info.process=(long) uint4korr(head+3);
- if (!opt_processes)
- file_info.process=0;
- result=uint2korr(head+7);
- if ((curr_file_info=(struct isamlog_file_info*)
- tree_search(&tree, &file_info, tree.custom_arg)))
- {
- curr_file_info->accessed=access_time;
- if (update && curr_file_info->used && curr_file_info->closed)
- {
- if (reopen_closed_file(&tree,curr_file_info))
- {
- command=sizeof(com_count)/sizeof(com_count[0][0])/3;
- result=0;
- goto com_err;
- }
- }
- }
- command=(uint) head[0];
- if (command < sizeof(com_count)/sizeof(com_count[0][0])/3 &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- {
- com_count[command][0]++;
- if (result)
- com_count[command][1]++;
- }
- switch ((enum nisam_log_commands) command) {
- case LOG_OPEN:
- if (!table_names[0])
- {
- com_count[command][0]--; /* Must be counted explicite */
- if (result)
- com_count[command][1]--;
- }
-
- if (curr_file_info)
- printf("\nWarning: %s is opened with same process and filenumber\nMaybe you should use the -P option ?\n",
- curr_file_info->show_name);
- if (my_b_read(&cache,(byte*) head,2))
- goto err;
- file_info.name=0;
- file_info.show_name=0;
- file_info.record=0;
- if (read_string(&cache,(gptr*) &file_info.name,(uint) uint2korr(head)))
- goto err;
- {
- uint i;
- char *pos,*to;
-
- /* Fix if old DOS files to new format */
- for (pos=file_info.name; (pos=strchr(pos,'\\')) ; pos++)
- *pos= '/';
-
- pos=file_info.name;
- for (i=0 ; i < prefix_remove ; i++)
- {
- char *next;
- if (!(next=strchr(pos,'/')))
- break;
- pos=next+1;
- }
- to=isam_file_name;
- if (filepath)
- to=convert_dirname(isam_file_name, filepath, NullS);
- strmov(to,pos);
- fn_ext(isam_file_name)[0]=0; /* Remove extension */
- }
- open_param.name=file_info.name;
- open_param.max_id=0;
- VOID(tree_walk(&tree,(tree_walk_action) test_if_open,(void*) &open_param,
- left_root_right));
- file_info.id=open_param.max_id+1;
- file_info.show_name=my_memdup(isam_file_name,
- (uint) strlen(isam_file_name)+6,
- MYF(MY_WME));
- if (file_info.id > 1)
- sprintf(strend(file_info.show_name),"<%d>",file_info.id);
- file_info.closed=1;
- file_info.accessed=access_time;
- file_info.used=1;
- if (table_names[0])
- {
- char **name;
- file_info.used=0;
- for (name=table_names ; *name ; name++)
- {
- if (!strcmp(*name,isam_file_name))
- file_info.used=1; /* Update/log only this */
- }
- }
- if (update && file_info.used)
- {
- if (files_open >= max_files)
- {
- if (close_some_file(&tree))
- goto com_err;
- files_open--;
- }
- if (!(file_info.isam= nisam_open(isam_file_name,O_RDWR,
- HA_OPEN_WAIT_IF_LOCKED)))
- goto com_err;
- if (!(file_info.record=my_malloc(file_info.isam->s->base.reclength,
- MYF(MY_WME))))
- goto end;
- files_open++;
- file_info.closed=0;
- }
- VOID(tree_insert(&tree, (gptr) &file_info, 0, tree.custom_arg));
- if (file_info.used)
- {
- if (verbose && !record_pos_file)
- printf_log("%s: open -> %d",file_info.show_name, file_info.filenr);
- com_count[command][0]++;
- if (result)
- com_count[command][1]++;
- }
- break;
- case LOG_CLOSE:
- if (verbose && !record_pos_file &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- printf_log("%s: %s -> %d",FILENAME(curr_file_info),
- command_name[command],result);
- if (curr_file_info)
- {
- if (!curr_file_info->closed)
- files_open--;
- VOID(tree_delete(&tree, (gptr) curr_file_info, tree.custom_arg));
- }
- break;
- case LOG_EXTRA:
- if (my_b_read(&cache,(byte*) head,sizeof(extra_command)))
- goto err;
- memcpy_fixed(&extra_command,head,sizeof(extra_command));
- if (verbose && !record_pos_file &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- printf_log("%s: %s(%d) -> %d",FILENAME(curr_file_info),
- command_name[command], (int) extra_command,result);
- if (update && curr_file_info && !curr_file_info->closed)
- {
- if (nisam_extra(curr_file_info->isam,extra_command) != (int) result)
- {
- fflush(stdout);
- VOID(fprintf(stderr,
- "Warning: error %d, expected %d on command %s at %s\n",
- my_errno,result,command_name[command],
- llstr(isamlog_filepos,llbuff)));
- fflush(stderr);
- }
- }
- break;
- case LOG_DELETE:
- if (my_b_read(&cache,(byte*) head,sizeof(filepos)))
- goto err;
- memcpy_fixed(&filepos,head,sizeof(filepos));
- if (verbose && (!record_pos_file ||
- ((record_pos == filepos || record_pos == NO_FILEPOS) &&
- !cmp_filename(curr_file_info,record_pos_file))) &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- printf_log("%s: %s at %ld -> %d",FILENAME(curr_file_info),
- command_name[command],(long) filepos,result);
- if (update && curr_file_info && !curr_file_info->closed)
- {
- if (nisam_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
- {
- if (!recover)
- goto com_err;
- com_count[command][2]++; /* Mark error */
- }
- ni_result=nisam_delete(curr_file_info->isam,curr_file_info->record);
- if ((ni_result == 0 && result) ||
- (ni_result && (uint) my_errno != result))
- {
- if (!recover)
- goto com_err;
- if (ni_result)
- com_count[command][2]++; /* Mark error */
- if (verbose)
- printf_log("error: Got result %d from mi_delete instead of %d",
- ni_result, result);
- }
- }
- break;
- case LOG_WRITE:
- case LOG_UPDATE:
- if (my_b_read(&cache,(byte*) head,8))
- goto err;
- filepos=uint4korr(head);
- length=uint4korr(head+4);
- buff=0;
- if (read_string(&cache,&buff,(uint) length))
- goto err;
- if ((!record_pos_file ||
- ((record_pos == filepos || record_pos == NO_FILEPOS) &&
- !cmp_filename(curr_file_info,record_pos_file))) &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- {
- if (write_file &&
- (my_fwrite(write_file,buff,length,MYF(MY_WAIT_IF_FULL | MY_NABP))))
- goto end;
- if (verbose)
- printf_log("%s: %s at %ld, length=%ld -> %d",
- FILENAME(curr_file_info),
- command_name[command], filepos,length,result);
- }
- if (update && curr_file_info && !curr_file_info->closed)
- {
- if (curr_file_info->isam->s->base.blobs)
- fix_blob_pointers(curr_file_info->isam,buff);
- if ((enum nisam_log_commands) command == LOG_UPDATE)
- {
- if (nisam_rrnd(curr_file_info->isam,curr_file_info->record,filepos))
- {
- if (!recover)
- {
- result=0;
- goto com_err;
- }
- if (verbose)
- printf_log("error: Didn't find row to update with mi_rrnd");
- if (recover == 1 || result ||
- find_record_with_key(curr_file_info,buff))
- {
- com_count[command][2]++; /* Mark error */
- break;
- }
- }
- ni_result=nisam_update(curr_file_info->isam,curr_file_info->record,
- buff);
- if ((ni_result == 0 && result) ||
- (ni_result && (uint) my_errno != result))
- {
- if (!recover)
- goto com_err;
- if (verbose)
- printf_log("error: Got result %d from mi_update instead of %d",
- ni_result, result);
- if (ni_result)
- com_count[command][2]++; /* Mark error */
- }
- }
- else
- {
- ni_result=nisam_write(curr_file_info->isam,buff);
- if ((ni_result == 0 && result) ||
- (ni_result && (uint) my_errno != result))
- {
- if (!recover)
- goto com_err;
- if (ni_result)
- com_count[command][2]++; /* Mark error */
- }
- if (! recover && filepos != curr_file_info->isam->lastpos)
- {
- printf("error: Wrote at position: %s, should have been %s",
- llstr(curr_file_info->isam->lastpos,llbuff),
- llstr(filepos,llbuff2));
- goto end;
- }
- }
- }
- my_free(buff,MYF(0));
- break;
- case LOG_LOCK:
- if (my_b_read(&cache,(byte*) head,sizeof(lock_command)))
- goto err;
- memcpy_fixed(&lock_command,head,sizeof(lock_command));
- if (verbose && !record_pos_file &&
- (!table_names[0] || (curr_file_info && curr_file_info->used)))
- printf_log("%s: %s(%d) -> %d\n",FILENAME(curr_file_info),
- command_name[command],lock_command,result);
- if (update && curr_file_info && !curr_file_info->closed)
- {
- if (nisam_lock_database(curr_file_info->isam,lock_command) !=
- (int) result)
- goto com_err;
- }
- break;
- default:
- VOID(fprintf(stderr,
- "Error: found unknown command %d in logfile, aborted\n",
- command));
- fflush(stderr);
- goto end;
- }
- }
- end_key_cache(dflt_key_cache,1);
- delete_tree(&tree);
- VOID(end_io_cache(&cache));
- VOID(my_close(file,MYF(0)));
- if (write_file && my_fclose(write_file,MYF(MY_WME)))
- DBUG_RETURN(1);
- DBUG_RETURN(0);
-
- err:
- fflush(stdout);
- VOID(fprintf(stderr,"Got error %d when reading from logfile\n",my_errno));
- fflush(stderr);
- goto end;
- com_err:
- fflush(stdout);
- VOID(fprintf(stderr,"Got error %d, expected %d on command %s at %s\n",
- my_errno,result,command_name[command],
- llstr(isamlog_filepos,llbuff)));
- fflush(stderr);
- end:
- end_key_cache(dflt_key_cache,1);
- delete_tree(&tree);
- VOID(end_io_cache(&cache));
- VOID(my_close(file,MYF(0)));
- if (write_file)
- VOID(my_fclose(write_file,MYF(MY_WME)));
- DBUG_RETURN(1);
-}
-
-
-static int read_string(IO_CACHE *file, reg1 gptr *to, reg2 uint length)
-{
- DBUG_ENTER("read_string");
-
- if (*to)
- my_free((gptr) *to,MYF(0));
- if (!(*to= (gptr) my_malloc(length+1,MYF(MY_WME))) ||
- my_b_read(file,(byte*) *to,length))
- {
- if (*to)
- my_free(*to,MYF(0));
- *to= 0;
- DBUG_RETURN(1);
- }
- *((char*) *to+length)= '\0';
- DBUG_RETURN (0);
-} /* read_string */
-
-
-static int file_info_compare(void *a, void *b)
-{
- long lint;
-
- if ((lint=((struct isamlog_file_info*) a)->process -
- ((struct isamlog_file_info*) b)->process))
- return lint < 0L ? -1 : 1;
- return (((struct isamlog_file_info*) a)->filenr -
- ((struct isamlog_file_info*) b)->filenr);
-}
-
- /* ARGSUSED */
-
-static int test_if_open (struct isamlog_file_info *key,
- element_count count __attribute__((unused)),
- struct test_if_open_param *param)
-{
- if (!strcmp(key->name,param->name) && key->id > param->max_id)
- param->max_id=key->id;
- return 0;
-}
-
-
-static void fix_blob_pointers( N_INFO *info, byte *record)
-{
- byte *pos;
- N_BLOB *blob,*end;
-
- pos=record+info->s->base.reclength;
- for (end=info->blobs+info->s->base.blobs, blob= info->blobs;
- blob != end ;
- blob++)
- {
- bmove(record+blob->offset+blob->pack_length,&pos,sizeof(char*));
- pos+=_calc_blob_length(blob->pack_length,record+blob->offset);
- }
-}
-
-static uint set_maximum_open_files(uint maximum_files)
-{
-#if defined(HAVE_GETRUSAGE) && defined(RLIMIT_NOFILE)
- struct rlimit rlimit;
- int old_max;
-
- if (maximum_files > MY_NFILE)
- maximum_files=MY_NFILE; /* Don't crash my_open */
-
- if (!getrlimit(RLIMIT_NOFILE,&rlimit))
- {
- old_max=rlimit.rlim_max;
- if (maximum_files && (int) maximum_files > old_max)
- rlimit.rlim_max=maximum_files;
- rlimit.rlim_cur=rlimit.rlim_max;
- if (setrlimit(RLIMIT_NOFILE,&rlimit))
- {
- if (old_max != (int) maximum_files)
- { /* Set as much as we can */
- rlimit.rlim_max=rlimit.rlim_cur=old_max;
- setrlimit(RLIMIT_NOFILE,&rlimit);
- }
- }
- getrlimit(RLIMIT_NOFILE,&rlimit); /* Read if broken setrlimit */
- if (maximum_files && maximum_files < rlimit.rlim_cur)
- VOID(fprintf(stderr,"Warning: Error from setrlimit: Max open files is %d\n",old_max));
- return rlimit.rlim_cur;
- }
-#endif
- return min(maximum_files,MY_NFILE);
-}
-
- /* close the file with hasn't been accessed for the longest time */
- /* ARGSUSED */
-
-static int test_when_accessed (struct isamlog_file_info *key,
- element_count count __attribute__((unused)),
- struct st_access_param *access_param)
-{
- if (key->accessed < access_param->min_accessed && ! key->closed)
- {
- access_param->min_accessed=key->accessed;
- access_param->found=key;
- }
- return 0;
-}
-
-
-static void file_info_free(struct isamlog_file_info *fileinfo)
-{
- DBUG_ENTER("file_info_free");
- if (update)
- {
- if (!fileinfo->closed)
- VOID(nisam_close(fileinfo->isam));
- if (fileinfo->record)
- my_free(fileinfo->record,MYF(0));
- }
- my_free(fileinfo->name,MYF(0));
- my_free(fileinfo->show_name,MYF(0));
- DBUG_VOID_RETURN;
-}
-
-
-
-static int close_some_file(TREE *tree)
-{
- struct st_access_param access_param;
-
- access_param.min_accessed=LONG_MAX;
- access_param.found=0;
-
- VOID(tree_walk(tree,(tree_walk_action) test_when_accessed,
- (void*) &access_param,left_root_right));
- if (!access_param.found)
- return 1; /* No open file that is possibly to close */
- if (nisam_close(access_param.found->isam))
- return 1;
- access_param.found->closed=1;
- return 0;
-}
-
-
-static int reopen_closed_file(TREE *tree, struct isamlog_file_info *fileinfo)
-{
- char name[FN_REFLEN];
- if (close_some_file(tree))
- return 1; /* No file to close */
- strmov(name,fileinfo->show_name);
- if (fileinfo->id > 1)
- *strrchr(name,'<')='\0'; /* Remove "<id>" */
-
- if (!(fileinfo->isam= nisam_open(name,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)))
- return 1;
- fileinfo->closed=0;
- re_open_count++;
- return 0;
-}
-
- /* Try to find record with uniq key */
-
-static int find_record_with_key(struct isamlog_file_info *file_info,
- byte *record)
-{
- uint key;
- N_INFO *info=file_info->isam;
- uchar tmp_key[N_MAX_KEY_BUFF];
-
- for (key=0 ; key < info->s->state.keys ; key++)
- {
- if (info->s->keyinfo[key].base.flag & HA_NOSAME)
- {
- VOID(_nisam_make_key(info,key,tmp_key,record,0L));
- return nisam_rkey(info,file_info->record,(int) key,(char*) tmp_key,0,
- HA_READ_KEY_EXACT);
- }
- }
- return 1;
-}
-
-
-static void printf_log(const char *format,...)
-{
- char llbuff[21];
- va_list args;
- va_start(args,format);
- if (verbose > 2)
- printf("%9s:",llstr(isamlog_filepos,llbuff));
- if (verbose > 1)
- printf("%5ld ",isamlog_process); /* Write process number */
- (void) vprintf((char*) format,args);
- putchar('\n');
- va_end(args);
-}
-
-
-static bool cmp_filename(struct isamlog_file_info *file_info,my_string name)
-{
- if (!file_info)
- return 1;
- return strcmp(file_info->name,name) ? 1 : 0;
-}
diff --git a/isam/log.c b/isam/log.c
deleted file mode 100644
index 78b56690401..00000000000
--- a/isam/log.c
+++ /dev/null
@@ -1,156 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Logging of isamcommands and records on logfile */
-
-#include "isamdef.h"
-#if defined(MSDOS) || defined(__WIN__)
-#include <errno.h>
-#include <fcntl.h>
-#ifndef __WIN__
-#include <process.h>
-#endif
-#endif
-#ifdef VMS
-#include <processes.h>
-#endif
-
-#ifdef THREAD
-#undef GETPID
-#define GETPID() (log_type == 1 ? getpid() : (long) my_thread_id());
-#else
-#define GETPID() getpid()
-#endif
-
- /* Activate logging if flag is 1 and reset logging if flag is 0 */
-
-static int log_type=0;
-
-int nisam_log(int activate_log)
-{
- int error=0;
- char buff[FN_REFLEN];
- DBUG_ENTER("nisam_log");
-
- log_type=activate_log;
- if (activate_log)
- {
- if (nisam_log_file < 0)
- {
- if ((nisam_log_file = my_create(fn_format(buff,nisam_log_filename,
- "",".log",4),
- 0,(O_RDWR | O_BINARY | O_APPEND),MYF(0)))
- < 0)
- DBUG_RETURN(1);
- }
- }
- else if (nisam_log_file >= 0)
- {
- error=my_close(nisam_log_file,MYF(0));
- nisam_log_file= -1;
- }
- DBUG_RETURN(error);
-}
-
-
- /* Logging of records and commands on logfile */
- /* All logs starts with command(1) dfile(2) process(4) result(2) */
-
-void _nisam_log(enum nisam_log_commands command, N_INFO *info, const byte *buffert, uint length)
-{
- char buff[11];
- int error,old_errno;
- ulong pid=(ulong) GETPID();
- old_errno=my_errno;
- bzero(buff,sizeof(buff));
- buff[0]=(char) command;
- int2store(buff+1,info->dfile);
- int4store(buff+3,pid);
- int2store(buff+9,length);
-
- pthread_mutex_lock(&THR_LOCK_isam);
- error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
- VOID(my_write(nisam_log_file,buffert,length,MYF(0)));
- if (!error)
- error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- pthread_mutex_unlock(&THR_LOCK_isam);
- my_errno=old_errno;
-}
-
-
-void _nisam_log_command(enum nisam_log_commands command, N_INFO *info, const byte *buffert, uint length, int result)
-{
- char buff[9];
- int error,old_errno;
- ulong pid=(ulong) GETPID();
-
- old_errno=my_errno;
- buff[0]=(char) command;
- int2store(buff+1,info->dfile);
- int4store(buff+3,pid);
- int2store(buff+7,result);
- pthread_mutex_lock(&THR_LOCK_isam);
- error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
- if (buffert)
- VOID(my_write(nisam_log_file,buffert,length,MYF(0)));
- if (!error)
- error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- pthread_mutex_unlock(&THR_LOCK_isam);
- my_errno=old_errno;
-}
-
-
-void _nisam_log_record(enum nisam_log_commands command, N_INFO *info, const byte *record, ulong filepos, int result)
-{
- char buff[17],*pos;
- int error,old_errno;
- uint length;
- ulong pid=(ulong) GETPID();
-
- old_errno=my_errno;
- if (!info->s->base.blobs)
- length=info->s->base.reclength;
- else
- length=info->s->base.reclength+ _calc_total_blob_length(info,record);
- buff[0]=(char) command;
- int2store(buff+1,info->dfile);
- int4store(buff+3,pid);
- int2store(buff+7,result);
- int4store(buff+9,filepos);
- int4store(buff+13,length);
- pthread_mutex_lock(&THR_LOCK_isam);
- error=my_lock(nisam_log_file,F_WRLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- VOID(my_write(nisam_log_file,buff,sizeof(buff),MYF(0)));
- VOID(my_write(nisam_log_file,(byte*) record,info->s->base.reclength,MYF(0)));
- if (info->s->base.blobs)
- {
- N_BLOB *blob,*end;
-
- for (end=info->blobs+info->s->base.blobs, blob= info->blobs;
- blob != end ;
- blob++)
- {
- bmove(&pos,record+blob->offset+blob->pack_length,sizeof(char*));
- VOID(my_write(nisam_log_file,pos,blob->length,MYF(0)));
- }
- }
- if (!error)
- error=my_lock(nisam_log_file,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE));
- pthread_mutex_unlock(&THR_LOCK_isam);
- my_errno=old_errno;
-}
diff --git a/isam/make-ccc b/isam/make-ccc
deleted file mode 100755
index d9a95dbc14b..00000000000
--- a/isam/make-ccc
+++ /dev/null
@@ -1,3 +0,0 @@
-ccc -DHAVE_CONFIG_H -I. -I. -I.. -I./../include -I../include -DDBUG_OFF -fast -O3 -fomit-frame-pointer -c _cache.c _dbug.c _dynrec.c _key.c _locking.c _packrec.c _page.c _search.c _statrec.c changed.c close.c create.c delete.c extra.c info.c log.c open.c panic.c range.c rfirst.c rkey.c rlast.c rnext.c rprev.c rrnd.c rsame.c rsamepos.c static.c update.c write.c
-rm libnisam.a
-ar -cr libnisam.a _cache.o
diff --git a/isam/open.c b/isam/open.c
deleted file mode 100644
index be62fd86192..00000000000
--- a/isam/open.c
+++ /dev/null
@@ -1,477 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* open a isam-database */
-
-#include "isamdef.h"
-#if defined(MSDOS) || defined(__WIN__)
-#ifdef __WIN__
-#include <fcntl.h>
-#else
-#include <process.h> /* Prototype for getpid */
-#endif
-#endif
-#ifdef VMS
-#include "static.c"
-#endif
-
-static void setup_functions(ISAM_SHARE *info);
-static void setup_key_functions(N_KEYDEF *keyinfo);
-
-#define get_next_element(to,pos,size) { memcpy((char*) to,pos,(size_t) size); \
- pos+=size;}
-
-/******************************************************************************
-** Return the shared struct if the table is already open.
-** In MySQL the server will handle version issues.
-******************************************************************************/
-
-static N_INFO *test_if_reopen(char *filename)
-{
- LIST *pos;
-
- for (pos=nisam_open_list ; pos ; pos=pos->next)
- {
- N_INFO *info=(N_INFO*) pos->data;
- ISAM_SHARE *share=info->s;
- if (!strcmp(share->filename,filename) && share->last_version)
- return info;
- }
- return 0;
-}
-
-
-/******************************************************************************
- open a isam database.
- By default exit with error if database is locked
- if handle_locking & HA_OPEN_WAIT_IF_LOCKED then wait if database is locked
- if handle_locking & HA_OPEN_IGNORE_IF_LOCKED then continue, but count-vars
- in st_i_info may be wrong. count-vars are automaticly fixed after next
- isam request.
-******************************************************************************/
-
-
-N_INFO *nisam_open(const char *name, int mode, uint handle_locking)
-{
- int lock_error,kfile,open_mode,save_errno;
- uint i,j,len,errpos,head_length,base_pos,offset,info_length,extra;
- char name_buff[FN_REFLEN],*disk_cache,*disk_pos;
- N_INFO info,*m_info,*old_info;
- ISAM_SHARE share_buff,*share;
- DBUG_ENTER("nisam_open");
-
- LINT_INIT(m_info);
- kfile= -1;
- lock_error=1;
- errpos=0;
- head_length=sizeof(share_buff.state.header);
- bzero((byte*) &info,sizeof(info));
-
- VOID(fn_format(name_buff,name,"",N_NAME_IEXT,4+16+32));
- pthread_mutex_lock(&THR_LOCK_isam);
- if (!(old_info=test_if_reopen(name_buff)))
- {
- share= &share_buff;
- bzero((gptr) &share_buff,sizeof(share_buff));
-
- if ((kfile=my_open(name_buff,(open_mode=O_RDWR) | O_SHARE,MYF(0))) < 0)
- {
- if ((errno != EROFS && errno != EACCES) ||
- mode != O_RDONLY ||
- (kfile=my_open(name_buff,(open_mode=O_RDONLY) | O_SHARE,MYF(0))) < 0)
- goto err;
- }
- errpos=1;
- if (my_read(kfile,(char*) share->state.header.file_version,head_length,
- MYF(MY_NABP)))
- goto err;
-
- if (memcmp((byte*) share->state.header.file_version,
- (byte*) nisam_file_magic, 3) ||
- share->state.header.file_version[3] == 0 ||
- (uchar) share->state.header.file_version[3] > 3)
- {
- DBUG_PRINT("error",("Wrong header in %s",name_buff));
- DBUG_DUMP("error_dump",(char*) share->state.header.file_version,
- head_length);
- my_errno=HA_ERR_CRASHED;
- goto err;
- }
- if (uint2korr(share->state.header.options) &
- ~(HA_OPTION_PACK_RECORD | HA_OPTION_PACK_KEYS |
- HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA |
- HA_OPTION_TEMP_COMPRESS_RECORD))
- {
- DBUG_PRINT("error",("wrong options: 0x%lx",
- uint2korr(share->state.header.options)));
- my_errno=HA_ERR_OLD_FILE;
- goto err;
- }
- info_length=uint2korr(share->state.header.header_length);
- base_pos=uint2korr(share->state.header.base_pos);
- if (!(disk_cache=(char*) my_alloca(info_length)))
- {
- my_errno=ENOMEM;
- goto err;
- }
- errpos=2;
-
- VOID(my_seek(kfile,0L,MY_SEEK_SET,MYF(0)));
-#ifndef NO_LOCKING
- if (!(handle_locking & HA_OPEN_TMP_TABLE))
- {
- if ((lock_error=my_lock(kfile,F_RDLCK,0L,F_TO_EOF,
- MYF(handle_locking & HA_OPEN_WAIT_IF_LOCKED ?
- 0 : MY_DONT_WAIT))) &&
- !(handle_locking & HA_OPEN_IGNORE_IF_LOCKED))
- goto err;
- }
-#endif
- errpos=3;
- if (my_read(kfile,disk_cache,info_length,MYF(MY_NABP)))
- goto err;
- len=uint2korr(share->state.header.state_info_length);
- if (len != sizeof(N_STATE_INFO))
- {
- DBUG_PRINT("warning",
- ("saved_state_info_length: %d base_info_length: %d",
- len,sizeof(N_STATE_INFO)));
- }
- if (len > sizeof(N_STATE_INFO))
- len=sizeof(N_STATE_INFO);
- share->state_length=len;
- memcpy(&share->state.header.file_version[0],disk_cache,(size_t) len);
- len=uint2korr(share->state.header.base_info_length);
- if (len != sizeof(N_BASE_INFO))
- {
- DBUG_PRINT("warning",("saved_base_info_length: %d base_info_length: %d",
- len,sizeof(N_BASE_INFO)));
- if (len <= offsetof(N_BASE_INFO,sortkey))
- share->base.sortkey=(ushort) ~0;
- }
- memcpy((char*) (byte*) &share->base,disk_cache+base_pos,
- (size_t) min(len,sizeof(N_BASE_INFO)));
- disk_pos=disk_cache+base_pos+len;
- share->base.options=uint2korr(share->state.header.options);
- if (share->base.max_key_length > N_MAX_KEY_BUFF)
- {
- my_errno=HA_ERR_UNSUPPORTED;
- goto err;
- }
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- share->base.max_key_length+=2; /* For safety */
-
- if (!my_multi_malloc(MY_WME,
- &share,sizeof(*share),
- &share->keyinfo,share->base.keys*sizeof(N_KEYDEF),
- &share->rec,(share->base.fields+1)*sizeof(N_RECINFO),
- &share->blobs,sizeof(N_BLOB)*share->base.blobs,
- &share->filename,strlen(name_buff)+1,
- NullS))
- goto err;
- errpos=4;
- *share=share_buff;
- strmov(share->filename,name_buff);
-
- /* Fix key in used if old nisam-database */
- if (share->state_length <= offsetof(N_STATE_INFO,keys))
- share->state.keys=share->base.keys;
-
- share->blocksize=min(IO_SIZE,nisam_block_size);
- for (i=0 ; i < share->base.keys ; i++)
- {
- get_next_element(&share->keyinfo[i].base,disk_pos,sizeof(N_SAVE_KEYDEF));
- setup_key_functions(share->keyinfo+i);
- set_if_smaller(share->blocksize,share->keyinfo[i].base.block_length);
- for (j=0 ; j <= share->keyinfo[i].base.keysegs ; j++)
- {
- get_next_element(&share->keyinfo[i].seg[j],disk_pos,
- sizeof(N_SAVE_KEYSEG));
- }
- }
- if (!share->blocksize)
- {
- my_errno=HA_ERR_CRASHED;
- goto err;
- }
-
- for (i=j=offset=0 ; i < share->base.fields ; i++)
- {
- get_next_element(&share->rec[i].base,disk_pos,sizeof(N_SAVE_RECINFO));
-#ifndef NOT_PACKED_DATABASES
- share->rec[i].pack_type=0;
- share->rec[i].huff_tree=0;
-#endif
- if (share->rec[i].base.type == (int) FIELD_BLOB)
- {
- share->blobs[j].pack_length=share->rec[i].base.length;
- share->blobs[j].offset=offset;
- j++;
- offset+=sizeof(char*);
- }
- offset+=share->rec[i].base.length;
- }
- share->rec[i].base.type=(int) FIELD_LAST;
-
-#ifndef NO_LOCKING
- if (! lock_error)
- {
- VOID(my_lock(kfile,F_UNLCK,0L,F_TO_EOF,MYF(MY_SEEK_NOT_DONE)));
- lock_error=1; /* Database unlocked */
- }
-#endif
-
- if ((info.dfile=my_open(fn_format(name_buff,name,"",N_NAME_DEXT,2+4),
- mode | O_SHARE,
- MYF(MY_WME))) < 0)
- goto err;
- errpos=5;
-
- share->kfile=kfile;
- share->mode=open_mode;
- share->this_process=(ulong) getpid();
- share->rnd= (int) share->this_process; /* rnd-counter for splitts */
-#ifndef DBUG_OFF
- share->rnd=0; /* To make things repeatable */
-#endif
- share->last_process= share->state.process;
- if (!(share->last_version=share->state.version))
- share->last_version=1; /* Safety */
- share->rec_reflength=share->base.rec_reflength; /* May be changed */
-
- share->data_file_type=STATIC_RECORD;
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- share->data_file_type = COMPRESSED_RECORD;
- share->base.options|= HA_OPTION_READ_ONLY_DATA;
- info.s=share;
- if (_nisam_read_pack_info(&info,
- (pbool) test(!(share->base.options &
- (HA_OPTION_PACK_RECORD |
- HA_OPTION_TEMP_COMPRESS_RECORD)))))
- goto err;
- }
- else if (share->base.options & HA_OPTION_PACK_RECORD)
- share->data_file_type = DYNAMIC_RECORD;
- my_afree((gptr) disk_cache);
- setup_functions(share);
-#ifdef THREAD
- thr_lock_init(&share->lock);
- VOID(pthread_mutex_init(&share->intern_lock,MY_MUTEX_INIT_FAST));
-#endif
- }
- else
- {
- share= old_info->s;
- if (mode == O_RDWR && share->mode == O_RDONLY)
- {
- my_errno=EACCES; /* Can't open in write mode*/
- goto err;
- }
- if ((info.dfile=my_open(fn_format(name_buff,old_info->filename,"",
- N_NAME_DEXT,2+4),
- mode | O_SHARE,MYF(MY_WME))) < 0)
- {
- my_errno=errno;
- goto err;
- }
- errpos=5;
- }
-
- /* alloc and set up private structure parts */
- if (!my_multi_malloc(MY_WME,
- &m_info,sizeof(N_INFO),
- &info.blobs,sizeof(N_BLOB)*share->base.blobs,
- &info.buff,(share->base.max_block*2+
- share->base.max_key_length),
- &info.lastkey,share->base.max_key_length*3+1,
- &info.filename,strlen(name)+1,
- NullS))
- goto err;
- errpos=6;
- strmov(info.filename,name);
- memcpy(info.blobs,share->blobs,sizeof(N_BLOB)*share->base.blobs);
-
- info.s=share;
- info.lastpos= NI_POS_ERROR;
- info.update= (short) (HA_STATE_NEXT_FOUND+HA_STATE_PREV_FOUND);
- info.opt_flag=READ_CHECK_USED;
- info.alloced_rec_buff_length=share->base.pack_reclength;
- info.this_uniq= (ulong) info.dfile; /* Uniq number in process */
- info.this_loop=0; /* Update counter */
- info.last_uniq= share->state.uniq;
- info.last_loop= share->state.loop;
- info.options=share->base.options |
- (mode == O_RDONLY ? HA_OPTION_READ_ONLY_DATA : 0);
- info.lock_type=F_UNLCK;
- info.errkey= -1;
- pthread_mutex_lock(&share->intern_lock);
- info.read_record=share->read_record;
- share->reopen++;
- if (share->base.options & HA_OPTION_READ_ONLY_DATA)
- {
- info.lock_type=F_RDLCK;
- share->r_locks++;
- info.this_uniq=share->state.uniq; /* Row checksum */
- }
-#ifndef NO_LOCKING
- if (handle_locking & HA_OPEN_TMP_TABLE)
-#endif
- {
- share->w_locks++; /* We don't have to update status */
- info.lock_type=F_WRLCK;
- }
- pthread_mutex_unlock(&share->intern_lock);
-
- /* Allocate buffer for one record */
-
- extra=0;
- if (share->base.options & HA_OPTION_PACK_RECORD)
- extra=ALIGN_SIZE(MAX_DYN_BLOCK_HEADER)+N_SPLITT_LENGTH+
- DYN_DELETE_BLOCK_HEADER;
- if (!(info.rec_alloc=(byte*) my_malloc(share->base.pack_reclength+extra+
- 6,
- MYF(MY_WME | MY_ZEROFILL))))
- goto err;
- if (extra)
- info.rec_buff=info.rec_alloc+ALIGN_SIZE(MAX_DYN_BLOCK_HEADER);
- else
- info.rec_buff=info.rec_alloc;
-
- *m_info=info;
-#ifdef THREAD
- thr_lock_data_init(&share->lock,&m_info->lock,NULL);
-#endif
-
- m_info->open_list.data=(void*) m_info;
- nisam_open_list=list_add(nisam_open_list,&m_info->open_list);
-
- pthread_mutex_unlock(&THR_LOCK_isam);
- nisam_log_simple(LOG_OPEN,m_info,share->filename,
- (uint) strlen(share->filename));
- DBUG_RETURN(m_info);
-
-err:
- save_errno=my_errno ? my_errno : HA_ERR_END_OF_FILE;
- switch (errpos) {
- case 6:
- my_free((gptr) m_info,MYF(0));
- /* fall through */
- case 5:
- VOID(my_close(info.dfile,MYF(0)));
- if (old_info)
- break; /* Don't remove open table */
- /* fall through */
- case 4:
- my_free((gptr) share,MYF(0));
- /* fall through */
- case 3:
-#ifndef NO_LOCKING
- if (! lock_error)
- VOID(my_lock(kfile, F_UNLCK, 0L, F_TO_EOF, MYF(MY_SEEK_NOT_DONE)));
-#endif
- /* fall through */
- case 2:
- my_afree((gptr) disk_cache);
- /* fall through */
- case 1:
- VOID(my_close(kfile,MYF(0)));
- /* fall through */
- case 0:
- default:
- break;
- }
- pthread_mutex_unlock(&THR_LOCK_isam);
- my_errno=save_errno;
- DBUG_RETURN (NULL);
-} /* nisam_open */
-
-
- /* Set up functions in structs */
-
-static void setup_functions(register ISAM_SHARE *share)
-{
- if (share->base.options & HA_OPTION_COMPRESS_RECORD)
- {
- share->read_record=_nisam_read_pack_record;
- share->read_rnd=_nisam_read_rnd_pack_record;
- }
- else if (share->base.options & HA_OPTION_PACK_RECORD)
- {
- share->read_record=_nisam_read_dynamic_record;
- share->read_rnd=_nisam_read_rnd_dynamic_record;
- share->delete_record=_nisam_delete_dynamic_record;
- share->compare_record=_nisam_cmp_dynamic_record;
-
- /* add bits used to pack data to pack_reclength for faster allocation */
- share->base.pack_reclength+= share->base.pack_bits;
- if (share->base.blobs)
- {
- share->update_record=_nisam_update_blob_record;
- share->write_record=_nisam_write_blob_record;
- }
- else
- {
- share->write_record=_nisam_write_dynamic_record;
- share->update_record=_nisam_update_dynamic_record;
- }
- }
- else
- {
- share->read_record=_nisam_read_static_record;
- share->read_rnd=_nisam_read_rnd_static_record;
- share->delete_record=_nisam_delete_static_record;
- share->compare_record=_nisam_cmp_static_record;
- share->update_record=_nisam_update_static_record;
- share->write_record=_nisam_write_static_record;
- }
- return;
-}
-
-
-static void setup_key_functions(register N_KEYDEF *keyinfo)
-{
- if (keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED))
- {
- keyinfo->bin_search=_nisam_seq_search;
- keyinfo->get_key=_nisam_get_key;
- }
- else
- {
- keyinfo->bin_search=_nisam_bin_search;
- keyinfo->get_key=_nisam_get_static_key;
- }
- return;
-}
-
-/*
- Calculate a long checksum for a memoryblock. Used to verify pack_isam
-
- SYNOPSIS
- checksum()
- mem Pointer to memory block
- count Count of bytes
-*/
-
-ulong _nisam_checksum(const byte *mem, uint count)
-{
- ulong crc;
- for (crc= 0; count-- ; mem++)
- crc= ((crc << 1) + *((uchar*) mem)) +
- test(crc & ((ulong) 1L << (8*sizeof(ulong)-1)));
- return crc;
-}
-
diff --git a/isam/pack_isam.c b/isam/pack_isam.c
deleted file mode 100644
index aa83b2b2a96..00000000000
--- a/isam/pack_isam.c
+++ /dev/null
@@ -1,2042 +0,0 @@
-/* Copyright (C) 1979-2002 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Pack isam file */
-
-#ifndef USE_MY_FUNC
-#define USE_MY_FUNC /* We nead at least my_malloc */
-#endif
-
-#include "isamdef.h"
-#include <queues.h>
-#include <my_tree.h>
-#include "mysys_err.h"
-#ifdef MSDOS
-#include <io.h>
-#endif
-#ifndef __GNU_LIBRARY__
-#define __GNU_LIBRARY__ /* Skip warnings in getopt.h */
-#endif
-#include <my_getopt.h>
-
-#if INT_MAX > 32767
-#define BITS_SAVED 32
-#else
-#define BITS_SAVED 16
-#endif
-
-#define IS_OFFSET ((uint) 32768) /* Bit if offset or char in tree */
-#define HEAD_LENGTH 32
-#define ALLOWED_JOIN_DIFF 256 /* Diff allowed to join trees */
-
-#define DATA_TMP_EXT ".TMD"
-#define OLD_EXT ".OLD"
-#define WRITE_COUNT MY_HOW_OFTEN_TO_WRITE
-
-struct st_file_buffer {
- File file;
- char *buffer,*pos,*end;
- my_off_t pos_in_file;
- int bits;
- uint bytes;
-};
-
-struct st_huff_tree;
-struct st_huff_element;
-
-typedef struct st_huff_counts {
- uint field_length,max_zero_fill;
- uint pack_type;
- uint max_end_space,max_pre_space,length_bits,min_space;
- enum en_fieldtype field_type;
- struct st_huff_tree *tree; /* Tree for field */
- my_off_t counts[256];
- my_off_t end_space[8];
- my_off_t pre_space[8];
- my_off_t tot_end_space,tot_pre_space,zero_fields,empty_fields,bytes_packed;
- TREE int_tree;
- byte *tree_buff;
- byte *tree_pos;
-} HUFF_COUNTS;
-
-typedef struct st_huff_element HUFF_ELEMENT;
-
-struct st_huff_element {
- my_off_t count;
- union un_element {
- struct st_nod {
- HUFF_ELEMENT *left,*right;
- } nod;
- struct st_leaf {
- HUFF_ELEMENT *null;
- uint element_nr; /* Number of element */
- } leaf;
- } a;
-};
-
-
-typedef struct st_huff_tree {
- HUFF_ELEMENT *root,*element_buffer;
- HUFF_COUNTS *counts;
- uint tree_number;
- uint elements;
- my_off_t bytes_packed;
- uint tree_pack_length;
- uint min_chr,max_chr,char_bits,offset_bits,max_offset,height;
- ulong *code;
- uchar *code_len;
-} HUFF_TREE;
-
-
-typedef struct st_isam_mrg {
- N_INFO **file,**current,**end;
- uint count;
- uint min_pack_length; /* Theese is used by packed data */
- uint max_pack_length;
- uint ref_length;
- my_off_t records;
-} MRG_INFO;
-
-
-extern int main(int argc,char * *argv);
-static void get_options(int *argc,char ***argv);
-static N_INFO *open_isam_file(char *name,int mode);
-static bool open_isam_files(MRG_INFO *mrg,char **names,uint count);
-static int compress(MRG_INFO *file,char *join_name);
-static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records);
-static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees,
- uint trees,
- HUFF_COUNTS *huff_counts,
- uint fields);
-static int compare_tree(const uchar *s,const uchar *t);
-static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts);
-static void check_counts(HUFF_COUNTS *huff_counts,uint trees,
- my_off_t records);
-static int test_space_compress(HUFF_COUNTS *huff_counts,my_off_t records,
- uint max_space_length,my_off_t *space_counts,
- my_off_t tot_space_count,
- enum en_fieldtype field_type);
-static HUFF_TREE* make_huff_trees(HUFF_COUNTS *huff_counts,uint trees);
-static int make_huff_tree(HUFF_TREE *tree,HUFF_COUNTS *huff_counts);
-static int compare_huff_elements(void *not_used, byte *a,byte *b);
-static int save_counts_in_queue(byte *key,element_count count,
- HUFF_TREE *tree);
-static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts,uint flag);
-static uint join_same_trees(HUFF_COUNTS *huff_counts,uint trees);
-static int make_huff_decode_table(HUFF_TREE *huff_tree,uint trees);
-static void make_traverse_code_tree(HUFF_TREE *huff_tree,
- HUFF_ELEMENT *element,uint size,
- ulong code);
-static int write_header(MRG_INFO *isam_file, uint header_length,uint trees,
- my_off_t tot_elements,my_off_t filelength);
-static void write_field_info(HUFF_COUNTS *counts, uint fields,uint trees);
-static my_off_t write_huff_tree(HUFF_TREE *huff_tree,uint trees);
-static uint *make_offset_code_tree(HUFF_TREE *huff_tree,
- HUFF_ELEMENT *element,
- uint *offset);
-static uint max_bit(uint value);
-static int compress_isam_file(MRG_INFO *file,HUFF_COUNTS *huff_counts);
-static char *make_new_name(char *new_name,char *old_name);
-static char *make_old_name(char *new_name,char *old_name);
-static void init_file_buffer(File file,pbool read_buffer);
-static int flush_buffer(uint neaded_length);
-static void end_file_buffer(void);
-static void write_bits(ulong value,uint bits);
-static void flush_bits(void);
-static void save_integer(byte *pos,uint pack_length,my_off_t value);
-static void save_state(N_INFO *isam_file,MRG_INFO *mrg,my_off_t new_length,
- ulong crc);
-static int save_state_mrg(File file,MRG_INFO *isam_file,my_off_t new_length,
- ulong crc);
-static int mrg_close(MRG_INFO *mrg);
-static int mrg_rrnd(MRG_INFO *info,byte *buf);
-static void mrg_reset(MRG_INFO *mrg);
-
-
-static int error_on_write=0,test_only=0,verbose=0,silent=0,
- write_loop=0,force_pack=0,isamchk_neaded=0;
-static my_bool backup, opt_wait;
-static int tmpfile_createflag=O_RDWR | O_TRUNC | O_EXCL;
-static uint tree_buff_length=8196-MALLOC_OVERHEAD,force_pack_ref_length;
-static char tmp_dir[FN_REFLEN]={0},*join_table;
-static my_off_t intervall_length;
-static ulong crc;
-static struct st_file_buffer file_buffer;
-static QUEUE queue;
-static HUFF_COUNTS *global_count;
-static char zero_string[]={0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0};
-static const char *load_default_groups[]= { "pack_isam",0 };
-
- /* The main program */
-
-int main(int argc, char **argv)
-{
- int error,ok;
- MRG_INFO merge;
- MY_INIT(argv[0]);
-
- load_defaults("my",load_default_groups,&argc,&argv);
- get_options(&argc,&argv);
-
- error=ok=isamchk_neaded=0;
- if (join_table)
- { /* Join files into one */
- if (open_isam_files(&merge,argv,(uint) argc) ||
- compress(&merge,join_table))
- error=1;
- }
- else while (argc--)
- {
- N_INFO *isam_file;
- if (!(isam_file=open_isam_file(*argv++,O_RDWR)))
- error=1;
- else
- {
- merge.file= &isam_file;
- merge.current=0;
- merge.count=1;
- if (compress(&merge,0))
- error=1;
- else
- ok=1;
- }
- }
- if (ok && isamchk_neaded && !silent)
- puts("Remember to run isamchk -rq on compressed databases");
- VOID(fflush(stdout)); VOID(fflush(stderr));
- my_end(verbose ? MY_CHECK_ERROR | MY_GIVE_INFO : MY_CHECK_ERROR);
- exit(error ? 2 : 0);
-#ifndef _lint
- return 0; /* No compiler warning */
-#endif
-}
-
-
-static struct my_option my_long_options[] =
-{
- {"backup", 'b', "Make a backup of the table as table_name.OLD",
- (gptr*) &backup, (gptr*) &backup, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"debug", '#', "Output debug log. Often this is 'd:t:o,filename'",
- 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
- {"force", 'f',
- "Force packing of table even if it's gets bigger or tempfile exists.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"join", 'j',
- "Join all given tables into 'new_table_name'. All tables MUST have the identical layout.",
- (gptr*) &join_table, (gptr*) &join_table, 0, GET_STR, REQUIRED_ARG, 0, 0,
- 0, 0, 0, 0},
- {"help", '?', "Display this help and exit.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"packlength", 'p', "Force storage size of recordlength (1, 2 or 3)",
- (gptr*) &force_pack_ref_length, (gptr*) &force_pack_ref_length, 0,
- GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"silent", 's', "Be more silent.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0},
- {"tmpdir", 'T', "Use temporary directory to store temporary table",
- (gptr*) &tmp_dir, (gptr*) &tmp_dir, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0,
- 0, 0},
- {"test", 't', "Don't pack table, only test packing it",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0},
- {"verbose", 'v', "Write info about progress and packing result",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0},
- {"version", 'V', "output version information and exit",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0 ,0},
- {"wait", 'w', "Wait and retry if table is in use", (gptr*) &opt_wait,
- (gptr*) &opt_wait, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
- { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
-};
-
-
-static void print_version(void)
-{
- printf("%s Ver 5.10 for %s on %s\n", my_progname, SYSTEM_TYPE, MACHINE_TYPE);
-}
-
-static void usage(void)
-{
- print_version();
- puts("Copyright (C) 2002 MySQL AB");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software,");
- puts("and you are welcome to modify and redistribute it under the GPL license\n");
-
- puts("Pack a ISAM-table to take much smaller space");
- puts("Keys are not updated, so you must run isamchk -rq on any table");
- puts("that has keys after you have compressed it");
- puts("You should give the .ISM file as the filename argument");
-
- printf("\nUsage: %s [OPTIONS] filename...\n", my_progname);
- my_print_help(my_long_options);
- print_defaults("my", load_default_groups);
- my_print_variables(my_long_options);
-}
-
-
-static my_bool
-get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
- char *argument)
-{
- uint length;
-
- switch(optid) {
- case 'f':
- force_pack= 1;
- tmpfile_createflag= O_RDWR | O_TRUNC;
- break;
- case 'p':
- if (force_pack_ref_length > 3)
- force_pack_ref_length= 0;
- break;
- case 's':
- write_loop= verbose= 0;
- silent= 1;
- break;
- case 't':
- test_only= verbose= 1;
- break;
- case 'T':
- length=(uint) (strmov(tmp_dir, argument) - tmp_dir);
- if (length != dirname_length(tmp_dir))
- {
- tmp_dir[length]= FN_LIBCHAR;
- tmp_dir[length + 1]= 0;
- }
- break;
- case 'v':
- verbose= 1;
- silent= 0;
- break;
- case '#':
- DBUG_PUSH(argument ? argument : "d:t:o");
- break;
- case 'V': print_version(); exit(0);
- case 'I':
- case '?':
- usage();
- exit(0);
- }
- return 0;
-}
-
- /* reads options */
- /* Initiates DEBUG - but no debugging here ! */
-
-static void get_options(int *argc, char ***argv)
-{
- int ho_error;
-
- if ((ho_error=handle_options(argc, argv, my_long_options, get_one_option)))
- exit(ho_error);
-
- my_progname= argv[0][0];
- if (isatty(fileno(stdout)))
- write_loop=1;
-
- if (!*argc)
- {
- usage();
- exit(1);
- }
- if (join_table)
- {
- backup=0; /* Not needed */
- tmp_dir[0]=0;
- }
- return;
-}
-
-
-static N_INFO *open_isam_file(char *name,int mode)
-{
- N_INFO *isam_file;
- ISAM_SHARE *share;
- DBUG_ENTER("open_isam_file");
-
- if (!(isam_file=nisam_open(name,mode,(opt_wait ? HA_OPEN_WAIT_IF_LOCKED :
- HA_OPEN_ABORT_IF_LOCKED))))
- {
- VOID(fprintf(stderr,"%s gave error %d on open\n",name,my_errno));
- DBUG_RETURN(0);
- }
- share=isam_file->s;
- if (share->base.blobs)
- {
- VOID(fprintf(stderr,"%s has blobs, can't pack it\n",name));
- VOID(nisam_close(isam_file));
- DBUG_RETURN(0);
- }
- if (share->base.options & HA_OPTION_COMPRESS_RECORD && !join_table)
- {
- if (!force_pack)
- {
- VOID(fprintf(stderr,"%s is already compressed\n",name));
- VOID(nisam_close(isam_file));
- DBUG_RETURN(0);
- }
- if (verbose)
- puts("Recompressing already compressed table");
- share->base.options&= ~HA_OPTION_READ_ONLY_DATA; /* We are modifing it */
- }
- if (! force_pack && share->state.records != 0 &&
- (share->state.records <= 1 ||
- share->state.data_file_length < 1024) && ! join_table)
- {
- VOID(fprintf(stderr,"%s is too small to compress\n",name));
- VOID(nisam_close(isam_file));
- DBUG_RETURN(0);
- }
- VOID(nisam_lock_database(isam_file,F_WRLCK));
- DBUG_RETURN(isam_file);
-}
-
-
-static bool open_isam_files(MRG_INFO *mrg,char **names,uint count)
-{
- uint i,j;
- mrg->count=0;
- mrg->current=0;
- mrg->file=(N_INFO**) my_malloc(sizeof(N_INFO*)*count,MYF(MY_FAE));
- for (i=0; i < count ; i++)
- {
- if (!(mrg->file[i]=open_isam_file(names[i],O_RDONLY)))
- goto error;
- }
- /* Check that files are identical */
- for (j=0 ; j < count-1 ; j++)
- {
- N_RECINFO *m1,*m2,*end;
- if (mrg->file[j]->s->base.reclength != mrg->file[j+1]->s->base.reclength ||
- mrg->file[j]->s->base.fields != mrg->file[j+1]->s->base.fields)
- goto diff_file;
- m1=mrg->file[j]->s->rec;
- end=m1+mrg->file[j]->s->base.fields;
- m2=mrg->file[j+1]->s->rec;
- for ( ; m1 != end ; m1++,m2++)
- {
- if ((m1->base.type != m2->base.type && ! force_pack) ||
- m1->base.length != m2->base.length)
- goto diff_file;
- }
- }
- mrg->count=count;
- return 0;
-
- diff_file:
- fprintf(stderr,"%s: Tables '%s' and '%s' are not identical\n",
- my_progname,names[j],names[j+1]);
- error:
- while (i--)
- nisam_close(mrg->file[i]);
- return 1;
-}
-
-
-static int compress(MRG_INFO *mrg,char *result_table)
-{
- int error;
- File new_file,join_isam_file;
- N_INFO *isam_file;
- ISAM_SHARE *share;
- char org_name[FN_REFLEN],new_name[FN_REFLEN],temp_name[FN_REFLEN];
- uint i,header_length,fields,trees,used_trees;
- my_off_t old_length,new_length,tot_elements;
- HUFF_COUNTS *huff_counts;
- HUFF_TREE *huff_trees;
- DBUG_ENTER("compress");
-
- isam_file=mrg->file[0]; /* Take this as an example */
- share=isam_file->s;
- new_file=join_isam_file= -1;
- trees=fields=0;
- huff_trees=0;
- huff_counts=0;
-
- /* Create temporary or join file */
-
- if (backup)
- VOID(fn_format(org_name,isam_file->filename,"",N_NAME_DEXT,2));
- else
- VOID(fn_format(org_name,isam_file->filename,"",N_NAME_DEXT,2+4+16));
- if (!test_only && result_table)
- {
- /* Make a new indexfile based on first file in list */
- uint length;
- char *buff;
- strmov(org_name,result_table); /* Fix error messages */
- VOID(fn_format(new_name,result_table,"",N_NAME_IEXT,2));
- if ((join_isam_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME)))
- < 0)
- goto err;
- length=share->base.keystart;
- if (!(buff=my_malloc(length,MYF(MY_WME))))
- goto err;
- if (my_pread(share->kfile,buff,length,0L,MYF(MY_WME | MY_NABP)) ||
- my_write(join_isam_file,buff,length,
- MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)))
- {
- my_free(buff,MYF(0));
- goto err;
- }
- my_free(buff,MYF(0));
- VOID(fn_format(new_name,result_table,"",N_NAME_DEXT,2));
- }
- else if (!tmp_dir[0])
- VOID(make_new_name(new_name,org_name));
- else
- VOID(fn_format(new_name,org_name,tmp_dir,DATA_TMP_EXT,1+2+4));
- if (!test_only &&
- (new_file=my_create(new_name,0,tmpfile_createflag,MYF(MY_WME))) < 0)
- goto err;
-
- /* Start calculating statistics */
-
- mrg->records=0;
- for (i=0 ; i < mrg->count ; i++)
- mrg->records+=mrg->file[i]->s->state.records;
- if (write_loop || verbose)
- {
- printf("Compressing %s: (%lu records)\n",
- result_table ? new_name : org_name,(ulong) mrg->records);
- }
- trees=fields=share->base.fields;
- huff_counts=init_huff_count(isam_file,mrg->records);
- QUICK_SAFEMALLOC;
- if (write_loop || verbose)
- printf("- Calculating statistics\n");
- if (get_statistic(mrg,huff_counts))
- goto err;
- NORMAL_SAFEMALLOC;
- old_length=0;
- for (i=0; i < mrg->count ; i++)
- old_length+= (mrg->file[i]->s->state.data_file_length -
- mrg->file[i]->s->state.empty);
-
- if (init_queue(&queue,256,0,0,compare_huff_elements,0))
- goto err;
- check_counts(huff_counts,fields,mrg->records);
- huff_trees=make_huff_trees(huff_counts,trees);
- if ((int) (used_trees=join_same_trees(huff_counts,trees)) < 0)
- goto err;
- if (make_huff_decode_table(huff_trees,fields))
- goto err;
-
- init_file_buffer(new_file,0);
- file_buffer.pos_in_file=HEAD_LENGTH;
- if (! test_only)
- VOID(my_seek(new_file,file_buffer.pos_in_file,MY_SEEK_SET,MYF(0)));
-
- write_field_info(huff_counts,fields,used_trees);
- if (!(tot_elements=write_huff_tree(huff_trees,trees)))
- goto err;
- header_length=(uint) file_buffer.pos_in_file+
- (uint) (file_buffer.pos-file_buffer.buffer);
-
- /* Compress file */
- if (write_loop || verbose)
- printf("- Compressing file\n");
- error=compress_isam_file(mrg,huff_counts);
- new_length=file_buffer.pos_in_file;
- if (!error && !test_only)
- {
- char buff[MEMMAP_EXTRA_MARGIN]; /* End marginal for memmap */
- bzero(buff,sizeof(buff));
- error=my_write(file_buffer.file,buff,sizeof(buff),
- MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
- }
- if (!error)
- error=write_header(mrg,header_length,used_trees,tot_elements,
- new_length);
- end_file_buffer();
-
- if (verbose && mrg->records)
- printf("Min record length: %6d Max length: %6d Mean total length: %6lu\n",
- mrg->min_pack_length,mrg->max_pack_length,
- (ulong) (new_length/mrg->records));
-
- if (!test_only)
- {
- error|=my_close(new_file,MYF(MY_WME));
- if (!result_table)
- {
- error|=my_close(isam_file->dfile,MYF(MY_WME));
- isam_file->dfile= -1; /* Tell nisam_close file is closed */
- }
- }
-
- free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields);
- if (! test_only && ! error)
- {
- if (result_table)
- {
- error=save_state_mrg(join_isam_file,mrg,new_length,crc);
- }
- else
- {
- if (backup)
- {
- if (my_rename(org_name,make_old_name(temp_name,isam_file->filename),
- MYF(MY_WME)))
- error=1;
- else
- {
- if (tmp_dir[0])
- {
- if (!(error=my_copy(new_name,org_name,MYF(MY_WME))))
- VOID(my_delete(new_name,MYF(MY_WME)));
- }
- else
- error=my_rename(new_name,org_name,MYF(MY_WME));
- if (!error)
- VOID(my_copystat(temp_name,org_name,MYF(MY_COPYTIME)));
- }
- }
- else
- {
- if (tmp_dir[0])
- {
-
- if (!(error=my_copy(new_name,org_name,
- MYF(MY_WME | MY_HOLD_ORIGINAL_MODES
- | MY_COPYTIME))))
- VOID(my_delete(new_name,MYF(MY_WME)));
- }
- else
- error=my_redel(org_name,new_name,MYF(MY_WME | MY_COPYTIME));
- }
- if (! error)
- save_state(isam_file,mrg,new_length,crc);
- }
- }
- error|=mrg_close(mrg);
- if (join_isam_file >= 0)
- error|=my_close(join_isam_file,MYF(MY_WME));
- if (error)
- {
- VOID(fprintf(stderr,"Aborting: %s is not compressed\n",org_name));
- DBUG_RETURN(-1);
- }
- if (write_loop || verbose)
- {
- if (old_length)
- printf("%.4g%% \n",
- my_off_t2double(old_length-new_length)*100.0/
- my_off_t2double(old_length));
- else
- puts("Empty file saved in compressed format");
- }
- DBUG_RETURN(0);
-
- err:
- free_counts_and_tree_and_queue(huff_trees,trees,huff_counts,fields);
- if (new_file >= 0)
- VOID(my_close(new_file,MYF(0)));
- if (join_isam_file >= 0)
- VOID(my_close(join_isam_file,MYF(0)));
- mrg_close(mrg);
- VOID(fprintf(stderr,"Aborted: %s is not compressed\n",org_name));
- DBUG_RETURN(-1);
-}
-
- /* Init a huff_count-struct for each field and init it */
-
-static HUFF_COUNTS *init_huff_count(N_INFO *info,my_off_t records)
-{
- reg2 uint i;
- reg1 HUFF_COUNTS *count;
- if ((count = (HUFF_COUNTS*) my_malloc(info->s->base.fields*sizeof(HUFF_COUNTS),
- MYF(MY_ZEROFILL | MY_WME))))
- {
- for (i=0 ; i < info->s->base.fields ; i++)
- {
- enum en_fieldtype type;
- count[i].field_length=info->s->rec[i].base.length;
- type= count[i].field_type= (enum en_fieldtype) info->s->rec[i].base.type;
- if (type == FIELD_INTERVALL ||
- type == FIELD_CONSTANT ||
- type == FIELD_ZERO)
- type = FIELD_NORMAL;
- if (count[i].field_length <= 8 &&
- (type == FIELD_NORMAL ||
- type == FIELD_SKIP_ZERO))
- count[i].max_zero_fill= count[i].field_length;
- init_tree(&count[i].int_tree,0,0,-1,(qsort_cmp2) compare_tree,0,
- NULL, NULL);
- if (records)
- count[i].tree_pos=count[i].tree_buff =
- my_malloc(count[i].field_length > 1 ? tree_buff_length : 2,
- MYF(MY_WME));
- }
- }
- return count;
-}
-
-
- /* Free memory used by counts and trees */
-
-static void free_counts_and_tree_and_queue(HUFF_TREE *huff_trees, uint trees, HUFF_COUNTS *huff_counts, uint fields)
-{
- register uint i;
-
- if (huff_trees)
- {
- for (i=0 ; i < trees ; i++)
- {
- if (huff_trees[i].element_buffer)
- my_free((gptr) huff_trees[i].element_buffer,MYF(0));
- if (huff_trees[i].code)
- my_free((gptr) huff_trees[i].code,MYF(0));
- }
- my_free((gptr) huff_trees,MYF(0));
- }
- if (huff_counts)
- {
- for (i=0 ; i < fields ; i++)
- {
- if (huff_counts[i].tree_buff)
- {
- my_free((gptr) huff_counts[i].tree_buff,MYF(0));
- delete_tree(&huff_counts[i].int_tree);
- }
- }
- my_free((gptr) huff_counts,MYF(0));
- }
- delete_queue(&queue); /* This is safe to free */
- return;
-}
-
- /* Read through old file and gather some statistics */
-
-static int get_statistic(MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
-{
- int error;
- uint length,reclength;
- byte *record,*pos,*next_pos,*end_pos,*start_pos;
- my_off_t record_count;
- HUFF_COUNTS *count,*end_count;
- TREE_ELEMENT *element;
- DBUG_ENTER("get_statistic");
-
- reclength=mrg->file[0]->s->base.reclength;
- record=(byte*) my_alloca(reclength);
- end_count=huff_counts+mrg->file[0]->s->base.fields;
- record_count=crc=0;
-
- mrg_reset(mrg);
- while ((error=mrg_rrnd(mrg,record)) >= 0)
- {
- if (! error)
- {
- crc^=_nisam_checksum(record,reclength);
- for (pos=record,count=huff_counts ;
- count < end_count ;
- count++,
- pos=next_pos)
- {
- next_pos=end_pos=(start_pos=pos)+count->field_length;
-
- /* Put value in tree if there is room for it */
- if (count->tree_buff)
- {
- global_count=count;
- if (!(element=tree_insert(&count->int_tree, pos, 0,
- count->int_tree.custom_arg)) ||
- ((element->count == 1 &&
- count->tree_buff + tree_buff_length <
- count->tree_pos + count->field_length) ||
- (count->field_length == 1 &&
- count->int_tree.elements_in_tree > 1)))
- {
- delete_tree(&count->int_tree);
- my_free(count->tree_buff,MYF(0));
- count->tree_buff=0;
- }
- else
- {
- if (element->count == 1)
- { /* New element */
- memcpy(count->tree_pos,pos,(size_t) count->field_length);
- tree_set_pointer(element,count->tree_pos);
- count->tree_pos+=count->field_length;
- }
- }
- }
-
- /* Save character counters and space-counts and zero-field-counts */
- if (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIP_ENDSPACE)
- {
- for ( ; end_pos > pos ; end_pos--)
- if (end_pos[-1] != ' ')
- break;
- if (end_pos == pos)
- {
- count->empty_fields++;
- count->max_zero_fill=0;
- continue;
- }
- length= (uint) (next_pos-end_pos);
- count->tot_end_space+=length;
- if (length < 8)
- count->end_space[length]++;
- if (count->max_end_space < length)
- count->max_end_space = length;
- }
- if (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIP_PRESPACE)
- {
- for (pos=start_pos; pos < end_pos ; pos++)
- if (pos[0] != ' ')
- break;
- if (end_pos == pos)
- {
- count->empty_fields++;
- count->max_zero_fill=0;
- continue;
- }
- length= (uint) (pos-start_pos);
- count->tot_pre_space+=length;
- if (length < 8)
- count->pre_space[length]++;
- if (count->max_pre_space < length)
- count->max_pre_space = length;
- }
- if (count->field_length <= 8 &&
- (count->field_type == FIELD_NORMAL ||
- count->field_type == FIELD_SKIP_ZERO))
- {
- uint i;
- if (!memcmp((byte*) start_pos,zero_string,count->field_length))
- {
- count->zero_fields++;
- continue;
- }
-#ifdef BYTE_ORDER_HIGH_FIRST
- for (i =0 ; i < count->max_zero_fill && ! start_pos[i] ; i++) ;
- if (i < count->max_zero_fill)
- count->max_zero_fill=i;
-#else
- for (i =0 ; i < count->max_zero_fill && ! end_pos[-1 - (int) i] ; i++) ;
- if (i < count->max_zero_fill)
- count->max_zero_fill=i;
-#endif
- }
- for (pos=start_pos ; pos < end_pos ; pos++)
- count->counts[(uchar) *pos]++;
- }
- record_count++;
- if (write_loop && record_count % WRITE_COUNT == 0)
- {
- printf("%lu\r",(ulong) record_count); VOID(fflush(stdout));
- }
- }
- }
- if (write_loop)
- {
- printf(" \r"); VOID(fflush(stdout));
- }
- mrg->records=record_count;
- my_afree((gptr) record);
- DBUG_RETURN(0);
-}
-
-static int compare_huff_elements(void *not_used __attribute__((unused)),
- byte *a, byte *b)
-{
- return *((my_off_t*) a) < *((my_off_t*) b) ? -1 :
- (*((my_off_t*) a) == *((my_off_t*) b) ? 0 : 1);
-}
-
- /* Check each tree if we should use pre-space-compress, end-space-
- compress, empty-field-compress or zero-field-compress */
-
-static void check_counts(HUFF_COUNTS *huff_counts, uint trees, my_off_t records)
-{
- uint space_fields,fill_zero_fields,field_count[(int) FIELD_ZERO+1];
- my_off_t old_length,new_length,length;
- DBUG_ENTER("check_counts");
-
- bzero((gptr) field_count,sizeof(field_count));
- space_fields=fill_zero_fields=0;
-
- for (; trees-- ; huff_counts++)
- {
- huff_counts->field_type=FIELD_NORMAL;
- huff_counts->pack_type=0;
-
- if (huff_counts->zero_fields || ! records)
- {
- my_off_t old_space_count;
- if (huff_counts->zero_fields == records)
- {
- huff_counts->field_type= FIELD_ZERO;
- huff_counts->bytes_packed=0;
- huff_counts->counts[0]=0;
- goto found_pack;
- }
- old_space_count=huff_counts->counts[' '];
- huff_counts->counts[' ']+=huff_counts->tot_end_space+
- huff_counts->tot_pre_space +
- huff_counts->empty_fields * huff_counts->field_length;
- old_length=calc_packed_length(huff_counts,0)+records/8;
- length=huff_counts->zero_fields*huff_counts->field_length;
- huff_counts->counts[0]+=length;
- new_length=calc_packed_length(huff_counts,0);
- if (old_length < new_length && huff_counts->field_length > 1)
- {
- huff_counts->field_type=FIELD_SKIP_ZERO;
- huff_counts->counts[0]-=length;
- huff_counts->bytes_packed=old_length- records/8;
- goto found_pack;
- }
- huff_counts->counts[' ']=old_space_count;
- }
- huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
- if (huff_counts->empty_fields)
- {
- if (huff_counts->field_length > 2 &&
- huff_counts->empty_fields + (records - huff_counts->empty_fields)*
- (1+max_bit(max(huff_counts->max_pre_space,
- huff_counts->max_end_space))) <
- records * max_bit(huff_counts->field_length))
- {
- huff_counts->pack_type |= PACK_TYPE_SPACE_FIELDS;
- }
- else
- {
- length=huff_counts->empty_fields*huff_counts->field_length;
- if (huff_counts->tot_end_space || ! huff_counts->tot_pre_space)
- {
- huff_counts->tot_end_space+=length;
- huff_counts->max_end_space=huff_counts->field_length;
- if (huff_counts->field_length < 8)
- huff_counts->end_space[huff_counts->field_length]+=
- huff_counts->empty_fields;
- }
- else
- {
- huff_counts->tot_pre_space+=length;
- huff_counts->max_pre_space=huff_counts->field_length;
- if (huff_counts->field_length < 8)
- huff_counts->pre_space[huff_counts->field_length]+=
- huff_counts->empty_fields;
- }
- }
- }
- if (huff_counts->tot_end_space)
- {
- huff_counts->counts[' ']+=huff_counts->tot_pre_space;
- if (test_space_compress(huff_counts,records,huff_counts->max_end_space,
- huff_counts->end_space,
- huff_counts->tot_end_space,FIELD_SKIP_ENDSPACE))
- goto found_pack;
- huff_counts->counts[' ']-=huff_counts->tot_pre_space;
- }
- if (huff_counts->tot_pre_space)
- {
- if (test_space_compress(huff_counts,records,huff_counts->max_pre_space,
- huff_counts->pre_space,
- huff_counts->tot_pre_space,FIELD_SKIP_PRESPACE))
- goto found_pack;
- }
-
- found_pack: /* Found field-packing */
-
- /* Test if we can use zero-fill */
-
- if (huff_counts->max_zero_fill &&
- (huff_counts->field_type == FIELD_NORMAL ||
- huff_counts->field_type == FIELD_SKIP_ZERO))
- {
- huff_counts->counts[0]-=huff_counts->max_zero_fill*
- (huff_counts->field_type == FIELD_SKIP_ZERO ?
- records - huff_counts->zero_fields : records);
- huff_counts->pack_type|=PACK_TYPE_ZERO_FILL;
- huff_counts->bytes_packed=calc_packed_length(huff_counts,0);
- }
-
- /* Test if intervall-field is better */
-
- if (huff_counts->tree_buff)
- {
- HUFF_TREE tree;
-
- tree.element_buffer=0;
- if (!make_huff_tree(&tree,huff_counts) &&
- tree.bytes_packed+tree.tree_pack_length < huff_counts->bytes_packed)
- {
- if (tree.elements == 1)
- huff_counts->field_type=FIELD_CONSTANT;
- else
- huff_counts->field_type=FIELD_INTERVALL;
- huff_counts->pack_type=0;
- }
- else
- {
- my_free((gptr) huff_counts->tree_buff,MYF(0));
- delete_tree(&huff_counts->int_tree);
- huff_counts->tree_buff=0;
- }
- if (tree.element_buffer)
- my_free((gptr) tree.element_buffer,MYF(0));
- }
- if (huff_counts->pack_type & PACK_TYPE_SPACE_FIELDS)
- space_fields++;
- if (huff_counts->pack_type & PACK_TYPE_ZERO_FILL)
- fill_zero_fields++;
- field_count[huff_counts->field_type]++;
- }
- if (verbose)
- printf("\nnormal: %3d empty-space: %3d empty-zero: %3d empty-fill: %3d\npre-space: %3d end-space: %3d table-lookup: %3d zero: %3d\n",
- field_count[FIELD_NORMAL],space_fields,
- field_count[FIELD_SKIP_ZERO],fill_zero_fields,
- field_count[FIELD_SKIP_PRESPACE],
- field_count[FIELD_SKIP_ENDSPACE],
- field_count[FIELD_INTERVALL],
- field_count[FIELD_ZERO]);
- DBUG_VOID_RETURN;
-}
-
- /* Test if we can use space-compression and empty-field-compression */
-
-static int
-test_space_compress(HUFF_COUNTS *huff_counts, my_off_t records,
- uint max_space_length, my_off_t *space_counts,
- my_off_t tot_space_count, enum en_fieldtype field_type)
-{
- int min_pos;
- uint length_bits,i;
- my_off_t space_count,min_space_count,min_pack,new_length,skipp;
-
- length_bits=max_bit(max_space_length);
-
- /* Default no end_space-packing */
- space_count=huff_counts->counts[(uint) ' '];
- min_space_count= (huff_counts->counts[(uint) ' ']+= tot_space_count);
- min_pack=calc_packed_length(huff_counts,0);
- min_pos= -2;
- huff_counts->counts[(uint) ' ']=space_count;
-
- /* Test with allways space-count */
- new_length=huff_counts->bytes_packed+length_bits*records/8;
- if (new_length+1 < min_pack)
- {
- min_pos= -1;
- min_pack=new_length;
- min_space_count=space_count;
- }
- /* Test with length-flag */
- for (skipp=0L, i=0 ; i < 8 ; i++)
- {
- if (space_counts[i])
- {
- if (i)
- huff_counts->counts[(uint) ' ']+=space_counts[i];
- skipp+=huff_counts->pre_space[i];
- new_length=calc_packed_length(huff_counts,0)+
- (records+(records-skipp)*(1+length_bits))/8;
- if (new_length < min_pack)
- {
- min_pos=(int) i;
- min_pack=new_length;
- min_space_count=huff_counts->counts[(uint) ' '];
- }
- }
- }
-
- huff_counts->counts[(uint) ' ']=min_space_count;
- huff_counts->bytes_packed=min_pack;
- switch (min_pos) {
- case -2:
- return(0); /* No space-compress */
- case -1: /* Always space-count */
- huff_counts->field_type=field_type;
- huff_counts->min_space=0;
- huff_counts->length_bits=max_bit(max_space_length);
- break;
- default:
- huff_counts->field_type=field_type;
- huff_counts->min_space=(uint) min_pos;
- huff_counts->pack_type|=PACK_TYPE_SELECTED;
- huff_counts->length_bits=max_bit(max_space_length);
- break;
- }
- return(1); /* Using space-compress */
-}
-
-
- /* Make a huff_tree of each huff_count */
-
-static HUFF_TREE* make_huff_trees(HUFF_COUNTS *huff_counts, uint trees)
-{
- uint tree;
- HUFF_TREE *huff_tree;
- DBUG_ENTER("make_huff_trees");
-
- if (!(huff_tree=(HUFF_TREE*) my_malloc(trees*sizeof(HUFF_TREE),
- MYF(MY_WME | MY_ZEROFILL))))
- DBUG_RETURN(0);
-
- for (tree=0 ; tree < trees ; tree++)
- {
- if (make_huff_tree(huff_tree+tree,huff_counts+tree))
- {
- while (tree--)
- my_free((gptr) huff_tree[tree].element_buffer,MYF(0));
- my_free((gptr) huff_tree,MYF(0));
- DBUG_RETURN(0);
- }
- }
- DBUG_RETURN(huff_tree);
-}
-
- /* Update huff_tree according to huff_counts->counts or
- huff_counts->tree_buff */
-
-static int make_huff_tree(HUFF_TREE *huff_tree, HUFF_COUNTS *huff_counts)
-{
- uint i,found,bits_packed,first,last;
- my_off_t bytes_packed;
- HUFF_ELEMENT *a,*b,*new;
-
- first=last=0;
- if (huff_counts->tree_buff)
- {
- found= (uint) (huff_counts->tree_pos - huff_counts->tree_buff) /
- huff_counts->field_length;
- first=0; last=found-1;
- }
- else
- {
- for (i=found=0 ; i < 256 ; i++)
- {
- if (huff_counts->counts[i])
- {
- if (! found++)
- first=i;
- last=i;
- }
- }
- if (found < 2)
- found=2;
- }
-
- if (queue.max_elements < found)
- {
- delete_queue(&queue);
- if (init_queue(&queue,found,0,0,compare_huff_elements,0))
- return -1;
- }
-
- if (!huff_tree->element_buffer)
- {
- if (!(huff_tree->element_buffer=
- (HUFF_ELEMENT*) my_malloc(found*2*sizeof(HUFF_ELEMENT),MYF(MY_WME))))
- return 1;
- }
- else
- {
- HUFF_ELEMENT *temp;
- if (!(temp=
- (HUFF_ELEMENT*) my_realloc((gptr) huff_tree->element_buffer,
- found*2*sizeof(HUFF_ELEMENT),
- MYF(MY_WME))))
- return 1;
- huff_tree->element_buffer=temp;
- }
-
- huff_counts->tree=huff_tree;
- huff_tree->counts=huff_counts;
- huff_tree->min_chr=first;
- huff_tree->max_chr=last;
- huff_tree->char_bits=max_bit(last-first);
- huff_tree->offset_bits=max_bit(found-1)+1;
-
- if (huff_counts->tree_buff)
- {
- huff_tree->elements=0;
- tree_walk(&huff_counts->int_tree,
- (int (*)(void*, element_count,void*)) save_counts_in_queue,
- (gptr) huff_tree, left_root_right);
- huff_tree->tree_pack_length=(1+15+16+5+5+
- (huff_tree->char_bits+1)*found+
- (huff_tree->offset_bits+1)*
- (found-2)+7)/8 +
- (uint) (huff_tree->counts->tree_pos-
- huff_tree->counts->tree_buff);
- }
- else
- {
- huff_tree->elements=found;
- huff_tree->tree_pack_length=(9+9+5+5+
- (huff_tree->char_bits+1)*found+
- (huff_tree->offset_bits+1)*
- (found-2)+7)/8;
-
- for (i=first, found=0 ; i <= last ; i++)
- {
- if (huff_counts->counts[i])
- {
- new=huff_tree->element_buffer+(found++);
- new->count=huff_counts->counts[i];
- new->a.leaf.null=0;
- new->a.leaf.element_nr=i;
- queue.root[found]=(byte*) new;
- }
- }
- while (found < 2)
- { /* Our huff_trees request at least 2 elements */
- new=huff_tree->element_buffer+(found++);
- new->count=0;
- new->a.leaf.null=0;
- if (last)
- new->a.leaf.element_nr=huff_tree->min_chr=last-1;
- else
- new->a.leaf.element_nr=huff_tree->max_chr=last+1;
- queue.root[found]=(byte*) new;
- }
- }
- queue.elements=found;
-
- for (i=found/2 ; i > 0 ; i--)
- _downheap(&queue,i);
- bytes_packed=0; bits_packed=0;
- for (i=1 ; i < found ; i++)
- {
- a=(HUFF_ELEMENT*) queue_remove(&queue,0);
- b=(HUFF_ELEMENT*) queue.root[1];
- new=huff_tree->element_buffer+found+i;
- new->count=a->count+b->count;
- bits_packed+=(uint) (new->count & 7);
- bytes_packed+=new->count/8;
- new->a.nod.left=a; /* lesser in left */
- new->a.nod.right=b;
- queue.root[1]=(byte*) new;
- queue_replaced(&queue);
- }
- huff_tree->root=(HUFF_ELEMENT*) queue.root[1];
- huff_tree->bytes_packed=bytes_packed+(bits_packed+7)/8;
- return 0;
-}
-
-static int compare_tree(register const uchar *s, register const uchar *t)
-{
- uint length;
- for (length=global_count->field_length; length-- ;)
- if (*s++ != *t++)
- return (int) s[-1] - (int) t[-1];
- return 0;
-}
-
- /* Used by make_huff_tree to save intervall-counts in queue */
-
-static int save_counts_in_queue(byte *key, element_count count, HUFF_TREE *tree)
-{
- HUFF_ELEMENT *new;
-
- new=tree->element_buffer+(tree->elements++);
- new->count=count;
- new->a.leaf.null=0;
- new->a.leaf.element_nr= (uint) (key- tree->counts->tree_buff) /
- tree->counts->field_length;
- queue.root[tree->elements]=(byte*) new;
- return 0;
-}
-
-
- /* Calculate length of file if given counts should be used */
- /* Its actually a faster version of make_huff_tree */
-
-static my_off_t calc_packed_length(HUFF_COUNTS *huff_counts, uint add_tree_lenght)
-{
- uint i,found,bits_packed,first,last;
- my_off_t bytes_packed;
- HUFF_ELEMENT element_buffer[256];
- DBUG_ENTER("calc_packed_length");
-
- first=last=0;
- for (i=found=0 ; i < 256 ; i++)
- {
- if (huff_counts->counts[i])
- {
- if (! found++)
- first=i;
- last=i;
- queue.root[found]=(byte*) &huff_counts->counts[i];
- }
- }
- if (!found)
- DBUG_RETURN(0); /* Empty tree */
- if (found < 2)
- queue.root[++found]=(byte*) &huff_counts->counts[last ? 0 : 1];
-
- queue.elements=found;
-
- bytes_packed=0; bits_packed=0;
- if (add_tree_lenght)
- bytes_packed=(8+9+5+5+(max_bit(last-first)+1)*found+
- (max_bit(found-1)+1+1)*(found-2) +7)/8;
- for (i=(found+1)/2 ; i > 0 ; i--)
- _downheap(&queue,i);
- for (i=0 ; i < found-1 ; i++)
- {
- HUFF_ELEMENT *a,*b,*new;
- a=(HUFF_ELEMENT*) queue_remove(&queue,0);
- b=(HUFF_ELEMENT*) queue.root[1];
- new=element_buffer+i;
- new->count=a->count+b->count;
- bits_packed+=(uint) (new->count & 7);
- bytes_packed+=new->count/8;
- queue.root[1]=(byte*) new;
- queue_replaced(&queue);
- }
- DBUG_RETURN(bytes_packed+(bits_packed+7)/8);
-}
-
-
- /* Remove trees that don't give any compression */
-
-static uint join_same_trees(HUFF_COUNTS *huff_counts, uint trees)
-{
- uint k,tree_number;
- HUFF_COUNTS count,*i,*j,*last_count;
-
- last_count=huff_counts+trees;
- for (tree_number=0, i=huff_counts ; i < last_count ; i++)
- {
- if (!i->tree->tree_number)
- {
- i->tree->tree_number= ++tree_number;
- if (i->tree_buff)
- continue; /* Don't join intervall */
- for (j=i+1 ; j < last_count ; j++)
- {
- if (! j->tree->tree_number && ! j->tree_buff)
- {
- for (k=0 ; k < 256 ; k++)
- count.counts[k]=i->counts[k]+j->counts[k];
- if (calc_packed_length(&count,1) <=
- i->tree->bytes_packed + j->tree->bytes_packed+
- i->tree->tree_pack_length+j->tree->tree_pack_length+
- ALLOWED_JOIN_DIFF)
- {
- memcpy((byte*) i->counts,(byte*) count.counts,
- sizeof(count.counts[0])*256);
- my_free((gptr) j->tree->element_buffer,MYF(0));
- j->tree->element_buffer=0;
- j->tree=i->tree;
- bmove((byte*) i->counts,(byte*) count.counts,
- sizeof(count.counts[0])*256);
- if (make_huff_tree(i->tree,i))
- return (uint) -1;
- }
- }
- }
- }
- }
- if (verbose)
- printf("Original trees: %d After join: %d\n",trees,tree_number);
- return tree_number; /* Return trees left */
-}
-
-
- /* Fill in huff_tree decode tables */
-
-static int make_huff_decode_table(HUFF_TREE *huff_tree, uint trees)
-{
- uint elements;
- for ( ; trees-- ; huff_tree++)
- {
- if (huff_tree->tree_number > 0)
- {
- elements=huff_tree->counts->tree_buff ? huff_tree->elements : 256;
- if (!(huff_tree->code =
- (ulong*) my_malloc(elements*
- (sizeof(ulong)+sizeof(uchar)),
- MYF(MY_WME | MY_ZEROFILL))))
- return 1;
- huff_tree->code_len=(uchar*) (huff_tree->code+elements);
- make_traverse_code_tree(huff_tree,huff_tree->root,32,0);
- }
- }
- return 0;
-}
-
-
-static void make_traverse_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element,
- uint size, ulong code)
-{
- uint chr;
- if (!element->a.leaf.null)
- {
- chr=element->a.leaf.element_nr;
- huff_tree->code_len[chr]=(uchar) (32-size);
- huff_tree->code[chr]= (code >> size);
- if (huff_tree->height < 32-size)
- huff_tree->height= 32-size;
- }
- else
- {
- size--;
- make_traverse_code_tree(huff_tree,element->a.nod.left,size,code);
- make_traverse_code_tree(huff_tree,element->a.nod.right,size,
- code+((ulong) 1L << size));
- }
- return;
-}
-
-
- /* Write header to new packed data file */
-
-static int write_header(MRG_INFO *mrg,uint head_length,uint trees,
- my_off_t tot_elements,my_off_t filelength)
-{
- byte *buff=file_buffer.pos;
-
- bzero(buff,HEAD_LENGTH);
- memcpy(buff,nisam_pack_file_magic,4);
- int4store(buff+4,head_length);
- int4store(buff+8, mrg->min_pack_length);
- int4store(buff+12,mrg->max_pack_length);
- int4store(buff+16,tot_elements);
- int4store(buff+20,intervall_length);
- int2store(buff+24,trees);
- buff[26]=(char) mrg->ref_length;
- /* Save record pointer length */
- buff[27]= (uchar) (filelength >= (1L << 24) ? 4 :
- filelength >= (1L << 16) ? 3 : 2);
- if (test_only)
- return 0;
- VOID(my_seek(file_buffer.file,0L,MY_SEEK_SET,MYF(0)));
- return my_write(file_buffer.file,file_buffer.pos,HEAD_LENGTH,
- MYF(MY_WME | MY_NABP | MY_WAIT_IF_FULL)) != 0;
-}
-
- /* Write fieldinfo to new packed file */
-
-static void write_field_info(HUFF_COUNTS *counts, uint fields, uint trees)
-{
- reg1 uint i;
- uint huff_tree_bits;
- huff_tree_bits=max_bit(trees ? trees-1 : 0);
-
- for (i=0 ; i++ < fields ; counts++)
- {
- write_bits((ulong) (int) counts->field_type,4);
- write_bits(counts->pack_type,4);
- if (counts->pack_type & PACK_TYPE_ZERO_FILL)
- write_bits(counts->max_zero_fill,4);
- else
- write_bits(counts->length_bits,4);
- write_bits((ulong) counts->tree->tree_number-1,huff_tree_bits);
- }
- flush_bits();
- return;
-}
-
- /* Write all huff_trees to new datafile. Return tot count of
- elements in all trees
- Returns 0 on error */
-
-static my_off_t write_huff_tree(HUFF_TREE *huff_tree, uint trees)
-{
- uint i,int_length;
- uint *packed_tree,*offset,length;
- my_off_t elements;
-
- for (i=length=0 ; i < trees ; i++)
- if (huff_tree[i].tree_number > 0 && huff_tree[i].elements > length)
- length=huff_tree[i].elements;
- if (!(packed_tree=(uint*) my_alloca(sizeof(uint)*length*2)))
- {
- my_error(EE_OUTOFMEMORY,MYF(ME_BELL),sizeof(uint)*length*2);
- return 0;
- }
-
- intervall_length=0;
- for (elements=0; trees-- ; huff_tree++)
- {
- if (huff_tree->tree_number == 0)
- continue; /* Deleted tree */
- elements+=huff_tree->elements;
- huff_tree->max_offset=2;
- if (huff_tree->elements <= 1)
- offset=packed_tree;
- else
- offset=make_offset_code_tree(huff_tree,huff_tree->root,packed_tree);
- huff_tree->offset_bits=max_bit(huff_tree->max_offset);
- if (huff_tree->max_offset >= IS_OFFSET)
- { /* This should be impossible */
- VOID(fprintf(stderr,"Tree offset got too big: %d, aborted\n",
- huff_tree->max_offset));
- my_afree((gptr) packed_tree);
- return 0;
- }
-
-#ifdef EXTRA_DBUG
- printf("pos: %d elements: %d tree-elements: %d char_bits: %d\n",
- (uint) (file_buffer.pos-file_buffer.buffer),
- huff_tree->elements, (offset-packed_tree),huff_tree->char_bits);
-#endif
- if (!huff_tree->counts->tree_buff)
- {
- write_bits(0,1);
- write_bits(huff_tree->min_chr,8);
- write_bits(huff_tree->elements,9);
- write_bits(huff_tree->char_bits,5);
- write_bits(huff_tree->offset_bits,5);
- int_length=0;
- }
- else
- {
- int_length=(uint) (huff_tree->counts->tree_pos -
- huff_tree->counts->tree_buff);
- write_bits(1,1);
- write_bits(huff_tree->elements,15);
- write_bits(int_length,16);
- write_bits(huff_tree->char_bits,5);
- write_bits(huff_tree->offset_bits,5);
- intervall_length+=int_length;
- }
- length=(uint) (offset-packed_tree);
- if (length != huff_tree->elements*2-2)
- printf("error: Huff-tree-length: %d != calc_length: %d\n",
- length,huff_tree->elements*2-2);
-
- for (i=0 ; i < length ; i++)
- {
- if (packed_tree[i] & IS_OFFSET)
- write_bits(packed_tree[i] - IS_OFFSET+ ((ulong) 1L << huff_tree->offset_bits),
- huff_tree->offset_bits+1);
- else
- write_bits(packed_tree[i]-huff_tree->min_chr,huff_tree->char_bits+1);
- }
- flush_bits();
- if (huff_tree->counts->tree_buff)
- {
- for (i=0 ; i < int_length ; i++)
- write_bits((uint) (uchar) huff_tree->counts->tree_buff[i],8);
- }
- flush_bits();
- }
- my_afree((gptr) packed_tree);
- return elements;
-}
-
-
-static uint *make_offset_code_tree(HUFF_TREE *huff_tree, HUFF_ELEMENT *element,
- uint *offset)
-{
- uint *prev_offset;
-
- prev_offset= offset;
- if (!element->a.nod.left->a.leaf.null)
- {
- offset[0] =(uint) element->a.nod.left->a.leaf.element_nr;
- offset+=2;
- }
- else
- {
- prev_offset[0]= IS_OFFSET+2;
- offset=make_offset_code_tree(huff_tree,element->a.nod.left,offset+2);
- }
- if (!element->a.nod.right->a.leaf.null)
- {
- prev_offset[1]=element->a.nod.right->a.leaf.element_nr;
- return offset;
- }
- else
- {
- uint temp=(uint) (offset-prev_offset-1);
- prev_offset[1]= IS_OFFSET+ temp;
- if (huff_tree->max_offset < temp)
- huff_tree->max_offset = temp;
- return make_offset_code_tree(huff_tree,element->a.nod.right,offset);
- }
-}
-
- /* Get number of bits neaded to represent value */
-
-static uint max_bit(register uint value)
-{
- reg2 uint power=1;
-
- while ((value>>=1))
- power++;
- return (power);
-}
-
-
-static int compress_isam_file(MRG_INFO *mrg, HUFF_COUNTS *huff_counts)
-{
- int error;
- uint i,max_calc_length,pack_ref_length,min_record_length,max_record_length,
- intervall,field_length;
- my_off_t record_count,max_allowed_length;
- ulong length;
- byte *record,*pos,*end_pos,*record_pos,*start_pos;
- HUFF_COUNTS *count,*end_count;
- HUFF_TREE *tree;
- N_INFO *isam_file=mrg->file[0];
- DBUG_ENTER("compress_isam_file");
-
- if (!(record=(byte*) my_alloca(isam_file->s->base.reclength)))
- return -1;
- end_count=huff_counts+isam_file->s->base.fields;
- min_record_length= (uint) ~0;
- max_record_length=0;
-
- for (i=max_calc_length=0 ; i < isam_file->s->base.fields ; i++)
- {
- if (!(huff_counts[i].pack_type & PACK_TYPE_ZERO_FILL))
- huff_counts[i].max_zero_fill=0;
- if (huff_counts[i].field_type == FIELD_CONSTANT ||
- huff_counts[i].field_type == FIELD_ZERO)
- continue;
- if (huff_counts[i].field_type == FIELD_INTERVALL)
- max_calc_length+=huff_counts[i].tree->height;
- else
- max_calc_length+=
- (huff_counts[i].field_length - huff_counts[i].max_zero_fill)*
- huff_counts[i].tree->height+huff_counts[i].length_bits;
- }
- max_calc_length/=8;
- if (max_calc_length <= 255)
- pack_ref_length=1;
- else if (max_calc_length <= 65535)
- pack_ref_length=2;
- else
- pack_ref_length=3;
- if (force_pack_ref_length)
- pack_ref_length=force_pack_ref_length;
- max_allowed_length= 1L << (pack_ref_length*8);
- record_count=0;
-
- mrg_reset(mrg);
- while ((error=mrg_rrnd(mrg,record)) >= 0)
- {
- if (! error)
- {
- if (flush_buffer(max_calc_length+pack_ref_length))
- break;
- record_pos=file_buffer.pos;
- file_buffer.pos+=pack_ref_length;
- for (start_pos=record, count= huff_counts; count < end_count ; count++)
- {
- end_pos=start_pos+(field_length=count->field_length);
- tree=count->tree;
-
- if (count->pack_type & PACK_TYPE_SPACE_FIELDS)
- {
- for (pos=start_pos ; *pos == ' ' && pos < end_pos; pos++) ;
- if (pos == end_pos)
- {
- write_bits(1,1);
- start_pos=end_pos;
- continue;
- }
- write_bits(0,1);
- }
-
-#ifdef BYTE_ORDER_HIGH_FIRST
- start_pos+=count->max_zero_fill;
-#else
- end_pos-=count->max_zero_fill;
-#endif
- field_length-=count->max_zero_fill;
-
- switch(count->field_type) {
- case FIELD_SKIP_ZERO:
- if (!memcmp((byte*) start_pos,zero_string,field_length))
- {
- write_bits(1,1);
- start_pos=end_pos;
- break;
- }
- write_bits(0,1);
- /* Fall through */
- case FIELD_NORMAL:
- for ( ; start_pos < end_pos ; start_pos++)
- write_bits(tree->code[(uchar) *start_pos],
- (uint) tree->code_len[(uchar) *start_pos]);
- break;
- case FIELD_SKIP_ENDSPACE:
- for (pos=end_pos ; pos > start_pos && pos[-1] == ' ' ; pos--) ;
- length=(uint) (end_pos-pos);
- if (count->pack_type & PACK_TYPE_SELECTED)
- {
- if (length > count->min_space)
- {
- write_bits(1,1);
- write_bits(length,count->length_bits);
- }
- else
- {
- write_bits(0,1);
- pos=end_pos;
- }
- }
- else
- write_bits(length,count->length_bits);
- for ( ; start_pos < pos ; start_pos++)
- write_bits(tree->code[(uchar) *start_pos],
- (uint) tree->code_len[(uchar) *start_pos]);
- start_pos=end_pos;
- break;
- case FIELD_SKIP_PRESPACE:
- for (pos=start_pos ; pos < end_pos && pos[0] == ' ' ; pos++) ;
- length=(uint) (pos-start_pos);
- if (count->pack_type & PACK_TYPE_SELECTED)
- {
- if (length > count->min_space)
- {
- write_bits(1,1);
- write_bits(length,count->length_bits);
- }
- else
- {
- pos=start_pos;
- write_bits(0,1);
- }
- }
- else
- write_bits(length,count->length_bits);
- for (start_pos=pos ; start_pos < end_pos ; start_pos++)
- write_bits(tree->code[(uchar) *start_pos],
- (uint) tree->code_len[(uchar) *start_pos]);
- break;
- case FIELD_CONSTANT:
- case FIELD_ZERO:
- start_pos=end_pos;
- break;
- case FIELD_INTERVALL:
- global_count=count;
- pos=(byte*) tree_search(&count->int_tree, start_pos,
- count->int_tree.custom_arg);
- intervall=(uint) (pos - count->tree_buff)/field_length;
- write_bits(tree->code[intervall],(uint) tree->code_len[intervall]);
- start_pos=end_pos;
- break;
- case FIELD_BLOB:
- VOID(fprintf(stderr,"Can't pack files with blobs. Aborting\n"));
- DBUG_RETURN(1);
- case FIELD_LAST:
- case FIELD_VARCHAR:
- case FIELD_CHECK:
- abort(); /* Impossible */
- }
-#ifndef BYTE_ORDER_HIGH_FIRST
- start_pos+=count->max_zero_fill;
-#endif
- }
- flush_bits();
- length=(ulong) (file_buffer.pos-record_pos)-pack_ref_length;
- save_integer(record_pos,pack_ref_length,length);
- if (length < (ulong) min_record_length)
- min_record_length=(uint) length;
- if (length > (ulong) max_record_length)
- {
- max_record_length=(uint) length;
- if (max_record_length >= max_allowed_length)
- {
- fprintf(stderr,
- "Error: Found record with packed-length: %d, max is: %lu\n",
- max_record_length, (ulong) max_allowed_length);
- error=1;
- break;
- }
- }
- if (write_loop && ++record_count % WRITE_COUNT == 0)
- {
- printf("%lu\r",(ulong) record_count); VOID(fflush(stdout));
- }
- }
- else if (my_errno != HA_ERR_RECORD_DELETED)
- break;
- }
- if (error < 0)
- {
- error=0;
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%s: Got error %d reading records\n",my_progname,my_errno);
- error= 1;
- }
- }
-
- my_afree((gptr) record);
- mrg->ref_length=pack_ref_length;
- mrg->min_pack_length=max_record_length ? min_record_length : 0;
- mrg->max_pack_length=max_record_length;
- if (verbose && max_record_length &&
- max_record_length < max_allowed_length/256)
- printf("Record-length is %d bytes, could have been %d bytes\nYou can change this by using -p=%d next time you pack this file\n",
- pack_ref_length,
- max_record_length/256+1,
- max_record_length/256+1);
- DBUG_RETURN(error || error_on_write || flush_buffer((uint) ~0));
-}
-
-
-static char *make_new_name(char *new_name, char *old_name)
-{
- return fn_format(new_name,old_name,"",DATA_TMP_EXT,2+4);
-}
-
-static char *make_old_name(char *new_name, char *old_name)
-{
- return fn_format(new_name,old_name,"",OLD_EXT,2+4);
-}
-
- /* rutines for bit writing buffer */
-
-static void init_file_buffer(File file, pbool read_buffer)
-{
- file_buffer.file=file;
- file_buffer.buffer=my_malloc(ALIGN_SIZE(RECORD_CACHE_SIZE),MYF(MY_WME));
- file_buffer.end=file_buffer.buffer+ALIGN_SIZE(RECORD_CACHE_SIZE)-4;
- file_buffer.pos_in_file=0;
- error_on_write=0;
- if (read_buffer)
- {
-
- file_buffer.pos=file_buffer.end;
- file_buffer.bits=0;
- }
- else
- {
- file_buffer.pos=file_buffer.buffer;
- file_buffer.bits=BITS_SAVED;
- }
- file_buffer.bytes=0;
-}
-
-
-static int flush_buffer(uint neaded_length)
-{
- uint length;
- if ((uint) (file_buffer.end - file_buffer.pos) > neaded_length)
- return 0;
- length=(uint) (file_buffer.pos-file_buffer.buffer);
- file_buffer.pos=file_buffer.buffer;
- file_buffer.pos_in_file+=length;
- if (test_only)
- return 0;
- return (error_on_write|=test(my_write(file_buffer.file,file_buffer.buffer,
- length,
- MYF(MY_WME | MY_NABP |
- MY_WAIT_IF_FULL))));
-}
-
-static void end_file_buffer(void)
-{
- my_free((gptr) file_buffer.buffer,MYF(0));
-}
-
- /* output `bits` low bits of `value' */
-
-static void write_bits (register ulong value, register uint bits)
-{
- if ((file_buffer.bits-=(int) bits) >= 0)
- {
- file_buffer.bytes|=value << file_buffer.bits;
- }
- else
- {
- reg3 uint byte_buff;
- bits= (uint) -file_buffer.bits;
- byte_buff=file_buffer.bytes | (uint) (value >> bits);
-#if BITS_SAVED == 32
- *file_buffer.pos++= (byte) (byte_buff >> 24) ;
- *file_buffer.pos++= (byte) (byte_buff >> 16) ;
-#endif
- *file_buffer.pos++= (byte) (byte_buff >> 8) ;
- *file_buffer.pos++= (byte) byte_buff;
-
- value&=((ulong) 1L << bits)-1;
-#if BITS_SAVED == 16
- if (bits >= sizeof(uint))
- {
- bits-=8;
- *file_buffer.pos++= (uchar) (value >> bits);
- value&= ((ulong) 1L << bits)-1;
- if (bits >= sizeof(uint))
- {
- bits-=8;
- *file_buffer.pos++= (uchar) (value >> bits);
- value&= ((ulong) 1L << bits)-1;
- }
- }
-#endif
- if (file_buffer.pos >= file_buffer.end)
- VOID(flush_buffer((uint) ~0));
- file_buffer.bits=(int) (BITS_SAVED - bits);
- file_buffer.bytes=(uint) (value << (BITS_SAVED - bits));
- }
- return;
-}
-
- /* Flush bits in bit_buffer to buffer */
-
-static void flush_bits (void)
-{
- uint bits,byte_buff;
-
- bits=(file_buffer.bits) & ~7;
- byte_buff = file_buffer.bytes >> bits;
- bits=BITS_SAVED - bits;
- while (bits > 0)
- {
- bits-=8;
- *file_buffer.pos++= (byte) (uchar) (byte_buff >> bits) ;
- }
- file_buffer.bits=BITS_SAVED;
- file_buffer.bytes=0;
- return;
-}
-
- /* Store long in 1,2,3,4 or 5 bytes */
-
-static void save_integer(byte *pos, uint pack_length, my_off_t value)
-{
- switch (pack_length) {
- case 5: int5store(pos,(ulonglong) value); break;
- default: int4store(pos,(ulong) value); break;
- case 3: int3store(pos,(ulong) value); break;
- case 2: int2store(pos,(uint) value); break;
- case 1: pos[0]= (byte) (uchar) value; break;
- }
- return;
-}
-
-
-/****************************************************************************
-** functions to handle the joined files
-****************************************************************************/
-
-static void save_state(N_INFO *isam_file,MRG_INFO *mrg,my_off_t new_length,
- ulong crc)
-{
- ISAM_SHARE *share=isam_file->s;
- uint options=uint2korr(share->state.header.options);
- DBUG_ENTER("save_state");
-
- options|= HA_OPTION_COMPRESS_RECORD | HA_OPTION_READ_ONLY_DATA;
- int2store(share->state.header.options,options);
-
- share->state.data_file_length=(ulong) new_length;
- share->state.del=share->state.empty=0;
- share->state.dellink= (ulong) NI_POS_ERROR;
- share->state.splitt=(ulong) mrg->records;
- share->state.version=(ulong) time((time_t*) 0);
- share->state.keys=0;
- share->state.key_file_length=share->base.keystart;
-
- isam_file->update|=(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- isam_file->this_uniq=crc; /* Save crc here */
- share->changed=1; /* Force write of header */
- VOID(my_chsize(share->kfile, share->state.key_file_length, 0,
- MYF(0)));
- if (share->state.keys != share->base.keys)
- isamchk_neaded=1;
- DBUG_VOID_RETURN;
-}
-
-
-static int save_state_mrg(File file,MRG_INFO *mrg,my_off_t new_length,
- ulong crc)
-{
- N_STATE_INFO state;
- N_INFO *isam_file=mrg->file[0];
- uint options;
- DBUG_ENTER("save_state_mrg");
-
- memcpy(&state,&isam_file->s->state,sizeof(state));
- options= (uint2korr(state.header.options) | HA_OPTION_COMPRESS_RECORD |
- HA_OPTION_READ_ONLY_DATA);
- int2store(state.header.options,options);
- state.data_file_length=(ulong) new_length;
- state.del=state.empty=0;
- state.dellink= (ulong) NI_POS_ERROR;
- state.records=state.splitt=(ulong) mrg->records;
- state.version=(ulong) time((time_t*) 0);
- state.keys=0;
- state.key_file_length=isam_file->s->base.keystart;
- state.uniq=crc;
- if (state.keys != isam_file->s->base.keys)
- isamchk_neaded=1;
- DBUG_RETURN (my_pwrite(file,(char*) &state.header,
- isam_file->s->state_length,0L,
- MYF(MY_NABP | MY_WME)) != 0);
-}
-
-
-/* reset for mrg_rrnd */
-
-static void mrg_reset(MRG_INFO *mrg)
-{
- if (mrg->current)
- {
- nisam_extra(*mrg->current,HA_EXTRA_NO_CACHE);
- mrg->current=0;
- }
-}
-
-static int mrg_rrnd(MRG_INFO *info,byte *buf)
-{
- int error;
- N_INFO *isam_info;
- my_off_t filepos;
-
- if (!info->current)
- {
- isam_info= *(info->current=info->file);
- info->end=info->current+info->count;
- nisam_extra(isam_info,HA_EXTRA_RESET);
- nisam_extra(isam_info,HA_EXTRA_CACHE);
- filepos=isam_info->s->pack.header_length;
- }
- else
- {
- isam_info= *info->current;
- filepos= isam_info->nextpos;
- }
-
- for (;;)
- {
- isam_info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- if ((error=(*isam_info->s->read_rnd)(isam_info,(byte*) buf,
- (ulong) filepos, 1)) >= 0 ||
- my_errno != HA_ERR_END_OF_FILE)
- return (error);
- nisam_extra(isam_info,HA_EXTRA_NO_CACHE);
- if (info->current+1 == info->end)
- return(-1);
- info->current++;
- isam_info= *info->current;
- filepos=isam_info->s->pack.header_length;
- nisam_extra(isam_info,HA_EXTRA_RESET);
- nisam_extra(isam_info,HA_EXTRA_CACHE);
- }
-}
-
-
-static int mrg_close(MRG_INFO *mrg)
-{
- uint i;
- int error=0;
- for (i=0 ; i < mrg->count ; i++)
- error|=nisam_close(mrg->file[i]);
- return error;
-}
diff --git a/isam/panic.c b/isam/panic.c
deleted file mode 100644
index 7af979a5104..00000000000
--- a/isam/panic.c
+++ /dev/null
@@ -1,135 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "isamdef.h"
-
- /* if flag == HA_PANIC_CLOSE then all misam files are closed */
- /* if flag == HA_PANIC_WRITE then all misam files are unlocked and
- all changed data in single user misam is written to file */
- /* if flag == HA_PANIC_READ then all misam files that was locked when
- nisam_panic(HA_PANIC_WRITE) was done is locked. A ni_readinfo() is
- done for all single user files to get changes in database */
-
-
-int nisam_panic(enum ha_panic_function flag)
-{
- int error=0;
- LIST *list_element,*next_open;
- N_INFO *info;
- DBUG_ENTER("nisam_panic");
-
- pthread_mutex_lock(&THR_LOCK_isam);
- for (list_element=nisam_open_list ; list_element ; list_element=next_open)
- {
- next_open=list_element->next; /* Save if close */
- info=(N_INFO*) list_element->data;
- switch (flag) {
- case HA_PANIC_CLOSE:
- pthread_mutex_unlock(&THR_LOCK_isam); /* Not exactly right... */
- if (nisam_close(info))
- error=my_errno;
- pthread_mutex_lock(&THR_LOCK_isam);
- break;
- case HA_PANIC_WRITE: /* Do this to free databases */
-#ifdef CANT_OPEN_FILES_TWICE
- if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
- break;
-#endif
- if (flush_key_blocks(dflt_key_cache,info->s->kfile,FLUSH_RELEASE))
- error=my_errno;
- if (info->opt_flag & WRITE_CACHE_USED)
- if (flush_io_cache(&info->rec_cache))
- error=my_errno;
- if (info->opt_flag & READ_CACHE_USED)
- {
- if (flush_io_cache(&info->rec_cache))
- error=my_errno;
- reinit_io_cache(&info->rec_cache,READ_CACHE,0,
- (pbool) (info->lock_type != F_UNLCK),1);
- }
-#ifndef NO_LOCKING
- if (info->lock_type != F_UNLCK && ! info->was_locked)
- {
- info->was_locked=info->lock_type;
- if (nisam_lock_database(info,F_UNLCK))
- error=my_errno;
- }
-#else
- {
- int save_status=info->s->w_locks; /* Only w_locks! */
- info->s->w_locks=0;
- if (_nisam_writeinfo(info, test(info->update & HA_STATE_CHANGED)))
- error=my_errno;
- info->s->w_locks=save_status;
- info->update&= ~HA_STATE_CHANGED; /* Not changed */
- }
-#endif /* NO_LOCKING */
-#ifdef CANT_OPEN_FILES_TWICE
- if (info->s->kfile >= 0 && my_close(info->s->kfile,MYF(0)))
- error = my_errno;
- if (info->dfile >= 0 && my_close(info->dfile,MYF(0)))
- error = my_errno;
- info->s->kfile=info->dfile= -1; /* Files aren't open anymore */
- break;
-#endif
- case HA_PANIC_READ: /* Restore to before WRITE */
-#ifdef CANT_OPEN_FILES_TWICE
- { /* Open closed files */
- char name_buff[FN_REFLEN];
- if (info->s->kfile < 0)
- if ((info->s->kfile= my_open(fn_format(name_buff,info->filename,"",
- N_NAME_IEXT,4),info->mode,
- MYF(MY_WME))) < 0)
- error = my_errno;
- if (info->dfile < 0)
- {
- if ((info->dfile= my_open(fn_format(name_buff,info->filename,"",
- N_NAME_DEXT,4),info->mode,
- MYF(MY_WME))) < 0)
- error = my_errno;
- info->rec_cache.file=info->dfile;
- }
- }
-#endif
-#ifndef NO_LOCKING
- if (info->was_locked)
- {
- if (nisam_lock_database(info, info->was_locked))
- error=my_errno;
- info->was_locked=0;
- }
-#else
- {
- int lock_type,w_locks;
- lock_type=info->lock_type ; w_locks=info->s->w_locks;
- info->lock_type=0; info->s->w_locks=0;
- if (_nisam_readinfo(info,0,1)) /* Read changed data */
- error=my_errno;
- info->lock_type=lock_type; info->s->w_locks=w_locks;
- }
- /* Don't use buffer when doing next */
- info->update|=HA_STATE_WRITTEN;
-#endif /* NO_LOCKING */
- break;
- }
- }
- if (flag == HA_PANIC_CLOSE)
- VOID(nisam_log(0)); /* Close log if neaded */
- pthread_mutex_unlock(&THR_LOCK_isam);
- if (!error) DBUG_RETURN(0);
- my_errno=error;
- DBUG_RETURN(-1);
-} /* nisam_panic */
diff --git a/isam/range.c b/isam/range.c
deleted file mode 100644
index 3b79b6d93a9..00000000000
--- a/isam/range.c
+++ /dev/null
@@ -1,191 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- Gives a approximated number of how many records there is between two keys.
- Used when optimizing querries.
- */
-
-#include "isamdef.h"
-
-static ulong _nisam_record_pos(N_INFO *info,const byte *key,uint key_len,
- enum ha_rkey_function search_flag);
-static double _nisam_search_pos(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- uint key_len,uint nextflag,ulong pos);
-static uint _nisam_keynr(N_INFO *info,N_KEYDEF *keyinfo,uchar *page,
- uchar *keypos,uint *ret_max_key);
-
-
- /* If start_key = 0 assume read from start */
- /* If end_key = 0 assume read to end */
- /* Returns NI_POS_ERROR on error */
-
-ulong nisam_records_in_range(N_INFO *info, int inx, const byte *start_key,
- uint start_key_len,
- enum ha_rkey_function start_search_flag,
- const byte *end_key, uint end_key_len,
- enum ha_rkey_function end_search_flag)
-{
- ulong start_pos,end_pos;
- DBUG_ENTER("nisam_records_in_range");
-
- if ((inx = _nisam_check_index(info,inx)) < 0)
- DBUG_RETURN(NI_POS_ERROR);
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1))
- DBUG_RETURN(NI_POS_ERROR);
-#endif
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- start_pos= (start_key ?
- _nisam_record_pos(info,start_key,start_key_len,start_search_flag) :
- 0L);
- end_pos= (end_key ?
- _nisam_record_pos(info,end_key,end_key_len,end_search_flag) :
- info->s->state.records+1L);
- VOID(_nisam_writeinfo(info,0));
- if (start_pos == NI_POS_ERROR || end_pos == NI_POS_ERROR)
- DBUG_RETURN(NI_POS_ERROR);
- DBUG_PRINT("info",("records: %ld",end_pos-start_pos));
- DBUG_RETURN(end_pos < start_pos ? 0L :
- (end_pos == start_pos ? 1L : end_pos-start_pos));
-}
-
-
- /* Find relative position (in records) for key in index-tree */
-
-static ulong _nisam_record_pos(N_INFO *info, const byte *key, uint key_len,
- enum ha_rkey_function search_flag)
-{
- uint inx=(uint) info->lastinx;
- N_KEYDEF *keyinfo=info->s->keyinfo+inx;
- uchar *key_buff;
- double pos;
-
- DBUG_ENTER("_nisam_record_pos");
- DBUG_PRINT("enter",("search_flag: %d",search_flag));
-
- if (key_len >= (keyinfo->base.keylength-info->s->rec_reflength)
- && !(keyinfo->base.flag & HA_SPACE_PACK_USED))
- key_len=USE_HOLE_KEY;
- key_buff=info->lastkey+info->s->base.max_key_length;
- key_len=_nisam_pack_key(info,inx,key_buff,(uchar*) key,key_len);
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,
- (uchar*) key_buff););
- pos=_nisam_search_pos(info,keyinfo,key_buff,key_len,
- nisam_read_vec[search_flag] | SEARCH_SAVE_BUFF,
- info->s->state.key_root[inx]);
- if (pos >= 0.0)
- {
- DBUG_PRINT("exit",("pos: %ld",(ulong) (pos*info->s->state.records)));
- DBUG_RETURN((ulong) (pos*info->s->state.records+0.5));
- }
- DBUG_RETURN(NI_POS_ERROR);
-}
-
-
- /* This is a modified version of _nisam_search */
- /* Returns offset for key in indextable (decimal 0.0 <= x <= 1.0) */
-
-static double _nisam_search_pos(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, uint key_len, uint nextflag,
- register ulong pos)
-{
- int flag;
- uint nod_flag,keynr,max_keynr;
- uchar *keypos,*buff;
- double offset;
- DBUG_ENTER("_nisam_search_pos");
-
- if (pos == NI_POS_ERROR)
- DBUG_RETURN(0.5);
-
- if (!(buff=_nisam_fetch_keypage(info,keyinfo,pos,info->buff,1)))
- goto err;
- flag=(*keyinfo->bin_search)(info,keyinfo,buff,key,key_len,nextflag,
- &keypos,info->lastkey);
- nod_flag=test_if_nod(buff);
- keynr=_nisam_keynr(info,keyinfo,buff,keypos,&max_keynr);
-
- if (flag)
- {
- /*
- ** Didn't found match. keypos points at next (bigger) key
- * Try to find a smaller, better matching key.
- ** Matches keynr + [0-1]
- */
- if ((offset=_nisam_search_pos(info,keyinfo,key,key_len,nextflag,
- _nisam_kpos(nod_flag,keypos))) < 0)
- DBUG_RETURN(offset);
- }
- else
- {
- /*
- ** Found match. Keypos points at the start of the found key
- ** Matches keynr+1
- */
- offset=1.0; /* Matches keynr+1 */
- if (nextflag & SEARCH_FIND && (!(keyinfo->base.flag & HA_NOSAME)
- || key_len) && nod_flag)
- {
- /*
- ** There may be identical keys in the tree. Try to match on of those.
- ** Matches keynr + [0-1]
- */
- if ((offset=_nisam_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
- _nisam_kpos(nod_flag,keypos))) < 0)
- DBUG_RETURN(offset); /* Read error */
- }
- }
- DBUG_PRINT("info",("keynr: %d offset: %g max_keynr: %d nod: %d flag: %d",
- keynr,offset,max_keynr,nod_flag,flag));
- DBUG_RETURN((keynr+offset)/(max_keynr+1));
-err:
- DBUG_PRINT("exit",("Error: %d",my_errno));
- DBUG_RETURN (-1.0);
-}
-
-
- /* Get keynummer of current key and max number of keys in nod */
-
-static uint _nisam_keynr(N_INFO *info, register N_KEYDEF *keyinfo, uchar *page, uchar *keypos, uint *ret_max_key)
-{
- uint nod_flag,keynr,max_key;
- uchar t_buff[N_MAX_KEY_BUFF],*end;
-
- end= page+getint(page);
- nod_flag=test_if_nod(page);
- page+=2+nod_flag;
-
- if (!(keyinfo->base.flag &
- (HA_PACK_KEY | HA_SPACE_PACK | HA_SPACE_PACK_USED)))
- {
- *ret_max_key= (uint) (end-page)/(keyinfo->base.keylength+nod_flag);
- return (uint) (keypos-page)/(keyinfo->base.keylength+nod_flag);
- }
-
- max_key=keynr=0;
- while (page < end)
- {
- t_buff[0]=0; /* Don't move packed key */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,t_buff));
- max_key++;
- if (page == keypos)
- keynr=max_key;
- }
- *ret_max_key=max_key;
- return(keynr);
-}
diff --git a/isam/rfirst.c b/isam/rfirst.c
deleted file mode 100644
index cc1cbee92bf..00000000000
--- a/isam/rfirst.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser f|rsta posten som har samma isam-nyckel */
-
-#include "isamdef.h"
-
- /*
- L{ser f|rsta posten med samma isamnyckel som f|reg}ende l{sning.
- Man kan ha gjort write, update eller delete p} f|reg}ende post.
- OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
- posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
- */
-
-int nisam_rfirst(N_INFO *info, byte *buf, int inx)
-{
- DBUG_ENTER("nisam_rfirst");
- info->lastpos= NI_POS_ERROR;
- info->update|= HA_STATE_PREV_FOUND;
- DBUG_RETURN(nisam_rnext(info,buf,inx));
-} /* nisam_rfirst */
diff --git a/isam/rkey.c b/isam/rkey.c
deleted file mode 100644
index bbe4576418b..00000000000
--- a/isam/rkey.c
+++ /dev/null
@@ -1,63 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser p} basen av en isam_nyckel */
-
-#include "isamdef.h"
-
-
- /* Read a record using key */
- /* Ordinary search_flag is 0 ; Give error if no record with key */
-
-int nisam_rkey(N_INFO *info, byte *buf, int inx, const byte *key, uint key_len, enum ha_rkey_function search_flag)
-{
- uchar *key_buff;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("nisam_rkey");
- DBUG_PRINT("enter",("base: %lx inx: %d search_flag: %d",
- info,inx,search_flag));
-
- if ((inx = _nisam_check_index(info,inx)) < 0)
- DBUG_RETURN(-1);
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- if (key_len >= (share->keyinfo[inx].base.keylength - share->rec_reflength)
- && !(info->s->keyinfo[inx].base.flag & HA_SPACE_PACK_USED))
- key_len=USE_HOLE_KEY;
- key_buff=info->lastkey+info->s->base.max_key_length;
- key_len=_nisam_pack_key(info,(uint) inx,key_buff,(uchar*) key,key_len);
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,share->keyinfo[inx].seg,
- (uchar*) key););
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1))
- goto err;
-#endif
-
- VOID(_nisam_search(info,info->s->keyinfo+inx,key_buff,key_len,
- nisam_read_vec[search_flag],info->s->state.key_root[inx]));
- if ((*info->read_record)(info,info->lastpos,buf) >= 0)
- {
- info->update|= HA_STATE_AKTIV; /* Record is read */
- DBUG_RETURN(0);
- }
-
- info->lastpos = NI_POS_ERROR; /* Didn't find key */
- VOID(_nisam_move_key(info->s->keyinfo+inx,info->lastkey,key_buff));
- if (search_flag == HA_READ_AFTER_KEY)
- info->update|=HA_STATE_NEXT_FOUND; /* Previous gives last row */
-err:
- DBUG_RETURN(-1);
-} /* nisam_rkey */
diff --git a/isam/rlast.c b/isam/rlast.c
deleted file mode 100644
index a91f1f1011b..00000000000
--- a/isam/rlast.c
+++ /dev/null
@@ -1,34 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser sista posten som har samma isam-nyckel */
-
-#include "isamdef.h"
-
- /*
- L{ser sista posten med samma isamnyckel som f|reg}ende l{sning.
- Man kan ha gjort write, update eller delete p} f|reg}ende post.
- OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
- posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
- */
-
-int nisam_rlast(N_INFO *info, byte *buf, int inx)
-{
- DBUG_ENTER("nisam_rlast");
- info->lastpos= NI_POS_ERROR;
- info->update|= HA_STATE_NEXT_FOUND;
- DBUG_RETURN(nisam_rprev(info,buf,inx));
-} /* nisam_rlast */
diff --git a/isam/rnext.c b/isam/rnext.c
deleted file mode 100644
index be26098c901..00000000000
--- a/isam/rnext.c
+++ /dev/null
@@ -1,67 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser n{sta post med samma isam-nyckel */
-
-#include "isamdef.h"
-
- /*
- L{ser n{sta post med samma isamnyckel som f|reg}ende l{sning.
- Man kan ha gjort write, update eller delete p} f|reg}ende post.
- OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
- posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
- */
-
-int nisam_rnext(N_INFO *info, byte *buf, int inx)
-{
- int error,changed;
- uint flag;
- DBUG_ENTER("nisam_rnext");
-
- if ((inx = _nisam_check_index(info,inx)) < 0)
- DBUG_RETURN(-1);
- flag=SEARCH_BIGGER; /* Read next */
- if (info->lastpos == NI_POS_ERROR && info->update & HA_STATE_PREV_FOUND)
- flag=0; /* Read first */
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1);
-#endif
- changed=_nisam_test_if_changed(info);
- if (!flag)
- error=_nisam_search_first(info,info->s->keyinfo+inx,
- info->s->state.key_root[inx]);
- else if (!changed)
- error=_nisam_search_next(info,info->s->keyinfo+inx,info->lastkey,flag,
- info->s->state.key_root[inx]);
- else
- error=_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,flag,
- info->s->state.key_root[inx]);
-
- /* Don't clear if database-changed */
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |
- HA_STATE_BUFF_SAVED);
- info->update|= HA_STATE_NEXT_FOUND;
-
- if (error && my_errno == HA_ERR_KEY_NOT_FOUND)
- my_errno=HA_ERR_END_OF_FILE;
- if ((*info->read_record)(info,info->lastpos,buf) >=0)
- {
- info->update|= HA_STATE_AKTIV; /* Record is read */
- DBUG_RETURN(0);
- }
- DBUG_RETURN(-1);
-} /* nisam_rnext */
diff --git a/isam/rprev.c b/isam/rprev.c
deleted file mode 100644
index 0997a04fbbe..00000000000
--- a/isam/rprev.c
+++ /dev/null
@@ -1,64 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser f|reg}ende post med samma isam-nyckel */
-
-#include "isamdef.h"
-
- /*
- L{ser f|reg}ende post med samma isamnyckel som f|reg}ende l{sning.
- Man kan ha gjort write, update eller delete p} f|reg}ende post.
- OBS! [ven om man {ndrade isamnyckeln p} f|reg}ende post l{ses
- posten i avseende p} f|reg}ende isam-nyckel-l{sning !!
- */
-
-int nisam_rprev(N_INFO *info, byte *buf, int inx)
-{
- int error,changed;
- register uint flag;
- DBUG_ENTER("nisam_rprev");
-
- if ((inx = _nisam_check_index(info,inx)) < 0)
- DBUG_RETURN(-1);
- flag=SEARCH_SMALLER; /* Read previous */
- if (info->lastpos == NI_POS_ERROR && info->update & HA_STATE_NEXT_FOUND)
- flag=0; /* Read last */
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1)) DBUG_RETURN(-1);
-#endif
- changed=_nisam_test_if_changed(info);
- if (!flag)
- error=_nisam_search_last(info,info->s->keyinfo+inx,info->s->state.key_root[inx]);
- else if (!changed)
- error=_nisam_search_next(info,info->s->keyinfo+inx,info->lastkey,flag,
- info->s->state.key_root[inx]);
- else
- error=_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,flag,
- info->s->state.key_root[inx]);
-
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |
- HA_STATE_BUFF_SAVED);
- info->update|= HA_STATE_PREV_FOUND;
- if (error && my_errno == HA_ERR_KEY_NOT_FOUND)
- my_errno=HA_ERR_END_OF_FILE;
- if ((*info->read_record)(info,info->lastpos,buf) >=0)
- {
- info->update|= HA_STATE_AKTIV; /* Record is read */
- DBUG_RETURN(0);
- }
- DBUG_RETURN(-1);
-} /* nisam_rprev */
diff --git a/isam/rrnd.c b/isam/rrnd.c
deleted file mode 100644
index 16b3ab1b859..00000000000
--- a/isam/rrnd.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Read a record with random-access. The position to the record must
- get by N_INFO. The next record can be read with pos= -1 */
-
-
-#include "isamdef.h"
-
-/*
- If filepos == NI_POS_ERROR, read next
- Returns:
- 0 = Ok.
- 1 = Row was deleted
- -1 = EOF (check errno to verify)
-*/
-
-int nisam_rrnd(N_INFO *info, byte *buf, register ulong filepos)
-{
- int skipp_deleted_blocks;
- DBUG_ENTER("nisam_rrnd");
-
- skipp_deleted_blocks=0;
-
- if (filepos == NI_POS_ERROR)
- {
- skipp_deleted_blocks=1;
- if (info->lastpos == NI_POS_ERROR) /* First read ? */
- filepos= info->s->pack.header_length; /* Read first record */
- else
- filepos= info->nextpos;
- }
-
- info->lastinx= -1; /* Can't forward or backward */
- /* Init all but update-flag */
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
-
- if (info->opt_flag & WRITE_CACHE_USED && flush_io_cache(&info->rec_cache))
- DBUG_RETURN(my_errno);
-
- DBUG_RETURN ((*info->s->read_rnd)(info,buf,filepos,skipp_deleted_blocks));
-}
diff --git a/isam/rsame.c b/isam/rsame.c
deleted file mode 100644
index 9a2a03da054..00000000000
--- a/isam/rsame.c
+++ /dev/null
@@ -1,70 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* L{ser nuvarande record med direktl{sning */
-/* Klarar b}de poster l{sta med nyckel och rrnd. */
-
-#include "isamdef.h"
-
- /* Funktionen ger som resultat:
- 0 = Ok.
- 1 = Posten borttagen
- -1 = EOF (eller motsvarande: se errno) */
-
-
-int nisam_rsame(N_INFO *info, byte *record, int inx)
-
-
- /* If inx >= 0 find record using key */
-{
- DBUG_ENTER("nisam_rsame");
-
- if (inx >= (int) info->s->state.keys || inx < -1)
- {
- my_errno=HA_ERR_WRONG_INDEX;
- DBUG_RETURN(-1);
- }
- if (info->lastpos == NI_POS_ERROR || info->update & HA_STATE_DELETED)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND; /* No current record */
- DBUG_RETURN(-1);
- }
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
-
- /* L{s record fr}n datafilen */
-
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_RDLCK,1))
- DBUG_RETURN(-1);
-#endif
-
- if (inx >= 0)
- {
- info->lastinx=inx;
- VOID(_nisam_make_key(info,(uint) inx,info->lastkey,record,info->lastpos));
- VOID(_nisam_search(info,info->s->keyinfo+inx,info->lastkey,0,SEARCH_SAME,
- info->s->state.key_root[inx]));
- }
-
- if ((*info->read_record)(info,info->lastpos,record) == 0)
- DBUG_RETURN(0);
- if (my_errno == HA_ERR_RECORD_DELETED)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND;
- DBUG_RETURN(1);
- }
- DBUG_RETURN(-1);
-} /* nisam_rsame */
diff --git a/isam/rsamepos.c b/isam/rsamepos.c
deleted file mode 100644
index c64ac492d1a..00000000000
--- a/isam/rsamepos.c
+++ /dev/null
@@ -1,59 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* read record through position and fix key-position */
-/* As nisam_rsame but supply a position */
-
-#include "isamdef.h"
-
-
- /*
- ** If inx >= 0 update index pointer
- ** Returns one of the following values:
- ** 0 = Ok.
- ** 1 = Record deleted
- ** -1 = EOF (or something similar. More information in my_errno)
- */
-
-int nisam_rsame_with_pos(N_INFO *info, byte *record, int inx, ulong filepos)
-{
- DBUG_ENTER("nisam_rsame_with_pos");
-
- if (inx >= (int) info->s->state.keys || inx < -1)
- {
- my_errno=HA_ERR_WRONG_INDEX;
- DBUG_RETURN(-1);
- }
-
- info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- if ((*info->s->read_rnd)(info,record,filepos,0))
- {
- if (my_errno == HA_ERR_RECORD_DELETED)
- {
- my_errno=HA_ERR_KEY_NOT_FOUND;
- DBUG_RETURN(1);
- }
- DBUG_RETURN(-1);
- }
- info->lastpos=filepos;
- info->lastinx=inx;
- if (inx >= 0)
- {
- VOID(_nisam_make_key(info,(uint) inx,info->lastkey,record,info->lastpos));
- info->update|=HA_STATE_KEY_CHANGED; /* Don't use indexposition */
- }
- DBUG_RETURN(0);
-} /* nisam_rsame_pos */
diff --git a/isam/sort.c b/isam/sort.c
deleted file mode 100644
index d22b0e648a0..00000000000
--- a/isam/sort.c
+++ /dev/null
@@ -1,558 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- Creates a index for a database by reading keys, sorting them and outputing
- them in sorted order through SORT_INFO functions.
-*/
-
-#include "isamdef.h"
-#if defined(MSDOS) || defined(__WIN__)
-#include <fcntl.h>
-#else
-#include <stddef.h>
-#endif
-#include <queues.h>
-
- /* static variabels */
-
-#define MERGEBUFF 15
-#define MERGEBUFF2 31
-#define MIN_SORT_MEMORY (4096-MALLOC_OVERHEAD)
-#define MYF_RW MYF(MY_NABP | MY_WME | MY_WAIT_IF_FULL)
-
-typedef struct st_buffpek { /* Struktur om sorteringsbuffrarna */
- my_off_t file_pos; /* Position var bufferten finns */
- ulong count; /* Antal nycklar i bufferten */
- uchar *base,*key; /* Pekare inom sort_key - indexdel */
- uint mem_count; /* Antal nycklar kvar i minnet */
- uint max_keys; /* Max keys in buffert */
-} BUFFPEK;
-
-extern void print_error _VARARGS((const char *fmt,...));
-
- /* functions defined in this file */
-
-static ulong NEAR_F find_all_keys(SORT_PARAM *info,uint keys,
- uchar * *sort_keys,
- BUFFPEK *buffpek,int *maxbuffer,
- FILE **tempfile, my_string tempname);
-static int NEAR_F write_keys(SORT_PARAM *info,uchar * *sort_keys,
- uint count, BUFFPEK *buffpek,FILE **tempfile,
- my_string tempname);
-static int NEAR_F write_index(SORT_PARAM *info,uchar * *sort_keys,
- uint count);
-static int NEAR_F merge_many_buff(SORT_PARAM *info,uint keys,
- uchar * *sort_keys,
- BUFFPEK *buffpek,int *maxbuffer,
- FILE * *t_file, my_string tempname);
-static uint NEAR_F read_to_buffer(FILE *fromfile,BUFFPEK *buffpek,
- uint sort_length);
-static int NEAR_F merge_buffers(SORT_PARAM *info,uint keys,FILE *from_file,
- FILE *to_file, uchar * *sort_keys,
- BUFFPEK *lastbuff,BUFFPEK *Fb,
- BUFFPEK *Tb);
-static int NEAR_F merge_index(SORT_PARAM *,uint,uchar **,BUFFPEK *, int,
- FILE *);
-static char **make_char_array(uint fields,uint length,myf my_flag);
-static FILE *opentemp(my_string name);
-static void closetemp(char *name,FILE *stream);
-
-
- /* Creates a index of sorted keys */
- /* Returns 0 if everything went ok */
-
-int _create_index_by_sort(info,no_messages,sortbuff_size)
-SORT_PARAM *info;
-pbool no_messages;
-uint sortbuff_size;
-{
- int error,maxbuffer,skr;
- uint memavl,old_memavl,keys,sort_length;
- BUFFPEK *buffpek;
- char tempname[FN_REFLEN];
- ulong records;
- uchar **sort_keys;
- FILE *tempfile;
- DBUG_ENTER("_create_index_by_sort");
-
- tempfile=0; buffpek= (BUFFPEK *) NULL; sort_keys= (uchar **) NULL; error= 1;
- maxbuffer=1;
-
- memavl=max(sortbuff_size,MIN_SORT_MEMORY);
- records= info->max_records;
- sort_length= info->key_length;
- LINT_INIT(keys);
-
- while (memavl >= MIN_SORT_MEMORY)
- {
- if ((records+1)*(sort_length+sizeof(char*)) < (ulong) memavl)
- keys= records+1;
- else
- do
- {
- skr=maxbuffer;
- if (memavl < sizeof(BUFFPEK)*(uint) maxbuffer ||
- (keys=(memavl-sizeof(BUFFPEK)*(uint) maxbuffer)/
- (sort_length+sizeof(char*))) <= 1)
- {
- print_error("Sortbuffer to small");
- goto err;
- }
- }
- while ((maxbuffer= (int) (records/(keys-1)+1)) != skr);
-
- if ((sort_keys= (uchar **) make_char_array(keys,sort_length,MYF(0))))
- {
- if ((buffpek = (BUFFPEK*) my_malloc((uint) (sizeof(BUFFPEK)*
- (uint) maxbuffer),
- MYF(0))))
- break;
- else
- my_free((gptr) sort_keys,MYF(0));
- }
- old_memavl=memavl;
- if ((memavl=memavl/4*3) < MIN_SORT_MEMORY && old_memavl > MIN_SORT_MEMORY)
- memavl=MIN_SORT_MEMORY;
- }
- if (memavl < MIN_SORT_MEMORY)
- {
- print_error("Sortbuffer to small");
- goto err;
- }
- (*info->lock_in_memory)(); /* Everything is allocated */
-
- if (!no_messages)
- printf(" - Searching for keys, allocating buffer for %d keys\n",keys);
-
- if ((records=find_all_keys(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile,
- tempname))
- == (ulong) -1)
- goto err;
- if (maxbuffer == 0)
- {
- if (!no_messages)
- printf(" - Dumping %lu keys\n",records);
- if (write_index(info,sort_keys,(uint) records))
- goto err;
- }
- else
- {
- keys=(keys*(sort_length+sizeof(char*)))/sort_length;
- if (maxbuffer >= MERGEBUFF2)
- {
- if (!no_messages)
- printf(" - Merging %lu keys\n",records);
- if (merge_many_buff(info,keys,sort_keys,buffpek,&maxbuffer,&tempfile,
- tempname))
- goto err;
- }
- if (!no_messages)
- puts(" - Last merge and dumping keys");
- if (merge_index(info,keys,sort_keys,buffpek,maxbuffer,tempfile))
- goto err;
- }
- error =0;
-
-err:
- if (sort_keys)
- my_free((gptr) sort_keys,MYF(0));
- if (buffpek)
- my_free((gptr) buffpek,MYF(0));
- if (tempfile)
- closetemp(tempname,tempfile);
-
- DBUG_RETURN(error ? -1 : 0);
-} /* _create_index_by_sort */
-
-
- /* Search after all keys and place them in a temp. file */
-
-static ulong NEAR_F find_all_keys(info,keys,sort_keys,buffpek,maxbuffer,
- tempfile,tempname)
-SORT_PARAM *info;
-uint keys;
-uchar **sort_keys;
-BUFFPEK *buffpek;
-int *maxbuffer;
-FILE **tempfile;
-my_string tempname;
-{
- int error;
- uint index,indexpos;
- DBUG_ENTER("find_all_keys");
-
- index=indexpos=error=0;
-
- while (!(error=(*info->key_read)(sort_keys[index])))
- {
- if ((uint) ++index == keys)
- {
- if (indexpos >= (uint) *maxbuffer ||
- write_keys(info,sort_keys,index-1,buffpek+indexpos,tempfile,
- tempname))
- DBUG_RETURN(NI_POS_ERROR);
- memcpy(sort_keys[0],sort_keys[index-1],(size_t) info->key_length);
- index=1; indexpos++;
- }
- }
- if (error > 0)
- DBUG_RETURN(NI_POS_ERROR); /* Aborted by get_key */
- if (indexpos)
- if (indexpos >= (uint) *maxbuffer ||
- write_keys(info,sort_keys,index,buffpek+indexpos,tempfile,tempname))
- DBUG_RETURN(NI_POS_ERROR);
- *maxbuffer=(int) indexpos;
- DBUG_RETURN(indexpos*(keys-1)+index);
-} /* find_all_keys */
-
-
- /* Write all keys in memory to file for later merge */
-
-static int NEAR_F write_keys(info,sort_keys,count,buffpek,tempfile,tempname)
-SORT_PARAM *info;
-reg1 uchar **sort_keys;
-uint count;
-BUFFPEK *buffpek;
-reg2 FILE **tempfile;
-my_string tempname;
-{
- DBUG_ENTER("write_keys");
-
- qsort2((byte*) sort_keys,count,sizeof(byte*),(qsort2_cmp) info->key_cmp,
- NullS);
- if (! *tempfile && ! (*tempfile=opentemp(tempname)))
- DBUG_RETURN(1);
- buffpek->file_pos=my_ftell(*tempfile,MYF(0));
- buffpek->count=count;
- while (count--)
- if (my_fwrite(*tempfile,(byte*)*sort_keys++,info->key_length,MYF_RW))
- DBUG_RETURN(1);
- DBUG_RETURN(0);
-} /* write_keys */
-
-
- /* Write index */
-
-static int NEAR_F write_index(info,sort_keys,count)
-SORT_PARAM *info;
-reg1 uchar **sort_keys;
-reg2 uint count;
-{
- DBUG_ENTER("write_index");
-
- qsort2((gptr) sort_keys,(size_t) count,sizeof(byte*),
- (qsort2_cmp) info->key_cmp, NullS);
- while (count--)
- if ((*info->key_write)(*sort_keys++))
- DBUG_RETURN(-1);
- DBUG_RETURN(0);
-} /* write_index */
-
-
- /* Merge buffers to make < MERGEBUFF2 buffers */
-
-static int NEAR_F merge_many_buff(info,keys,sort_keys,buffpek,maxbuffer,t_file,
- t_name)
-SORT_PARAM *info;
-uint keys;
-uchar **sort_keys;
-int *maxbuffer;
-BUFFPEK *buffpek;
-FILE **t_file;
-my_string t_name;
-{
- register int i;
- FILE *from_file,*to_file,*temp;
- FILE *t_file2;
- char t_name2[FN_REFLEN];
- BUFFPEK *lastbuff;
- DBUG_ENTER("merge_many_buff");
-
- if (!(t_file2=opentemp(t_name2)))
- DBUG_RETURN(1);
-
- from_file= *t_file ; to_file= t_file2;
- while (*maxbuffer >= MERGEBUFF2)
- {
- lastbuff=buffpek;
- for (i=0 ; i <= *maxbuffer-MERGEBUFF*3/2 ; i+=MERGEBUFF)
- {
- if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
- buffpek+i,buffpek+i+MERGEBUFF-1))
- break;
- }
- if (merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff++,
- buffpek+i,buffpek+ *maxbuffer))
- break;
- *maxbuffer= (int) (lastbuff-buffpek)-1;
- temp=from_file; from_file=to_file; to_file=temp;
- VOID(my_fseek(to_file,0L,MY_SEEK_SET,MYF(0)));
- }
- if (to_file == *t_file)
- {
- closetemp(t_name,to_file);
- *t_file=t_file2;
- VOID(strmov(t_name,t_name2));
- }
- else closetemp(t_name2,to_file);
-
- DBUG_RETURN(*maxbuffer >= MERGEBUFF2); /* Return 1 if interrupted */
-} /* merge_many_buff */
-
-
- /* Read data to buffer */
- /* This returns (uint) -1 if something goes wrong */
-
-static uint NEAR_F read_to_buffer(fromfile,buffpek,sort_length)
-FILE *fromfile;
-BUFFPEK *buffpek;
-uint sort_length;
-{
- register uint count;
- uint length;
-
- if ((count=(uint) min((ulong) buffpek->max_keys,buffpek->count)))
- {
- VOID(my_fseek(fromfile,buffpek->file_pos,MY_SEEK_SET,MYF(0)));
- if (my_fread(fromfile,(byte*) buffpek->base,
- (length= sort_length*count),MYF_RW))
- return((uint) -1);
- buffpek->key=buffpek->base;
- buffpek->file_pos+= length; /* New filepos */
- buffpek->count-= count;
- buffpek->mem_count= count;
- }
- return (count*sort_length);
-} /* read_to_buffer */
-
-
- /* Merge buffers to one buffer */
- /* If to_file == 0 then use info->key_write */
-
-static int NEAR_F merge_buffers(info,keys,from_file,to_file,sort_keys,lastbuff,
- Fb,Tb)
-SORT_PARAM *info;
-uint keys;
-FILE *from_file,*to_file;
-uchar **sort_keys;
-BUFFPEK *lastbuff,*Fb,*Tb;
-{
- int error;
- uint sort_length,maxcount;
- ulong count;
- my_off_t to_start_filepos;
- uchar *strpos;
- BUFFPEK *buffpek,**refpek;
- QUEUE queue;
- DBUG_ENTER("merge_buffers");
-
- count=error=0;
- maxcount=keys/((uint) (Tb-Fb) +1);
- sort_length=info->key_length;
-
- LINT_INIT(to_start_filepos);
- if (to_file)
- to_start_filepos=my_ftell(to_file,MYF(0));
- strpos=(uchar*) sort_keys;
-
- if (init_queue(&queue,(uint) (Tb-Fb)+1,offsetof(BUFFPEK,key),0,
- (int (*)(void *, byte *,byte *)) info->key_cmp,0))
- DBUG_RETURN(1);
-
- for (buffpek= Fb ; buffpek <= Tb && error != -1 ; buffpek++)
- {
- count+= buffpek->count;
- buffpek->base= strpos;
- buffpek->max_keys=maxcount;
- strpos+= (uint) (error=(int) read_to_buffer(from_file,buffpek,
- sort_length));
- queue_insert(&queue,(void*) buffpek);
- }
- if (error == -1)
- goto err;
-
- while (queue.elements > 1)
- {
- for (;;)
- {
- buffpek=(BUFFPEK*) queue_top(&queue);
- if (to_file)
- {
- if (my_fwrite(to_file,(byte*) buffpek->key,(uint) sort_length,
- MYF_RW | MY_WAIT_IF_FULL))
- {
- error=1; goto err;
- }
- }
- else
- {
- if ((*info->key_write)((void*) buffpek->key))
- {
- error=1; goto err;
- }
- }
- buffpek->key+=sort_length;
- if (! --buffpek->mem_count)
- {
- if (!(error=(int) read_to_buffer(from_file,buffpek,sort_length)))
- {
- uchar *base=buffpek->base;
- uint max_keys=buffpek->max_keys;
-
- VOID(queue_remove(&queue,0));
-
- /* Put room used by buffer to use in other buffer */
- for (refpek= (BUFFPEK**) &queue_top(&queue);
- refpek <= (BUFFPEK**) &queue_end(&queue);
- refpek++)
- {
- buffpek= *refpek;
- if (buffpek->base+buffpek->max_keys*sort_length == base)
- {
- buffpek->max_keys+=max_keys;
- break;
- }
- else if (base+max_keys*sort_length == buffpek->base)
- {
- buffpek->base=base;
- buffpek->max_keys+=max_keys;
- break;
- }
- }
- break; /* One buffer have been removed */
- }
- }
- queue_replaced(&queue); /* Top element has been replaced */
- }
- }
- buffpek=(BUFFPEK*) queue_top(&queue);
- buffpek->base=(uchar *) sort_keys;
- buffpek->max_keys=keys;
- do
- {
- if (to_file)
- {
- if (my_fwrite(to_file,(byte*) buffpek->key,
- (uint) (sort_length*buffpek->mem_count),
- MYF_RW | MY_WAIT_IF_FULL))
- {
- error=1; goto err;
- }
- }
- else
- {
- register uchar *end;
- strpos= buffpek->key;
- for (end=strpos+buffpek->mem_count*sort_length;
- strpos != end ;
- strpos+=sort_length)
- {
- if ((*info->key_write)((void*) strpos))
- {
- error=1; goto err;
- }
- }
- }
- }
- while ((error=(int) read_to_buffer(from_file,buffpek,sort_length)) != -1 &&
- error != 0);
-
- lastbuff->count=count;
- if (to_file)
- lastbuff->file_pos=to_start_filepos; /* New block starts here */
-err:
- delete_queue(&queue);
- DBUG_RETURN(error);
-} /* merge_buffers */
-
-
- /* Do a merge to output-file (save only positions) */
-
-static int NEAR_F merge_index(info,keys,sort_keys,buffpek,maxbuffer,tempfile)
-SORT_PARAM *info;
-uint keys;
-uchar **sort_keys;
-BUFFPEK *buffpek;
-int maxbuffer;
-FILE *tempfile;
-{
- DBUG_ENTER("merge_index");
- if (merge_buffers(info,keys,tempfile,(FILE*) 0,sort_keys,buffpek,buffpek,
- buffpek+maxbuffer))
- DBUG_RETURN(1);
- DBUG_RETURN(0);
-} /* merge_index */
-
-
- /* Make a pointer of arrays to keys */
-
-static char **make_char_array(fields,length,my_flag)
-register uint fields;
-uint length;
-myf my_flag;
-{
- register char **pos;
- char **old_pos,*char_pos;
- DBUG_ENTER("make_char_array");
-
- if ((old_pos= (char**) my_malloc( fields*(length+sizeof(char*)), my_flag)))
- {
- pos=old_pos; char_pos=((char*) (pos+fields)) -length;
- while (fields--)
- *(pos++) = (char_pos+= length);
- }
-
- DBUG_RETURN(old_pos);
-} /* make_char_array */
-
-
- /* |ppnar en tempor{rfil som kommer att raderas efter anv{nding */
-
-static FILE *opentemp(name)
-my_string name;
-{
- FILE *stream;
- reg1 my_string str_pos;
- DBUG_ENTER("opentemp");
-
- if (!(str_pos=my_tempnam(NullS,"ST",MYF(MY_WME))))
- DBUG_RETURN(0);
- VOID(strmov(name,str_pos));
- (*free)(str_pos); /* Inte via vanliga malloc */
-
- stream=my_fopen(name,(int) (O_RDWR | FILE_BINARY | O_CREAT | O_TEMPORARY),
- MYF(MY_WME));
-#if O_TEMPORARY == 0 && !defined(CANT_DELETE_OPEN_FILES)
- VOID(my_delete(name,MYF(MY_WME | ME_NOINPUT)));
-#endif
- DBUG_PRINT("exit",("stream: %lx",stream));
- DBUG_RETURN (stream);
-} /* opentemp */
-
-
-static void closetemp(char *name __attribute__((unused)) ,FILE *stream)
-{
- DBUG_ENTER("closetemp");
-
- if (stream)
- VOID(my_fclose(stream,MYF(MY_WME)));
-#ifdef CANT_DELETE_OPEN_FILES
- if (name)
- VOID(my_delete(name,MYF(MY_WME)));
-#endif
- DBUG_VOID_RETURN;
-} /* closetemp */
diff --git a/isam/static.c b/isam/static.c
deleted file mode 100644
index 0a8dc809ad7..00000000000
--- a/isam/static.c
+++ /dev/null
@@ -1,45 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- Static variables for ISAM library. All definied here for easy making of
- a shared library
-*/
-
-#ifndef _global_h
-#include "isamdef.h"
-#endif
-
-LIST *nisam_open_list=0;
-uchar NEAR nisam_file_magic[]=
-{ (uchar) 254, (uchar) 254,'\005', '\002', };
-uchar NEAR nisam_pack_file_magic[]=
-{ (uchar) 254, (uchar) 254,'\006', '\001', };
-my_string nisam_log_filename= (char*) "isam.log";
-File nisam_log_file= -1;
-uint nisam_quick_table_bits=9;
-uint nisam_block_size=1024; /* Best by test */
-my_bool nisam_flush=0;
-
-/* read_vec[] is used for converting between P_READ_KEY.. and SEARCH_ */
-/* Position is , == , >= , <= , > , < */
-
-uint NEAR nisam_read_vec[]=
-{
- SEARCH_FIND, SEARCH_FIND | SEARCH_BIGGER, SEARCH_FIND | SEARCH_SMALLER,
- SEARCH_NO_FIND | SEARCH_BIGGER, SEARCH_NO_FIND | SEARCH_SMALLER,
- SEARCH_FIND, SEARCH_LAST,SEARCH_LAST | SEARCH_SMALLER
-};
diff --git a/isam/test1.c b/isam/test1.c
deleted file mode 100644
index b9f4d8242c3..00000000000
--- a/isam/test1.c
+++ /dev/null
@@ -1,179 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#include "isamdef.h"
-
-static void get_options(int argc, char *argv[]);
-
-static int rec_pointer_size=0,verbose=0,remove_ant=0,pack_keys=1,flags[50],
- packed_field=FIELD_SKIP_PRESPACE;
-
-int main(int argc, char *argv[])
-{
- N_INFO *file;
- int i,j,error,deleted,found;
- char record[128],key[32],*filename,read_record[128];
- N_KEYDEF keyinfo[10];
- N_RECINFO recinfo[10];
- MY_INIT(argv[0]);
-
- filename= (char*) "test1";
- my_init();
- get_options(argc,argv);
- keyinfo[0].seg[0].base.type=HA_KEYTYPE_NUM;
- keyinfo[0].seg[0].base.flag=(uint8) (pack_keys ?
- HA_PACK_KEY | HA_SPACE_PACK : 0);
- keyinfo[0].seg[0].base.start=0;
- keyinfo[0].seg[0].base.length=6;
- keyinfo[0].seg[1].base.type=HA_KEYTYPE_END;
- keyinfo[0].base.flag = (uint8) (pack_keys ?
- HA_NOSAME | HA_PACK_KEY : HA_NOSAME);
-
- recinfo[0].base.type=packed_field; recinfo[0].base.length=6;
- recinfo[1].base.type=FIELD_NORMAL; recinfo[1].base.length=24;
- recinfo[2].base.type=FIELD_LAST;
-
- deleted=0;
- bzero((byte*) flags,sizeof(flags));
-
- printf("- Creating isam-file\n");
- if (nisam_create(filename,1,keyinfo,recinfo,
- (ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/40 :
- 0),10l,0,0,0L))
- goto err;
- if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
- goto err;
- printf("- Writing key:s\n");
- strmov(record," ..... key"); strappend(record,30,' ');
-
- my_errno=0;
- for (i=49 ; i>=1 ; i-=2 )
- {
- j=i%25 +1;
- sprintf(key,"%6d",j);
- bmove(record,key,6);
- error=nisam_write(file,record);
- flags[j]=1;
- if (verbose || error)
- printf("J= %2d nisam_write: %d errno: %d\n", j,error,my_errno);
- }
- if (nisam_close(file)) goto err;
- printf("- Reopening file\n");
- if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED))) goto err;
- printf("- Removing keys\n");
- for (i=1 ; i<=10 ; i++)
- {
- if (i == remove_ant) { VOID(nisam_close(file)) ; exit(0) ; }
- sprintf(key,"%6d",(j=(int) ((rand() & 32767)/32767.*25)));
- my_errno=0;
- if ((error = nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)))
- {
- if (verbose || (flags[j] == 1 ||
- (error && my_errno != HA_ERR_KEY_NOT_FOUND)))
- printf("key: %s nisam_rkey: %3d errno: %3d\n",key,error,my_errno);
- }
- else
- {
- error=nisam_delete(file,read_record);
- if (verbose || error)
- printf("key: %s nisam_delete: %3d errno: %3d\n",key,error,my_errno);
- flags[j]=0;
- if (! error)
- deleted++;
- }
- }
- printf("- Reading records with key\n");
- for (i=1 ; i<=25 ; i++)
- {
- sprintf(key,"%6d",i);
- bmove(record,key,6);
- my_errno=0;
- error=nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT);
- if (verbose ||
- (error == 0 && flags[i] != 1) ||
- (error && (flags[i] != 0 || my_errno != HA_ERR_KEY_NOT_FOUND)))
- {
- printf("key: %s nisam_rkey: %3d errno: %3d record: %s\n",
- key,error,my_errno,record+1);
- }
- }
-
- printf("- Reading records with position\n");
- for (i=1,found=0 ; i <= 30 ; i++)
- {
- my_errno=0;
- if ((error=nisam_rrnd(file,read_record,i == 1 ? 0L : NI_POS_ERROR)) == -1)
- {
- if (found != 25-deleted)
- printf("Found only %d of %d records\n",found,25-deleted);
- break;
- }
- if (!error)
- found++;
- if (verbose || (error != 0 && error != 1))
- {
- printf("pos: %2d nisam_rrnd: %3d errno: %3d record: %s\n",
- i-1,error,my_errno,read_record+1);
- }
- }
- if (nisam_close(file)) goto err;
- my_end(MY_CHECK_ERROR);
-
- exit(0);
-err:
- printf("got error: %3d when using nisam-database\n",my_errno);
- exit(1);
- return 0; /* skip warning */
-} /* main */
-
-
- /* l{ser optioner */
- /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */
-
-static void get_options(int argc, char *argv[])
-{
- char *pos;
-
- while (--argc >0 && *(pos = *(++argv)) == '-' ) {
- switch(*++pos) {
- case 'R': /* Length of record pointer */
- rec_pointer_size=atoi(++pos);
- if (rec_pointer_size > 3)
- rec_pointer_size=0;
- break;
- case 'P':
- pack_keys=0; /* Don't use packed key */
- break;
- case 'S':
- packed_field=FIELD_NORMAL; /* static-size record*/
- break;
- case 'v': /* verbose */
- verbose=1;
- break;
- case 'm':
- remove_ant=atoi(++pos);
- break;
- case 'V':
- printf("isamtest1 Ver 1.0 \n");
- exit(0);
- case '#':
- DEBUGGER_ON;
- DBUG_PUSH (++pos);
- break;
- }
- }
- return;
-} /* get options */
diff --git a/isam/test2.c b/isam/test2.c
deleted file mode 100644
index 4b22f2d679c..00000000000
--- a/isam/test2.c
+++ /dev/null
@@ -1,841 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Test av isam-databas: stor test */
-
-#ifndef USE_MY_FUNC /* We want to be able to dbug this !! */
-#define USE_MY_FUNC
-#endif
-#ifdef DBUG_OFF
-#undef DBUG_OFF
-#endif
-#ifndef SAFEMALLOC
-#define SAFEMALLOC
-#endif
-
-#include "isamdef.h"
-
-#define STANDAR_LENGTH 37
-#define NISAM_KEYS 6
-#if !defined(MSDOS) && !defined(labs)
-#define labs(a) abs(a)
-#endif
-
-static void get_options(int argc, char *argv[]);
-static uint rnd(uint max_value);
-static void fix_length(byte *record,uint length);
-static void put_blob_in_record(char *blob_pos,char **blob_buffer);
-static void copy_key(struct st_isam_info *info,uint inx,
- uchar *record,uchar *key);
-
-static int verbose=0,testflag=0,pack_type=HA_SPACE_PACK,
- first_key=0,async_io=0,key_cacheing=0,write_cacheing=0,locking=0,
- rec_pointer_size=0,pack_fields=1,use_log=0;
-static uint keys=NISAM_KEYS,recant=1000;
-static uint use_blob=0;
-static uint16 key1[1000],key3[5000];
-static char record[300],record2[300],key[100],key2[100],
- read_record[300],read_record2[300],read_record3[300];
-
-
- /* Test program */
-
-int main(int argc, char *argv[])
-{
- uint i;
- int j,n1,n2,n3,error,k;
- uint write_count,update,dupp_keys,opt_delete,start,length,blob_pos,
- reclength,ant;
- ulong lastpos,range_records,records;
- N_INFO *file;
- N_KEYDEF keyinfo[10];
- N_RECINFO recinfo[10];
- N_ISAMINFO info;
- char *filename,*blob_buffer;
- MY_INIT(argv[0]);
-
- filename= (char*) "test2.ISM";
- get_options(argc,argv);
- if (! async_io)
- my_disable_async_io=1;
-
- reclength=STANDAR_LENGTH+60+(use_blob ? 8 : 0);
- blob_pos=STANDAR_LENGTH+60;
- keyinfo[0].seg[0].base.start=0;
- keyinfo[0].seg[0].base.length=6;
- keyinfo[0].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[0].seg[0].base.flag=(uint8) pack_type;
- keyinfo[0].seg[1].base.type=0;
- keyinfo[0].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
- keyinfo[1].seg[0].base.start=7;
- keyinfo[1].seg[0].base.length=6;
- keyinfo[1].seg[0].base.type=HA_KEYTYPE_BINARY;
- keyinfo[1].seg[0].base.flag=0;
- keyinfo[1].seg[1].base.start=0; /* Tv}delad nyckel */
- keyinfo[1].seg[1].base.length=6;
- keyinfo[1].seg[1].base.type=HA_KEYTYPE_NUM;
- keyinfo[1].seg[1].base.flag=HA_REVERSE_SORT;
- keyinfo[1].seg[2].base.type=0;
- keyinfo[1].base.flag =0;
- keyinfo[2].seg[0].base.start=12;
- keyinfo[2].seg[0].base.length=8;
- keyinfo[2].seg[0].base.type=HA_KEYTYPE_BINARY;
- keyinfo[2].seg[0].base.flag=HA_REVERSE_SORT;
- keyinfo[2].seg[1].base.type=0;
- keyinfo[2].base.flag =HA_NOSAME;
- keyinfo[3].seg[0].base.start=0;
- keyinfo[3].seg[0].base.length=reclength-(use_blob ? 8 : 0);
- keyinfo[3].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[3].seg[0].base.flag=(uint8) pack_type;
- keyinfo[3].seg[1].base.type=0;
- keyinfo[3].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
- keyinfo[4].seg[0].base.start=0;
- keyinfo[4].seg[0].base.length=5;
- keyinfo[4].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[4].seg[0].base.flag=0;
- keyinfo[4].seg[1].base.type=0;
- keyinfo[4].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
- keyinfo[5].seg[0].base.start=0;
- keyinfo[5].seg[0].base.length=4;
- keyinfo[5].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[5].seg[0].base.flag=(uint8) pack_type;
- keyinfo[5].seg[1].base.type=0;
- keyinfo[5].base.flag = (uint8) (pack_type ? HA_PACK_KEY : 0);
-
- recinfo[0].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
- recinfo[0].base.length=7;
- recinfo[1].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
- recinfo[1].base.length=5;
- recinfo[2].base.type=pack_fields ? FIELD_SKIP_PRESPACE : 0;
- recinfo[2].base.length=9;
- recinfo[3].base.type=FIELD_NORMAL;
- recinfo[3].base.length=STANDAR_LENGTH-7-5-9-4;
- recinfo[4].base.type=pack_fields ? FIELD_SKIP_ZERO : 0;
- recinfo[4].base.length=4;
- recinfo[5].base.type=pack_fields ? FIELD_SKIP_ENDSPACE : 0;
- recinfo[5].base.length=60;
- if (use_blob)
- {
- recinfo[6].base.type=FIELD_BLOB;
- recinfo[6].base.length=4+sizeof(char*); /* 4 byte ptr, 4 byte length */
- recinfo[7].base.type= FIELD_LAST;
- }
- else
- recinfo[6].base.type= FIELD_LAST;
-
- write_count=update=dupp_keys=opt_delete=0;
- blob_buffer=0;
-
- for (i=999 ; i>0 ; i--) key1[i]=0;
- for (i=4999 ; i>0 ; i--) key3[i]=0;
-
- printf("- Creating isam-file\n");
- /* DBUG_PUSH(""); */
- my_delete(filename,MYF(0)); /* Remove old locks under gdb */
- file= 0;
- if (nisam_create(filename,keys,&keyinfo[first_key],&recinfo[0],
- (ulong) (rec_pointer_size ? (1L << (rec_pointer_size*8))/
- reclength : 0),100l,0,0,0L))
- goto err;
- if (use_log)
- nisam_log(1);
- if (!(file=nisam_open(filename,2,HA_OPEN_ABORT_IF_LOCKED)))
- goto err;
- printf("- Writing key:s\n");
- if (key_cacheing)
- init_key_cache(dflt_key_cache,512,IO_SIZE*16,0,0); /* Use a small cache */
- if (locking)
- nisam_lock_database(file,F_WRLCK);
- if (write_cacheing)
- nisam_extra(file,HA_EXTRA_WRITE_CACHE);
-
- for (i=0 ; i < recant ; i++)
- {
- n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
- sprintf(record,"%6d:%4d:%8d:Pos: %4d ",n1,n2,n3,write_count);
- longstore(record+STANDAR_LENGTH-4,(long) i);
- fix_length(record,(uint) STANDAR_LENGTH+rnd(60));
- put_blob_in_record(record+blob_pos,&blob_buffer);
- DBUG_PRINT("test",("record: %d",i));
-
- if (nisam_write(file,record))
- {
- if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
- {
- printf("Error: %d in write at record: %d\n",my_errno,i);
- goto err;
- }
- if (verbose) printf(" Double key: %d\n",n3);
- }
- else
- {
- if (key3[n3] == 1 && first_key <3 && first_key+keys >= 3)
- {
- printf("Error: Didn't get error when writing second key: '%8d'\n",n3);
- goto err;
- }
- write_count++; key1[n1]++; key3[n3]=1;
- }
-
- /* Check if we can find key without flushing database */
- if (i == recant/2)
- {
- for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
- if (!j)
- for (j=999 ; j>0 && key1[j] == 0 ; j--) ;
- sprintf(key,"%6d",j);
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
- {
- printf("Test in loop: Can't find key: \"%s\"\n",key);
- goto err;
- }
- }
- }
- if (testflag==1) goto end;
-
- if (write_cacheing)
- if (nisam_extra(file,HA_EXTRA_NO_CACHE))
- {
- puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)");
- goto end;
- }
-
- printf("- Delete\n");
- for (i=0 ; i<recant/10 ; i++)
- {
- for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
- if (j != 0)
- {
- sprintf(key,"%6d",j);
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
- {
- printf("can't find key1: \"%s\"\n",key);
- goto err;
- }
- if (nisam_delete(file,read_record))
- {
- printf("error: %d; can't delete record: \"%s\"\n", my_errno,read_record);
- goto err;
- }
- opt_delete++;
- key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--;
- key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0;
- }
- }
- if (testflag==2) goto end;
-
- printf("- Update\n");
- for (i=0 ; i<recant/10 ; i++)
- {
- n1=rnd(1000); n2=rnd(100); n3=rnd(5000);
- sprintf(record2,"%6d:%4d:%8d:XXX: %4d ",n1,n2,n3,update);
- longstore(record2+STANDAR_LENGTH-4,(long) i);
- fix_length(record2,(uint) STANDAR_LENGTH+rnd(60));
-
- for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
- if (j != 0)
- {
- sprintf(key,"%6d",j);
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT))
- {
- printf("can't find key1: \"%s\"\n",key);
- goto err;
- }
- if (use_blob)
- {
- if (i & 1)
- put_blob_in_record(record+blob_pos,&blob_buffer);
- else
- bmove(record+blob_pos,read_record+blob_pos,8);
- }
- if (nisam_update(file,read_record,record2))
- {
- if (my_errno != HA_ERR_FOUND_DUPP_KEY || key3[n3] == 0)
- {
- printf("error: %d; can't update:\nFrom: \"%s\"\nTo: \"%s\"\n",
- my_errno,read_record,record2);
- goto err;
- }
- if (verbose)
- printf("Double key when tried to update:\nFrom: \"%s\"\nTo: \"%s\"\n",record,record2);
- }
- else
- {
- key1[atoi(read_record+keyinfo[0].seg[0].base.start)]--;
- key3[atoi(read_record+keyinfo[2].seg[0].base.start)]=0;
- key1[n1]++; key3[n3]=1;
- update++;
- }
- }
- }
- if (testflag==3) goto end;
-
- printf("- Same key: first - next -> last - prev -> first\n");
- DBUG_PRINT("progpos",("first - next -> last - prev -> first"));
- for (i=999, dupp_keys=j=0 ; i>0 ; i--)
- {
- if (key1[i] >dupp_keys) { dupp_keys=key1[i]; j=i; }
- }
- sprintf(key,"%6d",j);
- if (verbose) printf(" Using key: \"%s\" Keys: %d\n",key,dupp_keys);
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
- if (nisam_rsame(file,read_record2,-1)) goto err;
- if (memcmp(read_record,read_record2,reclength) != 0)
- {
- printf("nisam_rsame didn't find same record\n");
- goto end;
- }
- nisam_info(file,&info,0);
- if (nisam_rfirst(file,read_record2,0) ||
- nisam_rsame_with_pos(file,read_record2,0,info.recpos) ||
- memcmp(read_record,read_record2,reclength) != 0)
- {
- printf("nisam_rsame_with_pos didn't find same record\n");
- goto end;
- }
- {
- int skr=nisam_rnext(file,read_record2,0);
- if ((skr && my_errno != HA_ERR_END_OF_FILE) ||
- nisam_rprev(file,read_record2,-1) ||
- memcmp(read_record,read_record2,reclength) != 0)
- {
- printf("nisam_rsame_with_pos lost position\n");
- goto end;
- }
- }
- ant=1;
- start=keyinfo[0].seg[0].base.start; length=keyinfo[0].seg[0].base.length;
- while (nisam_rnext(file,read_record2,0) == 0 &&
- memcmp(read_record2+start,key,length) == 0) ant++;
- if (ant != dupp_keys)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys);
- goto end;
- }
- ant=0;
- while (nisam_rprev(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys)
- {
- printf("prev: I can only find: %d records of %d\n",ant,dupp_keys);
- goto end;
- }
-
- printf("- All keys: first - next -> last - prev -> first\n");
- DBUG_PRINT("progpos",("All keys: first - next -> last - prev -> first"));
- ant=1;
- if (nisam_rfirst(file,read_record,0))
- {
- printf("Can't find first record\n");
- goto end;
- }
- while (nisam_rnext(file,read_record3,0) == 0 && ant < write_count+10)
- ant++;
- if (ant != write_count - opt_delete)
- {
- printf("next: I found: %d records of %d\n",ant,write_count - opt_delete);
- goto end;
- }
- if (nisam_rlast(file,read_record2,0) ||
- bcmp(read_record2,read_record3,reclength))
- {
- printf("Can't find last record\n");
- DBUG_DUMP("record2",(byte*) read_record2,reclength);
- DBUG_DUMP("record3",(byte*) read_record3,reclength);
- goto end;
- }
- ant=1;
- while (nisam_rprev(file,read_record3,0) == 0 && ant < write_count+10)
- ant++;
- if (ant != write_count - opt_delete)
- {
- printf("prev: I found: %d records of %d\n",ant,write_count);
- goto end;
- }
- if (bcmp(read_record,read_record3,reclength))
- {
- printf("Can't find first record\n");
- goto end;
- }
-
- printf("- Test if: Read first - next - prev - prev - next == first\n");
- DBUG_PRINT("progpos",("- Read first - next - prev - prev - next == first"));
- if (nisam_rfirst(file,read_record,0) ||
- nisam_rnext(file,read_record3,0) ||
- nisam_rprev(file,read_record3,0) ||
- nisam_rprev(file,read_record3,0) == 0 ||
- nisam_rnext(file,read_record3,0))
- goto err;
- if (bcmp(read_record,read_record3,reclength) != 0)
- printf("Can't find first record\n");
-
- printf("- Test if: Read last - prev - next - next - prev == last\n");
- DBUG_PRINT("progpos",("Read last - prev - next - next - prev == last"));
- if (nisam_rlast(file,read_record2,0) ||
- nisam_rprev(file,read_record3,0) ||
- nisam_rnext(file,read_record3,0) ||
- nisam_rnext(file,read_record3,0) == 0 ||
- nisam_rprev(file,read_record3,0))
- goto err;
- if (bcmp(read_record2,read_record3,reclength))
- printf("Can't find last record\n");
-
- puts("- Test read key-part");
- strmov(key2,key);
- for(i=strlen(key2) ; i-- > 1 ;)
- {
- key2[i]=0;
- if (nisam_rkey(file,read_record,0,key2,(uint) i,HA_READ_KEY_EXACT)) goto err;
- if (bcmp(read_record+start,key,(uint) i))
- {
- puts("Didn't find right record");
- goto end;
- }
- }
- if (dupp_keys > 2)
- {
- printf("- Read key (first) - next - delete - next -> last\n");
- DBUG_PRINT("progpos",("first - next - delete - next -> last"));
- if (nisam_rkey(file,read_record,0,key,0,HA_READ_KEY_EXACT)) goto err;
- if (nisam_rnext(file,read_record3,0)) goto err;
- if (nisam_delete(file,read_record3)) goto err;
- opt_delete++;
- ant=1;
- while (nisam_rnext(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys-1)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-1);
- goto end;
- }
- }
- if (dupp_keys>4)
- {
- printf("- Read last of key - prev - delete - prev -> first\n");
- DBUG_PRINT("progpos",("last - prev - delete - prev -> first"));
- if (nisam_rprev(file,read_record3,0)) goto err;
- if (nisam_rprev(file,read_record3,0)) goto err;
- if (nisam_delete(file,read_record3)) goto err;
- opt_delete++;
- ant=1;
- while (nisam_rprev(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys-2)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-2);
- goto end;
- }
- }
- if (dupp_keys > 6)
- {
- printf("- Read first - delete - next -> last\n");
- DBUG_PRINT("progpos",("first - delete - next -> last"));
- if (nisam_rkey(file,read_record3,0,key,0,HA_READ_KEY_EXACT)) goto err;
- if (nisam_delete(file,read_record3)) goto err;
- opt_delete++;
- ant=1;
- if (nisam_rnext(file,read_record,0))
- goto err; /* Skall finnas poster */
- while (nisam_rnext(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys-3)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-3);
- goto end;
- }
-
- printf("- Read last - delete - prev -> first\n");
- DBUG_PRINT("progpos",("last - delete - prev -> first"));
- if (nisam_rprev(file,read_record3,0)) goto err;
- if (nisam_delete(file,read_record3)) goto err;
- opt_delete++;
- ant=0;
- while (nisam_rprev(file,read_record3,0) == 0 &&
- bcmp(read_record3+start,key,length) == 0) ant++;
- if (ant != dupp_keys-4)
- {
- printf("next: I can only find: %d keys of %d\n",ant,dupp_keys-4);
- goto end;
- }
- }
-
- puts("- Test if: Read rrnd - same");
- DBUG_PRINT("progpos",("Read rrnd - same"));
- for (i=0 ; i < write_count ; i++)
- {
- if (nisam_rrnd(file,read_record,i == 0 ? 0L : NI_POS_ERROR) == 0)
- break;
- }
- if (i == write_count)
- goto err;
-
- bmove(read_record2,read_record,reclength);
- for (i=2 ; i-- > 0 ;)
- {
- if (nisam_rsame(file,read_record2,(int) i)) goto err;
- if (bcmp(read_record,read_record2,reclength) != 0)
- {
- printf("is_rsame didn't find same record\n");
- goto end;
- }
- }
- puts("- Test nisam_records_in_range");
- nisam_info(file,&info,HA_STATUS_VARIABLE);
- for (i=0 ; i < info.keys ; i++)
- {
- if (nisam_rfirst(file,read_record,(int) i) ||
- nisam_rlast(file,read_record2,(int) i))
- goto err;
- copy_key(file,(uint) i,(uchar*) read_record,(uchar*) key);
- copy_key(file,(uint) i,(uchar*) read_record2,(uchar*) key2);
- range_records=nisam_records_in_range(file,(int) i,key,0,HA_READ_KEY_EXACT,
- key2,0,HA_READ_AFTER_KEY);
- if (range_records < info.records*8/10 ||
- range_records > info.records*12/10)
- {
- printf("ni_records_range returned %lu; Should be about %lu\n",
- range_records,info.records);
- goto end;
- }
- if (verbose)
- {
- printf("ni_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
- range_records,info.records,
- labs((long) range_records - (long) info.records)*100.0/
- info.records);
-
- }
- }
- for (i=0 ; i < 5 ; i++)
- {
- for (j=rnd(1000) ; j>0 && key1[j] == 0 ; j--) ;
- for (k=rnd(1000) ; k>0 && key1[k] == 0 ; k--) ;
- if (j != 0 && k != 0)
- {
- if (j > k)
- swap_variables(int, j, k);
- sprintf(key,"%6d",j);
- sprintf(key2,"%6d",k);
- range_records=nisam_records_in_range(file,0,key,0,HA_READ_AFTER_KEY,
- key2,0,HA_READ_BEFORE_KEY);
- records=0;
- for (j++ ; j < k ; j++)
- records+=key1[j];
- if ((long) range_records < (long) records*7/10-2 ||
- (long) range_records > (long) records*13/10+2)
- {
- printf("ni_records_range returned %ld; Should be about %ld\n",
- range_records,records);
- goto end;
- }
- if (verbose && records)
- {
- printf("ni_records_range returned %ld; Exact is %ld (diff: %4.2g %%)\n",
- range_records,records,
- labs((long) range_records-(long) records)*100.0/records);
-
- }
- }
- }
-
- printf("- nisam_info\n");
- nisam_info(file,&info,0);
- if (info.records != write_count-opt_delete || info.deleted > opt_delete + update
- || info.keys != keys)
- {
- puts("Wrong info from nisam_info");
- printf("Got: records: %ld opt_delete: %ld i_keys: %d\n",
- info.records,info.deleted,info.keys);
- }
- if (verbose)
- {
- char buff[80];
- get_date(buff,3,info.create_time);
- printf("info: Created %s\n",buff);
- get_date(buff,3,info.isamchk_time);
- printf("info: checked %s\n",buff);
- get_date(buff,3,info.update_time);
- printf("info: Modified %s\n",buff);
- }
-
- nisam_panic(HA_PANIC_WRITE);
- nisam_panic(HA_PANIC_READ);
- if (nisam_is_changed(file))
- puts("Warning: nisam_is_changed reported that datafile was changed");
-
- printf("- nisam_extra(CACHE) + nisam_rrnd.... + nisam_extra(NO_CACHE)\n");
- if (nisam_extra(file,HA_EXTRA_RESET) || nisam_extra(file,HA_EXTRA_CACHE))
- {
- if (locking || (!use_blob && !pack_fields))
- {
- puts("got error from nisam_extra(HA_EXTRA_CACHE)");
- goto end;
- }
- }
- ant=0;
- while ((error=nisam_rrnd(file,record,NI_POS_ERROR)) >= 0 &&
- ant < write_count + 10)
- ant+= error ? 0 : 1;
- if (ant != write_count-opt_delete)
- {
- printf("rrnd with cache: I can only find: %d records of %d\n",
- ant,write_count-opt_delete);
- goto end;
- }
- if (nisam_extra(file,HA_EXTRA_NO_CACHE))
- {
- puts("got error from nisam_extra(HA_EXTRA_NO_CACHE)");
- goto end;
- }
-
- if (testflag == 4) goto end;
-
- printf("- Removing keys\n");
- lastpos = NI_POS_ERROR;
- /* DBUG_POP(); */
- nisam_extra(file,HA_EXTRA_RESET);
- while ((error=nisam_rrnd(file,read_record,NI_POS_ERROR)) >=0)
- {
- nisam_info(file,&info,1);
- if (lastpos >= info.recpos && lastpos != NI_POS_ERROR)
- {
- printf("nisam_rrnd didn't advance filepointer; old: %ld, new: %ld\n",
- lastpos,info.recpos);
- goto err;
- }
- lastpos=info.recpos;
- if (error == 0)
- {
- if (nisam_rsame(file,read_record,-1))
- {
- printf("can't find record %lx\n",info.recpos);
- goto err;
- }
- if (use_blob)
- {
- ulong blob_length,pos;
- uchar *ptr;
- longget(blob_length,read_record+blob_pos+4);
- ptr=(uchar*) blob_length;
- longget(blob_length,read_record+blob_pos);
- for (pos=0 ; pos < blob_length ; pos++)
- {
- if (ptr[pos] != (uchar) (blob_length+pos))
- {
- printf("found blob with wrong info at %ld\n",lastpos);
- use_blob=0;
- break;
- }
- }
- }
- if (nisam_delete(file,read_record))
- {
- printf("can't delete record: %s\n",read_record);
- goto err;
- }
- opt_delete++;
- }
- }
- if (my_errno != HA_ERR_END_OF_FILE && my_errno != HA_ERR_RECORD_DELETED)
- printf("error: %d from nisam_rrnd\n",my_errno);
- if (write_count != opt_delete)
- {
- printf("Deleted only %d of %d records\n",write_count,opt_delete);
- goto err;
- }
-end:
- if (nisam_close(file))
- goto err;
- nisam_panic(HA_PANIC_CLOSE); /* Should close log */
- printf("\nFollowing test have been made:\n");
- printf("Write records: %d\nUpdate records: %d\nSame-key-read: %d\nDelete records: %d\n", write_count,update,dupp_keys,opt_delete);
- if (rec_pointer_size)
- printf("Record pointer size: %d\n",rec_pointer_size);
- if (key_cacheing)
- puts("Key cacheing used");
- if (write_cacheing)
- puts("Write cacheing used");
- if (async_io && locking)
- puts("Asyncron io with locking used");
- else if (locking)
- puts("Locking used");
- if (use_blob)
- puts("blobs used");
- end_key_cache(dflt_key_cache,1);
- if (blob_buffer)
- my_free(blob_buffer,MYF(0));
- my_end(MY_CHECK_ERROR | MY_GIVE_INFO);
- return(0);
-err:
- printf("got error: %d when using NISAM-database\n",my_errno);
- if (file)
- VOID(nisam_close(file));
- return(1);
-} /* main */
-
-
- /* l{ser optioner */
- /* OBS! intierar endast DEBUG - ingen debuggning h{r ! */
-
-static void get_options( int argc, char *argv[])
-{
- char *pos,*progname;
- DEBUGGER_OFF;
-
- progname= argv[0];
-
- while (--argc >0 && *(pos = *(++argv)) == '-' ) {
- switch(*++pos) {
- case 'b':
- if (*++pos)
- nisam_block_size= MY_ALIGN(atoi(pos),512);
- set_if_bigger(nisam_block_size,8192); /* Max block size */
- set_if_smaller(nisam_block_size,1024);
- break;
- case 'B':
- use_blob=1;
- break;
- case 'K': /* Use key cacheing */
- key_cacheing=1;
- break;
- case 'W': /* Use write cacheing */
- write_cacheing=1;
- if (*++pos)
- my_default_record_cache_size=atoi(pos);
- break;
- case 'i':
- if (*++pos)
- srand(atoi(pos));
- break;
- case 'l':
- use_log=1;
- break;
- case 'L':
- locking=1;
- break;
- case 'A': /* use asyncron io */
- async_io=1;
- if (*++pos)
- my_default_record_cache_size=atoi(pos);
- break;
- case 'v': /* verbose */
- verbose=1;
- break;
- case 'm': /* records */
- recant=atoi(++pos);
- break;
- case 'f':
- if ((first_key=atoi(++pos)) <0 || first_key >= NISAM_KEYS)
- first_key=0;
- break;
- case 'k':
- if ((keys=(uint) atoi(++pos)) < 1 ||
- keys > (uint) (NISAM_KEYS-first_key))
- keys=NISAM_KEYS-first_key;
- break;
- case 'P':
- pack_type=0; /* Don't use DIFF_LENGTH */
- break;
- case 'R': /* Length of record pointer */
- rec_pointer_size=atoi(++pos);
- if (rec_pointer_size > 3)
- rec_pointer_size=0;
- break;
- case 'S':
- pack_fields=0; /* Static-length-records */
- break;
- case 't':
- testflag=atoi(++pos); /* testmod */
- break;
- case '?':
- case 'I':
- case 'V':
- printf("%s Ver 1.4 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
- puts("TCX Datakonsult AB, by Monty, for your professional use\n");
- printf("Usage: %s [-?ABIKLPRSVWltv] [-b#] [-k#] [-f#] [-m#] [-t#]\n",progname);
- exit(0);
- case '#':
- DEBUGGER_ON;
- DBUG_PUSH (++pos);
- break;
- default:
- printf("Illegal option: '%c'\n",*pos);
- break;
- }
- }
- return;
-} /* get options */
-
- /* Ge ett randomv{rde inom ett intervall 0 <=x <= n */
-
-static uint rnd( uint max_value)
-{
- return (uint) ((rand() & 32767)/32767.0*max_value);
-} /* rnd */
-
-
- /* G|r en record av skiftande length */
-
-static void fix_length( byte *rec, uint length)
-{
- bmove(rec+STANDAR_LENGTH,
- "0123456789012345678901234567890123456789012345678901234567890",
- length-STANDAR_LENGTH);
- strfill(rec+length,STANDAR_LENGTH+60-length,' ');
-} /* fix_length */
-
-
- /* Put maybe a blob in record */
-
-static void put_blob_in_record(char *blob_pos, char **blob_buffer)
-{
- ulong i,length;
- if (use_blob)
- {
- if (rnd(10) == 0)
- {
- if (! *blob_buffer &&
- !(*blob_buffer=my_malloc((uint) use_blob,MYF(MY_WME))))
- {
- use_blob=0;
- return;
- }
- length=rnd(use_blob);
- for (i=0 ; i < length ; i++)
- (*blob_buffer)[i]=(char) (length+i);
- longstore(blob_pos,length);
- bmove(blob_pos+4,(char*) blob_buffer,sizeof(char*));
- }
- else
- {
- longstore(blob_pos,0);
- }
- }
- return;
-}
-
-
-static void copy_key( N_INFO *info, uint inx, uchar *rec, uchar *key_buff)
-{
- N_KEYSEG *keyseg;
-
- for (keyseg=info->s->keyinfo[inx].seg ; keyseg->base.type ; keyseg++)
- {
- memcpy(key_buff,rec+keyseg->base.start,(size_t) keyseg->base.length);
- key_buff+=keyseg->base.length;
- }
- return;
-}
diff --git a/isam/test3.c b/isam/test3.c
deleted file mode 100644
index 9195fcbf1b6..00000000000
--- a/isam/test3.c
+++ /dev/null
@@ -1,494 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Test av locking */
-
-#ifndef __NETWARE__
-
-#include "nisam.h"
-#include <sys/types.h>
-#include <keycache.h>
-#ifdef HAVE_SYS_WAIT_H
-# include <sys/wait.h>
-#endif
-#ifndef WEXITSTATUS
-# define WEXITSTATUS(stat_val) ((unsigned)(stat_val) >> 8)
-#endif
-#ifndef WIFEXITED
-# define WIFEXITED(stat_val) (((stat_val) & 255) == 0)
-#endif
-
-
-#if defined(HAVE_LRAND48)
-#define rnd(X) (lrand48() % X)
-#define rnd_init(X) srand48(X)
-#else
-#define rnd(X) (random() % X)
-#define rnd_init(X) srandom(X)
-#endif
-
-
-const char *filename= "test3.ISM";
-uint tests=10,forks=10,key_cacheing=0,use_log=0;
-
-static void get_options(int argc, char *argv[]);
-void start_test(int id);
-int test_read(N_INFO *,int),test_write(N_INFO *,int,int),
- test_update(N_INFO *,int,int),test_rrnd(N_INFO *,int);
-
-struct record {
- char id[8];
- uint32 nr;
- char text[10];
-} record;
-
-
-int main(int argc,char **argv)
-{
- int status,wait_ret;
- uint i;
- N_KEYDEF keyinfo[10];
- N_RECINFO recinfo[10];
- MY_INIT(argv[0]);
-
- get_options(argc,argv);
-
- keyinfo[0].seg[0].base.start=0;
- keyinfo[0].seg[0].base.length=8;
- keyinfo[0].seg[0].base.type=HA_KEYTYPE_TEXT;
- keyinfo[0].seg[0].base.flag=HA_SPACE_PACK;
- keyinfo[0].seg[1].base.type=0;
- keyinfo[0].base.flag = (uint8) HA_PACK_KEY;
- keyinfo[1].seg[0].base.start=8;
- keyinfo[1].seg[0].base.length=sizeof(uint32);
- keyinfo[1].seg[0].base.type=HA_KEYTYPE_LONG_INT;
- keyinfo[1].seg[0].base.flag=0;
- keyinfo[1].seg[1].base.type=0;
- keyinfo[1].base.flag =HA_NOSAME;
-
- recinfo[0].base.type=0;
- recinfo[0].base.length=sizeof(record.id);
- recinfo[1].base.type=0;
- recinfo[1].base.length=sizeof(record.nr);
- recinfo[2].base.type=0;
- recinfo[2].base.length=sizeof(record.text);
- recinfo[3].base.type=FIELD_LAST;
-
- puts("- Creating isam-file");
- my_delete(filename,MYF(0)); /* Remove old locks under gdb */
- if (nisam_create(filename,2,&keyinfo[0],&recinfo[0],10000,0,0,0,0L))
- exit(1);
-
- rnd_init(0);
- printf("- Starting %d processes\n",forks); fflush(stdout);
- for (i=0 ; i < forks; i++)
- {
- if (!fork())
- {
- start_test(i+1);
- sleep(1);
- return 0;
- }
- VOID(rnd(1));
- }
-
- for (i=0 ; i < forks ; i++)
- while ((wait_ret=wait(&status)) && wait_ret == -1);
- return 0;
-}
-
-
-static void get_options(argc,argv)
-int argc;
-char *argv[];
-{
- char *pos,*progname;
- DEBUGGER_OFF;
-
- progname= argv[0];
-
- while (--argc >0 && *(pos = *(++argv)) == '-' ) {
- switch(*++pos) {
- case 'l':
- use_log=1;
- break;
- case 'f':
- forks=atoi(++pos);
- break;
- case 't':
- tests=atoi(++pos);
- break;
- case 'K': /* Use key cacheing */
- key_cacheing=1;
- break;
- case 'A': /* All flags */
- use_log=key_cacheing=1;
- break;
- case '?':
- case 'I':
- case 'V':
- printf("%s Ver 1.0 for %s at %s\n",progname,SYSTEM_TYPE,MACHINE_TYPE);
- puts("TCX Datakonsult AB, by Monty, for your professional use\n");
- puts("Test av locking with threads\n");
- printf("Usage: %s [-?lKA] [-f#] [-t#]\n",progname);
- exit(0);
- case '#':
- DEBUGGER_ON;
- DBUG_PUSH (++pos);
- break;
- default:
- printf("Illegal option: '%c'\n",*pos);
- break;
- }
- }
- return;
-}
-
-
-void start_test(int id)
-{
- uint i;
- int error,lock_type;
- N_ISAMINFO isam_info;
- N_INFO *file,*file1,*file2,*lock;
-
- if (use_log)
- nisam_log(1);
- if (!(file1=nisam_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)) ||
- !(file2=nisam_open(filename,O_RDWR,HA_OPEN_WAIT_IF_LOCKED)))
- {
- fprintf(stderr,"Can't open isam-file: %s\n",filename);
- exit(1);
- }
- if (key_cacheing && rnd(2) == 0)
- init_key_cache(dflt_key_cache,512,65536L,0,0);
- printf("Process %d, pid: %d\n",id,(int) getpid()); fflush(stdout);
-
- for (error=i=0 ; i < tests && !error; i++)
- {
- file= (rnd(2) == 1) ? file1 : file2;
- lock=0 ; lock_type=0;
- if (rnd(10) == 0)
- {
- if (nisam_lock_database(lock=(rnd(2) ? file1 : file2),
- lock_type=(rnd(2) == 0 ? F_RDLCK : F_WRLCK)))
- {
- fprintf(stderr,"%2d: start: Can't lock table %d\n",id,my_errno);
- error=1;
- break;
- }
- }
- switch (rnd(4)) {
- case 0: error=test_read(file,id); break;
- case 1: error=test_rrnd(file,id); break;
- case 2: error=test_write(file,id,lock_type); break;
- case 3: error=test_update(file,id,lock_type); break;
- }
- if (lock)
- nisam_lock_database(lock,F_UNLCK);
- }
- if (!error)
- {
- nisam_info(file1,&isam_info,0);
- printf("%2d: End of test. Records: %ld Deleted: %ld\n",
- id,isam_info.records,isam_info.deleted);
- fflush(stdout);
- }
-
- nisam_close(file1);
- nisam_close(file2);
- if (use_log)
- nisam_log(0);
- if (error)
- {
- printf("%2d: Aborted\n",id); fflush(stdout);
- exit(1);
- }
-}
-
-
-int test_read(N_INFO *file,int id)
-{
- uint i,lock,found,next,prev;
- ulong find;
-
- lock=0;
- if (rnd(2) == 0)
- {
- lock=1;
- if (nisam_lock_database(file,F_RDLCK))
- {
- fprintf(stderr,"%2d: Can't lock table %d\n",id,my_errno);
- return 1;
- }
- }
-
- found=next=prev=0;
- for (i=0 ; i < 100 ; i++)
- {
- find=rnd(100000);
- if (!nisam_rkey(file,record.id,1,(byte*) &find,
- sizeof(find),HA_READ_KEY_EXACT))
- found++;
- else
- {
- if (my_errno != HA_ERR_KEY_NOT_FOUND)
- {
- fprintf(stderr,"%2d: Got error %d from read in read\n",id,my_errno);
- return 1;
- }
- else if (!nisam_rnext(file,record.id,1))
- next++;
- else
- {
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rnext in read\n",id,my_errno);
- return 1;
- }
- else if (!nisam_rprev(file,record.id,1))
- prev++;
- else
- {
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rnext in read\n",
- id,my_errno);
- return 1;
- }
- }
- }
- }
- }
- if (lock)
- {
- if (nisam_lock_database(file,F_UNLCK))
- {
- fprintf(stderr,"%2d: Can't unlock table\n",id);
- return 1;
- }
- }
- printf("%2d: read: found: %5d next: %5d prev: %5d\n",
- id,found,next,prev);
- fflush(stdout);
- return 0;
-}
-
-
-int test_rrnd(N_INFO *file,int id)
-{
- uint count,lock;
-
- lock=0;
- if (rnd(2) == 0)
- {
- lock=1;
- if (nisam_lock_database(file,F_RDLCK))
- {
- fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
- nisam_close(file);
- return 1;
- }
- if (rnd(2) == 0)
- nisam_extra(file,HA_EXTRA_CACHE);
- }
-
- count=0;
- if (nisam_rrnd(file,record.id,0L))
- {
- if (my_errno == HA_ERR_END_OF_FILE)
- goto end;
- fprintf(stderr,"%2d: Can't read first record (%d)\n",id,my_errno);
- return 1;
- }
- for (count=1 ; !nisam_rrnd(file,record.id,NI_POS_ERROR) ;count++) ;
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rrnd\n",id,my_errno);
- return 1;
- }
-
-end:
- if (lock)
- {
- nisam_extra(file,HA_EXTRA_NO_CACHE);
- if (nisam_lock_database(file,F_UNLCK))
- {
- fprintf(stderr,"%2d: Can't unlock table\n",id);
- exit(0);
- }
- }
- printf("%2d: rrnd: %5d\n",id,count); fflush(stdout);
- return 0;
-}
-
-
-int test_write(N_INFO *file,int id,int lock_type)
-{
- uint i,tries,count,lock;
-
- lock=0;
- if (rnd(2) == 0 || lock_type == F_RDLCK)
- {
- lock=1;
- if (nisam_lock_database(file,F_WRLCK))
- {
- if (lock_type == F_RDLCK && my_errno == EDEADLK)
- {
- printf("%2d: write: deadlock\n",id); fflush(stdout);
- return 0;
- }
- fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
- nisam_close(file);
- return 1;
- }
- if (rnd(2) == 0)
- nisam_extra(file,HA_EXTRA_WRITE_CACHE);
- }
-
- sprintf(record.id,"%7d",(int) getpid());
- strmov(record.text,"Testing...");
-
- tries=(uint) rnd(100)+10;
- for (i=count=0 ; i < tries ; i++)
- {
- record.nr=rnd(80000)+20000;
- if (!nisam_write(file,record.id))
- count++;
- else
- {
- if (my_errno != HA_ERR_FOUND_DUPP_KEY)
- {
- fprintf(stderr,"%2d: Got error %d (errno %d) from write\n",id,my_errno,
- errno);
- return 1;
- }
- }
- }
- if (lock)
- {
- nisam_extra(file,HA_EXTRA_NO_CACHE);
- if (nisam_lock_database(file,F_UNLCK))
- {
- fprintf(stderr,"%2d: Can't unlock table\n",id);
- exit(0);
- }
- }
- printf("%2d: write: %5d\n",id,count); fflush(stdout);
- return 0;
-}
-
-
-int test_update(N_INFO *file,int id,int lock_type)
-{
- uint i,lock,found,next,prev,update;
- ulong find;
- struct record new_record;
-
- lock=0;
- if (rnd(2) == 0 || lock_type == F_RDLCK)
- {
- lock=1;
- if (nisam_lock_database(file,F_WRLCK))
- {
- if (lock_type == F_RDLCK && my_errno == EDEADLK)
- {
- printf("%2d: write: deadlock\n",id); fflush(stdout);
- return 0;
- }
- fprintf(stderr,"%2d: Can't lock table (%d)\n",id,my_errno);
- return 1;
- }
- }
- bzero((char*) &new_record,sizeof(new_record));
- strmov(new_record.text,"Updated");
-
- found=next=prev=update=0;
- for (i=0 ; i < 100 ; i++)
- {
- find=rnd(100000);
- if (!nisam_rkey(file,record.id,1,(byte*) &find,
- sizeof(find),HA_READ_KEY_EXACT))
- found++;
- else
- {
- if (my_errno != HA_ERR_KEY_NOT_FOUND)
- {
- fprintf(stderr,"%2d: Got error %d from read in update\n",id,my_errno);
- return 1;
- }
- else if (!nisam_rnext(file,record.id,1))
- next++;
- else
- {
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rnext in update\n",
- id,my_errno);
- return 1;
- }
- else if (!nisam_rprev(file,record.id,1))
- prev++;
- else
- {
- if (my_errno != HA_ERR_END_OF_FILE)
- {
- fprintf(stderr,"%2d: Got error %d from rnext in update\n",
- id,my_errno);
- return 1;
- }
- continue;
- }
- }
- }
- memcpy_fixed(new_record.id,record.id,sizeof(record.id));
- new_record.nr=rnd(20000)+40000;
- if (!nisam_update(file,record.id,new_record.id))
- update++;
- else
- {
- if (my_errno != HA_ERR_RECORD_CHANGED &&
- my_errno != HA_ERR_RECORD_DELETED &&
- my_errno != HA_ERR_FOUND_DUPP_KEY)
- {
- fprintf(stderr,"%2d: Got error %d from update\n",id,my_errno);
- return 1;
- }
- }
- }
- if (lock)
- {
- if (nisam_lock_database(file,F_UNLCK))
- {
- fprintf(stderr,"Can't unlock table,id, error%d\n",my_errno);
- return 1;
- }
- }
- printf("%2d: update: %5d\n",id,update); fflush(stdout);
- return 0;
-}
-
-#else /* __NETWARE__ */
-
-#include <stdio.h>
-
-main()
-{
- fprintf(stderr,"this test has not been ported to NetWare\n");
- return 0;
-}
-
-#endif /* __NETWARE__ */
diff --git a/isam/test_all b/isam/test_all
deleted file mode 100755
index 5de37e44585..00000000000
--- a/isam/test_all
+++ /dev/null
@@ -1,30 +0,0 @@
-echo "test2 -L -K -W -P"
-test2 -L -K -W -P
-echo "test2 -L -K -W -P -A"
-test2 -L -K -W -P -A
-echo "test2 -L -K -W -P -S -R1 -m500"
-test2 -L -K -W -P -S -R1 -m500
-echo "test2 -L -K -R1 -m2000 ; Should give error 135"
-test2 -L -K -R1 -m2000
-echo "test2 -L -K -P -S -R3 -m50 -b1000000"
-test2 -L -K -P -S -R3 -m50 -b1000000
-echo "test2 -L -B"
-test2 -L -B
-echo "test2 -L -K -W -P -m50 -l"
-test2 -L -K -W -P -m50 -l
-isamlog
-echo "test2 -L -K -W -P -m50 -l -b100"
-test2 -L -K -W -P -m50 -l -b100
-isamlog
-echo "time test2"
-time test2
-echo "time test2 -K"
-time test2 -K
-echo "time test2 -L"
-time test2 -L
-echo "time test2 -L -K"
-time test2 -L -K
-echo "time test2 -L -K -W"
-time test2 -L -K -W
-echo "time test2 -L -K -W -S"
-time test2 -L -K -W -S
diff --git a/isam/test_all.res b/isam/test_all.res
deleted file mode 100644
index 5de37e44585..00000000000
--- a/isam/test_all.res
+++ /dev/null
@@ -1,30 +0,0 @@
-echo "test2 -L -K -W -P"
-test2 -L -K -W -P
-echo "test2 -L -K -W -P -A"
-test2 -L -K -W -P -A
-echo "test2 -L -K -W -P -S -R1 -m500"
-test2 -L -K -W -P -S -R1 -m500
-echo "test2 -L -K -R1 -m2000 ; Should give error 135"
-test2 -L -K -R1 -m2000
-echo "test2 -L -K -P -S -R3 -m50 -b1000000"
-test2 -L -K -P -S -R3 -m50 -b1000000
-echo "test2 -L -B"
-test2 -L -B
-echo "test2 -L -K -W -P -m50 -l"
-test2 -L -K -W -P -m50 -l
-isamlog
-echo "test2 -L -K -W -P -m50 -l -b100"
-test2 -L -K -W -P -m50 -l -b100
-isamlog
-echo "time test2"
-time test2
-echo "time test2 -K"
-time test2 -K
-echo "time test2 -L"
-time test2 -L
-echo "time test2 -L -K"
-time test2 -L -K
-echo "time test2 -L -K -W"
-time test2 -L -K -W
-echo "time test2 -L -K -W -S"
-time test2 -L -K -W -S
diff --git a/isam/update.c b/isam/update.c
deleted file mode 100644
index b3b676f967d..00000000000
--- a/isam/update.c
+++ /dev/null
@@ -1,117 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Uppdaterare nuvarande record i en pisam-databas */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* Updaterar senaste l{sta record i databasen */
-
-int nisam_update(register N_INFO *info, const byte *oldrec, const byte *newrec)
-{
- int flag,key_changed,save_errno;
- reg3 ulong pos;
- uint i,length;
- uchar old_key[N_MAX_KEY_BUFF],*new_key;
- DBUG_ENTER("nisam_update");
-
- LINT_INIT(save_errno);
- if (!(info->update & HA_STATE_AKTIV))
- {
- my_errno=HA_ERR_KEY_NOT_FOUND;
- DBUG_RETURN(-1);
- }
- if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
- {
- my_errno=EACCES;
- DBUG_RETURN(-1);
- }
- pos=info->lastpos;
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
-#endif
- if ((*info->s->compare_record)(info,oldrec))
- {
- save_errno=my_errno;
- goto err_end; /* Record has changed */
- }
- if (info->s->state.key_file_length >=
- info->s->base.max_key_file_length -
- info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys)
- {
- save_errno=HA_ERR_INDEX_FILE_FULL;
- goto err_end;
- }
-
- /* Flyttar de element i isamfilen som m}ste flyttas */
-
- new_key=info->lastkey+info->s->base.max_key_length;
- key_changed=HA_STATE_KEY_CHANGED; /* We changed current database */
- /* Remove key that didn't change */
- for (i=0 ; i < info->s->state.keys ; i++)
- {
- length=_nisam_make_key(info,i,new_key,newrec,pos);
- if (length != _nisam_make_key(info,i,old_key,oldrec,pos) ||
- memcmp((byte*) old_key,(byte*) new_key,length))
- {
- if ((int) i == info->lastinx)
- key_changed|=HA_STATE_WRITTEN; /* Mark that keyfile changed */
- if (_nisam_ck_delete(info,i,old_key)) goto err;
- if (_nisam_ck_write(info,i,new_key)) goto err;
- }
- }
-
- if ((*info->s->update_record)(info,pos,newrec))
- goto err;
-
- info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV |
- key_changed);
- nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,0);
- VOID(_nisam_writeinfo(info,test(key_changed)));
- allow_break(); /* Allow SIGHUP & SIGINT */
- DBUG_RETURN(0);
-
-err:
- DBUG_PRINT("error",("key: %d errno: %d",i,my_errno));
- save_errno=my_errno;
- if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
- {
- info->errkey= (int) i;
- flag=0;
- do
- {
- length=_nisam_make_key(info,i,new_key,newrec,pos);
- if (length != _nisam_make_key(info,i,old_key,oldrec,pos) ||
- memcmp((byte*) old_key,(byte*) new_key,length))
- {
- if ((flag++ && _nisam_ck_delete(info,i,new_key)) ||
- _nisam_ck_write(info,i,old_key))
- break;
- }
- } while (i-- != 0);
- }
- info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_AKTIV |
- key_changed);
- err_end:
- nisam_log_record(LOG_UPDATE,info,newrec,info->lastpos,save_errno);
- VOID(_nisam_writeinfo(info,1));
- allow_break(); /* Allow SIGHUP & SIGINT */
- my_errno=(save_errno == HA_ERR_KEY_NOT_FOUND) ? HA_ERR_CRASHED : save_errno;
- DBUG_RETURN(-1);
-} /* nisam_update */
diff --git a/isam/write.c b/isam/write.c
deleted file mode 100644
index f2c0d8dbc45..00000000000
--- a/isam/write.c
+++ /dev/null
@@ -1,840 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* Skriver ett record till en isam-databas */
-
-#include "isamdef.h"
-#ifdef __WIN__
-#include <errno.h>
-#endif
-
- /* Functions declared in this file */
-
-static int w_search(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- ulong pos, uchar *father_buff, uchar *father_keypos,
- ulong father_page);
-static int _nisam_balance_page(N_INFO *info,N_KEYDEF *keyinfo,uchar *key,
- uchar *curr_buff,uchar *father_buff,
- uchar *father_keypos,ulong father_page);
-
-
- /* Write new record to database */
-
-int nisam_write(N_INFO *info, const byte *record)
-{
- uint i;
- ulong filepos;
- uchar *buff;
- DBUG_ENTER("nisam_write");
- DBUG_PRINT("enter",("isam: %d data: %d",info->s->kfile,info->dfile));
-
- if (info->s->base.options & HA_OPTION_READ_ONLY_DATA)
- {
- my_errno=EACCES;
- DBUG_RETURN(-1);
- }
-#ifndef NO_LOCKING
- if (_nisam_readinfo(info,F_WRLCK,1)) DBUG_RETURN(-1);
-#endif
- dont_break(); /* Dont allow SIGHUP or SIGINT */
-#if !defined(NO_LOCKING) && defined(USE_RECORD_LOCK)
- if (!info->locked && my_lock(info->dfile,F_WRLCK,0L,F_TO_EOF,
- MYF(MY_SEEK_NOT_DONE) | info->lock_wait))
- goto err;
-#endif
- filepos= ((info->s->state.dellink != NI_POS_ERROR) ?
- info->s->state.dellink :
- info->s->state.data_file_length);
-
- if (info->s->base.reloc == 1L && info->s->base.records == 1L &&
- info->s->state.records == 1L)
- { /* System file */
- my_errno=HA_ERR_RECORD_FILE_FULL;
- goto err2;
- }
- if (info->s->state.key_file_length >=
- info->s->base.max_key_file_length -
- info->s->blocksize* INDEX_BLOCK_MARGIN *info->s->state.keys)
- {
- my_errno=HA_ERR_INDEX_FILE_FULL;
- goto err2;
- }
-
- /* Write all keys to indextree */
- buff=info->lastkey+info->s->base.max_key_length;
- for (i=0 ; i < info->s->state.keys ; i++)
- {
- VOID(_nisam_make_key(info,i,buff,record,filepos));
- if (_nisam_ck_write(info,i,buff)) goto err;
- }
-
- if ((*info->s->write_record)(info,record))
- goto err;
-
- info->update= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED |HA_STATE_AKTIV |
- HA_STATE_WRITTEN);
- info->s->state.records++;
- info->lastpos=filepos;
- nisam_log_record(LOG_WRITE,info,record,filepos,0);
- VOID(_nisam_writeinfo(info,1));
- allow_break(); /* Allow SIGHUP & SIGINT */
- DBUG_RETURN(0);
-
-err:
- if (my_errno == HA_ERR_FOUND_DUPP_KEY || my_errno == HA_ERR_RECORD_FILE_FULL)
- {
- info->errkey= (int) i;
- while ( i-- > 0)
- {
- VOID(_nisam_make_key(info,i,buff,record,filepos));
- if (_nisam_ck_delete(info,i,buff))
- break;
- }
- }
- info->update=(HA_STATE_CHANGED | HA_STATE_ROW_CHANGED | HA_STATE_WRITTEN);
-err2:
- nisam_log_record(LOG_WRITE,info,record,filepos,my_errno);
- VOID(_nisam_writeinfo(info,1));
- allow_break(); /* Allow SIGHUP & SIGINT */
- DBUG_RETURN(-1);
-} /* nisam_write */
-
-
- /* Write one key to btree */
-
-int _nisam_ck_write(register N_INFO *info, uint keynr, uchar *key)
-{
- int error;
- DBUG_ENTER("_nisam_ck_write");
-
- if ((error=w_search(info,info->s->keyinfo+keynr,key,
- info->s->state.key_root[keynr], (uchar *) 0, (uchar*) 0,
- 0L)) > 0)
- error=_nisam_enlarge_root(info,keynr,key);
- DBUG_RETURN(error);
-} /* _nisam_ck_write */
-
-
- /* Make a new root with key as only pointer */
-
-int _nisam_enlarge_root(register N_INFO *info, uint keynr, uchar *key)
-{
- uint t_length,nod_flag;
- reg2 N_KEYDEF *keyinfo;
- S_PARAM s_temp;
- ISAM_SHARE *share=info->s;
- DBUG_ENTER("_nisam_enlarge_root");
-
- info->page_changed=1;
- nod_flag= (share->state.key_root[keynr] != NI_POS_ERROR) ?
- share->base.key_reflength : 0;
- _nisam_kpointer(info,info->buff+2,share->state.key_root[keynr]); /* if nod */
- keyinfo=share->keyinfo+keynr;
- t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,(uchar*) 0,(uchar*) 0,
- key,&s_temp);
- putint(info->buff,t_length+2+nod_flag,nod_flag);
- _nisam_store_key(keyinfo,info->buff+2+nod_flag,&s_temp);
- if ((share->state.key_root[keynr]= _nisam_new(info,keyinfo)) ==
- NI_POS_ERROR ||
- _nisam_write_keypage(info,keyinfo,share->state.key_root[keynr],info->buff))
- DBUG_RETURN(-1);
- DBUG_RETURN(0);
-} /* _nisam_enlarge_root */
-
-
- /* S|ker reda p} vart nyckeln skall s{ttas och placerar den dit */
- /* Returnerar -1 om fel ; 0 om ok. 1 om nyckel propagerar upp}t */
-
-static int w_search(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, ulong page, uchar *father_buff,
- uchar *father_keypos, ulong father_page)
-{
- int error,flag;
- uint comp_flag,nod_flag;
- uchar *temp_buff,*keypos;
- uchar keybuff[N_MAX_KEY_BUFF];
- DBUG_ENTER("w_search");
- DBUG_PRINT("enter",("page: %ld",page));
-
- if (page == NI_POS_ERROR)
- DBUG_RETURN(1); /* No key, make new */
-
- if (keyinfo->base.flag & HA_SORT_ALLOWS_SAME)
- comp_flag=SEARCH_BIGGER; /* Put after same key */
- else if (keyinfo->base.flag & HA_NOSAME)
- comp_flag=SEARCH_FIND; /* No dupplicates */
- else
- comp_flag=SEARCH_SAME; /* Keys in rec-pos order */
-
- if (!(temp_buff= (uchar*) my_alloca((uint) keyinfo->base.block_length+
- N_MAX_KEY_BUFF)))
- DBUG_RETURN(-1);
- if (!_nisam_fetch_keypage(info,keyinfo,page,temp_buff,0))
- goto err;
-
- flag=(*keyinfo->bin_search)(info,keyinfo,temp_buff,key,0,comp_flag,&keypos,
- keybuff);
- nod_flag=test_if_nod(temp_buff);
- if (flag == 0)
- {
- my_errno=HA_ERR_FOUND_DUPP_KEY;
- /* get position to record with dupplicated key */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff));
- info->dupp_key_pos=_nisam_dpos(info,test_if_nod(temp_buff),keypos);
- my_afree((byte*) temp_buff);
- DBUG_RETURN(-1);
- }
- if ((error=w_search(info,keyinfo,key,_nisam_kpos(nod_flag,keypos),
- temp_buff,keypos,page)) >0)
- {
- error=_nisam_insert(info,keyinfo,key,temp_buff,keypos,keybuff,father_buff,
- father_keypos,father_page);
- if (_nisam_write_keypage(info,keyinfo,page,temp_buff))
- goto err;
- }
- my_afree((byte*) temp_buff);
- DBUG_RETURN(error);
-err:
- my_afree((byte*) temp_buff);
- DBUG_PRINT("exit",("Error: %d",my_errno));
- DBUG_RETURN (-1);
-} /* w_search */
-
-
- /* Insert new key at right of key_pos */
- /* Returns 2 if key contains key to upper level */
-
-int _nisam_insert(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, uchar *anc_buff, uchar *key_pos, uchar *key_buff,
- uchar *father_buff, uchar *father_key_pos, ulong father_page)
-{
- uint a_length,t_length,nod_flag;
- uchar *endpos;
- int key_offset;
- S_PARAM s_temp;
- DBUG_ENTER("_nisam_insert");
- DBUG_PRINT("enter",("key_pos: %lx",key_pos));
- DBUG_EXECUTE("key",_nisam_print_key(DBUG_FILE,keyinfo->seg,key););
-
- nod_flag=test_if_nod(anc_buff);
- a_length=getint(anc_buff);
- endpos= anc_buff+ a_length;
- t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,
- (key_pos == endpos ? (uchar*) 0 : key_pos),
- (key_pos == anc_buff+2+nod_flag ?
- (uchar*) 0 : key_buff),key,&s_temp);
-#ifndef DBUG_OFF
- if (key_pos != anc_buff+2+nod_flag)
- DBUG_DUMP("prev_key",(byte*) key_buff,_nisam_keylength(keyinfo,key_buff));
- if (keyinfo->base.flag & HA_PACK_KEY)
- {
- DBUG_PRINT("test",("t_length: %d ref_len: %d",
- t_length,s_temp.ref_length));
- DBUG_PRINT("test",("n_ref_len: %d n_length: %d key: %lx",
- s_temp.n_ref_length,s_temp.n_length,s_temp.key));
- }
-#endif
- key_offset = (uint)(endpos-key_pos);
- if((int) t_length < 0)
- key_offset += (int) t_length;
- if (key_offset < 0)
- {
- DBUG_PRINT("error",("Found a bug: negative key_offset %d\n", key_offset));
- DBUG_RETURN(-1);
- }
- if ((int) t_length >= 0) /* t_length is almost always > 0 */
- bmove_upp((byte*) endpos+t_length,(byte*) endpos,(uint)key_offset );
- else
- {
- /* This may happen if a key was deleted and the next key could be
- compressed better than before */
- DBUG_DUMP("anc_buff",(byte*) anc_buff,a_length);
-
- bmove(key_pos,key_pos - (int) t_length,(uint)key_offset);
- }
- _nisam_store_key(keyinfo,key_pos,&s_temp);
- a_length+=t_length;
- putint(anc_buff,a_length,nod_flag);
- if (a_length <= keyinfo->base.block_length)
- DBUG_RETURN(0); /* There is room on page */
-
- /* Page is full */
-
- if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)) &&
- father_buff)
- DBUG_RETURN(_nisam_balance_page(info,keyinfo,key,anc_buff,father_buff,
- father_key_pos,father_page));
- DBUG_RETURN(_nisam_splitt_page(info,keyinfo,key,anc_buff,key_buff));
-} /* _nisam_insert */
-
-
- /* splitt a full page in two and assign emerging item to key */
-
-int _nisam_splitt_page(register N_INFO *info, register N_KEYDEF *keyinfo,
- uchar *key, uchar *buff, uchar *key_buff)
-{
- uint length,a_length,key_ref_length,t_length,nod_flag;
- uchar *key_pos,*pos;
- ulong new_pos;
- S_PARAM s_temp;
- DBUG_ENTER("ni_splitt_page");
- DBUG_DUMP("buff",(byte*) buff,getint(buff));
-
- nod_flag=test_if_nod(buff);
- key_ref_length=2+nod_flag;
- key_pos=_nisam_find_half_pos(info,keyinfo,buff,key_buff);
- length=(uint) (key_pos-buff);
- a_length=getint(buff);
- putint(buff,length,nod_flag);
- info->page_changed=1;
-
- /* Correct new page pointer */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff));
- if (nod_flag)
- {
- DBUG_PRINT("test",("Splitting nod"));
- pos=key_pos-nod_flag;
- memcpy((byte*) info->buff+2,(byte*) pos,(size_t) nod_flag);
- }
-
- /* Move midle item to key and pointer to new page */
- if ((new_pos=_nisam_new(info,keyinfo)) == NI_POS_ERROR)
- DBUG_RETURN(-1);
- _nisam_kpointer(info,_nisam_move_key(keyinfo,key,key_buff),new_pos);
-
- /* Store new page */
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&key_pos,key_buff));
- t_length=_nisam_get_pack_key_length(keyinfo,nod_flag,(uchar *) 0, (uchar*) 0,
- key_buff, &s_temp);
- s_temp.n_length= *key_pos; /* Needed by ni_store_key */
- length=(uint) ((buff+a_length)-key_pos);
- memcpy((byte*) info->buff+key_ref_length+t_length,(byte*) key_pos,
- (size_t) length);
- _nisam_store_key(keyinfo,info->buff+key_ref_length,&s_temp);
- putint(info->buff,length+t_length+key_ref_length,nod_flag);
-
- if (_nisam_write_keypage(info,keyinfo,new_pos,info->buff))
- DBUG_RETURN(-1);
- DBUG_DUMP("key",(byte*) key,_nisam_keylength(keyinfo,key));
- DBUG_RETURN(2); /* Middle key up */
-} /* _nisam_splitt_page */
-
-
- /* find out how much more room a key will take */
-
-#ifdef QQ
-uint _nisam_get_pack_key_length(N_KEYDEF *keyinfo, uint nod_flag, uchar *key_pos, uchar *key_buff, uchar *key, S_PARAM *s_temp)
-
- /* If nod: Length of nod-pointer */
- /* Position to pos after key in buff */
- /* Last key before current key */
- /* Current key */
- /* How next key will be packed */
-{
- reg1 N_KEYSEG *keyseg;
- int length;
- uint key_length,ref_length,n_length,diff_flag,same_length;
- uchar *start,*end,*key_end;
-
- s_temp->key=key;
- if (!(keyinfo->base.flag & HA_PACK_KEY))
- return (s_temp->totlength=_nisam_keylength(keyinfo,key)+nod_flag);
- s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
- s_temp->prev_length=0;
-
- same_length=0; keyseg=keyinfo->seg;
- key_length=_nisam_keylength(keyinfo,key)+nod_flag;
-
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- diff_flag=1;
- end=key_end= key+ *key+1;
- if (key_buff)
- {
- if (*key == *key_buff && *key)
- same_length=1; /* Don't use key-pack if length == 0 */
- else if (*key > *key_buff)
- end=key+ *key_buff+1;
- key_buff++;
- }
- key++;
- }
- else
- {
- diff_flag=0;
- key_end=end= key+keyseg->base.length;
- }
-
- start=key;
- if (key_buff)
- while (key < end && *key == *key_buff)
- {
- key++; key_buff++;
- }
-
- s_temp->key=key; s_temp->key_length= (uint) (key_end-key);
-
- if (same_length && key == key_end)
- {
- s_temp->ref_length=128;
- length=(int) key_length-(int)(key_end-start); /* Same as prev key */
- if (key_pos)
- {
- s_temp->n_length= *key_pos;
- key_pos=0; /* Can't combine with next */
- }
- }
- else
- {
- if (start != key)
- { /* Starts as prev key */
- s_temp->ref_length= (uint) (key-start)+128;
- length=(int) (1+key_length-(uint) (key-start));
- }
- else
- length=(int) (key_length+ (1-diff_flag)); /* Not packed key */
- }
- s_temp->totlength=(uint) length;
-
- DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d",
- key_length,length,s_temp->key_length));
-
- /* If something after that is not 0 length test if we can combine */
-
- if (key_pos && (n_length= *key_pos))
- {
- key_pos++;
- ref_length=0;
- if (n_length & 128)
- {
- if ((ref_length=n_length & 127))
- if (diff_flag)
- n_length= *key_pos++; /* Length of key-part */
- else
- n_length=keyseg->base.length - ref_length;
- }
- else
- if (*start == *key_pos && diff_flag && start != key_end)
- length++; /* One new pos for ref.len */
-
- DBUG_PRINT("test",("length: %d key_pos: %lx",length,key_pos));
- if (n_length != 128)
- { /* Not same key after */
- key=start+ref_length;
- while (n_length > 0 && key < key_end && *key == *key_pos)
- {
- key++; key_pos++;
- ref_length++;
- n_length--;
- length--; /* We gained one char */
- }
-
- if (n_length == 0 && diff_flag)
- {
- n_length=128; /* Same as prev key */
- length--; /* We don't need key-length */
- }
- else if (ref_length)
- s_temp->n_ref_length=ref_length | 128;
- }
- s_temp->n_length=n_length;
- }
- return (uint) length;
-} /* _nisam_get_pack_key_length */
-
-#else
-
-uint
-_nisam_get_pack_key_length(N_KEYDEF *keyinfo,
- uint nod_flag, /* If nod: Length of nod-pointer */
- uchar *key_pos, /* Position to pos after key in buff */
- uchar *key_buff,/* Last key before current key */
- uchar *key, /* Current key */
- S_PARAM *s_temp/* How next key will be packed */
- )
-{
- reg1 N_KEYSEG *keyseg;
- int length;
- uint key_length,ref_length,n_length,diff_flag,same_length,org_key_length=0;
- uchar *start,*end,*key_end;
-
- s_temp->key=key;
- if (!(keyinfo->base.flag & HA_PACK_KEY))
- return (s_temp->totlength=_nisam_keylength(keyinfo,key)+nod_flag);
- s_temp->ref_length=s_temp->n_ref_length=s_temp->n_length=0;
-
- same_length=0; keyseg=keyinfo->seg;
- key_length=_nisam_keylength(keyinfo,key)+nod_flag;
- s_temp->prev_key=key_buff;
-
- if (keyseg->base.flag & HA_SPACE_PACK)
- {
- diff_flag=1;
- end=key_end= key+ *key+1;
- if (key_buff)
- {
- org_key_length= (uint) *key_buff;
- if (*key == *key_buff && *key)
- same_length=1; /* Don't use key-pack if length == 0 */
- else if (*key > *key_buff)
- end=key+ org_key_length+1;
- key_buff++;
- }
- key++;
- }
- else
- {
- diff_flag=0;
- key_end=end= key+(org_key_length=keyseg->base.length);
- }
-
- start=key;
- if (key_buff)
- while (key < end && *key == *key_buff)
- {
- key++; key_buff++;
- }
-
- s_temp->key=key; s_temp->key_length= (uint) (key_end-key);
-
- if (same_length && key == key_end)
- {
- s_temp->ref_length=128;
- length=(int) key_length-(int)(key_end-start); /* Same as prev key */
- if (key_pos)
- { /* Can't combine with next */
- s_temp->n_length= *key_pos; /* Needed by _nisam_store_key */
- key_pos=0;
- }
- }
- else
- {
- if (start != key)
- { /* Starts as prev key */
- s_temp->ref_length= (uint) (key-start)+128;
- length=(int) (1+key_length-(uint) (key-start));
- }
- else
- length=(int) (key_length+ (1-diff_flag)); /* Not packed key */
- }
- s_temp->totlength=(uint) length;
- s_temp->prev_length=0;
- DBUG_PRINT("test",("tot_length: %d length: %d uniq_key_length: %d",
- key_length,length,s_temp->key_length));
-
- /* If something after that is not 0 length test if we can combine */
-
- if (key_pos && (n_length= *key_pos++))
- {
- if (n_length == 128)
- {
- /*
- We put a different key between two identical keys
- Extend next key to have same prefix as this key
- */
- if (s_temp->ref_length)
- { /* make next key longer */
- s_temp->part_of_prev_key= s_temp->ref_length;
- s_temp->prev_length= org_key_length - (s_temp->ref_length-128);
- s_temp->n_length= s_temp->prev_length;
- s_temp->prev_key+= diff_flag + (s_temp->ref_length - 128);
- length+= s_temp->prev_length+diff_flag;
- }
- else
- { /* Can't use prev key */
- s_temp->part_of_prev_key=0;
- s_temp->prev_length= org_key_length;
- s_temp->n_length= org_key_length;
- s_temp->prev_key+= diff_flag; /* To start of key */
- length+= org_key_length;
- }
- return (uint) length;
- }
-
- if (n_length & 128)
- {
- ref_length=n_length & 127;
- if (diff_flag) /* If SPACE_PACK */
- n_length= *key_pos++; /* Length of key-part */
- else
- n_length=keyseg->base.length - ref_length;
-
- /* Test if new keys has fewer characters that match the previous key */
- if (!s_temp->ref_length)
- { /* Can't use prev key */
- s_temp->part_of_prev_key= 0;
- s_temp->prev_length= ref_length;
- s_temp->n_length= n_length+ref_length;
- s_temp->prev_key+= diff_flag; /* To start of key */
- return (uint) length+ref_length-diff_flag;
- }
- if (ref_length+128 > s_temp->ref_length)
- {
- /* We must copy characters from the original key to the next key */
- s_temp->part_of_prev_key= s_temp->ref_length;
- s_temp->prev_length= ref_length+128 - s_temp->ref_length;
- s_temp->n_length= n_length + s_temp->prev_length;
- s_temp->prev_key+= diff_flag + s_temp->ref_length -128;
- return (uint) length + s_temp->prev_length;
- }
- }
- else
- {
- ref_length=0;
- if (*start == *key_pos && diff_flag && start != key_end)
- length++; /* One new pos for ref.len */
- }
- DBUG_PRINT("test",("length: %d key_pos: %lx",length,key_pos));
-
- key=start+ref_length;
- while (n_length > 0 && key < key_end && *key == *key_pos)
- {
- key++; key_pos++;
- ref_length++;
- n_length--;
- length--; /* We gained one char */
- }
-
- if (n_length == 0 && diff_flag)
- {
- n_length=128; /* Same as prev key */
- length--; /* We don't need key-length */
- }
- else if (ref_length)
- s_temp->n_ref_length=ref_length | 128;
- s_temp->n_length=n_length;
- }
- return (uint) length;
-} /* _nisam_get_pack_key_length */
-#endif
-
-
- /* store a key in page-buffert */
-
-void _nisam_store_key(N_KEYDEF *keyinfo, register uchar *key_pos,
- register S_PARAM *s_temp)
-{
- uint length;
- uchar *start;
-
- if (! (keyinfo->base.flag & HA_PACK_KEY))
- {
- memcpy((byte*) key_pos,(byte*) s_temp->key,(size_t) s_temp->totlength);
- return;
- }
- start=key_pos;
- if ((*key_pos=(uchar) s_temp->ref_length))
- key_pos++;
- if (s_temp->ref_length == 0 ||
- (s_temp->ref_length > 128 &&
- (keyinfo->seg[0].base.flag & HA_SPACE_PACK)))
- *key_pos++= (uchar) s_temp->key_length;
- bmove((byte*) key_pos,(byte*) s_temp->key,
- (length=s_temp->totlength-(uint) (key_pos-start)));
- key_pos+=length;
-
- if (s_temp->prev_length)
- {
- /* Extend next key because new key didn't have same prefix as prev key */
- if (s_temp->part_of_prev_key)
- *key_pos++ = s_temp->part_of_prev_key;
- if (keyinfo->seg[0].base.flag & HA_SPACE_PACK)
- *key_pos++= s_temp->n_length;
- memcpy(key_pos, s_temp->prev_key, s_temp->prev_length);
- return;
- }
-
- if ((*key_pos = (uchar) s_temp->n_ref_length))
- {
- if (! (keyinfo->seg[0].base.flag & HA_SPACE_PACK))
- return; /* Don't save keylength */
- key_pos++; /* Store ref for next key */
- }
- *key_pos = (uchar) s_temp->n_length;
- return;
-} /* _nisam_store_key */
-
-
- /* Calculate how to much to move to split a page in two */
- /* Returns pointer and key for get_key() to get mid key */
- /* There is at last 2 keys after pointer in buff */
-
-uchar *_nisam_find_half_pos(N_INFO *info, N_KEYDEF *keyinfo, uchar *page, uchar *key)
-{
- uint keys,length,key_ref_length,nod_flag;
- uchar *end,*lastpos;
- DBUG_ENTER("_nisam_find_half_pos");
-
- nod_flag=test_if_nod(page);
- key_ref_length=2+nod_flag;
- length=getint(page)-key_ref_length;
- page+=key_ref_length;
- if (!(keyinfo->base.flag & (HA_PACK_KEY | HA_SPACE_PACK_USED)))
- {
- keys=(length/(keyinfo->base.keylength+nod_flag))/2;
- DBUG_RETURN(page+keys*(keyinfo->base.keylength+nod_flag));
- }
-
- end=page+length/2-key_ref_length; /* This is aprox. half */
- *key='\0';
- do
- {
- lastpos=page;
- VOID((*keyinfo->get_key)(keyinfo,nod_flag,&page,key));
- } while (page < end);
-
- DBUG_PRINT("exit",("returns: %lx page: %lx half: %lx",lastpos,page,end));
- DBUG_RETURN(lastpos);
-} /* _nisam_find_half_pos */
-
-
- /* Balance page with not packed keys with page on right/left */
- /* returns 0 if balance was done */
-
-static int _nisam_balance_page(register N_INFO *info, N_KEYDEF *keyinfo,
- uchar *key, uchar *curr_buff, uchar *father_buff,
- uchar *father_key_pos, ulong father_page)
-{
- my_bool right;
- uint k_length,father_length,father_keylength,nod_flag,curr_keylength,
- right_length,left_length,new_right_length,new_left_length,extra_length,
- length,keys;
- uchar *pos,*buff,*extra_buff;
- ulong next_page,new_pos;
- byte tmp_part_key[N_MAX_KEY_BUFF];
- DBUG_ENTER("_nisam_balance_page");
-
- k_length=keyinfo->base.keylength;
- father_length=getint(father_buff);
- father_keylength=k_length+info->s->base.key_reflength;
- nod_flag=test_if_nod(curr_buff);
- curr_keylength=k_length+nod_flag;
- info->page_changed=1;
-
- if ((father_key_pos != father_buff+father_length && (info->s->rnd++ & 1)) ||
- father_key_pos == father_buff+2+info->s->base.key_reflength)
- {
- right=1;
- next_page= _nisam_kpos(info->s->base.key_reflength,
- father_key_pos+father_keylength);
- buff=info->buff;
- DBUG_PRINT("test",("use right page: %lu",next_page));
- }
- else
- {
- right=0;
- father_key_pos-=father_keylength;
- next_page= _nisam_kpos(info->s->base.key_reflength,father_key_pos);
- /* Fix that curr_buff is to left */
- buff=curr_buff; curr_buff=info->buff;
- DBUG_PRINT("test",("use left page: %lu",next_page));
- } /* father_key_pos ptr to parting key */
-
- if (!_nisam_fetch_keypage(info,keyinfo,next_page,info->buff,0))
- goto err;
- DBUG_DUMP("next",(byte*) info->buff,getint(info->buff));
-
- /* Test if there is room to share keys */
-
- left_length=getint(curr_buff);
- right_length=getint(buff);
- keys=(left_length+right_length-4-nod_flag*2)/curr_keylength;
-
- if ((right ? right_length : left_length) + curr_keylength <=
- keyinfo->base.block_length)
- { /* Merge buffs */
- new_left_length=2+nod_flag+(keys/2)*curr_keylength;
- new_right_length=2+nod_flag+((keys+1)/2)*curr_keylength;
- putint(curr_buff,new_left_length,nod_flag);
- putint(buff,new_right_length,nod_flag);
-
- if (left_length < new_left_length)
- { /* Move keys buff -> leaf */
- pos=curr_buff+left_length;
- memcpy((byte*) pos,(byte*) father_key_pos, (size_t) k_length);
- memcpy((byte*) pos+k_length, (byte*) buff+2,
- (size_t) (length=new_left_length - left_length - k_length));
- pos=buff+2+length;
- memcpy((byte*) father_key_pos,(byte*) pos,(size_t) k_length);
- bmove((byte*) buff+2,(byte*) pos+k_length,new_right_length);
- }
- else
- { /* Move keys -> buff */
-
- bmove_upp((byte*) buff+new_right_length,(byte*) buff+right_length,
- right_length-2);
- length=new_right_length-right_length-k_length;
- memcpy((byte*) buff+2+length,father_key_pos,(size_t) k_length);
- pos=curr_buff+new_left_length;
- memcpy((byte*) father_key_pos,(byte*) pos,(size_t) k_length);
- memcpy((byte*) buff+2,(byte*) pos+k_length,(size_t) length);
- }
-
- if (_nisam_write_keypage(info,keyinfo,next_page,info->buff) ||
- _nisam_write_keypage(info,keyinfo,father_page,father_buff))
- goto err;
- DBUG_RETURN(0);
- }
-
- /* curr_buff[] and buff[] are full, lets splitt and make new nod */
-
- extra_buff=info->buff+info->s->base.max_block;
- new_left_length=new_right_length=2+nod_flag+(keys+1)/3*curr_keylength;
- if (keys == 5) /* Too few keys to balance */
- new_left_length-=curr_keylength;
- extra_length=nod_flag+left_length+right_length-new_left_length-new_right_length-curr_keylength;
- DBUG_PRINT("info",("left_length: %d right_length: %d new_left_length: %d new_right_length: %d extra_length: %d",
- left_length, right_length,
- new_left_length, new_right_length,
- extra_length));
- putint(curr_buff,new_left_length,nod_flag);
- putint(buff,new_right_length,nod_flag);
- putint(extra_buff,extra_length+2,nod_flag);
-
- /* move first largest keys to new page */
- pos=buff+right_length-extra_length;
- memcpy((byte*) extra_buff+2,pos,(size_t) extra_length);
-
- /* Save new parting key */
- memcpy(tmp_part_key, pos-k_length,k_length);
-
- /* Make place for new keys */
- bmove_upp((byte*) buff+new_right_length,(byte*) pos-k_length,
- right_length-extra_length-k_length-2);
- /* Copy keys from left page */
- pos= curr_buff+new_left_length;
- memcpy((byte*) buff+2,(byte*) pos+k_length,
- (size_t) (length=left_length-new_left_length-k_length));
- /* Copy old parting key */
- memcpy((byte*) buff+2+length,father_key_pos,(size_t) k_length);
-
- /* Move new parting keys up */
- memcpy((byte*) (right ? key : father_key_pos),pos, (size_t) k_length);
- memcpy((byte*) (right ? father_key_pos : key), tmp_part_key, k_length);
-
- if ((new_pos=_nisam_new(info,keyinfo)) == NI_POS_ERROR)
- goto err;
- _nisam_kpointer(info,key+k_length,new_pos);
- if (_nisam_write_keypage(info,keyinfo,(right ? new_pos : next_page),
- info->buff) ||
- _nisam_write_keypage(info,keyinfo,(right ? next_page : new_pos),extra_buff))
- goto err;
-
- DBUG_RETURN(1); /* Middle key up */
-
-err:
- DBUG_RETURN(-1);
-} /* _nisam_balance_page */
diff --git a/libmysql/Makefile.am b/libmysql/Makefile.am
index 5c2dc9c7ba6..72ff44ecef3 100644
--- a/libmysql/Makefile.am
+++ b/libmysql/Makefile.am
@@ -30,7 +30,7 @@ include $(srcdir)/Makefile.shared
libmysqlclient_la_SOURCES = $(target_sources)
libmysqlclient_la_LIBADD = $(target_libadd)
libmysqlclient_la_LDFLAGS = $(target_ldflags)
-EXTRA_DIST = Makefile.shared
+EXTRA_DIST = Makefile.shared libmysql.def
noinst_HEADERS = client_settings.h
# This is called from the toplevel makefile
diff --git a/libmysql/libmysql.c b/libmysql/libmysql.c
index 35d01b5bcec..dc0ef57e910 100644
--- a/libmysql/libmysql.c
+++ b/libmysql/libmysql.c
@@ -1563,7 +1563,8 @@ void my_net_local_init(NET *net)
trailing '. The caller must supply whichever of those is desired.
*/
-ulong mysql_hex_string(char *to, const char *from, ulong length)
+ulong STDCALL
+mysql_hex_string(char *to, const char *from, ulong length)
{
char *to0= to;
const char *end;
@@ -1887,22 +1888,6 @@ my_bool cli_read_prepare_result(MYSQL *mysql, MYSQL_STMT *stmt)
DBUG_RETURN(0);
}
-#ifdef HAVE_DEPRECATED_411_API
-MYSQL_STMT * STDCALL mysql_prepare(MYSQL *mysql, const char *query,
- unsigned long query_length)
-{
- MYSQL_STMT *stmt;
- DBUG_ENTER("mysql_prepare");
-
- stmt= mysql_stmt_init(mysql);
- if (stmt && mysql_stmt_prepare(stmt, query, query_length))
- {
- mysql_stmt_close(stmt);
- DBUG_RETURN(0);
- }
- DBUG_RETURN(stmt);
-}
-#endif
/*
Allocate memory and init prepared statement structure.
@@ -3166,6 +3151,7 @@ my_bool STDCALL mysql_stmt_bind_param(MYSQL_STMT *stmt, MYSQL_BIND *bind)
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
param->store_param_func= store_param_str;
@@ -3341,11 +3327,12 @@ static void read_binary_time(MYSQL_TIME *tm, uchar **pos)
tm->hour+= tm->day*24;
tm->day= 0;
}
+ tm->time_type= MYSQL_TIMESTAMP_TIME;
+
*pos+= length;
}
else
- set_zero_time(tm);
- tm->time_type= MYSQL_TIMESTAMP_TIME;
+ set_zero_time(tm, MYSQL_TIMESTAMP_TIME);
}
static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
@@ -3370,12 +3357,12 @@ static void read_binary_datetime(MYSQL_TIME *tm, uchar **pos)
else
tm->hour= tm->minute= tm->second= 0;
tm->second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
+ tm->time_type= MYSQL_TIMESTAMP_DATETIME;
*pos+= length;
}
else
- set_zero_time(tm);
- tm->time_type= MYSQL_TIMESTAMP_DATETIME;
+ set_zero_time(tm, MYSQL_TIMESTAMP_DATETIME);
}
static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
@@ -3392,12 +3379,12 @@ static void read_binary_date(MYSQL_TIME *tm, uchar **pos)
tm->hour= tm->minute= tm->second= 0;
tm->second_part= 0;
tm->neg= 0;
+ tm->time_type= MYSQL_TIMESTAMP_DATE;
*pos+= length;
}
else
- set_zero_time(tm);
- tm->time_type= MYSQL_TIMESTAMP_DATE;
+ set_zero_time(tm, MYSQL_TIMESTAMP_DATE);
}
@@ -4049,6 +4036,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
DBUG_ASSERT(param->buffer_length != 0);
param->fetch_result= fetch_result_bin;
break;
+ case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
DBUG_ASSERT(param->buffer_length != 0);
@@ -4113,6 +4101,7 @@ my_bool STDCALL mysql_stmt_bind_result(MYSQL_STMT *stmt, MYSQL_BIND *bind)
case MYSQL_TYPE_MEDIUM_BLOB:
case MYSQL_TYPE_LONG_BLOB:
case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_VARCHAR:
case MYSQL_TYPE_VAR_STRING:
case MYSQL_TYPE_STRING:
param->skip_result= skip_result_string;
diff --git a/libmysql/libmysql.def b/libmysql/libmysql.def
index bc91e90a41c..c9ff70f208d 100644
--- a/libmysql/libmysql.def
+++ b/libmysql/libmysql.def
@@ -47,6 +47,7 @@ EXPORTS
mysql_errno
mysql_error
mysql_escape_string
+ mysql_hex_string
mysql_stmt_execute
mysql_stmt_fetch
mysql_stmt_fetch_column
diff --git a/libmysqld/Makefile.am b/libmysqld/Makefile.am
index 56762f5771e..aaf1bb54ecc 100644
--- a/libmysqld/Makefile.am
+++ b/libmysqld/Makefile.am
@@ -26,7 +26,7 @@ DEFS = -DEMBEDDED_LIBRARY -DMYSQL_SERVER \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\""
INCLUDES= @MT_INCLUDES@ @bdb_includes@ -I$(top_srcdir)/include \
- -I$(top_srcdir)/sql -I$(top_srcdir)/regex \
+ -I$(top_srcdir)/sql -I$(top_srcdir)/sql/examples -I$(top_srcdir)/regex \
$(openssl_includes) @ZLIB_INCLUDES@
noinst_LIBRARIES = libmysqld_int.a
@@ -35,11 +35,12 @@ SUBDIRS = . examples
libmysqld_sources= libmysqld.c lib_sql.cc emb_qcache.cc
libmysqlsources = errmsg.c get_password.c libmysql.c client.c pack.c \
my_time.c
+sqlexamplessources = ha_example.cc ha_archive.cc ha_tina.cc
noinst_HEADERS = embedded_priv.h emb_qcache.h
sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
- ha_innodb.cc ha_berkeley.cc ha_heap.cc ha_isam.cc ha_isammrg.cc \
+ ha_innodb.cc ha_berkeley.cc ha_heap.cc \
ha_myisam.cc ha_myisammrg.cc handler.cc sql_handler.cc \
hostname.cc init.cc password.c \
item.cc item_buff.cc item_cmpfunc.cc item_create.cc \
@@ -61,7 +62,7 @@ sqlsources = derror.cc field.cc field_conv.cc strfunc.cc filesort.cc \
sp_head.cc sp_pcontext.cc sp.cc sp_cache.cc sp_rcontext.cc \
parse_file.cc sql_view.cc sql_trigger.cc
-libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources)
+libmysqld_int_a_SOURCES= $(libmysqld_sources) $(libmysqlsources) $(sqlsources) $(sqlexamplessources)
libmysqld_a_SOURCES=
# automake misses these
@@ -125,12 +126,16 @@ link_sources:
rm -f $(srcdir)/$$f; \
@LN_CP_F@ $(srcdir)/../libmysql/$$f $(srcdir)/$$f; \
done; \
+ for f in $(sqlexamplessources); do \
+ rm -f $(srcdir)/$$f; \
+ @LN_CP_F@ $(srcdir)/../sql/examples/$$f $(srcdir)/$$f; \
+ done; \
rm -f $(srcdir)/client_settings.h; \
@LN_CP_F@ $(srcdir)/../libmysql/client_settings.h $(srcdir)/client_settings.h;
clean-local:
- rm -f `echo $(sqlsources) $(libmysqlsources) | sed "s;\.lo;.c;g"` \
+ rm -f `echo $(sqlsources) $(libmysqlsources) $(sqlexamplessources) | sed "s;\.lo;.c;g"` \
$(top_srcdir)/linked_libmysqld_sources; \
rm -f client_settings.h
diff --git a/libmysqld/lib_sql.cc b/libmysqld/lib_sql.cc
index 9fba0327525..15f07667625 100644
--- a/libmysqld/lib_sql.cc
+++ b/libmysqld/lib_sql.cc
@@ -664,7 +664,7 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
DBUG_RETURN(prepare_for_send(list));
err:
- send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */
+ my_error(ER_OUT_OF_RESOURCES, MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
diff --git a/myisam/ft_boolean_search.c b/myisam/ft_boolean_search.c
index 196cb5c21fb..c432ac5a16c 100644
--- a/myisam/ft_boolean_search.c
+++ b/myisam/ft_boolean_search.c
@@ -164,9 +164,9 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
if (param.trunc) ftbw->flags|=FTB_FLAG_TRUNC;
ftbw->weight=weight;
ftbw->up=up;
- ftbw->docid[0]=ftbw->docid[1]=HA_POS_ERROR;
+ ftbw->docid[0]=ftbw->docid[1]=HA_OFFSET_ERROR;
ftbw->ndepth= (param.yesno<0) + depth;
- ftbw->key_root=HA_POS_ERROR;
+ ftbw->key_root=HA_OFFSET_ERROR;
memcpy(ftbw->word+1, w.pos, w.len);
ftbw->word[0]=w.len;
if (param.yesno > 0) up->ythresh++;
@@ -181,7 +181,7 @@ static void _ftb_parse_query(FTB *ftb, byte **start, byte *end,
ftbe->weight=weight;
ftbe->up=up;
ftbe->ythresh=ftbe->yweaks=0;
- ftbe->docid[0]=ftbe->docid[1]=HA_POS_ERROR;
+ ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR;
if ((ftbe->quot=param.quot)) ftb->with_scan|=2;
if (param.yesno > 0) up->ythresh++;
_ftb_parse_query(ftb, start, end, ftbe, depth+1);
@@ -259,7 +259,7 @@ static int _ft2_search(FTB *ftb, FTB_WORD *ftbw, my_bool init_search)
{
if (!ftbw->off || !(ftbw->flags & FTB_FLAG_TRUNC))
{
- ftbw->docid[0]=HA_POS_ERROR;
+ ftbw->docid[0]=HA_OFFSET_ERROR;
if ((ftbw->flags & FTB_FLAG_YES) && ftbw->up->up==0)
{
/*
@@ -346,9 +346,9 @@ static void _ftb_init_index_search(FT_INFO *ftb)
ftbe->up->ythresh - ftbe->up->yweaks >1) /* 1 */
{
FTB_EXPR *top_ftbe=ftbe->up->up;
- ftbw->docid[0]=HA_POS_ERROR;
+ ftbw->docid[0]=HA_OFFSET_ERROR;
for (ftbe=ftbw->up; ftbe != top_ftbe; ftbe=ftbe->up)
- if (ftbe->flags & FTB_FLAG_YES)
+ if (!(ftbe->flags & FTB_FLAG_NO))
ftbe->yweaks++;
ftbe=0;
break;
@@ -356,7 +356,7 @@ static void _ftb_init_index_search(FT_INFO *ftb)
}
if (!ftbe)
continue;
- /* 3 */
+ /* 4 */
if (!is_tree_inited(& ftb->no_dupes))
init_tree(& ftb->no_dupes,0,0,sizeof(my_off_t),
_ftb_no_dupes_cmp,0,0,0);
@@ -387,7 +387,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
ftb->charset= ((keynr==NO_SUCH_KEY) ?
default_charset_info : info->s->keyinfo[keynr].seg->charset);
ftb->with_scan=0;
- ftb->lastpos=HA_POS_ERROR;
+ ftb->lastpos=HA_OFFSET_ERROR;
bzero(& ftb->no_dupes, sizeof(TREE));
init_alloc_root(&ftb->mem_root, 1024, 1024);
@@ -410,7 +410,7 @@ FT_INFO * ft_init_boolean_search(MI_INFO *info, uint keynr, byte *query,
ftbe->quot=0;
ftbe->up=0;
ftbe->ythresh=ftbe->yweaks=0;
- ftbe->docid[0]=ftbe->docid[1]=HA_POS_ERROR;
+ ftbe->docid[0]=ftbe->docid[1]=HA_OFFSET_ERROR;
ftb->root=ftbe;
_ftb_parse_query(ftb, &query, query+query_len, ftbe, 0);
ftb->list=(FTB_WORD **)alloc_root(&ftb->mem_root,
@@ -561,7 +561,7 @@ int ft_boolean_read_next(FT_INFO *ftb, char *record)
while (ftb->state == INDEX_SEARCH &&
(curdoc=((FTB_WORD *)queue_top(& ftb->queue))->docid[0]) !=
- HA_POS_ERROR)
+ HA_OFFSET_ERROR)
{
while (curdoc == (ftbw=(FTB_WORD *)queue_top(& ftb->queue))->docid[0])
{
@@ -615,7 +615,7 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
const byte *end;
my_off_t docid=ftb->info->lastpos;
- if (docid == HA_POS_ERROR)
+ if (docid == HA_OFFSET_ERROR)
return -2.0;
if (!ftb->queue.elements)
return 0;
@@ -627,9 +627,9 @@ float ft_boolean_find_relevance(FT_INFO *ftb, byte *record, uint length)
for (i=0; i < ftb->queue.elements; i++)
{
- ftb->list[i]->docid[1]=HA_POS_ERROR;
+ ftb->list[i]->docid[1]=HA_OFFSET_ERROR;
for (x=ftb->list[i]->up; x; x=x->up)
- x->docid[1]=HA_POS_ERROR;
+ x->docid[1]=HA_OFFSET_ERROR;
}
}
diff --git a/myisam/ft_static.c b/myisam/ft_static.c
index 7168406d027..3b186f7b179 100644
--- a/myisam/ft_static.c
+++ b/myisam/ft_static.c
@@ -28,7 +28,7 @@ const HA_KEYSEG ft_keysegs[FT_SEGS]={
HA_KEYTYPE_VARTEXT, /* type */
63, /* language (will be overwritten) */
0, 0, 0, /* null_bit, bit_start, bit_end */
- HA_VAR_LENGTH | HA_PACK_KEY, /* flag */
+ HA_VAR_LENGTH_PART | HA_PACK_KEY, /* flag */
HA_FT_MAXBYTELEN, /* length */
HA_FT_WLEN, /* start */
0, /* null_pos */
diff --git a/myisam/ft_test1.c b/myisam/ft_test1.c
index f4884f8ca39..a92c85924de 100644
--- a/myisam/ft_test1.c
+++ b/myisam/ft_test1.c
@@ -91,7 +91,7 @@ static int run_test(const char *filename)
keyinfo[0].keysegs=1;
keyinfo[0].seg[0].type= key_type;
keyinfo[0].seg[0].flag= (key_field == FIELD_BLOB)?HA_BLOB_PART:
- (key_field == FIELD_VARCHAR)?HA_VAR_LENGTH:0;
+ (key_field == FIELD_VARCHAR)?HA_VAR_LENGTH_PART:0;
keyinfo[0].seg[0].start=recinfo[0].length;
keyinfo[0].seg[0].length=key_length;
keyinfo[0].seg[0].null_bit= 0;
diff --git a/myisam/ft_update.c b/myisam/ft_update.c
index beccc062270..8dafefe77a8 100644
--- a/myisam/ft_update.c
+++ b/myisam/ft_update.c
@@ -77,7 +77,7 @@ uint _mi_ft_segiterator(register FT_SEG_ITERATOR *ftsi)
DBUG_RETURN(1);
}
ftsi->pos= ftsi->rec+ftsi->seg->start;
- if (ftsi->seg->flag & HA_VAR_LENGTH)
+ if (ftsi->seg->flag & HA_VAR_LENGTH_PART)
{
ftsi->len=uint2korr(ftsi->pos);
ftsi->pos+=2; /* Skip VARCHAR length */
diff --git a/myisam/mi_check.c b/myisam/mi_check.c
index 4da388af1c7..112a371c9fe 100644
--- a/myisam/mi_check.c
+++ b/myisam/mi_check.c
@@ -656,6 +656,15 @@ static int chk_index(MI_CHECK *param, MI_INFO *info, MI_KEYDEF *keyinfo,
if (chk_index_down(param,info,&info->s->ft2_keyinfo,record,
temp_buff,&tmp_keys,key_checksum,1))
goto err;
+ if (tmp_keys + subkeys)
+ {
+ mi_check_print_error(param,
+ "Number of words in the 2nd level tree "
+ "does not match the number in the header. "
+ "Parent word in on the page %s, offset %u",
+ llstr(page,llbuff), (uint) (old_keypos-buff));
+ goto err;
+ }
(*keys)+=tmp_keys-1;
continue;
}
@@ -2024,7 +2033,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
sort_param.key_length+=keyseg[i].length;
if (keyseg[i].flag & HA_SPACE_PACK)
sort_param.key_length+=get_pack_length(keyseg[i].length);
- if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg[i].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
sort_param.key_length+=2 + test(keyseg[i].length >= 127);
if (keyseg[i].flag & HA_NULL_PART)
sort_param.key_length++;
@@ -2037,7 +2046,7 @@ int mi_repair_by_sort(MI_CHECK *param, register MI_INFO *info,
uint ft_max_word_len_for_sort=FT_MAX_WORD_LEN_FOR_SORT*
sort_param.keyinfo->seg->charset->mbmaxlen;
sort_info.max_records=
- (ha_rows) (sort_info.filelength/ft_max_word_len_for_sort+1);
+ (ha_rows) (sort_info.filelength/ft_min_word_len+1);
sort_param.key_read=sort_ft_key_read;
sort_param.key_write=sort_ft_key_write;
@@ -2433,7 +2442,7 @@ int mi_repair_parallel(MI_CHECK *param, register MI_INFO *info,
sort_param[i].key_length+=keyseg->length;
if (keyseg->flag & HA_SPACE_PACK)
sort_param[i].key_length+=get_pack_length(keyseg->length);
- if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg->flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
sort_param[i].key_length+=2 + test(keyseg->length >= 127);
if (keyseg->flag & HA_NULL_PART)
sort_param[i].key_length++;
diff --git a/myisam/mi_create.c b/myisam/mi_create.c
index 7fc7cc4edf1..e139997e0c7 100644
--- a/myisam/mi_create.c
+++ b/myisam/mi_create.c
@@ -16,7 +16,7 @@
/* Create a MyISAM table */
-#include "fulltext.h"
+#include "ftdefs.h"
#include "sp_defs.h"
#if defined(MSDOS) || defined(__WIN__)
@@ -41,7 +41,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
File dfile,file;
int errpos,save_errno;
myf create_flag;
- uint fields,length,max_key_length,packed,pointer,
+ uint fields,length,max_key_length,packed,pointer,real_length_diff,
key_length,info_length,key_segs,options,min_key_length_skip,
base_pos,varchar_count,long_varchar_count,varchar_length,
max_key_block_length,unique_key_parts,fulltext_keys,offset;
@@ -238,7 +238,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
{
share.state.key_root[i]= HA_OFFSET_ERROR;
- min_key_length_skip=length=0;
+ min_key_length_skip=length=real_length_diff=0;
key_length=pointer;
if (keydef->flag & HA_SPATIAL)
{
@@ -276,8 +276,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
goto err;
#endif /*HAVE_SPATIAL*/
}
- else
- if (keydef->flag & HA_FULLTEXT)
+ else if (keydef->flag & HA_FULLTEXT)
{
keydef->flag=HA_FULLTEXT | HA_PACK_KEY | HA_VAR_LENGTH_KEY;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
@@ -297,6 +296,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_length+= HA_FT_MAXBYTELEN+HA_FT_WLEN;
length++; /* At least one length byte */
min_key_length_skip+=HA_FT_MAXBYTELEN;
+ real_length_diff=HA_FT_MAXBYTELEN-FT_MAX_WORD_LEN_FOR_SORT;
}
else
{
@@ -310,7 +310,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
/* Only use HA_PACK_KEY when first segment is a variable length key */
if (!(keydef->seg[0].flag & (HA_SPACE_PACK | HA_BLOB_PART |
- HA_VAR_LENGTH)))
+ HA_VAR_LENGTH_PART)))
{
/* pack relative to previous key */
keydef->flag&= ~HA_PACK_KEY;
@@ -344,12 +344,18 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
case HA_KEYTYPE_UINT24:
case HA_KEYTYPE_INT8:
keyseg->flag|= HA_SWAP_KEY;
- /* fall through */
+ break;
+ case HA_KEYTYPE_VARTEXT:
+ case HA_KEYTYPE_VARBINARY:
+ if (!(keyseg->flag & HA_BLOB_PART))
+ keyseg->flag|= HA_VAR_LENGTH_PART;
+ break;
default:
break;
}
if (keyseg->flag & HA_SPACE_PACK)
{
+ DBUG_ASSERT(!(keyseg->flag & HA_VAR_LENGTH_PART));
keydef->flag |= HA_SPACE_PACK_USED | HA_VAR_LENGTH_KEY;
options|=HA_OPTION_PACK_KEYS; /* Using packed keys */
length++; /* At least one length byte */
@@ -360,7 +366,7 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
length+=2;
}
}
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
keydef->flag|=HA_VAR_LENGTH_KEY;
length++; /* At least one length byte */
@@ -397,7 +403,8 @@ int mi_create(const char *name,uint keys,MI_KEYDEF *keydefs,
key_segs)
share.state.rec_per_key_part[key_segs-1]=1L;
length+=key_length;
- keydef->block_length= MI_BLOCK_SIZE(length,pointer,MI_MAX_KEYPTR_SIZE);
+ keydef->block_length= MI_BLOCK_SIZE(length-real_length_diff,
+ pointer,MI_MAX_KEYPTR_SIZE);
if (keydef->block_length > MI_MAX_KEY_BLOCK_LENGTH ||
length >= MI_MAX_KEY_BUFF)
{
diff --git a/myisam/mi_key.c b/myisam/mi_key.c
index 3545756779f..a775e0ba2d0 100644
--- a/myisam/mi_key.c
+++ b/myisam/mi_key.c
@@ -102,7 +102,7 @@ uint _mi_make_key(register MI_INFO *info, uint keynr, uchar *key,
key+=char_length;
continue;
}
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint tmp_length=uint2korr(pos);
pos+=2; /* Skip VARCHAR length */
@@ -216,7 +216,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
if (!(*key++= (char) 1-*old++)) /* Copy null marker */
{
k_length-=length;
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
k_length-=2; /* Skip length */
continue; /* Found NULL */
}
@@ -244,7 +244,7 @@ uint _mi_pack_key(register MI_INFO *info, uint keynr, uchar *key, uchar *old,
key+= char_length;
continue;
}
- else if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART))
+ else if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART))
{
/* Length of key-part used with mi_rkey() always 2 */
uint tmp_length=uint2korr(pos);
@@ -356,7 +356,7 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
continue;
}
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint length;
get_key_length(length,key);
@@ -364,7 +364,10 @@ static int _mi_put_key_in_record(register MI_INFO *info, uint keynr,
if (length > keyseg->length || key+length > key_end)
goto err;
#endif
- memcpy(record+keyseg->start,(byte*) key, length);
+ /* Store key length */
+ int2store(record+keyseg->start, length);
+ /* And key data */
+ memcpy(record+keyseg->start+2,(byte*) key, length);
key+= length;
}
else if (keyseg->flag & HA_BLOB_PART)
diff --git a/myisam/mi_packrec.c b/myisam/mi_packrec.c
index 94eb2de17e2..a277c2ca9d1 100644
--- a/myisam/mi_packrec.c
+++ b/myisam/mi_packrec.c
@@ -42,8 +42,9 @@
{ bits-=(bit+1); break; } \
pos+= *pos
+#define OFFSET_TABLE_SIZE 512
-static void read_huff_table(MI_BIT_BUFF *bit_buff,MI_DECODE_TREE *decode_tree,
+static uint read_huff_table(MI_BIT_BUFF *bit_buff,MI_DECODE_TREE *decode_tree,
uint16 **decode_table,byte **intervall_buff,
uint16 *tmp_buff);
static void make_quick_table(uint16 *to_table,uint16 *decode_table,
@@ -53,7 +54,7 @@ static void fill_quick_table(uint16 *table,uint bits, uint max_bits,
uint value);
static uint copy_decode_table(uint16 *to_pos,uint offset,
uint16 *decode_table);
-static uint find_longest_bitstream(uint16 *table);
+static uint find_longest_bitstream(uint16 *table, uint16 *end);
static void (*get_unpack_function(MI_COLUMNDEF *rec))(MI_COLUMNDEF *field,
MI_BIT_BUFF *buff,
uchar *to,
@@ -146,12 +147,12 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
{
if (!my_errno)
my_errno=HA_ERR_END_OF_FILE;
- DBUG_RETURN(1);
+ goto err0;
}
if (memcmp((byte*) header,(byte*) myisam_pack_file_magic,4))
{
my_errno=HA_ERR_WRONG_IN_RECORD;
- DBUG_RETURN(1);
+ goto err0;
}
share->pack.header_length= uint4korr(header+4);
share->min_pack_length=(uint) uint4korr(header+8);
@@ -173,20 +174,20 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
my_malloc((uint) (trees*sizeof(MI_DECODE_TREE)+
intervall_length*sizeof(byte)),
MYF(MY_WME))))
- DBUG_RETURN(1);
+ goto err0;
intervall_buff=(byte*) (share->decode_trees+trees);
length=(uint) (elements*2+trees*(1 << myisam_quick_table_bits));
if (!(share->decode_tables=(uint16*)
- my_malloc((length+512)*sizeof(uint16)+
+ my_malloc((length+OFFSET_TABLE_SIZE)*sizeof(uint16)+
(uint) (share->pack.header_length+7),
MYF(MY_WME | MY_ZEROFILL))))
{
my_free((gptr) share->decode_trees,MYF(0));
- DBUG_RETURN(1);
+ goto err1;
}
tmp_buff=share->decode_tables+length;
- disk_cache=(byte*) (tmp_buff+512);
+ disk_cache=(byte*) (tmp_buff+OFFSET_TABLE_SIZE);
if (my_read(file,disk_cache,
(uint) (share->pack.header_length-sizeof(header)),
@@ -194,7 +195,7 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
{
my_free((gptr) share->decode_trees,MYF(0));
my_free((gptr) share->decode_tables,MYF(0));
- DBUG_RETURN(1);
+ goto err2;
}
huff_tree_bits=max_bit(trees ? trees-1 : 0);
@@ -213,8 +214,9 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
skip_to_next_byte(&bit_buff);
decode_table=share->decode_tables;
for (i=0 ; i < trees ; i++)
- read_huff_table(&bit_buff,share->decode_trees+i,&decode_table,
- &intervall_buff,tmp_buff);
+ if (read_huff_table(&bit_buff,share->decode_trees+i,&decode_table,
+ &intervall_buff,tmp_buff))
+ goto err3;
decode_table=(uint16*)
my_realloc((gptr) share->decode_tables,
(uint) ((byte*) decode_table - (byte*) share->decode_tables),
@@ -224,8 +226,7 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
share->decode_tables=decode_table;
for (i=0 ; i < trees ; i++)
share->decode_trees[i].table=ADD_TO_PTR(share->decode_trees[i].table,
- diff,
- uint16*);
+ diff, uint16*);
}
/* Fix record-ref-length for keys */
@@ -242,19 +243,24 @@ my_bool _mi_read_pack_info(MI_INFO *info, pbool fix_keys)
}
if (bit_buff.error || bit_buff.pos < bit_buff.end)
- { /* info_length was wrong */
- my_errno=HA_ERR_WRONG_IN_RECORD;
- my_free((gptr) share->decode_trees,MYF(0));
- my_free((gptr) share->decode_tables,MYF(0));
- DBUG_RETURN(1);
- }
+ goto err3;
+
DBUG_RETURN(0);
+
+err3:
+ my_errno=HA_ERR_WRONG_IN_RECORD;
+err2:
+ my_free((gptr) share->decode_tables,MYF(0));
+err1:
+ my_free((gptr) share->decode_trees,MYF(0));
+err0:
+ DBUG_RETURN(1);
}
/* Read on huff-code-table from datafile */
-static void read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree,
+static uint read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree,
uint16 **decode_table, byte **intervall_buff,
uint16 *tmp_buff)
{
@@ -297,7 +303,9 @@ static void read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree,
decode_tree->intervalls= *intervall_buff;
if (! intervall_length)
{
- table_bits=find_longest_bitstream(tmp_buff);
+ table_bits=find_longest_bitstream(tmp_buff, tmp_buff+OFFSET_TABLE_SIZE);
+ if (table_bits == (uint) ~0)
+ return 1;
if (table_bits > myisam_quick_table_bits)
table_bits=myisam_quick_table_bits;
next_free_offset= (1 << table_bits);
@@ -315,7 +323,7 @@ static void read_huff_table(MI_BIT_BUFF *bit_buff, MI_DECODE_TREE *decode_tree,
bit_buff->pos+=intervall_length;
bit_buff->bits=0;
}
- return;
+ return 0;
}
@@ -390,15 +398,23 @@ static uint copy_decode_table(uint16 *to_pos, uint offset,
}
-static uint find_longest_bitstream(uint16 *table)
+static uint find_longest_bitstream(uint16 *table, uint16 *end)
{
uint length=1,length2;
if (!(*table & IS_CHAR))
- length=find_longest_bitstream(table+ *table)+1;
+ {
+ uint16 *next= table + *table;
+ if (next > end || next == table)
+ return ~0;
+ length=find_longest_bitstream(next, end)+1;
+ }
table++;
if (!(*table & IS_CHAR))
{
- length2=find_longest_bitstream(table+ *table)+1;
+ uint16 *next= table + *table;
+ if (next > end || next == table)
+ return ~0;
+ length2=find_longest_bitstream(table+ *table, end)+1;
length=max(length,length2);
}
return length;
diff --git a/myisam/mi_range.c b/myisam/mi_range.c
index 1e0fd42334e..789607c9889 100644
--- a/myisam/mi_range.c
+++ b/myisam/mi_range.c
@@ -172,9 +172,9 @@ static double _mi_search_pos(register MI_INFO *info,
if (flag == MI_FOUND_WRONG_KEY)
DBUG_RETURN(-1); /* error */
/*
- ** Didn't found match. keypos points at next (bigger) key
- * Try to find a smaller, better matching key.
- ** Matches keynr + [0-1]
+ Didn't found match. keypos points at next (bigger) key
+ Try to find a smaller, better matching key.
+ Matches keynr + [0-1]
*/
if (flag > 0 && ! nod_flag)
offset= 1.0;
@@ -185,8 +185,8 @@ static double _mi_search_pos(register MI_INFO *info,
else
{
/*
- ** Found match. Keypos points at the start of the found key
- ** Matches keynr+1
+ Found match. Keypos points at the start of the found key
+ Matches keynr+1
*/
offset=1.0; /* Matches keynr+1 */
if ((nextflag & SEARCH_FIND) && nod_flag &&
@@ -194,8 +194,8 @@ static double _mi_search_pos(register MI_INFO *info,
key_len != USE_WHOLE_KEY))
{
/*
- ** There may be identical keys in the tree. Try to match on of those.
- ** Matches keynr + [0-1]
+ There may be identical keys in the tree. Try to match on of those.
+ Matches keynr + [0-1]
*/
if ((offset=_mi_search_pos(info,keyinfo,key,key_len,SEARCH_FIND,
_mi_kpos(nod_flag,keypos))) < 0)
diff --git a/myisam/mi_rnext_same.c b/myisam/mi_rnext_same.c
index 1342718d6aa..3060a55038a 100644
--- a/myisam/mi_rnext_same.c
+++ b/myisam/mi_rnext_same.c
@@ -57,7 +57,11 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
#endif
case HA_KEY_ALG_BTREE:
default:
- memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
+ if (!(info->update & HA_STATE_RNEXT_SAME))
+ {
+ /* First rnext_same; Store old key */
+ memcpy(info->lastkey2,info->lastkey,info->last_rkey_length);
+ }
for (;;)
{
if ((error=_mi_search_next(info,keyinfo,info->lastkey,
@@ -81,7 +85,7 @@ int mi_rnext_same(MI_INFO *info, byte *buf)
rw_unlock(&info->s->key_root_lock[inx]);
/* Don't clear if database-changed */
info->update&= (HA_STATE_CHANGED | HA_STATE_ROW_CHANGED);
- info->update|= HA_STATE_NEXT_FOUND;
+ info->update|= HA_STATE_NEXT_FOUND | HA_STATE_RNEXT_SAME;
if (error)
{
diff --git a/myisam/mi_search.c b/myisam/mi_search.c
index bc8be9c2732..2fef70db9f0 100644
--- a/myisam/mi_search.c
+++ b/myisam/mi_search.c
@@ -364,7 +364,7 @@ int _mi_prefix_search(MI_INFO *info, register MI_KEYDEF *keyinfo, uchar *page,
if (!(*from++))
continue;
}
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
get_key_length(l,from);
}
@@ -831,7 +831,7 @@ uint _mi_get_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
continue;
}
if (keyseg->flag &
- (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
uchar *tmp=page;
get_key_length(length,tmp);
@@ -896,7 +896,7 @@ uint _mi_get_binary_pack_key(register MI_KEYDEF *keyinfo, uint nod_flag,
if (!(*key++ = *from++))
continue; /* Null part */
}
- if (keyseg->flag & (HA_VAR_LENGTH | HA_BLOB_PART | HA_SPACE_PACK))
+ if (keyseg->flag & (HA_VAR_LENGTH_PART | HA_BLOB_PART | HA_SPACE_PACK))
{
/* Get length of dynamic length key part */
if (from == from_end) { from=page; from_end=page_end; }
@@ -1071,7 +1071,7 @@ uint _mi_keylength(MI_KEYDEF *keyinfo, register uchar *key)
if (keyseg->flag & HA_NULL_PART)
if (!*key++)
continue;
- if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint length;
get_key_length(length,key);
@@ -1103,7 +1103,7 @@ uint _mi_keylength_part(MI_KEYDEF *keyinfo, register uchar *key,
if (keyseg->flag & HA_NULL_PART)
if (!*key++)
continue;
- if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyseg->flag & (HA_SPACE_PACK | HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint length;
get_key_length(length,key);
diff --git a/myisam/mi_test1.c b/myisam/mi_test1.c
index 77c4d3dfbad..15ce7515ac2 100644
--- a/myisam/mi_test1.c
+++ b/myisam/mi_test1.c
@@ -134,7 +134,7 @@ static int run_test(const char *filename)
uniqueseg[1].flag|= HA_BLOB_PART;
}
else if (extra_field == FIELD_VARCHAR)
- uniqueseg[1].flag|= HA_VAR_LENGTH;
+ uniqueseg[1].flag|= HA_VAR_LENGTH_PART;
}
else
uniques=0;
@@ -372,7 +372,7 @@ static void create_key(char *key,uint rownr)
}
*key++=0;
}
- if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (keyinfo[0].seg[0].flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
uint tmp;
create_key_part(key+2,rownr);
@@ -524,7 +524,7 @@ static struct my_option my_long_options[] =
{"key_binary_pack", 'B', "Undocumented",
0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_blob", 'b', "Undocumented",
- 0, 0, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_cache", 'K', "Undocumented", (gptr*) &key_cacheing,
(gptr*) &key_cacheing, 0, GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0},
{"key_length", 'k', "Undocumented", (gptr*) &key_length, (gptr*) &key_length,
@@ -617,7 +617,7 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
key_field=FIELD_VARCHAR; /* varchar keys */
extra_field= FIELD_VARCHAR;
key_type= HA_KEYTYPE_VARTEXT;
- pack_seg|= HA_VAR_LENGTH;
+ pack_seg|= HA_VAR_LENGTH_PART;
create_flag|= HA_PACK_RECORD;
break;
case 'K': /* Use key cacheing */
diff --git a/myisam/mi_test3.c b/myisam/mi_test3.c
index dca04a9a64b..27d23317b5c 100644
--- a/myisam/mi_test3.c
+++ b/myisam/mi_test3.c
@@ -40,7 +40,7 @@
#endif
-const char *filename= "test3.MSI";
+const char *filename= "test3";
uint tests=10,forks=10,key_cacheing=0,use_log=0;
static void get_options(int argc, char *argv[]);
@@ -363,7 +363,7 @@ int test_write(MI_INFO *file,int id,int lock_type)
}
sprintf(record.id,"%7d",getpid());
- strmov(record.text,"Testing...");
+ strnmov(record.text,"Testing...", sizeof(record.text));
tries=(uint) rnd(100)+10;
for (i=count=0 ; i < tries ; i++)
diff --git a/myisam/mi_unique.c b/myisam/mi_unique.c
index ad685f4cbdc..c03182456df 100644
--- a/myisam/mi_unique.c
+++ b/myisam/mi_unique.c
@@ -93,7 +93,7 @@ ha_checksum mi_unique_hash(MI_UNIQUEDEF *def, const byte *record)
}
}
pos= record+keyseg->start;
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
uint tmp_length=uint2korr(pos);
pos+=2; /* Skip VARCHAR length */
@@ -136,7 +136,8 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
for (keyseg=def->seg ; keyseg < def->end ; keyseg++)
{
enum ha_base_keytype type=(enum ha_base_keytype) keyseg->type;
- uint length=keyseg->length;
+ uint a_length, b_length;
+ a_length= b_length= keyseg->length;
/* If part is NULL it's regarded as different */
if (keyseg->null_bit)
@@ -154,43 +155,49 @@ int mi_unique_comp(MI_UNIQUEDEF *def, const byte *a, const byte *b,
}
pos_a= a+keyseg->start;
pos_b= b+keyseg->start;
- if (keyseg->flag & HA_VAR_LENGTH)
+ if (keyseg->flag & HA_VAR_LENGTH_PART)
{
- uint tmp_length=uint2korr(pos_a);
- if (tmp_length != uint2korr(pos_b))
- return 1;
- pos_a+=2; /* Skip VARCHAR length */
- pos_b+=2;
- set_if_smaller(length,tmp_length);
+ a_length= uint2korr(pos_a);
+ b_length= uint2korr(pos_b);
+ pos_a+= 2; /* Skip VARCHAR length */
+ pos_b+= 2;
+ set_if_smaller(a_length, keyseg->length);
+ set_if_smaller(b_length, keyseg->length);
}
else if (keyseg->flag & HA_BLOB_PART)
{
- /* Only compare 'length' characters if length<> 0 */
- uint a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
- uint b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
+ /* Only compare 'length' characters if length != 0 */
+ a_length= _mi_calc_blob_length(keyseg->bit_start,pos_a);
+ b_length= _mi_calc_blob_length(keyseg->bit_start,pos_b);
/* Check that a and b are of equal length */
- if (length && a_length > length)
- a_length=length;
- if (!length || length > b_length)
- length=b_length;
- if (length != a_length)
- return 1;
- /* Both strings are at least 'length' long */
+ if (keyseg->length)
+ {
+ /*
+ This is used in some cases when we are not interested in comparing
+ the whole length of the blob.
+ */
+ set_if_smaller(a_length, keyseg->length);
+ set_if_smaller(b_length, keyseg->length);
+ }
memcpy_fixed((byte*) &pos_a,pos_a+keyseg->bit_start,sizeof(char*));
memcpy_fixed((byte*) &pos_b,pos_b+keyseg->bit_start,sizeof(char*));
}
if (type == HA_KEYTYPE_TEXT || type == HA_KEYTYPE_VARTEXT)
{
- if (mi_compare_text(keyseg->charset, (uchar *) pos_a, length,
- (uchar *) pos_b, length, 0, 0))
- return 1;
+ if (mi_compare_text(keyseg->charset, (uchar *) pos_a, a_length,
+ (uchar *) pos_b, b_length, 0, 1))
+ return 1;
}
else
{
- end= pos_a+length;
+ if (a_length != b_length)
+ return 1;
+ end= pos_a+a_length;
while (pos_a != end)
+ {
if (*pos_a++ != *pos_b++)
return 1;
+ }
}
}
return 0;
diff --git a/myisam/mi_write.c b/myisam/mi_write.c
index dc596672a84..c2f24ae1ae3 100644
--- a/myisam/mi_write.c
+++ b/myisam/mi_write.c
@@ -165,12 +165,7 @@ err:
{
uint j;
for (j=0 ; j < share->base.keys ; j++)
- {
- if (is_tree_inited(&info->bulk_insert[j]))
- {
- reset_tree(&info->bulk_insert[j]);
- }
- }
+ mi_flush_bulk_insert(info, j);
}
info->errkey= (int) i;
while ( i-- > 0)
@@ -253,7 +248,7 @@ int _mi_ck_write_btree(register MI_INFO *info, uint keynr, uchar *key,
comp_flag=SEARCH_BIGGER; /* Put after same key */
else if (keyinfo->flag & (HA_NOSAME|HA_FULLTEXT))
{
- comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No dupplicates */
+ comp_flag=SEARCH_FIND | SEARCH_UPDATE; /* No duplicates */
if (keyinfo->flag & HA_NULL_ARE_EQUAL)
comp_flag|= SEARCH_NULL_ARE_EQUAL;
}
@@ -329,7 +324,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
uchar *temp_buff,*keypos;
uchar keybuff[MI_MAX_KEY_BUFF];
my_bool was_last_key;
- my_off_t next_page;
+ my_off_t next_page, dupp_key_pos;
DBUG_ENTER("w_search");
DBUG_PRINT("enter",("page: %ld",page));
@@ -349,9 +344,9 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
/* get position to record with duplicated key */
tmp_key_length=(*keyinfo->get_key)(keyinfo,nod_flag,&keypos,keybuff);
if (tmp_key_length)
- info->dupp_key_pos=_mi_dpos(info,0,keybuff+tmp_key_length);
+ dupp_key_pos=_mi_dpos(info,0,keybuff+tmp_key_length);
else
- info->dupp_key_pos= HA_OFFSET_ERROR;
+ dupp_key_pos= HA_OFFSET_ERROR;
if (keyinfo->flag & HA_FULLTEXT)
{
uint off;
@@ -370,8 +365,9 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
else
{
/* popular word. two-level tree. going down */
- my_off_t root=info->dupp_key_pos;
+ my_off_t root=dupp_key_pos;
keyinfo=&info->s->ft2_keyinfo;
+ get_key_full_length_rdonly(off, key);
key+=off;
keypos-=keyinfo->keylength+nod_flag; /* we'll modify key entry 'in vivo' */
error=_mi_ck_real_write_btree(info, keyinfo, key, 0,
@@ -388,6 +384,7 @@ static int w_search(register MI_INFO *info, register MI_KEYDEF *keyinfo,
}
else /* not HA_FULLTEXT, normal HA_NOSAME key */
{
+ info->dupp_key_pos= dupp_key_pos;
my_afree((byte*) temp_buff);
my_errno=HA_ERR_FOUND_DUPP_KEY;
DBUG_RETURN(-1);
diff --git a/myisam/myisamchk.c b/myisam/myisamchk.c
index cad7be2e802..eeb1ccf528e 100644
--- a/myisam/myisamchk.c
+++ b/myisam/myisamchk.c
@@ -50,7 +50,7 @@ static int stopwords_inited= 0;
static MY_TMPDIR myisamchk_tmpdir;
static const char *type_names[]=
-{ "?","char","binary", "short", "long", "float",
+{ "impossible","char","binary", "short", "long", "float",
"double","number","unsigned short",
"unsigned long","longlong","ulonglong","int24",
"uint24","int8","varchar", "varbin","?",
@@ -354,8 +354,12 @@ static void usage(void)
puts("Description, check and repair of MyISAM tables.");
puts("Used without options all tables on the command will be checked for errors");
printf("Usage: %s [OPTIONS] tables[.MYI]\n", my_progname_short);
- printf("\nGlobal options:\n\
- -#, --debug=... Output debug log. Often this is 'd:t:o,filename'.\n\
+ printf("\nGlobal options:\n");
+#ifndef DBUG_OFF
+ printf("\
+ -#, --debug=... Output debug log. Often this is 'd:t:o,filename'.\n");
+#endif
+ printf("\
-?, --help Display this help and exit.\n\
-O, --set-variable var=option.\n\
Change the value of a variable. Please note that\n\
diff --git a/myisam/myisampack.c b/myisam/myisampack.c
index eae75b07760..cc520847f70 100644
--- a/myisam/myisampack.c
+++ b/myisam/myisampack.c
@@ -747,7 +747,8 @@ static int get_statistic(PACK_MRG_INFO *mrg,HUFF_COUNTS *huff_counts)
static_row_size=1;
for (count=huff_counts ; count < end_count ; count++)
{
- if (count->field_type == FIELD_BLOB || count->field_type == FIELD_VARCHAR)
+ if (count->field_type == FIELD_BLOB ||
+ count->field_type == FIELD_VARCHAR)
{
static_row_size=0;
break;
diff --git a/mysql-test/Makefile.am b/mysql-test/Makefile.am
index c3f9eea875d..c4b3fae40f9 100644
--- a/mysql-test/Makefile.am
+++ b/mysql-test/Makefile.am
@@ -36,12 +36,19 @@ test_SCRIPTS = mysql-test-run install_test_db
test_DATA = std_data/client-key.pem std_data/client-cert.pem std_data/cacert.pem
CLEANFILES = $(test_SCRIPTS) $(test_DATA)
+INCLUDES = -I$(srcdir)/../include -I../include -I..
+EXTRA_PROGRAMS = mysql_test_run_new
+noinst_HEADERS = my_manage.h
+mysql_test_run_new_SOURCES= mysql_test_run_new.c my_manage.c
+
+
dist-hook:
mkdir -p $(distdir)/t $(distdir)/r $(distdir)/include \
$(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/t/*.test $(srcdir)/t/*.opt $(srcdir)/t/*.sh $(srcdir)/t/*.slave-mi $(distdir)/t
$(INSTALL_DATA) $(srcdir)/include/*.inc $(distdir)/include
$(INSTALL_DATA) $(srcdir)/r/*.result $(srcdir)/r/*.require $(distdir)/r
+ $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(srcdir)/std_data/*.000001 $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(distdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.pem $(distdir)/std_data
@@ -64,6 +71,7 @@ install-data-local:
$(INSTALL_DATA) $(srcdir)/std_data/*.dat $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.*001 $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/des_key_file $(DESTDIR)$(testdir)/std_data
+ $(INSTALL_DATA) $(srcdir)/std_data/Moscow_leap $(DESTDIR)$(testdir)/std_data
$(INSTALL_DATA) $(srcdir)/std_data/*.pem $(DESTDIR)$(testdir)/std_data
std_data/%.pem:
diff --git a/mysql-test/include/ctype_common.inc b/mysql-test/include/ctype_common.inc
new file mode 100644
index 00000000000..77937bdb854
--- /dev/null
+++ b/mysql-test/include/ctype_common.inc
@@ -0,0 +1,56 @@
+#
+# Common tests for all character sets and collations.
+# Include this file from a test with @test_characrer_set
+# and @test_collation set to desired values.
+#
+# Please don't use SHOW CREATE TABLE in this file,
+# we want it to be HANDLER independent. You can
+# use SHOW FULL COLUMNS instead.
+#
+# Please surround all CREATE TABLE with --disable_warnings
+# and --enable_warnings to be able to set storage_engine
+# without having to check if the hanlder exists.
+
+SET @safe_character_set_server= @@character_set_server;
+SET @safe_collation_server= @@collation_server;
+SET character_set_server= @test_character_set;
+SET collation_server= @test_collation;
+CREATE DATABASE d1;
+USE d1;
+
+#
+# Bug 1883: LIKE did not work in some cases with a key.
+#
+--disable_warnings
+CREATE TABLE t1 (c CHAR(10), KEY(c));
+--enable_warnings
+# check the column was created with the expected charset/collation
+SHOW FULL COLUMNS FROM t1;
+INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa');
+SELECT c as want3results FROM t1 WHERE c LIKE 'aaa%';
+DROP TABLE t1;
+
+#
+# Bug 6643 incorrect response with partial utf8 index
+#
+--disable_warnings
+CREATE TABLE t1 (c1 varchar(15), KEY c1 (c1(2)));
+--enable_warnings
+# check the column was created with the expected charset/collation
+SHOW FULL COLUMNS FROM t1;
+INSERT INTO t1 VALUES ('location'),('loberge'),('lotre'),('boabab');
+SELECT c1 as want3results from t1 where c1 like 'l%';
+SELECT c1 as want3results from t1 where c1 like 'lo%';
+SELECT c1 as want1result from t1 where c1 like 'loc%';
+SELECT c1 as want1result from t1 where c1 like 'loca%';
+SELECT c1 as want1result from t1 where c1 like 'locat%';
+SELECT c1 as want1result from t1 where c1 like 'locati%';
+SELECT c1 as want1result from t1 where c1 like 'locatio%';
+SELECT c1 as want1result from t1 where c1 like 'location%';
+DROP TABLE t1;
+
+DROP DATABASE d1;
+# Restore settings
+USE test;
+SET character_set_server= @safe_character_set_server;
+SET collation_server= @safe_collation_server;
diff --git a/mysql-test/include/endspace.inc b/mysql-test/include/endspace.inc
new file mode 100644
index 00000000000..1692a258bde
--- /dev/null
+++ b/mysql-test/include/endspace.inc
@@ -0,0 +1,7 @@
+select 'a' = 'a', 'a' = 'a ', 'a ' = 'a';
+select 'a\0' = 'a', 'a\0' < 'a', 'a\0' > 'a';
+select 'a' = 'a\0', 'a' < 'a\0', 'a' > 'a\0';
+select 'a\0' = 'a ', 'a\0' < 'a ', 'a\0' > 'a ';
+select 'a ' = 'a\0', 'a ' < 'a\0', 'a ' > 'a\0';
+select 'a a' > 'a', 'a \0' < 'a';
+select binary 'a a' > 'a', binary 'a \0' > 'a', binary 'a\0' > 'a';
diff --git a/mysql-test/include/ps_modify.inc b/mysql-test/include/ps_modify.inc
index 372fc12b722..04b9734240b 100644
--- a/mysql-test/include/ps_modify.inc
+++ b/mysql-test/include/ps_modify.inc
@@ -321,8 +321,11 @@ select a,b from t1 where a >= 1000 order by a ;
delete from t1 where a >= 1000 ;
## replace
---error 1295
prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+execute stmt1;
+execute stmt1;
+execute stmt1;
+
## multi table statements
diff --git a/mysql-test/include/varchar.inc b/mysql-test/include/varchar.inc
new file mode 100644
index 00000000000..6c9b62065c5
--- /dev/null
+++ b/mysql-test/include/varchar.inc
@@ -0,0 +1,162 @@
+# Initialise
+--disable_warnings
+drop table if exists t1,t2,t3;
+--enable_warnings
+
+disable_query_log;
+select "--- Testing varchar ---";
+enable_query_log;
+
+#
+# Simple basic test that endspace is saved
+#
+
+create table t1 (v varchar(10), c char(10), t text);
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+select concat('*',v,'*',c,'*',t,'*') from t1;
+
+# Check how columns are copied
+show create table t1;
+create table t2 like t1;
+show create table t2;
+create table t3 select * from t1;
+show create table t3;
+alter table t1 modify c varchar(10);
+show create table t1;
+alter table t1 modify v char(10);
+show create table t1;
+alter table t1 modify t varchar(10);
+show create table t1;
+select concat('*',v,'*',c,'*',t,'*') from t1;
+drop table t1,t2,t3;
+
+#
+# Testing of keys
+#
+create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
+show create table t1;
+disable_query_log;
+let $1=10;
+while ($1)
+{
+ let $2=27;
+ eval set @space=repeat(' ',10-$1);
+ while ($2)
+ {
+ eval set @char=char(ascii('a')+$2-1);
+ insert into t1 values(concat(@char,@space),concat(@char,@space),concat(@char,@space));
+ dec $2;
+ }
+ dec $1;
+}
+enable_query_log;
+select count(*) from t1;
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+select count(*) from t1 where c='a';
+select count(*) from t1 where t='a';
+select count(*) from t1 where v='a ';
+select count(*) from t1 where c='a ';
+select count(*) from t1 where t='a ';
+select count(*) from t1 where v between 'a' and 'a ';
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+select count(*) from t1 where v like 'a%';
+select count(*) from t1 where c like 'a%';
+select count(*) from t1 where t like 'a%';
+select count(*) from t1 where v like 'a %';
+explain select count(*) from t1 where v='a ';
+explain select count(*) from t1 where c='a ';
+explain select count(*) from t1 where t='a ';
+explain select count(*) from t1 where v like 'a%';
+explain select count(*) from t1 where v between 'a' and 'a ';
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+
+--error 1062
+alter table t1 add unique(v);
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+explain select * from t1 where v='a';
+
+# GROUP BY
+
+select v,count(*) from t1 group by v limit 10;
+select v,count(t) from t1 group by v limit 10;
+select v,count(c) from t1 group by v limit 10;
+select sql_big_result v,count(t) from t1 group by v limit 10;
+select sql_big_result v,count(c) from t1 group by v limit 10;
+select c,count(*) from t1 group by c limit 10;
+select c,count(t) from t1 group by c limit 10;
+select sql_big_result c,count(t) from t1 group by c limit 10;
+select t,count(*) from t1 group by t limit 10;
+select t,count(t) from t1 group by t limit 10;
+select sql_big_result t,count(t) from t1 group by t limit 10;
+drop table t1;
+
+#
+# Test unique keys
+#
+
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+
+alter table t1 modify a varchar(10);
+--error 1062
+insert into t1 values ('a '),('a '),('a '),('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+update t1 set a='a ' where a like 'a%';
+select concat(a,'.') from t1;
+update t1 set a='abc ' where a like 'a ';
+select concat(a,'.') from t1;
+update t1 set a='a ' where a like 'a %';
+select concat(a,'.') from t1;
+update t1 set a='a ' where a like 'a ';
+select concat(a,'.') from t1;
+drop table t1;
+
+#
+# test show create table
+#
+
+create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+drop table t1;
+create table t1 (v char(10) character set utf8);
+show create table t1;
+drop table t1;
+
+create table t1 (v varchar(10), c char(10)) row_format=fixed;
+show create table t1;
+insert into t1 values('a','a'),('a ','a ');
+select concat('*',v,'*',c,'*') from t1;
+drop table t1;
+
+#
+# Test long varchars
+#
+
+create table t1 (v varchar(65530), key(v(10)));
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+drop table t1;
+
+#
+# Some errors/warnings on create
+#
+
+create table t1 (v varchar(65530), key(v));
+drop table if exists t1;
+create table t1 (v varchar(65536));
+show create table t1;
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+show create table t1;
+drop table t1;
diff --git a/mysql-test/init_db.sql b/mysql-test/init_db.sql
new file mode 100644
index 00000000000..63483af00d6
--- /dev/null
+++ b/mysql-test/init_db.sql
@@ -0,0 +1,58 @@
+CREATE DATABASE mysql;
+CREATE DATABASE test;
+
+USE mysql;
+
+
+CREATE TABLE db (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL,References_priv enum('N','Y') DEFAULT 'N' NOT NULL,Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,PRIMARY KEY Host (Host,Db,User),KEY User (User)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Database privileges';
+
+INSERT INTO db VALUES ('%','test','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');
+INSERT INTO db VALUES ('%','test\_%','','Y','Y','Y','Y','Y','Y','N','Y','Y','Y','Y','Y');
+
+
+CREATE TABLE host (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL,References_priv enum('N','Y') DEFAULT 'N' NOT NULL,Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,PRIMARY KEY Host (Host,Db)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Host privileges; Merged with database privileges';
+
+CREATE TABLE user (Host char(60) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Password char(41) binary DEFAULT '' NOT NULL,Select_priv enum('N','Y') DEFAULT 'N' NOT NULL,Insert_priv enum('N','Y') DEFAULT 'N' NOT NULL,Update_priv enum('N','Y') DEFAULT 'N' NOT NULL,Delete_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_priv enum('N','Y') DEFAULT 'N' NOT NULL,Drop_priv enum('N','Y') DEFAULT 'N' NOT NULL,Reload_priv enum('N','Y') DEFAULT 'N' NOT NULL,Shutdown_priv enum('N','Y') DEFAULT 'N' NOT NULL,Process_priv enum('N','Y') DEFAULT 'N' NOT NULL,File_priv enum('N','Y') DEFAULT 'N' NOT NULL,Grant_priv enum('N','Y') DEFAULT 'N' NOT NULL,References_priv enum('N','Y') DEFAULT 'N' NOT NULL,Index_priv enum('N','Y') DEFAULT 'N' NOT NULL,Alter_priv enum('N','Y') DEFAULT 'N' NOT NULL,Show_db_priv enum('N','Y') DEFAULT 'N' NOT NULL,Super_priv enum('N','Y') DEFAULT 'N' NOT NULL,Create_tmp_table_priv enum('N','Y') DEFAULT 'N' NOT NULL,Lock_tables_priv enum('N','Y') DEFAULT 'N' NOT NULL,Execute_priv enum('N','Y') DEFAULT 'N' NOT NULL,Repl_slave_priv enum('N','Y') DEFAULT 'N' NOT NULL,Repl_client_priv enum('N','Y') DEFAULT 'N' NOT NULL,ssl_type enum('','ANY','X509', 'SPECIFIED') DEFAULT '' NOT NULL,ssl_cipher BLOB NOT NULL,x509_issuer BLOB NOT NULL,x509_subject BLOB NOT NULL,max_questions int(11) unsigned DEFAULT 0 NOT NULL,max_updates int(11) unsigned DEFAULT 0 NOT NULL,max_connections int(11) unsigned DEFAULT 0 NOT NULL,PRIMARY KEY Host (Host,User)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Users and global privileges';
+
+INSERT INTO user VALUES ('%','root','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+INSERT INTO user VALUES ('localhost','','','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','Y','','','','',0,0,0);
+INSERT INTO user VALUES ('%','','','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','N','','','','',0,0,0);
+
+CREATE TABLE func (name char(64) binary DEFAULT '' NOT NULL,ret tinyint(1) DEFAULT '0' NOT NULL,dl char(128) DEFAULT '' NOT NULL,type enum ('function','aggregate') NOT NULL,PRIMARY KEY (name)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='User defined functions';
+
+CREATE TABLE tables_priv (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Table_name char(64) binary DEFAULT '' NOT NULL,Grantor char(77) DEFAULT '' NOT NULL,Timestamp timestamp(14),Table_priv set('Select','Insert','Update','Delete','Create','Drop','Grant','References','Index','Alter') DEFAULT '' NOT NULL,Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,PRIMARY KEY (Host,Db,User,Table_name),KEY Grantor (Grantor)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Table privileges';
+
+CREATE TABLE columns_priv (Host char(60) binary DEFAULT '' NOT NULL,Db char(64) binary DEFAULT '' NOT NULL,User char(16) binary DEFAULT '' NOT NULL,Table_name char(64) binary DEFAULT '' NOT NULL,Column_name char(64) binary DEFAULT '' NOT NULL,Timestamp timestamp(14),Column_priv set('Select','Insert','Update','References') DEFAULT '' NOT NULL,PRIMARY KEY (Host,Db,User,Table_name,Column_name)) engine=MyISAM CHARACTER SET utf8 COLLATE utf8_bin comment='Column privileges';
+
+CREATE TABLE help_topic (help_topic_id int unsigned not null,name varchar(64) not null,help_category_id smallint unsigned not null,description text not null,example text not null,url varchar(128) not null,primary key (help_topic_id),unique index (name)) engine=MyISAM CHARACTER SET utf8 comment='help topics';
+
+CREATE TABLE help_category (help_category_id smallint unsigned not null,name varchar(64) not null,parent_category_id smallint unsigned null,url varchar(128) not null,primary key (help_category_id),unique index (name)) engine=MyISAM CHARACTER SET utf8 comment='help categories';
+
+CREATE TABLE help_keyword (help_keyword_id int unsigned not null,name varchar(64) not null,primary key (help_keyword_id),unique index (name)) engine=MyISAM CHARACTER SET utf8 comment='help keywords';
+
+CREATE TABLE help_relation (help_topic_id int unsigned not null references help_topic,help_keyword_id int unsigned not null references help_keyword,primary key (help_keyword_id, help_topic_id)) engine=MyISAM CHARACTER SET utf8 comment='keyword-topic relation';
+
+CREATE TABLE time_zone_name (Name char(64) NOT NULL,Time_zone_id int unsigned NOT NULL,PRIMARY KEY Name (Name)) engine=MyISAM CHARACTER SET utf8 comment='Time zone names';
+
+INSERT INTO time_zone_name (Name, Time_Zone_id) VALUES ('MET', 1), ('UTC', 2), ('Universal', 2), ('Europe/Moscow',3), ('leap/Europe/Moscow',4), ('Japan', 5);
+
+
+CREATE TABLE time_zone (Time_zone_id int unsigned NOT NULL auto_increment,Use_leap_seconds enum('Y','N') DEFAULT 'N' NOT NULL,PRIMARY KEY TzId (Time_zone_id)) engine=MyISAM CHARACTER SET utf8 comment='Time zones';
+
+INSERT INTO time_zone (Time_zone_id, Use_leap_seconds) VALUES (1,'N'), (2,'N'), (3,'N'), (4,'Y'), (5,'N');
+
+
+CREATE TABLE time_zone_transition (Time_zone_id int unsigned NOT NULL,Transition_time bigint signed NOT NULL,Transition_type_id int unsigned NOT NULL,PRIMARY KEY TzIdTranTime (Time_zone_id, Transition_time)) engine=MyISAM CHARACTER SET utf8 comment='Time zone transitions';
+
+INSERT INTO time_zone_transition (Time_zone_id, Transition_time, Transition_type_id) VALUES (1, -1693706400, 0) ,(1, -1680483600, 1),(1, -1663455600, 2) ,(1, -1650150000, 3),(1, -1632006000, 2) ,(1, -1618700400, 3),(1, -938905200, 2) ,(1, -857257200, 3),(1, -844556400, 2) ,(1, -828226800, 3),(1, -812502000, 2) ,(1, -796777200, 3),(1, 228877200, 2) ,(1, 243997200, 3),(1, 260326800, 2) ,(1, 276051600, 3),(1, 291776400, 2) ,(1, 307501200, 3),(1, 323830800, 2) ,(1, 338950800, 3),(1, 354675600, 2) ,(1, 370400400, 3),(1, 386125200, 2) ,(1, 401850000, 3),(1, 417574800, 2) ,(1, 433299600, 3),(1, 449024400, 2) ,(1, 465354000, 3),(1, 481078800, 2) ,(1, 496803600, 3),(1, 512528400, 2) ,(1, 528253200, 3),(1, 543978000, 2) ,(1, 559702800, 3),(1, 575427600, 2) ,(1, 591152400, 3),(1, 606877200, 2) ,(1, 622602000, 3),(1, 638326800, 2) ,(1, 654656400, 3),(1, 670381200, 2) ,(1, 686106000, 3),(1, 701830800, 2) ,(1, 717555600, 3),(1, 733280400, 2) ,(1, 749005200, 3),(1, 764730000, 2) ,(1, 780454800, 3),(1, 796179600, 2) ,(1, 811904400, 3),(1, 828234000, 2) ,(1, 846378000, 3),(1, 859683600, 2) ,(1, 877827600, 3),(1, 891133200, 2) ,(1, 909277200, 3),(1, 922582800, 2) ,(1, 941331600, 3),(1, 954032400, 2) ,(1, 972781200, 3),(1, 985482000, 2) ,(1, 1004230800, 3),(1, 1017536400, 2) ,(1, 1035680400, 3),(1, 1048986000, 2) ,(1, 1067130000, 3),(1, 1080435600, 2) ,(1, 1099184400, 3),(1, 1111885200, 2) ,(1, 1130634000, 3),(1, 1143334800, 2) ,(1, 1162083600, 3),(1, 1174784400, 2) ,(1, 1193533200, 3),(1, 1206838800, 2) ,(1, 1224982800, 3),(1, 1238288400, 2) ,(1, 1256432400, 3),(1, 1269738000, 2) ,(1, 1288486800, 3),(1, 1301187600, 2) ,(1, 1319936400, 3),(1, 1332637200, 2) ,(1, 1351386000, 3),(1, 1364691600, 2) ,(1, 1382835600, 3),(1, 1396141200, 2) ,(1, 1414285200, 3),(1, 1427590800, 2) ,(1, 1445734800, 3),(1, 1459040400, 2) ,(1, 1477789200, 3),(1, 1490490000, 2) ,(1, 1509238800, 3),(1, 1521939600, 2) ,(1, 1540688400, 3),(1, 1553994000, 2) ,(1, 1572138000, 3),(1, 1585443600, 2) ,(1, 1603587600, 3),(1, 1616893200, 2) ,(1, 1635642000, 3),(1, 1648342800, 2) ,(1, 1667091600, 3),(1, 1679792400, 2) ,(1, 1698541200, 3),(1, 1711846800, 2) ,(1, 1729990800, 3),(1, 1743296400, 2) ,(1, 1761440400, 3),(1, 1774746000, 2) ,(1, 1792890000, 3),(1, 1806195600, 2) ,(1, 1824944400, 3),(1, 1837645200, 2) ,(1, 1856394000, 3),(1, 1869094800, 2) ,(1, 1887843600, 3),(1, 1901149200, 2) ,(1, 1919293200, 3),(1, 1932598800, 2) ,(1, 1950742800, 3),(1, 1964048400, 2) ,(1, 1982797200, 3),(1, 1995498000, 2) ,(1, 2014246800, 3),(1, 2026947600, 2) ,(1, 2045696400, 3),(1, 2058397200, 2) ,(1, 2077146000, 3),(1, 2090451600, 2) ,(1, 2108595600, 3),(1, 2121901200, 2) ,(1, 2140045200, 3),(3, -1688265000, 2) ,(3, -1656819048, 1),(3, -1641353448, 2) ,(3, -1627965048, 3),(3, -1618716648, 1) ,(3, -1596429048, 3),(3, -1593829848, 5) ,(3, -1589860800, 4),(3, -1542427200, 5) ,(3, -1539493200, 6),(3, -1525323600, 5) ,(3, -1522728000, 4),(3, -1491188400, 7) ,(3, -1247536800, 4),(3, 354920400, 5) ,(3, 370728000, 4),(3, 386456400, 5) ,(3, 402264000, 4),(3, 417992400, 5) ,(3, 433800000, 4),(3, 449614800, 5) ,(3, 465346800, 8),(3, 481071600, 9) ,(3, 496796400, 8),(3, 512521200, 9) ,(3, 528246000, 8),(3, 543970800, 9) ,(3, 559695600, 8),(3, 575420400, 9) ,(3, 591145200, 8),(3, 606870000, 9) ,(3, 622594800, 8),(3, 638319600, 9) ,(3, 654649200, 8),(3, 670374000, 10) ,(3, 686102400, 11),(3, 695779200, 8) ,(3, 701812800, 5),(3, 717534000, 4) ,(3, 733273200, 9),(3, 748998000, 8) ,(3, 764722800, 9),(3, 780447600, 8) ,(3, 796172400, 9),(3, 811897200, 8) ,(3, 828226800, 9),(3, 846370800, 8) ,(3, 859676400, 9),(3, 877820400, 8) ,(3, 891126000, 9),(3, 909270000, 8) ,(3, 922575600, 9),(3, 941324400, 8) ,(3, 954025200, 9),(3, 972774000, 8) ,(3, 985474800, 9),(3, 1004223600, 8) ,(3, 1017529200, 9),(3, 1035673200, 8) ,(3, 1048978800, 9),(3, 1067122800, 8) ,(3, 1080428400, 9),(3, 1099177200, 8) ,(3, 1111878000, 9),(3, 1130626800, 8) ,(3, 1143327600, 9),(3, 1162076400, 8) ,(3, 1174777200, 9),(3, 1193526000, 8) ,(3, 1206831600, 9),(3, 1224975600, 8) ,(3, 1238281200, 9),(3, 1256425200, 8) ,(3, 1269730800, 9),(3, 1288479600, 8) ,(3, 1301180400, 9),(3, 1319929200, 8) ,(3, 1332630000, 9),(3, 1351378800, 8) ,(3, 1364684400, 9),(3, 1382828400, 8) ,(3, 1396134000, 9),(3, 1414278000, 8) ,(3, 1427583600, 9),(3, 1445727600, 8) ,(3, 1459033200, 9),(3, 1477782000, 8) ,(3, 1490482800, 9),(3, 1509231600, 8) ,(3, 1521932400, 9),(3, 1540681200, 8) ,(3, 1553986800, 9),(3, 1572130800, 8) ,(3, 1585436400, 9),(3, 1603580400, 8) ,(3, 1616886000, 9),(3, 1635634800, 8) ,(3, 1648335600, 9),(3, 1667084400, 8) ,(3, 1679785200, 9),(3, 1698534000, 8) ,(3, 1711839600, 9),(3, 1729983600, 8) ,(3, 1743289200, 9),(3, 1761433200, 8) ,(3, 1774738800, 9),(3, 1792882800, 8) ,(3, 1806188400, 9),(3, 1824937200, 8) ,(3, 1837638000, 9),(3, 1856386800, 8) ,(3, 1869087600, 9),(3, 1887836400, 8) ,(3, 1901142000, 9),(3, 1919286000, 8) ,(3, 1932591600, 9),(3, 1950735600, 8) ,(3, 1964041200, 9),(3, 1982790000, 8) ,(3, 1995490800, 9),(3, 2014239600, 8) ,(3, 2026940400, 9),(3, 2045689200, 8) ,(3, 2058390000, 9),(3, 2077138800, 8) ,(3, 2090444400, 9),(3, 2108588400, 8) ,(3, 2121894000, 9),(3, 2140038000, 8),(4, -1688265000, 2) ,(4, -1656819048, 1),(4, -1641353448, 2) ,(4, -1627965048, 3),(4, -1618716648, 1) ,(4, -1596429048, 3),(4, -1593829848, 5) ,(4, -1589860800, 4),(4, -1542427200, 5) ,(4, -1539493200, 6),(4, -1525323600, 5) ,(4, -1522728000, 4),(4, -1491188400, 7) ,(4, -1247536800, 4),(4, 354920409, 5) ,(4, 370728010, 4),(4, 386456410, 5) ,(4, 402264011, 4),(4, 417992411, 5) ,(4, 433800012, 4),(4, 449614812, 5) ,(4, 465346812, 8),(4, 481071612, 9) ,(4, 496796413, 8),(4, 512521213, 9) ,(4, 528246013, 8),(4, 543970813, 9) ,(4, 559695613, 8),(4, 575420414, 9) ,(4, 591145214, 8),(4, 606870014, 9) ,(4, 622594814, 8),(4, 638319615, 9) ,(4, 654649215, 8),(4, 670374016, 10) ,(4, 686102416, 11),(4, 695779216, 8) ,(4, 701812816, 5),(4, 717534017, 4) ,(4, 733273217, 9),(4, 748998018, 8) ,(4, 764722818, 9),(4, 780447619, 8) ,(4, 796172419, 9),(4, 811897219, 8) ,(4, 828226820, 9),(4, 846370820, 8) ,(4, 859676420, 9),(4, 877820421, 8) ,(4, 891126021, 9),(4, 909270021, 8) ,(4, 922575622, 9),(4, 941324422, 8) ,(4, 954025222, 9),(4, 972774022, 8) ,(4, 985474822, 9),(4, 1004223622, 8) ,(4, 1017529222, 9),(4, 1035673222, 8) ,(4, 1048978822, 9),(4, 1067122822, 8) ,(4, 1080428422, 9),(4, 1099177222, 8) ,(4, 1111878022, 9),(4, 1130626822, 8) ,(4, 1143327622, 9),(4, 1162076422, 8) ,(4, 1174777222, 9),(4, 1193526022, 8) ,(4, 1206831622, 9),(4, 1224975622, 8) ,(4, 1238281222, 9),(4, 1256425222, 8) ,(4, 1269730822, 9),(4, 1288479622, 8) ,(4, 1301180422, 9),(4, 1319929222, 8) ,(4, 1332630022, 9),(4, 1351378822, 8) ,(4, 1364684422, 9),(4, 1382828422, 8) ,(4, 1396134022, 9),(4, 1414278022, 8) ,(4, 1427583622, 9),(4, 1445727622, 8) ,(4, 1459033222, 9),(4, 1477782022, 8) ,(4, 1490482822, 9),(4, 1509231622, 8) ,(4, 1521932422, 9),(4, 1540681222, 8) ,(4, 1553986822, 9),(4, 1572130822, 8) ,(4, 1585436422, 9),(4, 1603580422, 8) ,(4, 1616886022, 9),(4, 1635634822, 8) ,(4, 1648335622, 9),(4, 1667084422, 8) ,(4, 1679785222, 9),(4, 1698534022, 8) ,(4, 1711839622, 9),(4, 1729983622, 8) ,(4, 1743289222, 9),(4, 1761433222, 8) ,(4, 1774738822, 9),(4, 1792882822, 8) ,(4, 1806188422, 9),(4, 1824937222, 8) ,(4, 1837638022, 9),(4, 1856386822, 8) ,(4, 1869087622, 9),(4, 1887836422, 8) ,(4, 1901142022, 9),(4, 1919286022, 8) ,(4, 1932591622, 9),(4, 1950735622, 8) ,(4, 1964041222, 9),(4, 1982790022, 8) ,(4, 1995490822, 9),(4, 2014239622, 8) ,(4, 2026940422, 9),(4, 2045689222, 8) ,(4, 2058390022, 9),(4, 2077138822, 8) ,(4, 2090444422, 9),(4, 2108588422, 8) ,(4, 2121894022, 9),(4, 2140038022, 8);
+
+
+CREATE TABLE time_zone_transition_type (Time_zone_id int unsigned NOT NULL,Transition_type_id int unsigned NOT NULL,Offset int signed DEFAULT 0 NOT NULL,Is_DST tinyint unsigned DEFAULT 0 NOT NULL,Abbreviation char(8) DEFAULT '' NOT NULL,PRIMARY KEY TzIdTrTId (Time_zone_id, Transition_type_id)) engine=MyISAM CHARACTER SET utf8 comment='Time zone transition types';
+
+INSERT INTO time_zone_transition_type (Time_zone_id,Transition_type_id, Offset, Is_DST, Abbreviation) VALUES (1, 0, 7200, 1, 'MEST') ,(1, 1, 3600, 0, 'MET') ,(1, 2, 7200, 1, 'MEST') ,(1, 3, 3600, 0, 'MET') ,(2, 0, 0, 0, 'UTC') ,(3, 0, 9000, 0, 'MMT') ,(3, 1, 12648, 1, 'MST') ,(3, 2, 9048, 0, 'MMT') ,(3, 3, 16248, 1, 'MDST') ,(3, 4, 10800, 0, 'MSK') ,(3, 5, 14400, 1, 'MSD') ,(3, 6, 18000, 1, 'MSD') ,(3, 7, 7200, 0, 'EET') ,(3, 8, 10800, 0, 'MSK') ,(3, 9, 14400, 1, 'MSD') ,(3, 10, 10800, 1, 'EEST') ,(3, 11, 7200, 0, 'EET') ,(4, 0, 9000, 0, 'MMT') ,(4, 1, 12648, 1, 'MST') ,(4, 2, 9048, 0, 'MMT') ,(4, 3, 16248, 1, 'MDST') ,(4, 4, 10800, 0, 'MSK') ,(4, 5, 14400, 1, 'MSD') ,(4, 6, 18000, 1, 'MSD') ,(4, 7, 7200, 0, 'EET') ,(4, 8, 10800, 0, 'MSK') ,(4, 9, 14400, 1, 'MSD') ,(4, 10, 10800, 1, 'EEST') ,(4, 11, 7200, 0, 'EET') ,(5, 0, 32400, 0, 'CJT') ,(5, 1, 32400, 0, 'JST');
+
+CREATE TABLE time_zone_leap_second (Transition_time bigint signed NOT NULL,Correction int signed NOT NULL,PRIMARY KEY TranTime (Transition_time)) engine=MyISAM CHARACTER SET utf8 comment='Leap seconds information for time zones';
+
+INSERT INTO time_zone_leap_second (Transition_time, Correction) VALUES (78796800, 1) ,(94694401, 2) ,(126230402, 3) ,(157766403, 4) ,(189302404, 5) ,(220924805, 6) ,(252460806, 7) ,(283996807, 8) ,(315532808, 9) ,(362793609, 10) ,(394329610, 11) ,(425865611, 12) ,(489024012, 13) ,(567993613, 14) ,(631152014, 15) ,(662688015, 16) ,(709948816, 17) ,(741484817, 18) ,(773020818, 19) ,(820454419, 20) ,(867715220, 21) ,(915148821, 22);
+
+
diff --git a/mysql-test/my_manage.c b/mysql-test/my_manage.c
new file mode 100644
index 00000000000..cc27558f131
--- /dev/null
+++ b/mysql-test/my_manage.c
@@ -0,0 +1,877 @@
+/*
+ Copyright (c) 2003 Novell, Inc. All Rights Reserved.
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdio.h>
+#include <errno.h>
+#ifndef __WIN__
+#include <dirent.h>
+#endif
+#include <string.h>
+#ifdef __NETWARE__
+#include <screen.h>
+#include <proc.h>
+#else
+#include <sys/types.h>
+#ifndef __WIN__
+#include <sys/wait.h>
+#include <unistd.h>
+#include <signal.h>
+#include <fnmatch.h> /* FIXME HAVE_FNMATCH_H or something */
+#else
+#include <direct.h>
+#include <stdlib.h>
+#include <stdio.h>
+#endif
+#endif
+#include <ctype.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <assert.h>
+
+#include "my_manage.h"
+
+#ifndef __NETWARE__
+#define ASSERT assert
+extern char **environ;
+#endif
+
+
+
+/******************************************************************************
+
+ macros
+
+******************************************************************************/
+
+/******************************************************************************
+
+ global variables
+
+******************************************************************************/
+
+/******************************************************************************
+
+ functions
+
+******************************************************************************/
+
+/******************************************************************************
+
+ init_args()
+
+ Init an argument list.
+
+******************************************************************************/
+
+void init_args(arg_list_t *al)
+{
+ ASSERT(al != NULL);
+
+ al->argc= 0;
+ al->size= ARG_BUF;
+ al->argv= malloc(al->size * sizeof(char *));
+ ASSERT(al->argv != NULL);
+
+ return;
+}
+
+/******************************************************************************
+
+ add_arg()
+
+ Add an argument to a list.
+
+******************************************************************************/
+
+void add_arg(arg_list_t *al, const char *format, ...)
+{
+ va_list ap;
+ char temp[FN_REFLEN];
+
+ ASSERT(al != NULL);
+
+ /* increase size */
+ if (al->argc >= (int)al->size)
+ {
+ al->size+= ARG_BUF;
+ al->argv= realloc(al->argv, al->size * sizeof(char *));
+ ASSERT(al->argv != NULL);
+ }
+
+ if (format)
+ {
+ va_start(ap, format);
+ vsprintf(temp, format, ap);
+ va_end(ap);
+
+ al->argv[al->argc]= malloc(strlen(temp)+1);
+ ASSERT(al->argv[al->argc] != NULL);
+ strcpy(al->argv[al->argc], temp);
+
+ ++(al->argc);
+ }
+ else
+ {
+ al->argv[al->argc]= NULL;
+ }
+
+ return;
+}
+
+/******************************************************************************
+
+ free_args()
+
+ Free an argument list.
+
+******************************************************************************/
+
+void free_args(arg_list_t *al)
+{
+ int i;
+
+ ASSERT(al != NULL);
+
+ for (i= 0; i < al->argc; i++)
+ {
+ ASSERT(al->argv[i] != NULL);
+ free(al->argv[i]);
+ al->argv[i]= NULL;
+ }
+
+ free(al->argv);
+ al->argc= 0;
+ al->argv= NULL;
+
+ return;
+}
+
+/******************************************************************************
+
+ sleep_until_file_deleted()
+
+ Sleep until the given file is no longer found.
+
+******************************************************************************/
+
+#ifndef __WIN__
+int sleep_until_file_deleted(char *pid_file)
+#else
+int sleep_until_file_deleted(HANDLE pid_file)
+#endif
+{
+ int err= 0; /* Initiate to supress warning */
+#ifndef __WIN__
+ struct stat buf;
+ int i;
+
+ for (i= 0; (i < TRY_MAX) && (err= !stat(pid_file, &buf)); i++) sleep(1);
+
+ if (err != 0) err= errno;
+#else
+ err= (WaitForSingleObject(pid_file, TRY_MAX*1000) == WAIT_TIMEOUT);
+#endif
+ return err;
+}
+
+/******************************************************************************
+
+ sleep_until_file_exists()
+
+ Sleep until the given file exists.
+
+******************************************************************************/
+
+#ifndef __WIN__
+int sleep_until_file_exists(char *pid_file)
+#else
+int sleep_until_file_exists(HANDLE pid_file)
+#endif
+{
+ int err= 0; /* Initiate to supress warning */
+#ifndef __WIN__
+ struct stat buf;
+ int i;
+
+ for (i= 0; (i < TRY_MAX) && (err= stat(pid_file, &buf)); i++) sleep(1);
+
+ if (err != 0) err= errno;
+#else
+ err= (WaitForSingleObject(pid_file, TRY_MAX*1000) == WAIT_TIMEOUT);
+#endif
+ return err;
+}
+
+/******************************************************************************
+
+ wait_for_server_start()
+
+ Wait for the server on the given port to start.
+
+******************************************************************************/
+
+int wait_for_server_start(char *bin_dir __attribute__((unused)),
+ char *mysqladmin_file,
+ char *user, char *password, int port,char *tmp_dir)
+{
+ arg_list_t al;
+ int err= 0, i;
+ char trash[FN_REFLEN];
+
+ /* mysqladmin file */
+ snprintf(trash, FN_REFLEN, "%s/trash.out",tmp_dir);
+
+ /* args */
+ init_args(&al);
+ add_arg(&al, "%s", mysqladmin_file);
+ add_arg(&al, "--no-defaults");
+ add_arg(&al, "--port=%u", port);
+ add_arg(&al, "--user=%s", user);
+ add_arg(&al, "--password=%s", password);
+ add_arg(&al, "--silent");
+
+/* #ifdef NOT_USED */
+#ifndef __NETWARE__
+ add_arg(&al, "-O");
+ add_arg(&al, "connect_timeout=10");
+ add_arg(&al, "-w");
+#endif
+
+ add_arg(&al, "--host=localhost");
+#ifndef __NETWARE__
+ add_arg(&al, "--protocol=tcp");
+#endif
+ add_arg(&al, "ping");
+
+ /*
+ NetWare does not support the connect timeout in the TCP/IP stack
+ -- we will try the ping multiple times
+ */
+#ifndef __WIN__
+ for (i= 0; (i < TRY_MAX)
+ && (err= spawn(mysqladmin_file, &al, TRUE, NULL,
+ trash, NULL, NULL)); i++) sleep(1);
+#else
+ err= spawn(mysqladmin_file, &al, TRUE, NULL,trash, NULL, NULL);
+#endif
+
+ /* free args */
+ free_args(&al);
+
+ return err;
+}
+
+/******************************************************************************
+
+ spawn()
+
+ Spawn the given path with the given arguments.
+
+******************************************************************************/
+
+#ifdef __NETWARE__
+int spawn(char *path, arg_list_t *al, int join, char *input,
+ char *output, char *error, char *pid_file)
+{
+ pid_t pid;
+ int result= 0;
+ wiring_t wiring= { FD_UNUSED, FD_UNUSED, FD_UNUSED };
+ unsigned long flags= PROC_CURRENT_SPACE | PROC_INHERIT_CWD;
+
+ /* open wiring */
+ if (input)
+ wiring.infd= open(input, O_RDONLY);
+
+ if (output)
+ wiring.outfd= open(output, O_WRONLY | O_CREAT | O_TRUNC);
+
+ if (error)
+ wiring.errfd= open(error, O_WRONLY | O_CREAT | O_TRUNC);
+
+ /* procve requires a NULL */
+ add_arg(al, NULL);
+
+ /* go */
+ pid= procve(path, flags, NULL, &wiring, NULL, NULL, 0,
+ NULL, (const char **)al->argv);
+
+ /* close wiring */
+ if (wiring.infd != -1)
+ close(wiring.infd);
+
+ if (wiring.outfd != -1)
+ close(wiring.outfd);
+
+ if (wiring.errfd != -1)
+ close(wiring.errfd);
+
+ return result;
+}
+#elif __WIN__
+
+int spawn(char *path, arg_list_t *al, int join, char *input,
+ char *output, char *error, HANDLE *pid)
+{
+ intptr_t result;
+ int i;
+ STARTUPINFO startup_info;
+ PROCESS_INFORMATION process_information;
+ DWORD exit_code;
+ char win_args[1024]= "";
+ char command_line[1024]= "";
+
+ /* Skip the first parameter */
+ for (i= 1; i < al->argc; i++)
+ {
+ ASSERT(al->argv[i] != NULL);
+ strcat(win_args,al->argv[i]);
+ strcat(win_args," ");
+ }
+
+ memset(&startup_info,0,sizeof(STARTUPINFO));
+ startup_info.cb= sizeof(STARTUPINFO);
+
+ if (input)
+ freopen(input, "rb", stdin);
+
+ if (output)
+ freopen(output, "wb", stdout);
+
+ if (error)
+ freopen(error, "wb", stderr);
+
+ result= CreateProcess(
+ path,
+ (LPSTR)&win_args,
+ NULL,
+ NULL,
+ TRUE,
+ 0,
+ NULL,
+ NULL,
+ &startup_info,
+ &process_information
+ );
+
+ if (result && process_information.hProcess)
+ {
+ if (join)
+ {
+ if (WaitForSingleObject(process_information.hProcess, mysqld_timeout)
+ == WAIT_TIMEOUT)
+ {
+ exit_code= -1;
+ }
+ else
+ {
+ GetExitCodeProcess(process_information.hProcess, &exit_code);
+ }
+ CloseHandle(process_information.hProcess);
+ }
+ else
+ {
+ exit_code= 0;
+ }
+ if (pid != NULL)
+ *pid= process_information.hProcess;
+ }
+ else
+ {
+ exit_code= -1;
+ }
+ if (input)
+ freopen("CONIN$","rb",stdin);
+ if (output)
+ freopen("CONOUT$","wb",stdout);
+ if (error)
+ freopen("CONOUT$","wb",stderr);
+
+ return exit_code;
+}
+#else
+int spawn(char *path, arg_list_t *al, int join, char *input,
+ char *output, char *error, char *pid_file __attribute__((unused)))
+{
+ pid_t pid;
+ int res_exec= 0;
+ int result= 0;
+
+ pid= fork();
+
+ if (pid == -1)
+ {
+ fprintf(stderr, "fork was't created\n");
+ /* We can't create the fork...exit with error */
+ return EXIT_FAILURE;
+ }
+
+ if (pid > 0)
+ {
+ /* The parent process is waiting for child process if join is not zero */
+ if (join)
+ {
+ waitpid(pid, &result, 0);
+ if (WIFEXITED(result) != 0)
+ {
+ result= WEXITSTATUS(result);
+ }
+ else
+ {
+ result= EXIT_FAILURE;
+ }
+ }
+ }
+ else
+ {
+
+ /* Child process */
+ add_arg(al, NULL);
+
+ /* Reassign streams */
+ if (input)
+ freopen(input, "r", stdin);
+
+ if (output)
+ freopen(output, "w", stdout);
+
+ if (error)
+ freopen(error, "w", stderr);
+
+ /* Spawn the process */
+ if ((res_exec= execve(path, al->argv, environ)) < 0)
+ exit(EXIT_FAILURE);
+
+ /* Restore streams */
+ if (input)
+ freopen("/dev/tty", "r", stdin);
+
+ if (output)
+ freopen("/dev/tty", "w", stdout);
+
+ if (error)
+ freopen("/dev/tty", "w", stderr);
+
+ exit(0);
+ }
+
+ return result;
+}
+#endif
+/******************************************************************************
+
+ stop_server()
+
+ Stop the server with the given port and pid file.
+
+******************************************************************************/
+
+int stop_server(char *bin_dir __attribute__((unused)), char *mysqladmin_file,
+ char *user, char *password, int port,
+#ifndef __WIN__
+ char *pid_file,
+#else
+ HANDLE pid_file,
+#endif
+ char *tmp_dir)
+{
+ arg_list_t al;
+ int err= 0;
+ char trash[FN_REFLEN];
+
+ snprintf(trash, FN_REFLEN, "%s/trash.out",tmp_dir);
+
+ /* args */
+ init_args(&al);
+ add_arg(&al, "%s", mysqladmin_file);
+ add_arg(&al, "--no-defaults");
+ add_arg(&al, "--port=%u", port);
+ add_arg(&al, "--user=%s", user);
+ add_arg(&al, "--password=%s", password);
+ add_arg(&al, "-O");
+ add_arg(&al, "shutdown_timeout=20");
+#ifndef __NETWARE__
+ add_arg(&al, "--protocol=tcp");
+#endif
+ add_arg(&al, "shutdown");
+
+ /* spawn */
+ if ((err= spawn(mysqladmin_file, &al, TRUE, NULL,
+ trash, NULL, NULL)) == 0)
+ {
+ sleep_until_file_deleted(pid_file);
+ }
+ else
+ {
+#ifndef __WIN__
+ pid_t pid= get_server_pid(pid_file);
+
+ /* shutdown failed - kill server */
+ kill_server(pid);
+
+ sleep(TRY_MAX);
+
+ /* remove pid file if possible */
+ err= remove(pid_file);
+#else
+ TerminateProcess(pid_file,err);
+#endif
+ }
+
+ /* free args */
+ free_args(&al);
+
+ return err;
+}
+
+/******************************************************************************
+
+ get_server_pid()
+
+ Get the VM id with the given pid file.
+
+******************************************************************************/
+
+#ifndef __WIN__
+pid_t get_server_pid(char *pid_file)
+{
+ char buf[FN_REFLEN];
+ int fd, err;
+ char *p;
+ pid_t id= 0;
+
+ /* discover id */
+ fd= open(pid_file, O_RDONLY);
+
+ err= read(fd, buf, FN_REFLEN);
+
+ close(fd);
+
+ if (err > 0)
+ {
+ /* terminate string */
+ if ((p= strchr(buf, '\n')) != NULL)
+ {
+ *p= '\0';
+
+ /* check for a '\r' */
+ if ((p= strchr(buf, '\r')) != NULL)
+ {
+ *p= '\0';
+ }
+ }
+ else
+ {
+ buf[err]= '\0';
+ }
+
+ id= strtol(buf, NULL, 0);
+ }
+
+ return id;
+}
+
+/******************************************************************************
+
+ kill_server()
+
+ Force a kill of the server with the given pid.
+
+******************************************************************************/
+
+void kill_server(pid_t pid)
+{
+ if (pid > 0)
+ {
+#if !defined(__NETWARE__)
+ /* Send SIGTERM to pid */
+ kill(pid, SIGTERM);
+#else /* __NETWARE__ */
+ /* destroy vm */
+ NXVmDestroy(pid);
+#endif
+ }
+}
+#endif
+/******************************************************************************
+
+ del_tree()
+
+ Delete the directory and subdirectories.
+
+******************************************************************************/
+
+void del_tree(char *dir)
+{
+#ifndef __WIN__
+ DIR *parent= opendir(dir);
+ struct dirent *entry;
+ char temp[FN_REFLEN];
+
+ if (parent == NULL)
+ {
+ return;
+ }
+
+ while ((entry= readdir(parent)) != NULL)
+ {
+ /* create long name */
+ snprintf(temp, FN_REFLEN, "%s/%s", dir, entry->d_name);
+
+ if (entry->d_name[0] == '.')
+ {
+ /* Skip */
+ }
+ else
+ {
+/* FIXME missing test in acinclude.m4 */
+#ifndef STRUCT_DIRENT_HAS_D_TYPE
+ struct stat st;
+
+ if (lstat(entry->d_name, &st) == -1)
+ {
+ /* FIXME error */
+ return;
+ }
+ if (S_ISDIR(st.st_mode))
+#else
+ if (S_ISDIR(entry->d_type))
+#endif
+ {
+ /* delete subdirectory */
+ del_tree(temp);
+ }
+ else
+ {
+ /* remove file */
+ remove(temp);
+ }
+ }
+ }
+ /* remove directory */
+ rmdir(dir);
+#else
+ struct _finddata_t parent;
+ intptr_t handle;
+ char temp[FN_REFLEN];
+ char mask[FN_REFLEN];
+
+ snprintf(mask,FN_REFLEN,"%s/*.*",dir);
+
+ if ((handle=_findfirst(mask,&parent)) == -1L)
+ {
+ return;
+ }
+
+ do
+ {
+ /* create long name */
+ snprintf(temp, FN_REFLEN, "%s/%s", dir, parent.name);
+ if (parent.name[0] == '.')
+ {
+ /* Skip */
+ }
+ else
+ if (parent.attrib & _A_SUBDIR)
+ {
+ /* delete subdirectory */
+ del_tree(temp);
+ }
+ else
+ {
+ /* remove file */
+ remove(temp);
+ }
+ } while (_findnext(handle,&parent) == 0);
+
+ _findclose(handle);
+
+ /* remove directory */
+ _rmdir(dir);
+#endif
+}
+
+/******************************************************************************
+
+ removef()
+
+******************************************************************************/
+
+int removef(const char *format, ...)
+{
+#ifdef __NETWARE__
+ va_list ap;
+ char path[FN_REFLEN];
+
+ va_start(ap, format);
+
+ vsnprintf(path, FN_REFLEN, format, ap);
+
+ va_end(ap);
+ return remove(path);
+
+#eldef __WIN__
+ {
+ va_list ap;
+ char path[FN_REFLEN];
+ struct _finddata_t parent;
+ intptr_t handle;
+ char temp[FN_REFLEN];
+ char *p;
+
+ va_start(ap, format);
+
+ vsnprintf(path, FN_REFLEN, format, ap);
+
+ va_end(ap);
+
+ p= path + strlen(path);
+ while (*p != '\\' && *p != '/' && p > path) p--;
+
+ if ((handle=_findfirst(path,&parent)) == -1L)
+ {
+ /* if there is not files....it's ok */
+ return 0;
+ }
+
+ *p= '\0';
+
+ do
+ {
+ if (! (parent.attrib & _A_SUBDIR))
+ {
+ snprintf(temp, FN_REFLEN, "%s/%s", path, parent.name);
+ remove(temp);
+ }
+ }while (_findnext(handle,&parent) == 0);
+
+ _findclose(handle);
+ }
+#else
+ DIR *parent;
+ struct dirent *entry;
+ char temp[FN_REFLEN];
+ va_list ap;
+ char path[FN_REFLEN];
+ char *p;
+ /* Get path with mask */
+ va_start(ap, format);
+
+ vsnprintf(path, FN_REFLEN, format, ap);
+
+ va_end(ap);
+
+ p= path + strlen(path);
+ while (*p != '\\' && *p != '/' && p > path) p--;
+ *p= '\0';
+ p++;
+
+ parent= opendir(path);
+
+ if (parent == NULL)
+ {
+ return 1; /* Error, directory missing */
+ }
+
+ while ((entry= readdir(parent)) != NULL)
+ {
+ /* entry is not directory and entry matches with mask */
+#ifndef STRUCT_DIRENT_HAS_D_TYPE
+ struct stat st;
+
+ if (lstat(entry->d_name, &st) == -1)
+ {
+ return 1;
+ }
+
+ if (!S_ISDIR(st.st_mode) && !fnmatch(p, entry->d_name,0))
+#else
+ if (!S_ISDIR(entry->d_type) && !fnmatch(p, entry->d_name,0))
+#endif
+ {
+ /* create long name */
+ snprintf(temp, FN_REFLEN, "%s/%s", path, entry->d_name);
+ /* Delete only files */
+ remove(temp);
+ }
+ }
+#endif
+ return 0;
+}
+
+/******************************************************************************
+
+ get_basedir()
+
+******************************************************************************/
+
+void get_basedir(char *argv0, char *basedir)
+{
+ char temp[FN_REFLEN];
+ char *p;
+ int position;
+
+ ASSERT(argv0 != NULL);
+ ASSERT(basedir != NULL);
+
+ strcpy(temp, strlwr(argv0));
+ while ((p= strchr(temp, '\\')) != NULL) *p= '/';
+
+ if ((position= strinstr(temp, "/bin/")) != 0)
+ {
+ p= temp + position;
+ *p= '\0';
+ strcpy(basedir, temp);
+ }
+}
+
+uint strinstr(reg1 const char *str,reg4 const char *search)
+{
+ reg2 my_string i,j;
+ my_string start= (my_string) str;
+
+ skipp:
+ while (*str != '\0')
+ {
+ if (*str++ == *search)
+ {
+ i=(my_string) str;
+ j= (my_string) search+1;
+ while (*j)
+ if (*i++ != *j++) goto skipp;
+ return ((uint) (str - start));
+ }
+ }
+ return (0);
+}
+
+/******************************************************************************
+
+ remove_empty_file()
+
+******************************************************************************/
+
+void remove_empty_file(const char *file_name)
+{
+ struct stat file;
+
+ if (!stat(file_name,&file))
+ {
+ if (!file.st_size)
+ remove(file_name);
+ }
+}
diff --git a/mysql-test/my_manage.h b/mysql-test/my_manage.h
new file mode 100644
index 00000000000..7e371d36ab1
--- /dev/null
+++ b/mysql-test/my_manage.h
@@ -0,0 +1,133 @@
+/*
+ Copyright (c) 2002 Novell, Inc. All Rights Reserved.
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#ifndef _MY_MANAGE
+#define _MY_MANAGE
+
+/******************************************************************************
+
+ includes
+
+******************************************************************************/
+
+#include <stdlib.h>
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#ifndef __NETWARE__
+#include <string.h>
+#include <my_global.h>
+#include <m_string.h>
+
+#ifndef __WIN__
+#define strnicmp strncasecmp
+#define strlwr(STRARG) (STRARG)
+#else
+int my_vsnprintf_(char *to, size_t n, const char* value, ...);
+#endif
+#endif
+
+/******************************************************************************
+
+ macros
+
+******************************************************************************/
+
+#define ARG_BUF 10
+#define TRY_MAX 5
+
+#ifdef __WIN__
+#define kill(A,B) TerminateProcess((HANDLE)A,0)
+#define NOT_NEED_PID 0
+#define MASTER_PID 1
+#define SLAVE_PID 2
+#define mysqld_timeout 60000
+
+int pid_mode;
+bool run_server;
+bool skip_first_param;
+
+#define snprintf _snprintf
+#define vsnprintf _vsnprintf
+#endif
+
+
+/******************************************************************************
+
+ structures
+
+******************************************************************************/
+
+typedef struct
+{
+
+ int argc;
+ char **argv;
+
+ size_t size;
+
+} arg_list_t;
+
+#ifdef __WIN__
+typedef int pid_t;
+#endif
+/******************************************************************************
+
+ global variables
+
+******************************************************************************/
+
+/******************************************************************************
+
+ prototypes
+
+******************************************************************************/
+
+void init_args(arg_list_t *);
+void add_arg(arg_list_t *, const char *, ...);
+void free_args(arg_list_t *);
+
+#ifndef __WIN__
+int sleep_until_file_exists(char *);
+int sleep_until_file_deleted(char *);
+#else
+int sleep_until_file_exists(HANDLE);
+int sleep_until_file_deleted(HANDLE);
+#endif
+int wait_for_server_start(char *, char *, char *, char *, int,char *);
+
+#ifndef __WIN__
+int spawn(char *, arg_list_t *, int, char *, char *, char *, char *);
+#else
+int spawn(char *, arg_list_t *, int , char *, char *, char *, HANDLE *);
+#endif
+
+#ifndef __WIN__
+int stop_server(char *, char *, char *, char *, int, char *,char *);
+pid_t get_server_pid(char *);
+void kill_server(pid_t pid);
+#else
+int stop_server(char *, char *, char *, char *, int, HANDLE,char *);
+#endif
+void del_tree(char *);
+int removef(const char *, ...);
+
+void get_basedir(char *, char *);
+void remove_empty_file(const char *file_name);
+
+#endif /* _MY_MANAGE */
diff --git a/mysql-test/mysql-test-run.sh b/mysql-test/mysql-test-run.sh
index 07bc256eb2b..707f18d064e 100644
--- a/mysql-test/mysql-test-run.sh
+++ b/mysql-test/mysql-test-run.sh
@@ -227,7 +227,7 @@ DO_CLIENT_GDB=""
SLEEP_TIME_AFTER_RESTART=1
SLEEP_TIME_FOR_DELETE=10
SLEEP_TIME_FOR_FIRST_MASTER=400 # Enough time to create innodb tables
-SLEEP_TIME_FOR_SECOND_MASTER=30
+SLEEP_TIME_FOR_SECOND_MASTER=400
SLEEP_TIME_FOR_FIRST_SLAVE=400
SLEEP_TIME_FOR_SECOND_SLAVE=30
CHARACTER_SET=latin1
@@ -457,6 +457,9 @@ SMALL_SERVER="--key_buffer_size=1M --sort_buffer=256K --max_heap_table_size=1M"
export MASTER_MYPORT MASTER_MYPORT1 SLAVE_MYPORT MYSQL_TCP_PORT MASTER_MYSOCK MASTER_MYSOCK1
+NDBCLUSTER_BASE_PORT=`expr $NDBCLUSTER_PORT + 2`
+NDBCLUSTER_OPTS="--port=$NDBCLUSTER_PORT --port-base=$NDBCLUSTER_BASE_PORT --data-dir=$MYSQL_TEST_DIR/var"
+
if [ x$SOURCE_DIST = x1 ] ; then
MY_BASEDIR=$MYSQL_TEST_DIR
else
@@ -941,11 +944,11 @@ start_ndbcluster()
echo "Starting ndbcluster"
if [ "$DO_BENCH" = 1 ]
then
- NDBCLUSTER_OPTS=""
+ NDBCLUSTER_EXTRA_OPTS=""
else
- NDBCLUSTER_OPTS="--small"
+ NDBCLUSTER_EXTRA_OPTS="--small"
fi
- ./ndb/ndbcluster --port-base=$NDBCLUSTER_PORT $NDBCLUSTER_OPTS --diskless --initial --data-dir=$MYSQL_TEST_DIR/var || exit 1
+ ./ndb/ndbcluster $NDBCLUSTER_OPTS $NDBCLUSTER_EXTRA_OPTS --diskless --initial || exit 1
NDB_CONNECTSTRING="host=localhost:$NDBCLUSTER_PORT"
else
NDB_CONNECTSTRING="$USE_RUNNING_NDBCLUSTER"
@@ -963,7 +966,7 @@ stop_ndbcluster()
if [ -z "$USE_RUNNING_NDBCLUSTER" ]
then
# Kill any running ndbcluster stuff
- ./ndb/ndbcluster --data-dir=$MYSQL_TEST_DIR/var --port-base=$NDBCLUSTER_PORT --stop
+ ./ndb/ndbcluster $NDBCLUSTER_OPTS --stop
fi
fi
}
@@ -996,9 +999,11 @@ start_master()
if [ -n "$1" ] ; then
id=`$EXPR $1 + 101`;
this_master_myport=`$EXPR $MASTER_MYPORT + $1`
+ NOT_FIRST_MASTER_EXTRA_OPTS="--skip-innodb"
else
id=1;
this_master_myport=$MASTER_MYPORT
+ NOT_FIRST_MASTER_EXTRA_OPTS=""
fi
if [ -z "$DO_BENCH" ]
then
@@ -1022,7 +1027,8 @@ start_master()
--open-files-limit=1024 \
$MASTER_40_ARGS \
$SMALL_SERVER \
- $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT"
+ $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
+ $NOT_FIRST_MASTER_EXTRA_OPTS"
else
master_args="--no-defaults --log-bin=$MYSQL_TEST_DIR/var/log/master-bin$1 \
--server-id=$id --rpl-recovery-rank=1 \
@@ -1041,7 +1047,8 @@ start_master()
--innodb_data_file_path=ibdata1:50M \
$MASTER_40_ARGS \
$SMALL_SERVER \
- $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT"
+ $EXTRA_MASTER_OPT $EXTRA_MASTER_MYSQLD_OPT \
+ $NOT_FIRST_MASTER_EXTRA_OPTS"
fi
CUR_MYERR=$MASTER_MYERR
@@ -1385,13 +1392,18 @@ run_testcase ()
# script soon anyway so it is not worth it spending the time
if [ "x$USE_EMBEDDED_SERVER" = "x1" -a -z "$DO_TEST" ] ; then
for t in \
+ "alter_table" \
"bdb-deadlock" \
"connect" \
+ "ctype_latin1_de" \
+ "ctype_ucs" \
"flush_block_commit" \
"grant2" \
"grant_cache" \
"grant" \
"init_connect" \
+ "init_file" \
+ "innodb" \
"innodb-deadlock" \
"innodb-lock" \
"mix_innodb_myisam_binlog" \
@@ -1399,10 +1411,12 @@ run_testcase ()
"mysqlbinlog" \
"mysqldump" \
"mysql_protocols" \
+ "packet" \
"ps_1general" \
"rename" \
"show_check" \
"system_mysql_db_fix" \
+ "timezone2" \
"user_var" \
"variables"
do
diff --git a/mysql-test/mysql_test_run_new.c b/mysql-test/mysql_test_run_new.c
new file mode 100644
index 00000000000..d8bf731b398
--- /dev/null
+++ b/mysql-test/mysql_test_run_new.c
@@ -0,0 +1,1769 @@
+/*
+ Copyright (c) 2002, 2003 Novell, Inc. All Rights Reserved.
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+*/
+
+#include <stdlib.h>
+#include <stdio.h>
+#include <errno.h>
+#ifndef __WIN__
+#include <dirent.h>
+#endif
+#include <string.h>
+#ifdef __NETWARE__
+#include <screen.h>
+#include <nks/vm.h>
+#endif
+#include <ctype.h>
+#include <sys/stat.h>
+#ifndef __WIN__
+#include <unistd.h>
+#endif
+#include <fcntl.h>
+#ifdef __NETWARE__
+#include <sys/mode.h>
+#endif
+#ifdef __WIN__
+#include <Shlwapi.h>
+#include <direct.h>
+#endif
+
+#include "my_manage.h"
+
+/******************************************************************************
+
+ macros
+
+******************************************************************************/
+
+#define HEADER "TEST RESULT \n"
+#define DASH "-------------------------------------------------------\n"
+
+#define NW_TEST_SUFFIX ".nw-test"
+#define NW_RESULT_SUFFIX ".nw-result"
+#define TEST_SUFFIX ".test"
+#define RESULT_SUFFIX ".result"
+#define REJECT_SUFFIX ".reject"
+#define OUT_SUFFIX ".out"
+#define ERR_SUFFIX ".err"
+
+const char *TEST_PASS= "[ pass ]";
+const char *TEST_SKIP= "[ skip ]";
+const char *TEST_FAIL= "[ fail ]";
+const char *TEST_BAD= "[ bad ]";
+const char *TEST_IGNORE= "[ignore]";
+
+/******************************************************************************
+
+ global variables
+
+******************************************************************************/
+
+#ifdef __NETWARE__
+static char base_dir[FN_REFLEN]= "sys:/mysql";
+#else
+static char base_dir[FN_REFLEN]= "..";
+#endif
+static char db[FN_LEN]= "test";
+static char user[FN_LEN]= "root";
+static char password[FN_LEN]= "";
+
+int master_port= 9306;
+int slave_port= 9307;
+
+#if !defined(__NETWARE__) && !defined(__WIN__)
+static char master_socket[FN_REFLEN]= "./var/tmp/master.sock";
+static char slave_socket[FN_REFLEN]= "./var/tmp/slave.sock";
+#endif
+
+/* comma delimited list of tests to skip or empty string */
+#ifndef __WIN__
+static char skip_test[FN_REFLEN]= " lowercase_table3 , system_mysql_db_fix ";
+#else
+/*
+ The most ignore testes contain the calls of system command
+*/
+#define MAX_COUNT_TESTES 1024
+/*
+ lowercase_table3 is disabled by Gerg
+ system_mysql_db_fix is disabled by Gerg
+ sp contains a command system
+ rpl_EE_error contains a command system
+ rpl_loaddatalocal contains a command system
+ ndb_autodiscover contains a command system
+ rpl_rotate_logs contains a command system
+ repair contains a command system
+ rpl_trunc_binlog contains a command system
+ mysqldump contains a command system
+ rpl000001 makes non-exit loop...temporary skiped
+*/
+static char skip_test[FN_REFLEN]=
+" lowercase_table3 ,"
+" system_mysql_db_fix ,"
+" sp ,"
+" rpl_EE_error ,"
+" rpl_loaddatalocal ,"
+" ndb_autodiscover ,"
+" rpl_rotate_logs ,"
+" repair ,"
+" rpl_trunc_binlog ,"
+" mysqldump ,"
+" rpl000001 ";
+#endif
+static char ignore_test[FN_REFLEN]= "";
+
+static char bin_dir[FN_REFLEN];
+static char mysql_test_dir[FN_REFLEN];
+static char test_dir[FN_REFLEN];
+static char mysql_tmp_dir[FN_REFLEN];
+static char result_dir[FN_REFLEN];
+static char master_dir[FN_REFLEN];
+static char slave_dir[FN_REFLEN];
+static char lang_dir[FN_REFLEN];
+static char char_dir[FN_REFLEN];
+
+static char mysqladmin_file[FN_REFLEN];
+static char mysqld_file[FN_REFLEN];
+static char mysqltest_file[FN_REFLEN];
+#ifndef __WIN__
+static char master_pid[FN_REFLEN];
+static char slave_pid[FN_REFLEN];
+static char sh_file[FN_REFLEN]= "/bin/sh";
+#else
+static HANDLE master_pid;
+static HANDLE slave_pid;
+#endif
+
+static char master_opt[FN_REFLEN]= "";
+static char slave_opt[FN_REFLEN]= "";
+
+static char slave_master_info[FN_REFLEN]= "";
+
+static char master_init_script[FN_REFLEN]= "";
+static char slave_init_script[FN_REFLEN]= "";
+
+/* OpenSSL */
+static char ca_cert[FN_REFLEN];
+static char server_cert[FN_REFLEN];
+static char server_key[FN_REFLEN];
+static char client_cert[FN_REFLEN];
+static char client_key[FN_REFLEN];
+
+int total_skip= 0;
+int total_pass= 0;
+int total_fail= 0;
+int total_test= 0;
+
+int total_ignore= 0;
+
+int use_openssl= FALSE;
+int master_running= FALSE;
+int slave_running= FALSE;
+int skip_slave= TRUE;
+int single_test= TRUE;
+
+int restarts= 0;
+
+FILE *log_fd= NULL;
+
+/******************************************************************************
+
+ functions
+
+******************************************************************************/
+
+/******************************************************************************
+
+ prototypes
+
+******************************************************************************/
+
+void report_stats();
+void install_db(char *);
+void mysql_install_db();
+void start_master();
+void start_slave();
+void mysql_start();
+void stop_slave();
+void stop_master();
+void mysql_stop();
+void mysql_restart();
+int read_option(char *, char *);
+void run_test(char *);
+void setup(char *);
+void vlog(const char *, va_list);
+void mlog(const char *, ...);
+void log_info(const char *, ...);
+void log_error(const char *, ...);
+void log_errno(const char *, ...);
+void die(const char *);
+char *str_tok(char *string, const char *delim);
+#ifndef __WIN__
+void run_init_script(const char *script_name);
+#endif
+/******************************************************************************
+
+ report_stats()
+
+ Report the gathered statistics.
+
+******************************************************************************/
+
+void report_stats()
+{
+ if (total_fail == 0)
+ {
+ mlog("\nAll %d test(s) were successful.\n", total_test);
+ }
+ else
+ {
+ double percent= ((double)total_pass / total_test) * 100;
+
+ mlog("\nFailed %u/%u test(s), %.02f%% successful.\n",
+ total_fail, total_test, percent);
+ mlog("\nThe .out and .err files in %s may give you some\n", result_dir);
+ mlog("hint of what when wrong.\n");
+ mlog("\nIf you want to report this error, please first read "
+ "the documentation\n");
+ mlog("at: http://www.mysql.com/doc/M/y/MySQL_test_suite.html\n");
+ }
+}
+
+/******************************************************************************
+
+ install_db()
+
+ Install the a database.
+
+******************************************************************************/
+
+void install_db(char *datadir)
+{
+ arg_list_t al;
+ int err;
+ char input[FN_REFLEN];
+ char output[FN_REFLEN];
+ char error[FN_REFLEN];
+
+ /* input file */
+#ifdef __NETWARE__
+ snprintf(input, FN_REFLEN, "%s/bin/init_db.sql", base_dir);
+#else
+ snprintf(input, FN_REFLEN, "%s/mysql-test/init_db.sql", base_dir);
+#endif
+ snprintf(output, FN_REFLEN, "%s/install.out", datadir);
+ snprintf(error, FN_REFLEN, "%s/install.err", datadir);
+
+ /* args */
+ init_args(&al);
+ add_arg(&al, mysqld_file);
+ add_arg(&al, "--no-defaults");
+ add_arg(&al, "--bootstrap");
+ add_arg(&al, "--skip-grant-tables");
+ add_arg(&al, "--basedir=%s", base_dir);
+ add_arg(&al, "--datadir=%s", datadir);
+ add_arg(&al, "--skip-innodb");
+ add_arg(&al, "--skip-bdb");
+#ifndef __NETWARE__
+ add_arg(&al, "--character-sets-dir=%s", char_dir);
+ add_arg(&al, "--language=%s", lang_dir);
+#endif
+
+ /* spawn */
+ if ((err= spawn(mysqld_file, &al, TRUE, input, output, error, NULL)) != 0)
+ {
+ die("Unable to create database.");
+ }
+
+ /* free args */
+ free_args(&al);
+}
+
+/******************************************************************************
+
+ mysql_install_db()
+
+ Install the test databases.
+
+******************************************************************************/
+
+void mysql_install_db()
+{
+ char temp[FN_REFLEN];
+
+ /* var directory */
+ snprintf(temp, FN_REFLEN, "%s/var", mysql_test_dir);
+
+ /* clean up old direcotry */
+ del_tree(temp);
+
+ /* create var directory */
+#ifndef __WIN__
+ mkdir(temp, S_IRWXU);
+ /* create subdirectories */
+ mlog("Creating test-suite folders...\n");
+ snprintf(temp, FN_REFLEN, "%s/var/run", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, FN_REFLEN, "%s/var/tmp", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, FN_REFLEN, "%s/var/master-data", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, FN_REFLEN, "%s/var/master-data/mysql", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, FN_REFLEN, "%s/var/master-data/test", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, FN_REFLEN, "%s/var/slave-data", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, FN_REFLEN, "%s/var/slave-data/mysql", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+ snprintf(temp, FN_REFLEN, "%s/var/slave-data/test", mysql_test_dir);
+ mkdir(temp, S_IRWXU);
+#else
+ mkdir(temp);
+ /* create subdirectories */
+ mlog("Creating test-suite folders...\n");
+ snprintf(temp, FN_REFLEN, "%s/var/run", mysql_test_dir);
+ mkdir(temp);
+ snprintf(temp, FN_REFLEN, "%s/var/tmp", mysql_test_dir);
+ mkdir(temp);
+ snprintf(temp, FN_REFLEN, "%s/var/master-data", mysql_test_dir);
+ mkdir(temp);
+ snprintf(temp, FN_REFLEN, "%s/var/master-data/mysql", mysql_test_dir);
+ mkdir(temp);
+ snprintf(temp, FN_REFLEN, "%s/var/master-data/test", mysql_test_dir);
+ mkdir(temp);
+ snprintf(temp, FN_REFLEN, "%s/var/slave-data", mysql_test_dir);
+ mkdir(temp);
+ snprintf(temp, FN_REFLEN, "%s/var/slave-data/mysql", mysql_test_dir);
+ mkdir(temp);
+ snprintf(temp, FN_REFLEN, "%s/var/slave-data/test", mysql_test_dir);
+ mkdir(temp);
+#endif
+
+ /* install databases */
+ mlog("Creating test databases for master... \n");
+ install_db(master_dir);
+ mlog("Creating test databases for slave... \n");
+ install_db(slave_dir);
+}
+
+/******************************************************************************
+
+ start_master()
+
+ Start the master server.
+
+******************************************************************************/
+
+void start_master()
+{
+ arg_list_t al;
+ int err;
+ char master_out[FN_REFLEN];
+ char master_err[FN_REFLEN];
+/* char temp[FN_REFLEN]; */
+ char temp2[FN_REFLEN];
+
+ /* remove old berkeley db log files that can confuse the server */
+ removef("%s/log.*", master_dir);
+
+ /* remove stale binary logs */
+ removef("%s/var/log/*-bin.*", mysql_test_dir);
+
+ /* remove stale binary logs */
+ removef("%s/var/log/*.index", mysql_test_dir);
+
+ /* remove master.info file */
+ removef("%s/master.info", master_dir);
+
+ /* remove relay files */
+ removef("%s/var/log/*relay*", mysql_test_dir);
+
+ /* remove relay-log.info file */
+ removef("%s/relay-log.info", master_dir);
+
+ /* init script */
+ if (master_init_script[0] != 0)
+ {
+#ifdef __NETWARE__
+ /* TODO: use the scripts */
+ if (strinstr(master_init_script, "repair_part2-master.sh") != 0)
+ {
+ FILE *fp;
+
+ /* create an empty index file */
+ snprintf(temp, FN_REFLEN, "%s/test/t1.MYI", master_dir);
+ fp= fopen(temp, "wb+");
+
+ fputs("1", fp);
+
+ fclose(fp);
+ }
+#elif !defined(__WIN__)
+ run_init_script(master_init_script);
+#endif
+ }
+
+ /* redirection files */
+ snprintf(master_out, FN_REFLEN, "%s/var/run/master%u.out",
+ mysql_test_dir, restarts);
+ snprintf(master_err, FN_REFLEN, "%s/var/run/master%u.err",
+ mysql_test_dir, restarts);
+#ifndef __WIN__
+ snprintf(temp2,FN_REFLEN,"%s/var",mysql_test_dir);
+ mkdir(temp2,S_IRWXU);
+ snprintf(temp2,FN_REFLEN,"%s/var/log",mysql_test_dir);
+ mkdir(temp2,S_IRWXU);
+#else
+ snprintf(temp2,FN_REFLEN,"%s/var",mysql_test_dir);
+ mkdir(temp2);
+ snprintf(temp2,FN_REFLEN,"%s/var/log",mysql_test_dir);
+ mkdir(temp2);
+#endif
+ /* args */
+ init_args(&al);
+ add_arg(&al, "%s", mysqld_file);
+ add_arg(&al, "--no-defaults");
+ add_arg(&al, "--log-bin=%s/var/log/master-bin",mysql_test_dir);
+ add_arg(&al, "--server-id=1");
+ add_arg(&al, "--basedir=%s", base_dir);
+ add_arg(&al, "--port=%u", master_port);
+#if !defined(__NETWARE__) && !defined(__WIN__)
+ add_arg(&al, "--socket=%s",master_socket);
+#endif
+ add_arg(&al, "--local-infile");
+ add_arg(&al, "--core");
+ add_arg(&al, "--datadir=%s", master_dir);
+#ifndef __WIN__
+ add_arg(&al, "--pid-file=%s", master_pid);
+#endif
+ add_arg(&al, "--character-sets-dir=%s", char_dir);
+ add_arg(&al, "--tmpdir=%s", mysql_tmp_dir);
+ add_arg(&al, "--language=%s", lang_dir);
+#ifdef DEBUG /* only for debug builds */
+ add_arg(&al, "--debug");
+#endif
+
+ if (use_openssl)
+ {
+ add_arg(&al, "--ssl-ca=%s", ca_cert);
+ add_arg(&al, "--ssl-cert=%s", server_cert);
+ add_arg(&al, "--ssl-key=%s", server_key);
+ }
+
+ /* $MASTER_40_ARGS */
+ add_arg(&al, "--rpl-recovery-rank=1");
+ add_arg(&al, "--init-rpl-role=master");
+
+ /* $SMALL_SERVER */
+ add_arg(&al, "-O");
+ add_arg(&al, "key_buffer_size=1M");
+ add_arg(&al, "-O");
+ add_arg(&al, "sort_buffer=256K");
+ add_arg(&al, "-O");
+ add_arg(&al, "max_heap_table_size=1M");
+
+ /* $EXTRA_MASTER_OPT */
+ if (master_opt[0] != 0)
+ {
+ char *p;
+
+ p= (char *)str_tok(master_opt, " \t");
+ if (!strstr(master_opt, "timezone"))
+ {
+ while (p)
+ {
+ add_arg(&al, "%s", p);
+ p= (char *)str_tok(NULL, " \t");
+ }
+ }
+ }
+
+ /* remove the pid file if it exists */
+#ifndef __WIN__
+ remove(master_pid);
+#endif
+
+ /* spawn */
+#ifdef __WIN__
+ if ((err= spawn(mysqld_file, &al, FALSE, NULL,
+ master_out, master_err, &master_pid)) == 0)
+#else
+ if ((err= spawn(mysqld_file, &al, FALSE, NULL,
+ master_out, master_err, master_pid)) == 0)
+#endif
+ {
+ sleep_until_file_exists(master_pid);
+
+ if ((err= wait_for_server_start(bin_dir, mysqladmin_file, user, password,
+ master_port, mysql_tmp_dir)) == 0)
+ {
+ master_running= TRUE;
+ }
+ else
+ {
+ log_error("The master server went down early.");
+ }
+ }
+ else
+ {
+ log_error("Unable to start master server.");
+ }
+
+ /* free_args */
+ free_args(&al);
+}
+
+/******************************************************************************
+
+ start_slave()
+
+ Start the slave server.
+
+******************************************************************************/
+
+void start_slave()
+{
+ arg_list_t al;
+ int err;
+ char slave_out[FN_REFLEN];
+ char slave_err[FN_REFLEN];
+
+ /* skip? */
+ if (skip_slave) return;
+
+ /* remove stale binary logs */
+ removef("%s/*-bin.*", slave_dir);
+
+ /* remove stale binary logs */
+ removef("%s/*.index", slave_dir);
+
+ /* remove master.info file */
+ removef("%s/master.info", slave_dir);
+
+ /* remove relay files */
+ removef("%s/var/log/*relay*", mysql_test_dir);
+
+ /* remove relay-log.info file */
+ removef("%s/relay-log.info", slave_dir);
+
+ /* init script */
+ if (slave_init_script[0] != 0)
+ {
+#ifdef __NETWARE__
+ /* TODO: use the scripts */
+ if (strinstr(slave_init_script, "rpl000016-slave.sh") != 0)
+ {
+ /* create empty master.info file */
+ snprintf(temp, FN_REFLEN, "%s/master.info", slave_dir);
+ close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO));
+ }
+ else if (strinstr(slave_init_script, "rpl000017-slave.sh") != 0)
+ {
+ FILE *fp;
+
+ /* create a master.info file */
+ snprintf(temp, FN_REFLEN, "%s/master.info", slave_dir);
+ fp= fopen(temp, "wb+");
+
+ fputs("master-bin.000001\n", fp);
+ fputs("4\n", fp);
+ fputs("127.0.0.1\n", fp);
+ fputs("replicate\n", fp);
+ fputs("aaaaaaaaaaaaaaab\n", fp);
+ fputs("9306\n", fp);
+ fputs("1\n", fp);
+ fputs("0\n", fp);
+
+ fclose(fp);
+ }
+ else if (strinstr(slave_init_script, "rpl_rotate_logs-slave.sh") != 0)
+ {
+ /* create empty master.info file */
+ snprintf(temp, FN_REFLEN, "%s/master.info", slave_dir);
+ close(open(temp, O_WRONLY | O_CREAT,S_IRWXU|S_IRWXG|S_IRWXO));
+ }
+#elif !defined(__WIN__)
+ run_init_script(slave_init_script);
+#endif
+ }
+
+ /* redirection files */
+ snprintf(slave_out, FN_REFLEN, "%s/var/run/slave%u.out",
+ mysql_test_dir, restarts);
+ snprintf(slave_err, FN_REFLEN, "%s/var/run/slave%u.err",
+ mysql_test_dir, restarts);
+
+ /* args */
+ init_args(&al);
+ add_arg(&al, "%s", mysqld_file);
+ add_arg(&al, "--no-defaults");
+ add_arg(&al, "--log-bin=slave-bin");
+ add_arg(&al, "--relay_log=slave-relay-bin");
+ add_arg(&al, "--basedir=%s", base_dir);
+ add_arg(&al, "--port=%u", slave_port);
+#if !defined(__NETWARE__) && !defined(__WIN__)
+ add_arg(&al, "--socket=%s",slave_socket);
+#endif
+ add_arg(&al, "--datadir=%s", slave_dir);
+#ifndef __WIN__
+ add_arg(&al, "--pid-file=%s", slave_pid);
+#endif
+ add_arg(&al, "--character-sets-dir=%s", char_dir);
+ add_arg(&al, "--core");
+ add_arg(&al, "--tmpdir=%s", mysql_tmp_dir);
+ add_arg(&al, "--language=%s", lang_dir);
+
+ add_arg(&al, "--exit-info=256");
+ add_arg(&al, "--log-slave-updates");
+ add_arg(&al, "--init-rpl-role=slave");
+ add_arg(&al, "--skip-innodb");
+ add_arg(&al, "--skip-slave-start");
+ add_arg(&al, "--slave-load-tmpdir=../../var/tmp");
+
+ add_arg(&al, "--report-user=%s", user);
+ add_arg(&al, "--report-host=127.0.0.1");
+ add_arg(&al, "--report-port=%u", slave_port);
+
+ add_arg(&al, "--master-retry-count=10");
+ add_arg(&al, "-O");
+ add_arg(&al, "slave_net_timeout=10");
+#ifdef DEBUG /* only for debug builds */
+ add_arg(&al, "--debug");
+#endif
+
+ if (use_openssl)
+ {
+ add_arg(&al, "--ssl-ca=%s", ca_cert);
+ add_arg(&al, "--ssl-cert=%s", server_cert);
+ add_arg(&al, "--ssl-key=%s", server_key);
+ }
+
+ /* slave master info */
+ if (slave_master_info[0] != 0)
+ {
+ char *p;
+
+ p= (char *)str_tok(slave_master_info, " \t");
+
+ while (p)
+ {
+ add_arg(&al, "%s", p);
+ p= (char *)str_tok(NULL, " \t");
+ }
+ }
+ else
+ {
+ add_arg(&al, "--master-user=%s", user);
+ add_arg(&al, "--master-password=%s", password);
+ add_arg(&al, "--master-host=127.0.0.1");
+ add_arg(&al, "--master-port=%u", master_port);
+ add_arg(&al, "--master-connect-retry=1");
+ add_arg(&al, "--server-id=2");
+ add_arg(&al, "--rpl-recovery-rank=2");
+ }
+
+ /* small server */
+ add_arg(&al, "-O");
+ add_arg(&al, "key_buffer_size=1M");
+ add_arg(&al, "-O");
+ add_arg(&al, "sort_buffer=256K");
+ add_arg(&al, "-O");
+ add_arg(&al, "max_heap_table_size=1M");
+
+
+ /* opt args */
+ if (slave_opt[0] != 0)
+ {
+ char *p;
+
+ p= (char *)str_tok(slave_opt, " \t");
+
+ while (p)
+ {
+ add_arg(&al, "%s", p);
+ p= (char *)str_tok(NULL, " \t");
+ }
+ }
+
+ /* remove the pid file if it exists */
+#ifndef __WIN__
+ remove(slave_pid);
+#endif
+ /* spawn */
+#ifdef __WIN__
+ if ((err= spawn(mysqld_file, &al, FALSE, NULL,
+ slave_out, slave_err, &slave_pid)) == 0)
+#else
+ if ((err= spawn(mysqld_file, &al, FALSE, NULL,
+ slave_out, slave_err, slave_pid)) == 0)
+#endif
+ {
+ sleep_until_file_exists(slave_pid);
+
+ if ((err= wait_for_server_start(bin_dir, mysqladmin_file, user, password,
+ slave_port, mysql_tmp_dir)) == 0)
+ {
+ slave_running= TRUE;
+ }
+ else
+ {
+ log_error("The slave server went down early.");
+ }
+ }
+ else
+ {
+ log_error("Unable to start slave server.");
+ }
+
+ /* free args */
+ free_args(&al);
+}
+
+/******************************************************************************
+
+ mysql_start()
+
+ Start the mysql servers.
+
+******************************************************************************/
+
+void mysql_start()
+{
+/* log_info("Starting the MySQL server(s): %u", ++restarts); */
+ start_master();
+
+ start_slave();
+
+ /* activate the test screen */
+#ifdef __NETWARE__
+ ActivateScreen(getscreenhandle());
+#endif
+}
+
+/******************************************************************************
+
+ stop_slave()
+
+ Stop the slave server.
+
+******************************************************************************/
+
+void stop_slave()
+{
+ int err;
+
+ /* running? */
+ if (!slave_running) return;
+
+ /* stop */
+ if ((err= stop_server(bin_dir, mysqladmin_file, user, password,
+ slave_port, slave_pid, mysql_tmp_dir)) == 0)
+ {
+ slave_running= FALSE;
+ }
+ else
+ {
+ log_error("Unable to stop slave server.");
+ }
+}
+
+/******************************************************************************
+
+ stop_master()
+
+ Stop the master server.
+
+******************************************************************************/
+
+void stop_master()
+{
+ int err;
+
+ /* running? */
+ if (!master_running) return;
+
+ if ((err= stop_server(bin_dir, mysqladmin_file, user, password,
+ master_port, master_pid, mysql_tmp_dir)) == 0)
+ {
+ master_running= FALSE;
+ }
+ else
+ {
+ log_error("Unable to stop master server.");
+ }
+}
+
+/******************************************************************************
+
+ mysql_stop()
+
+ Stop the mysql servers.
+
+******************************************************************************/
+
+void mysql_stop()
+{
+
+ stop_master();
+
+ stop_slave();
+
+ /* activate the test screen */
+#ifdef __NETWARE__
+ ActivateScreen(getscreenhandle());
+#endif
+}
+
+/******************************************************************************
+
+ mysql_restart()
+
+ Restart the mysql servers.
+
+******************************************************************************/
+
+void mysql_restart()
+{
+/* log_info("Restarting the MySQL server(s): %u", ++restarts); */
+
+ mysql_stop();
+
+ mlog(DASH);
+
+ mysql_start();
+}
+
+/******************************************************************************
+
+ read_option()
+
+ Read the option file.
+
+******************************************************************************/
+
+int read_option(char *opt_file, char *opt)
+{
+ int fd, err;
+ char *p;
+ char buf[FN_REFLEN];
+
+ /* copy current option */
+ strncpy(buf, opt, FN_REFLEN);
+
+ /* open options file */
+ fd= open(opt_file, O_RDONLY);
+ err= read(fd, opt, FN_REFLEN);
+ close(fd);
+
+ if (err > 0)
+ {
+ /* terminate string */
+ if ((p= strchr(opt, '\n')) != NULL)
+ {
+ *p= 0;
+
+ /* check for a '\r' */
+ if ((p= strchr(opt, '\r')) != NULL)
+ {
+ *p= 0;
+ }
+ }
+ else
+ {
+ opt[err]= 0;
+ }
+
+ /* check for $MYSQL_TEST_DIR */
+ if ((p= strstr(opt, "$MYSQL_TEST_DIR")) != NULL)
+ {
+ char temp[FN_REFLEN];
+
+ *p= 0;
+
+ strcpy(temp, p + strlen("$MYSQL_TEST_DIR"));
+ strcat(opt, mysql_test_dir);
+ strcat(opt, temp);
+ }
+ /* Check for double backslash and replace it with single bakslash */
+ if ((p= strstr(opt, "\\\\")) != NULL)
+ {
+ /* bmove is guranteed to work byte by byte */
+ bmove(p, p+1, strlen(p+1));
+ }
+ }
+ else
+ {
+ /* clear option */
+ *opt= 0;
+ }
+
+ /* compare current option with previous */
+ return strcmp(opt, buf);
+}
+
+/******************************************************************************
+
+ run_test()
+
+ Run the given test case.
+
+******************************************************************************/
+
+void run_test(char *test)
+{
+ char temp[FN_REFLEN];
+ const char *rstr;
+ int skip= FALSE, ignore=FALSE;
+ int restart= FALSE;
+ int flag= FALSE;
+ struct stat info;
+
+ /* skip tests in the skip list */
+ snprintf(temp, FN_REFLEN, " %s ", test);
+ skip= (strinstr(skip_test, temp) != 0);
+ if (skip == FALSE)
+ ignore= (strinstr(ignore_test, temp) != 0);
+
+ snprintf(master_init_script, FN_REFLEN, "%s/%s-master.sh", test_dir, test);
+ snprintf(slave_init_script, FN_REFLEN, "%s/%s-slave.sh", test_dir, test);
+#ifdef __WIN__
+ if (! stat(master_init_script, &info))
+ skip= TRUE;
+ if (!stat(slave_init_script, &info))
+ skip= TRUE;
+#endif
+ if (ignore)
+ {
+ /* show test */
+ mlog("%-46s ", test);
+
+ /* ignore */
+ rstr= TEST_IGNORE;
+ ++total_ignore;
+ }
+ else if (!skip) /* skip test? */
+ {
+ char test_file[FN_REFLEN];
+ char master_opt_file[FN_REFLEN];
+ char slave_opt_file[FN_REFLEN];
+ char slave_master_info_file[FN_REFLEN];
+ char result_file[FN_REFLEN];
+ char reject_file[FN_REFLEN];
+ char out_file[FN_REFLEN];
+ char err_file[FN_REFLEN];
+ int err;
+ arg_list_t al;
+#ifdef __WIN__
+ /* Clean test database */
+ removef("%s/test/*.*", master_dir);
+ removef("%s/test/*.*", slave_dir);
+ removef("%s/mysqltest/*.*", master_dir);
+ removef("%s/mysqltest/*.*", slave_dir);
+
+#endif
+ /* skip slave? */
+ flag= skip_slave;
+ skip_slave= (strncmp(test, "rpl", 3) != 0);
+ if (flag != skip_slave) restart= TRUE;
+
+ /* create files */
+ snprintf(master_opt_file, FN_REFLEN, "%s/%s-master.opt", test_dir, test);
+ snprintf(slave_opt_file, FN_REFLEN, "%s/%s-slave.opt", test_dir, test);
+ snprintf(slave_master_info_file, FN_REFLEN, "%s/%s.slave-mi",
+ test_dir, test);
+ snprintf(reject_file, FN_REFLEN, "%s/%s%s",
+ result_dir, test, REJECT_SUFFIX);
+ snprintf(out_file, FN_REFLEN, "%s/%s%s", result_dir, test, OUT_SUFFIX);
+ snprintf(err_file, FN_REFLEN, "%s/%s%s", result_dir, test, ERR_SUFFIX);
+
+ /* netware specific files */
+ snprintf(test_file, FN_REFLEN, "%s/%s%s", test_dir, test, NW_TEST_SUFFIX);
+ if (stat(test_file, &info))
+ {
+ snprintf(test_file, FN_REFLEN, "%s/%s%s", test_dir, test, TEST_SUFFIX);
+ if (access(test_file,0))
+ {
+ printf("Invalid test name %s, %s file not found\n",test,test_file);
+ return;
+ }
+ }
+
+ snprintf(result_file, FN_REFLEN, "%s/%s%s",
+ result_dir, test, NW_RESULT_SUFFIX);
+ if (stat(result_file, &info))
+ {
+ snprintf(result_file, FN_REFLEN, "%s/%s%s",
+ result_dir, test, RESULT_SUFFIX);
+ }
+
+ /* init scripts */
+ if (stat(master_init_script, &info))
+ master_init_script[0]= 0;
+ else
+ restart= TRUE;
+
+ if (stat(slave_init_script, &info))
+ slave_init_script[0]= 0;
+ else
+ restart= TRUE;
+
+ /* read options */
+ if (read_option(master_opt_file, master_opt)) restart= TRUE;
+ if (read_option(slave_opt_file, slave_opt)) restart= TRUE;
+ if (read_option(slave_master_info_file, slave_master_info)) restart= TRUE;
+
+ /* cleanup previous run */
+ remove(reject_file);
+ remove(out_file);
+ remove(err_file);
+
+ /* start or restart? */
+ if (!master_running) mysql_start();
+ else if (restart) mysql_restart();
+
+ /* let the system stabalize */
+ sleep(1);
+
+ /* show test */
+ mlog("%-46s ", test);
+
+ /* args */
+ init_args(&al);
+ add_arg(&al, "%s", mysqltest_file);
+ add_arg(&al, "--no-defaults");
+ add_arg(&al, "--port=%u", master_port);
+#if !defined(__NETWARE__) && !defined(__WIN__)
+ add_arg(&al, "--socket=%s", master_socket);
+ add_arg(&al, "--tmpdir=%s", mysql_tmp_dir);
+#endif
+ add_arg(&al, "--database=%s", db);
+ add_arg(&al, "--user=%s", user);
+ add_arg(&al, "--password=%s", password);
+ add_arg(&al, "--silent");
+ add_arg(&al, "--basedir=%s/", mysql_test_dir);
+ add_arg(&al, "--host=127.0.0.1");
+ add_arg(&al, "-v");
+ add_arg(&al, "-R");
+ add_arg(&al, "%s", result_file);
+
+ if (use_openssl)
+ {
+ add_arg(&al, "--ssl-ca=%s", ca_cert);
+ add_arg(&al, "--ssl-cert=%s", client_cert);
+ add_arg(&al, "--ssl-key=%s", client_key);
+ }
+
+ /* spawn */
+ err= spawn(mysqltest_file, &al, TRUE, test_file, out_file, err_file, NULL);
+
+ /* free args */
+ free_args(&al);
+
+ remove_empty_file(out_file);
+ remove_empty_file(err_file);
+
+ if (err == 0)
+ {
+ /* pass */
+ rstr= TEST_PASS;
+ ++total_pass;
+
+ /* increment total */
+ ++total_test;
+ }
+ else if (err == 2)
+ {
+ /* skip */
+ rstr= TEST_SKIP;
+ ++total_skip;
+ }
+ else if (err == 1)
+ {
+ /* fail */
+ rstr= TEST_FAIL;
+ ++total_fail;
+
+ /* increment total */
+ ++total_test;
+ }
+ else
+ {
+ rstr= TEST_BAD;
+ }
+ }
+ else /* early skips */
+ {
+ /* show test */
+ mlog("%-46s ", test);
+
+ /* skip */
+ rstr= TEST_SKIP;
+ ++total_skip;
+ }
+
+ /* result */
+ mlog("%-14s\n", rstr);
+}
+
+/******************************************************************************
+
+ vlog()
+
+ Log the message.
+
+******************************************************************************/
+
+void vlog(const char *format, va_list ap)
+{
+ vfprintf(stdout, format, ap);
+ fflush(stdout);
+
+ if (log_fd)
+ {
+ vfprintf(log_fd, format, ap);
+ fflush(log_fd);
+ }
+}
+
+/******************************************************************************
+
+ log()
+
+ Log the message.
+
+******************************************************************************/
+
+void mlog(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ vlog(format, ap);
+
+ va_end(ap);
+}
+
+/******************************************************************************
+
+ log_info()
+
+ Log the given information.
+
+******************************************************************************/
+
+void log_info(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ mlog("-- INFO : ");
+ vlog(format, ap);
+ mlog("\n");
+
+ va_end(ap);
+}
+
+/******************************************************************************
+
+ log_error()
+
+ Log the given error.
+
+******************************************************************************/
+
+void log_error(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ mlog("-- ERROR: ");
+ vlog(format, ap);
+ mlog("\n");
+
+ va_end(ap);
+}
+
+/******************************************************************************
+
+ log_errno()
+
+ Log the given error and errno.
+
+******************************************************************************/
+
+void log_errno(const char *format, ...)
+{
+ va_list ap;
+
+ va_start(ap, format);
+
+ mlog("-- ERROR: (%003u) ", errno);
+ vlog(format, ap);
+ mlog("\n");
+
+ va_end(ap);
+}
+
+/******************************************************************************
+
+ die()
+
+ Exit the application.
+
+******************************************************************************/
+
+void die(const char *msg)
+{
+ log_error(msg);
+#ifdef __NETWARE__
+ pressanykey();
+#endif
+ exit(-1);
+}
+
+/******************************************************************************
+
+ setup()
+
+ Setup the mysql test enviornment.
+
+******************************************************************************/
+
+void setup(char *file __attribute__((unused)))
+{
+ char temp[FN_REFLEN];
+ char file_path[FN_REFLEN*2];
+ char *p;
+ int position;
+
+ /* set the timezone for the timestamp test */
+#ifdef __WIN__
+ _putenv( "TZ=GMT-3" );
+#else
+ putenv((char *)"TZ=GMT-3");
+#endif
+ /* find base dir */
+#ifdef __NETWARE__
+ strcpy(temp, strlwr(file));
+ while ((p= strchr(temp, '\\')) != NULL) *p= '/';
+#else
+ getcwd(temp, FN_REFLEN);
+ position= strlen(temp);
+ temp[position]= '/';
+ temp[position+1]= 0;
+#ifdef __WIN__
+ while ((p= strchr(temp, '\\')) != NULL) *p= '/';
+#endif
+#endif
+
+ if ((position= strinstr(temp, "/mysql-test/")) != 0)
+ {
+ p= temp + position - 1;
+ *p= 0;
+ strcpy(base_dir, temp);
+ }
+
+ log_info("Currect directory: %s",base_dir);
+
+#ifdef __NETWARE__
+ /* setup paths */
+ snprintf(bin_dir, FN_REFLEN, "%s/bin", base_dir);
+ snprintf(mysql_test_dir, FN_REFLEN, "%s/mysql-test", base_dir);
+ snprintf(test_dir, FN_REFLEN, "%s/t", mysql_test_dir);
+ snprintf(mysql_tmp_dir, FN_REFLEN, "%s/var/tmp", mysql_test_dir);
+ snprintf(result_dir, FN_REFLEN, "%s/r", mysql_test_dir);
+ snprintf(master_dir, FN_REFLEN, "%s/var/master-data", mysql_test_dir);
+ snprintf(slave_dir, FN_REFLEN, "%s/var/slave-data", mysql_test_dir);
+ snprintf(lang_dir, FN_REFLEN, "%s/share/english", base_dir);
+ snprintf(char_dir, FN_REFLEN, "%s/share/charsets", base_dir);
+
+#ifdef HAVE_OPENSSL
+ use_openssl= TRUE;
+#endif /* HAVE_OPENSSL */
+
+ /* OpenSSL paths */
+ snprintf(ca_cert, FN_REFLEN, "%s/SSL/cacert.pem", base_dir);
+ snprintf(server_cert, FN_REFLEN, "%s/SSL/server-cert.pem", base_dir);
+ snprintf(server_key, FN_REFLEN, "%s/SSL/server-key.pem", base_dir);
+ snprintf(client_cert, FN_REFLEN, "%s/SSL/client-cert.pem", base_dir);
+ snprintf(client_key, FN_REFLEN, "%s/SSL/client-key.pem", base_dir);
+
+ /* setup files */
+ snprintf(mysqld_file, FN_REFLEN, "%s/mysqld", bin_dir);
+ snprintf(mysqltest_file, FN_REFLEN, "%s/mysqltest", bin_dir);
+ snprintf(mysqladmin_file, FN_REFLEN, "%s/mysqladmin", bin_dir);
+ snprintf(master_pid, FN_REFLEN, "%s/var/run/master.pid", mysql_test_dir);
+ snprintf(slave_pid, FN_REFLEN, "%s/var/run/slave.pid", mysql_test_dir);
+#elif __WIN__
+ /* setup paths */
+#ifdef _DEBUG
+ snprintf(bin_dir, FN_REFLEN, "%s/client_debug", base_dir);
+#else
+ snprintf(bin_dir, FN_REFLEN, "%s/client_release", base_dir);
+#endif
+ snprintf(mysql_test_dir, FN_REFLEN, "%s/mysql-test", base_dir);
+ snprintf(test_dir, FN_REFLEN, "%s/t", mysql_test_dir);
+ snprintf(mysql_tmp_dir, FN_REFLEN, "%s/var/tmp", mysql_test_dir);
+ snprintf(result_dir, FN_REFLEN, "%s/r", mysql_test_dir);
+ snprintf(master_dir, FN_REFLEN, "%s/var/master-data", mysql_test_dir);
+ snprintf(slave_dir, FN_REFLEN, "%s/var/slave-data", mysql_test_dir);
+ snprintf(lang_dir, FN_REFLEN, "%s/share/english", base_dir);
+ snprintf(char_dir, FN_REFLEN, "%s/share/charsets", base_dir);
+
+#ifdef HAVE_OPENSSL
+ use_openssl= TRUE;
+#endif /* HAVE_OPENSSL */
+
+ /* OpenSSL paths */
+ snprintf(ca_cert, FN_REFLEN, "%s/SSL/cacert.pem", base_dir);
+ snprintf(server_cert, FN_REFLEN, "%s/SSL/server-cert.pem", base_dir);
+ snprintf(server_key, FN_REFLEN, "%s/SSL/server-key.pem", base_dir);
+ snprintf(client_cert, FN_REFLEN, "%s/SSL/client-cert.pem", base_dir);
+ snprintf(client_key, FN_REFLEN, "%s/SSL/client-key.pem", base_dir);
+
+ /* setup files */
+ snprintf(mysqld_file, FN_REFLEN, "%s/mysqld.exe", bin_dir);
+ snprintf(mysqltest_file, FN_REFLEN, "%s/mysqltest.exe", bin_dir);
+ snprintf(mysqladmin_file, FN_REFLEN, "%s/mysqladmin.exe", bin_dir);
+#else
+ /* setup paths */
+ snprintf(bin_dir, FN_REFLEN, "%s/client", base_dir);
+ snprintf(mysql_test_dir, FN_REFLEN, "%s/mysql-test", base_dir);
+ snprintf(test_dir, FN_REFLEN, "%s/t", mysql_test_dir);
+ snprintf(mysql_tmp_dir, FN_REFLEN, "%s/var/tmp", mysql_test_dir);
+ snprintf(result_dir, FN_REFLEN, "%s/r", mysql_test_dir);
+ snprintf(master_dir, FN_REFLEN, "%s/var/master-data", mysql_test_dir);
+ snprintf(slave_dir, FN_REFLEN, "%s/var/slave-data", mysql_test_dir);
+ snprintf(lang_dir, FN_REFLEN, "%s/sql/share/english", base_dir);
+ snprintf(char_dir, FN_REFLEN, "%s/sql/share/charsets", base_dir);
+
+#ifdef HAVE_OPENSSL
+ use_openssl= TRUE;
+#endif /* HAVE_OPENSSL */
+
+ /* OpenSSL paths */
+ snprintf(ca_cert, FN_REFLEN, "%s/SSL/cacert.pem", base_dir);
+ snprintf(server_cert, FN_REFLEN, "%s/SSL/server-cert.pem", base_dir);
+ snprintf(server_key, FN_REFLEN, "%s/SSL/server-key.pem", base_dir);
+ snprintf(client_cert, FN_REFLEN, "%s/SSL/client-cert.pem", base_dir);
+ snprintf(client_key, FN_REFLEN, "%s/SSL/client-key.pem", base_dir);
+
+ /* setup files */
+ snprintf(mysqld_file, FN_REFLEN, "%s/sql/mysqld", base_dir);
+ snprintf(mysqltest_file, FN_REFLEN, "%s/mysqltest", bin_dir);
+ snprintf(mysqladmin_file, FN_REFLEN, "%s/mysqladmin", bin_dir);
+ snprintf(master_pid, FN_REFLEN, "%s/var/run/master.pid", mysql_test_dir);
+ snprintf(slave_pid, FN_REFLEN, "%s/var/run/slave.pid", mysql_test_dir);
+
+ snprintf(master_socket,FN_REFLEN, "%s/var/tmp/master.sock", mysql_test_dir);
+ snprintf(slave_socket,FN_REFLEN, "%s/var/tmp/slave.sock", mysql_test_dir);
+
+#endif
+ /* create log file */
+ snprintf(temp, FN_REFLEN, "%s/mysql-test-run.log", mysql_test_dir);
+ if ((log_fd= fopen(temp, "w+")) == NULL)
+ {
+ log_errno("Unable to create log file.");
+ }
+
+ /* prepare skip test list */
+ while ((p= strchr(skip_test, ',')) != NULL) *p= ' ';
+ strcpy(temp, strlwr(skip_test));
+ snprintf(skip_test, FN_REFLEN, " %s ", temp);
+
+ /* environment */
+#ifdef __NETWARE__
+ setenv("MYSQL_TEST_DIR", mysql_test_dir, 1);
+ snprintf(file_path, FN_REFLEN*2,
+ "%s/client/mysqldump --no-defaults -u root --port=%u",
+ bin_dir, master_port);
+ setenv("MYSQL_DUMP", file_path, 1);
+ snprintf(file_path, FN_REFLEN*2,
+ "%s/client/mysqlbinlog --no-defaults --local-load=%s",
+ bin_dir, mysql_tmp_dir);
+ setenv("MYSQL_BINLOG", file_path, 1);
+#elif __WIN__
+ snprintf(file_path,FN_REFLEN,"MYSQL_TEST_DIR=%s",mysql_test_dir);
+ _putenv(file_path);
+ snprintf(file_path, FN_REFLEN*2,
+ "MYSQL_DUMP=%s/mysqldump.exe --no-defaults -u root --port=%u",
+ bin_dir, master_port);
+ _putenv(file_path);
+ snprintf(file_path, FN_REFLEN*2,
+ "MYSQL_BINLOG=%s/mysqlbinlog.exe --no-defaults --local-load=%s",
+ bin_dir, mysql_tmp_dir);
+ _putenv(file_path);
+#else
+ snprintf(file_path,FN_REFLEN,"MYSQL_TEST_DIR=%s",mysql_test_dir);
+ putenv(file_path);
+ snprintf(file_path, FN_REFLEN*2,
+ "MYSQL_DUMP=%s/mysqldump --no-defaults -u root --port=%u --socket=%s",
+ bin_dir, master_port, master_socket);
+ putenv(file_path);
+ snprintf(file_path, FN_REFLEN*2,
+ "MYSQL_BINLOG=%s/mysqlbinlog --no-defaults --local-load=%s",
+ bin_dir, mysql_tmp_dir);
+ putenv(file_path);
+#endif
+
+#ifndef __WIN__
+ putenv((char *)"MASTER_MYPORT=9306");
+ putenv((char *)"SLAVE_MYPORT=9307");
+ putenv((char *)"MYSQL_TCP_PORT=3306");
+#else
+ _putenv("MASTER_MYPORT=9306");
+ _putenv("SLAVE_MYPORT=9307");
+ _putenv("MYSQL_TCP_PORT=3306");
+#endif
+
+}
+
+/******************************************************************************
+
+ main()
+
+******************************************************************************/
+
+int main(int argc, char **argv)
+{
+ int is_ignore_list= 0;
+ /* setup */
+ setup(argv[0]);
+
+ /*
+ The --ignore option is comma saperated list of test cases to skip and
+ should be very first command line option to the test suite.
+
+ The usage is now:
+ mysql_test_run --ignore=test1,test2 test3 test4
+ where test1 and test2 are test cases to ignore
+ and test3 and test4 are test cases to run.
+ */
+ if (argc >= 2 && !strnicmp(argv[1], "--ignore=", sizeof("--ignore=")-1))
+ {
+ char *temp, *token;
+ temp= strdup(strchr(argv[1],'=') + 1);
+ for (token=str_tok(temp, ","); token != NULL; token=str_tok(NULL, ","))
+ {
+ if (strlen(ignore_test) + strlen(token) + 2 <= FN_REFLEN-1)
+ sprintf(ignore_test+strlen(ignore_test), " %s ", token);
+ else
+ {
+ free(temp);
+ die("ignore list too long.");
+ }
+ }
+ free(temp);
+ is_ignore_list= 1;
+ }
+ /* header */
+#ifndef __WIN__
+ mlog("MySQL Server %s, for %s (%s)\n\n", VERSION, SYSTEM_TYPE, MACHINE_TYPE);
+#else
+ mlog("MySQL Server ---, for %s (%s)\n\n", SYSTEM_TYPE, MACHINE_TYPE);
+#endif
+
+ mlog("Initializing Tests...\n");
+
+ /* install test databases */
+ mysql_install_db();
+
+ mlog("Starting Tests...\n");
+
+ mlog("\n");
+ mlog(HEADER);
+ mlog(DASH);
+
+ if ( argc > 1 + is_ignore_list )
+ {
+ int i;
+
+ /* single test */
+ single_test= TRUE;
+
+ for (i= 1 + is_ignore_list; i < argc; i++)
+ {
+ /* run given test */
+ run_test(argv[i]);
+ }
+ }
+ else
+ {
+ /* run all tests */
+#ifndef __WIN__
+ struct dirent *entry;
+ DIR *parent;
+ char test[FN_LEN];
+ int position;
+
+ /* FIXME are we sure the list is sorted if using readdir()? */
+ if ((parent= opendir(test_dir)) == NULL) /* Not thread safe */
+ die("Unable to open tests directory.");
+ else
+ {
+ while ((entry= readdir(parent)) != NULL) /* Not thread safe */
+ {
+ strcpy(test, strlwr(entry->d_name));
+ /* find the test suffix */
+ if ((position= strinstr(test, TEST_SUFFIX)) != 0)
+ {
+ /* null terminate at the suffix */
+ *(test + position - 1)= '\0';
+ /* run test */
+ run_test(test);
+ }
+ }
+ closedir(parent);
+ }
+#else
+ struct _finddata_t dir;
+ intptr_t handle;
+ char test[FN_LEN];
+ char mask[FN_REFLEN];
+ char *p;
+ int position;
+ char **names= 0;
+ char **testes= 0;
+ int name_index;
+ int index;
+
+ /* single test */
+ single_test= FALSE;
+
+ snprintf(mask,FN_REFLEN,"%s/*.test",test_dir);
+
+ if ((handle=_findfirst(mask,&dir)) == -1L)
+ {
+ die("Unable to open tests directory.");
+ }
+
+ names= malloc(MAX_COUNT_TESTES*4);
+ testes= names;
+ name_index= 0;
+
+ do
+ {
+ if (!(dir.attrib & _A_SUBDIR))
+ {
+ strcpy(test, strlwr(dir.name));
+
+ /* find the test suffix */
+ if ((position= strinstr(test, TEST_SUFFIX)) != 0)
+ {
+ p= test + position - 1;
+ /* null terminate at the suffix */
+ *p= 0;
+
+ /* insert test */
+ *names= malloc(FN_REFLEN);
+ strcpy(*names,test);
+ names++;
+ name_index++;
+ }
+ }
+ }while (_findnext(handle,&dir) == 0);
+
+ _findclose(handle);
+
+ qsort( (void *)testes, name_index, sizeof( char * ), compare );
+
+ for (index= 0; index <= name_index; index++)
+ {
+ run_test(testes[index]);
+ free(testes[index]);
+ }
+
+ free(testes);
+#endif
+ }
+
+ /* stop server */
+ mysql_stop();
+
+ mlog(DASH);
+ mlog("\n");
+
+ mlog("Ending Tests...\n");
+
+ /* report stats */
+ report_stats();
+
+ /* close log */
+ if (log_fd) fclose(log_fd);
+
+ /* keep results up */
+#ifdef __NETWARE__
+ pressanykey();
+#endif
+ return 0;
+}
+
+
+/*
+ Synopsis:
+ This function breaks the string into a sequence of tokens. The difference
+ between this function and strtok is that it respects the quoted string i.e.
+ it skips any delimiter character within the quoted part of the string.
+ It return tokens by eliminating quote character. It modifies the input string
+ passed. It will work with whitespace delimeter but may not work properly with
+ other delimeter. If the delimeter will contain any quote character, then
+ function will not tokenize and will return null string.
+ e.g. if input string is
+ --init-slave="set global max_connections=500" --skip-external-locking
+ then the output will two string i.e.
+ --init-slave=set global max_connections=500
+ --skip-external-locking
+
+Arguments:
+ string: input string
+ delim: set of delimiter character
+Output:
+ return the null terminated token of NULL.
+*/
+
+char *str_tok(char *string, const char *delim)
+{
+ char *token; /* current token received from strtok */
+ char *qt_token; /* token delimeted by the matching pair of quote */
+ /*
+ if there are any quote chars found in the token then this variable
+ will hold the concatenated string to return to the caller
+ */
+ char *ptr_token=NULL;
+ /* pointer to the quote character in the token from strtok */
+ char *ptr_quote=NULL;
+
+ /* See if the delimeter contains any quote character */
+ if (strchr(delim,'\'') || strchr(delim,'\"'))
+ return NULL;
+
+ /* repeate till we are getting some token from strtok */
+ while ((token= (char*)strtok(string, delim) ) != NULL)
+ {
+ /*
+ make the input string NULL so that next time onward strtok can
+ be called with NULL input string.
+ */
+ string= NULL;
+ /* We don't need to remove any quote character for Windows version */
+#ifndef __WIN__
+ /* check if the current token contain double quote character*/
+ if ((ptr_quote= (char*)strchr(token,'\"')) != NULL)
+ {
+ /*
+ get the matching the matching double quote in the remaining
+ input string
+ */
+ qt_token= (char*)strtok(NULL,"\"");
+ }
+ /* check if the current token contain single quote character*/
+ else if ((ptr_quote= (char*)strchr(token,'\'')) != NULL)
+ {
+ /*
+ get the matching the matching single quote in the remaining
+ input string
+ */
+ qt_token= (char*)strtok(NULL,"\'");
+ }
+#endif
+ /*
+ if the current token does not contains any quote character then
+ return to the caller.
+ */
+ if (ptr_quote == NULL)
+ {
+ /*
+ if there is any earlier token i.e. ptr_token then append the
+ current token in it and return it else return the current
+ token directly
+ */
+ return ptr_token ? strcat(ptr_token,token) : token;
+ }
+
+ /*
+ remove the quote character i.e. make NULL so that the token will
+ be devided in two part and later both part can be concatenated
+ and hence quote will be removed
+ */
+ *ptr_quote= 0;
+
+ /* check if ptr_token has been initialized or not */
+ if (ptr_token == NULL)
+ {
+ /* initialize the ptr_token with current token */
+ ptr_token= token;
+ /* copy entire string between matching pair of quote*/
+ sprintf(ptr_token+strlen(ptr_token),"%s %s", ptr_quote+1, qt_token);
+ }
+ else
+ {
+ /*
+ copy the current token and entire string between matching pair
+ of quote
+ */
+ if (qt_token == NULL)
+ {
+ sprintf(ptr_token+strlen(ptr_token),"%s%s", token, ptr_quote+1);
+ }
+ else
+ {
+ sprintf(ptr_token+strlen(ptr_token),"%s%s %s", token, ptr_quote+1,
+ qt_token );
+ }
+ }
+ }
+
+ /* return the concatenated token */
+ return ptr_token;
+}
+
+#ifndef __WIN__
+
+/*
+ Synopsis:
+ This function run scripts files on Linux and Netware
+
+Arguments:
+ script_name: name of script file
+
+Output:
+ nothing
+*/
+
+void run_init_script(const char *script_name)
+{
+ arg_list_t al;
+ int err;
+
+ /* args */
+ init_args(&al);
+ add_arg(&al, sh_file);
+ add_arg(&al, script_name);
+
+ /* spawn */
+ if ((err= spawn(sh_file, &al, TRUE, NULL, NULL, NULL, NULL)) != 0)
+ {
+ die("Unable to run script.");
+ }
+
+ /* free args */
+ free_args(&al);
+}
+#endif
diff --git a/mysql-test/ndb/Makefile.am b/mysql-test/ndb/Makefile.am
index 3ed222344a6..502ccee099e 100644
--- a/mysql-test/ndb/Makefile.am
+++ b/mysql-test/ndb/Makefile.am
@@ -13,6 +13,8 @@ SUFFIXES = .sh
.sh:
@RM@ -f $@ $@-t
@SED@ \
+ -e 's!@''ndb_port''@!$(ndb_port)!g' \
+ -e 's!@''ndb_port_base''@!$(ndb_port_base)!g' \
-e 's!@''ndbbindir''@!$(ndbbindir)!g' \
-e 's!@''ndbtoolsdir''@!$(ndbtoolsdir)!g' \
$< > $@-t
diff --git a/mysql-test/ndb/ndbcluster.sh b/mysql-test/ndb/ndbcluster.sh
index 294d32ac4be..60188705857 100644
--- a/mysql-test/ndb/ndbcluster.sh
+++ b/mysql-test/ndb/ndbcluster.sh
@@ -5,7 +5,8 @@
# This scripts starts the table handler ndbcluster
# configurable parameters, make sure to change in mysqlcluterd as well
-port_base="2200"
+port=@ndb_port@
+port_base=@ndb_port_base@
fsdir=`pwd`
# end configurable parameters
@@ -22,6 +23,7 @@ if [ -d ../sql ] ; then
exec_ndb=$ndbtop/src/kernel/ndbd
exec_mgmtsrvr=$ndbtop/src/mgmsrv/ndb_mgmd
exec_waiter=$ndbtop/tools/ndb_waiter
+ exec_test=$ndbtop/tools/ndb_test_platform
exec_mgmtclient=$ndbtop/src/mgmclient/ndb_mgm
else
BINARY_DIST=1
@@ -34,9 +36,15 @@ else
exec_mgmtsrvr=$BASEDIR/bin/ndb_mgmd
fi
exec_waiter=$BASEDIR/bin/ndb_waiter
+ exec_test=$BASEDIR/bin/ndb_test_platform
exec_mgmtclient=$BASEDIR/bin/ndb_mgm
fi
+if $exec_test ; then :; else
+ echo "ndb not correctly compiled to support this platform"
+ exit 1
+fi
+
pidfile=ndbcluster.pid
cfgfile=Ndb.cfg
stop_ndb=
@@ -77,6 +85,9 @@ while test $# -gt 0; do
--data-dir=*)
fsdir=`echo "$1" | sed -e "s;--data-dir=;;"`
;;
+ --port=*)
+ port=`echo "$1" | sed -e "s;--port=;;"`
+ ;;
--port-base=*)
port_base=`echo "$1" | sed -e "s;--port-base=;;"`
;;
@@ -87,7 +98,7 @@ while test $# -gt 0; do
shift
done
-fs_ndb="$fsdir/ndbcluster-$port_base"
+fs_ndb="$fsdir/ndbcluster-$port"
NDB_HOME=
if [ ! -x "$fsdir" ]; then
@@ -102,12 +113,43 @@ if [ ! -x "$exec_mgmtsrvr" ]; then
echo "$exec_mgmtsrvr missing"
exit 1
fi
+if [ ! -x "$exec_waiter" ]; then
+ echo "$exec_waiter missing"
+ exit 1
+fi
+
+exec_mgmtclient="$exec_mgmtclient --no-defaults"
+exec_mgmtsrvr="$exec_mgmtsrvr --no-defaults"
+exec_ndb="$exec_ndb --no-defaults"
+exec_waiter="$exec_waiter --no-defaults"
ndb_host="localhost"
-ndb_mgmd_port=$port_base
+ndb_mgmd_port=$port
NDB_CONNECTSTRING="host=$ndb_host:$ndb_mgmd_port"
export NDB_CONNECTSTRING
+sleep_until_file_created () {
+ file=$1
+ loop=$2
+ org_time=$2
+ message=$3
+ while (test $loop -gt 0)
+ do
+ if [ -r $file ]
+ then
+ return 0
+ fi
+ sleep 1
+ loop=`expr $loop - 1`
+ done
+ if [ $message ]
+ then
+ echo $message
+ fi
+ echo "ERROR: $file was not created in $org_time seconds; Aborting"
+ return 1;
+}
+
start_default_ndbcluster() {
# do some checks
@@ -120,15 +162,11 @@ if [ -d "$fs_ndb" ]; then :; else
exit 1
fi
-# set som help variables
-
-port_transporter=`expr $ndb_mgmd_port + 2`
-
# Start management server as deamon
# Edit file system path and ports in config file
-
if [ $initial_ndb ] ; then
+ rm -f $fs_ndb/ndb_*
sed \
-e s,"CHOOSE_MaxNoOfOrderedIndexes","$ndb_no_ord",g \
-e s,"CHOOSE_MaxNoOfConcurrentOperations","$ndb_con_op",g \
@@ -138,7 +176,7 @@ sed \
-e s,"CHOOSE_HOSTNAME_".*,"$ndb_host",g \
-e s,"CHOOSE_FILESYSTEM","$fs_ndb",g \
-e s,"CHOOSE_PORT_MGM","$ndb_mgmd_port",g \
- -e s,"CHOOSE_PORT_TRANSPORTER","$port_transporter",g \
+ -e s,"CHOOSE_PORT_TRANSPORTER","$port_base",g \
< ndb/ndb_config_2_node.ini \
> "$fs_ndb/config.ini"
fi
@@ -146,25 +184,36 @@ fi
rm -f "$cfgfile" 2>&1 | cat > /dev/null
rm -f "$fs_ndb/$cfgfile" 2>&1 | cat > /dev/null
-if ( cd "$fs_ndb" ; $exec_mgmtsrvr -c config.ini ) ; then :; else
+if ( cd "$fs_ndb" ; $exec_mgmtsrvr -f config.ini ) ; then :; else
echo "Unable to start $exec_mgmtsrvr from `pwd`"
exit 1
fi
-
+if sleep_until_file_created $fs_ndb/ndb_3.pid 30
+then :; else
+ exit 1
+fi
cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile"
# Start database node
echo "Starting ndbd"
( cd "$fs_ndb" ; $exec_ndb $flags_ndb & )
-
+if sleep_until_file_created $fs_ndb/ndb_1.pid 30
+then :; else
+ stop_default_ndbcluster
+ exit 1
+fi
cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile"
# Start database node
echo "Starting ndbd"
( cd "$fs_ndb" ; $exec_ndb $flags_ndb & )
-
+if sleep_until_file_created $fs_ndb/ndb_2.pid 30
+then :; else
+ stop_default_ndbcluster
+ exit 1
+fi
cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile"
# test if Ndb Cluster starts properly
@@ -172,6 +221,7 @@ cat `find "$fs_ndb" -name 'ndb_*.pid'` > "$fs_ndb/$pidfile"
echo "Waiting for started..."
if ( $exec_waiter ) | grep "NDBT_ProgramExit: 0 - OK"; then :; else
echo "Ndbcluster startup failed"
+ stop_default_ndbcluster
exit 1
fi
@@ -198,10 +248,12 @@ if [ -f "$fs_ndb/$pidfile" ] ; then
attempt=0
while [ $attempt -lt 10 ] ; do
new_kill_pid=""
+ kill_pids2=""
for p in $kill_pids ; do
kill -0 $p 2> /dev/null
if [ $? -eq 0 ] ; then
new_kill_pid="$p $new_kill_pid"
+ kill_pids2="-$p $kill_pids2"
fi
done
kill_pids=$new_kill_pid
@@ -211,9 +263,14 @@ if [ -f "$fs_ndb/$pidfile" ] ; then
sleep 1
attempt=`expr $attempt + 1`
done
- if [ "$kill_pids" != "" ] ; then
- echo "Failed to shutdown ndbcluster, executing kill -9 "$kill_pids
- kill -9 $kill_pids
+ if [ "$kill_pids2" != "" ] ; then
+ echo "Failed to shutdown ndbcluster, executing kill "$kill_pids2
+ kill -9 -- $kill_pids2 2> /dev/null
+ /bin/kill -9 -- $kill_pids2 2> /dev/null
+ /usr/bin/kill -9 -- $kill_pids2 2> /dev/null
+ kill -9 $kill_pids2 2> /dev/null
+ /bin/kill -9 $kill_pids2 2> /dev/null
+ /usr/bin/kill -9 $kill_pids2 2> /dev/null
fi
rm "$fs_ndb/$pidfile"
fi
diff --git a/mysql-test/r/alter_table.result b/mysql-test/r/alter_table.result
index f26ca4a5425..e0d484312e7 100644
--- a/mysql-test/r/alter_table.result
+++ b/mysql-test/r/alter_table.result
@@ -483,3 +483,13 @@ ERROR 42000: Incorrect table name 't1\\'
rename table t1 to `t1\\`;
ERROR 42000: Incorrect table name 't1\\'
drop table t1;
+create table t1 (a text) character set koi8r;
+insert into t1 values (_koi8r'ÔÅÓÔ');
+select hex(a) from t1;
+hex(a)
+D4C5D3D4
+alter table t1 convert to character set cp1251;
+select hex(a) from t1;
+hex(a)
+F2E5F1F2
+drop table t1;
diff --git a/mysql-test/r/analyse.result b/mysql-test/r/analyse.result
index b51afab5b54..063b7d2d2e9 100644
--- a/mysql-test/r/analyse.result
+++ b/mysql-test/r/analyse.result
@@ -36,16 +36,16 @@ create table t2 select * from t1 where 0=1 procedure analyse();
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `Field_name` char(255) NOT NULL default '',
- `Min_value` char(255) default NULL,
- `Max_value` char(255) default NULL,
+ `Field_name` varchar(255) NOT NULL default '',
+ `Min_value` varchar(255) default NULL,
+ `Max_value` varchar(255) default NULL,
`Min_length` bigint(11) NOT NULL default '0',
`Max_length` bigint(11) NOT NULL default '0',
`Empties_or_zeros` bigint(11) NOT NULL default '0',
`Nulls` bigint(11) NOT NULL default '0',
- `Avg_value_or_avg_length` char(255) NOT NULL default '',
- `Std` char(255) default NULL,
- `Optimal_fieldtype` char(64) NOT NULL default ''
+ `Avg_value_or_avg_length` varchar(255) NOT NULL default '',
+ `Std` varchar(255) default NULL,
+ `Optimal_fieldtype` varchar(64) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t1 where 0=1 procedure analyse();
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
@@ -55,16 +55,16 @@ create table t2 select * from t1 where 0=1 procedure analyse();
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `Field_name` char(255) NOT NULL default '',
- `Min_value` char(255) default NULL,
- `Max_value` char(255) default NULL,
+ `Field_name` varchar(255) NOT NULL default '',
+ `Min_value` varchar(255) default NULL,
+ `Max_value` varchar(255) default NULL,
`Min_length` bigint(11) NOT NULL default '0',
`Max_length` bigint(11) NOT NULL default '0',
`Empties_or_zeros` bigint(11) NOT NULL default '0',
`Nulls` bigint(11) NOT NULL default '0',
- `Avg_value_or_avg_length` char(255) NOT NULL default '',
- `Std` char(255) default NULL,
- `Optimal_fieldtype` char(64) NOT NULL default ''
+ `Avg_value_or_avg_length` varchar(255) NOT NULL default '',
+ `Std` varchar(255) default NULL,
+ `Optimal_fieldtype` varchar(64) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t2;
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
@@ -78,16 +78,16 @@ create table t2 select * from t1 where 0=1 procedure analyse();
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `Field_name` char(255) NOT NULL default '',
- `Min_value` char(255) default NULL,
- `Max_value` char(255) default NULL,
+ `Field_name` varchar(255) NOT NULL default '',
+ `Min_value` varchar(255) default NULL,
+ `Max_value` varchar(255) default NULL,
`Min_length` bigint(11) NOT NULL default '0',
`Max_length` bigint(11) NOT NULL default '0',
`Empties_or_zeros` bigint(11) NOT NULL default '0',
`Nulls` bigint(11) NOT NULL default '0',
- `Avg_value_or_avg_length` char(255) NOT NULL default '',
- `Std` char(255) default NULL,
- `Optimal_fieldtype` char(64) NOT NULL default ''
+ `Avg_value_or_avg_length` varchar(255) NOT NULL default '',
+ `Std` varchar(255) default NULL,
+ `Optimal_fieldtype` varchar(64) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t2;
Field_name Min_value Max_value Min_length Max_length Empties_or_zeros Nulls Avg_value_or_avg_length Std Optimal_fieldtype
diff --git a/mysql-test/r/ansi.result b/mysql-test/r/ansi.result
index 0b86634f67b..c515ee9a1e8 100644
--- a/mysql-test/r/ansi.result
+++ b/mysql-test/r/ansi.result
@@ -2,7 +2,7 @@ drop table if exists t1;
set sql_mode="MySQL40";
select @@sql_mode;
@@sql_mode
-NO_FIELD_OPTIONS,MYSQL40
+NO_FIELD_OPTIONS,MYSQL40,HIGH_NOT_PRECEDENCE
set @@sql_mode="ANSI";
select @@sql_mode;
@@sql_mode
diff --git a/mysql-test/r/archive.result b/mysql-test/r/archive.result
index 4adb8a5410e..e215e72d43f 100644
--- a/mysql-test/r/archive.result
+++ b/mysql-test/r/archive.result
@@ -2601,4 +2601,1215 @@ auto fld1 companynr fld3 fld4 fld5 fld6
2 011401 37 breaking dreaded Steinberg W
3 011402 37 Romans scholastics jarring
4 011403 37 intercepted audiology tinily
+INSERT INTO t2 VALUES (1,000001,00,'Omaha','teethe','neat','') , (2,011401,37,'breaking','dreaded','Steinberg','W') , (3,011402,37,'Romans','scholastics','jarring','') , (4,011403,37,'intercepted','audiology','tinily','');
+SELECT * FROM t2;
+auto fld1 companynr fld3 fld4 fld5 fld6
+1 000001 00 Omaha teethe neat
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+5 011501 37 bewilderingly wallet balled
+6 011701 37 astound parters persist W
+7 011702 37 admonishing eschew attainments
+8 011703 37 sumac quitter fanatic
+9 012001 37 flanking neat measures FAS
+10 012003 37 combed Steinberg rightfulness
+11 012004 37 subjective jarring capably
+12 012005 37 scatterbrain tinily impulsive
+13 012301 37 Eulerian balled starlet
+14 012302 36 dubbed persist terminators
+15 012303 37 Kane attainments untying
+16 012304 37 overlay fanatic announces FAS
+17 012305 37 perturb measures featherweight FAS
+18 012306 37 goblins rightfulness pessimist FAS
+19 012501 37 annihilates capably daughter
+20 012602 37 Wotan impulsive decliner FAS
+21 012603 37 snatching starlet lawgiver
+22 012604 37 concludes terminators stated
+23 012605 37 laterally untying readable
+24 012606 37 yelped announces attrition
+25 012701 37 grazing featherweight cascade FAS
+26 012702 37 Baird pessimist motors FAS
+27 012703 37 celery daughter interrogate
+28 012704 37 misunderstander decliner pests W
+29 013601 37 handgun lawgiver stairway
+30 013602 37 foldout stated dopers FAS
+31 013603 37 mystic readable testicle W
+32 013604 37 succumbed attrition Parsifal W
+33 013605 37 Nabisco cascade leavings
+34 013606 37 fingerings motors postulation W
+35 013607 37 aging interrogate squeaking
+36 013608 37 afield pests contrasted
+37 013609 37 ammonium stairway leftover
+38 013610 37 boat dopers whiteners
+39 013801 37 intelligibility testicle erases W
+40 013802 37 Augustine Parsifal Punjab W
+41 013803 37 teethe leavings Merritt
+42 013804 37 dreaded postulation Quixotism
+43 013901 37 scholastics squeaking sweetish FAS
+44 016001 37 audiology contrasted dogging FAS
+45 016201 37 wallet leftover scornfully FAS
+46 016202 37 parters whiteners bellow
+47 016301 37 eschew erases bills
+48 016302 37 quitter Punjab cupboard FAS
+49 016303 37 neat Merritt sureties FAS
+50 016304 37 Steinberg Quixotism puddings
+51 018001 37 jarring sweetish tapestry
+52 018002 37 tinily dogging fetters
+53 018003 37 balled scornfully bivalves
+54 018004 37 persist bellow incurring
+55 018005 37 attainments bills Adolph
+56 018007 37 fanatic cupboard pithed
+57 018008 37 measures sureties emergency
+58 018009 37 rightfulness puddings Miles
+59 018010 37 capably tapestry trimmings
+60 018012 37 impulsive fetters tragedies W
+61 018013 37 starlet bivalves skulking W
+62 018014 37 terminators incurring flint
+63 018015 37 untying Adolph flopping W
+64 018016 37 announces pithed relaxing FAS
+65 018017 37 featherweight emergency offload FAS
+66 018018 37 pessimist Miles suites W
+67 018019 37 daughter trimmings lists FAS
+68 018020 37 decliner tragedies animized FAS
+69 018021 37 lawgiver skulking multilayer W
+70 018022 37 stated flint standardizes FAS
+71 018023 37 readable flopping Judas
+72 018024 37 attrition relaxing vacuuming W
+73 018025 37 cascade offload dentally W
+74 018026 37 motors suites humanness W
+75 018027 37 interrogate lists inch W
+76 018028 37 pests animized Weissmuller W
+77 018029 37 stairway multilayer irresponsibly W
+78 018030 37 dopers standardizes luckily FAS
+79 018032 37 testicle Judas culled W
+80 018033 37 Parsifal vacuuming medical FAS
+81 018034 37 leavings dentally bloodbath FAS
+82 018035 37 postulation humanness subschema W
+83 018036 37 squeaking inch animals W
+84 018037 37 contrasted Weissmuller Micronesia
+85 018038 37 leftover irresponsibly repetitions
+86 018039 37 whiteners luckily Antares
+87 018040 37 erases culled ventilate W
+88 018041 37 Punjab medical pityingly
+89 018042 37 Merritt bloodbath interdependent
+90 018043 37 Quixotism subschema Graves FAS
+91 018044 37 sweetish animals neonatal
+92 018045 37 dogging Micronesia scribbled FAS
+93 018046 37 scornfully repetitions chafe W
+94 018048 37 bellow Antares honoring
+95 018049 37 bills ventilate realtor
+96 018050 37 cupboard pityingly elite
+97 018051 37 sureties interdependent funereal
+98 018052 37 puddings Graves abrogating
+99 018053 50 tapestry neonatal sorters
+100 018054 37 fetters scribbled Conley
+101 018055 37 bivalves chafe lectured
+102 018056 37 incurring honoring Abraham
+103 018057 37 Adolph realtor Hawaii W
+104 018058 37 pithed elite cage
+105 018059 36 emergency funereal hushes
+106 018060 37 Miles abrogating Simla
+107 018061 37 trimmings sorters reporters
+108 018101 37 tragedies Conley Dutchman FAS
+109 018102 37 skulking lectured descendants FAS
+110 018103 37 flint Abraham groupings FAS
+111 018104 37 flopping Hawaii dissociate
+112 018201 37 relaxing cage coexist W
+113 018202 37 offload hushes Beebe
+114 018402 37 suites Simla Taoism
+115 018403 37 lists reporters Connally
+116 018404 37 animized Dutchman fetched FAS
+117 018405 37 multilayer descendants checkpoints FAS
+118 018406 37 standardizes groupings rusting
+119 018409 37 Judas dissociate galling
+120 018601 37 vacuuming coexist obliterates
+121 018602 37 dentally Beebe traitor
+122 018603 37 humanness Taoism resumes FAS
+123 018801 37 inch Connally analyzable FAS
+124 018802 37 Weissmuller fetched terminator FAS
+125 018803 37 irresponsibly checkpoints gritty FAS
+126 018804 37 luckily rusting firearm W
+127 018805 37 culled galling minima
+128 018806 37 medical obliterates Selfridge
+129 018807 37 bloodbath traitor disable
+130 018808 37 subschema resumes witchcraft W
+131 018809 37 animals analyzable betroth W
+132 018810 37 Micronesia terminator Manhattanize
+133 018811 37 repetitions gritty imprint
+134 018812 37 Antares firearm peeked
+135 019101 37 ventilate minima swelling
+136 019102 37 pityingly Selfridge interrelationships W
+137 019103 37 interdependent disable riser
+138 019201 37 Graves witchcraft Gandhian W
+139 030501 37 neonatal betroth peacock A
+140 030502 50 scribbled Manhattanize bee A
+141 030503 37 chafe imprint kanji
+142 030504 37 honoring peeked dental
+143 031901 37 realtor swelling scarf FAS
+144 036001 37 elite interrelationships chasm A
+145 036002 37 funereal riser insolence A
+146 036004 37 abrogating Gandhian syndicate
+147 036005 37 sorters peacock alike
+148 038001 37 Conley bee imperial A
+149 038002 37 lectured kanji convulsion A
+150 038003 37 Abraham dental railway A
+151 038004 37 Hawaii scarf validate A
+152 038005 37 cage chasm normalizes A
+153 038006 37 hushes insolence comprehensive
+154 038007 37 Simla syndicate chewing
+155 038008 37 reporters alike denizen
+156 038009 37 Dutchman imperial schemer
+157 038010 37 descendants convulsion chronicle
+158 038011 37 groupings railway Kline
+159 038012 37 dissociate validate Anatole
+160 038013 37 coexist normalizes partridges
+161 038014 37 Beebe comprehensive brunch
+162 038015 37 Taoism chewing recruited
+163 038016 37 Connally denizen dimensions W
+164 038017 37 fetched schemer Chicana W
+165 038018 37 checkpoints chronicle announced
+166 038101 37 rusting Kline praised FAS
+167 038102 37 galling Anatole employing
+168 038103 37 obliterates partridges linear
+169 038104 37 traitor brunch quagmire
+170 038201 37 resumes recruited western A
+171 038202 37 analyzable dimensions relishing
+172 038203 37 terminator Chicana serving A
+173 038204 37 gritty announced scheduling
+174 038205 37 firearm praised lore
+175 038206 37 minima employing eventful
+176 038208 37 Selfridge linear arteriole A
+177 042801 37 disable quagmire disentangle
+178 042802 37 witchcraft western cured A
+179 046101 37 betroth relishing Fenton W
+180 048001 37 Manhattanize serving avoidable A
+181 048002 37 imprint scheduling drains A
+182 048003 37 peeked lore detectably FAS
+183 048004 37 swelling eventful husky
+184 048005 37 interrelationships arteriole impelling
+185 048006 37 riser disentangle undoes
+186 048007 37 Gandhian cured evened
+187 048008 37 peacock Fenton squeezes
+188 048101 37 bee avoidable destroyer FAS
+189 048102 37 kanji drains rudeness
+190 048201 37 dental detectably beaner FAS
+191 048202 37 scarf husky boorish
+192 048203 37 chasm impelling Everhart
+193 048204 37 insolence undoes encompass A
+194 048205 37 syndicate evened mushrooms
+195 048301 37 alike squeezes Alison A
+196 048302 37 imperial destroyer externally FAS
+197 048303 37 convulsion rudeness pellagra
+198 048304 37 railway beaner cult
+199 048305 37 validate boorish creek A
+200 048401 37 normalizes Everhart Huffman
+201 048402 37 comprehensive encompass Majorca FAS
+202 048403 37 chewing mushrooms governing A
+203 048404 37 denizen Alison gadfly FAS
+204 048405 37 schemer externally reassigned FAS
+205 048406 37 chronicle pellagra intentness W
+206 048407 37 Kline cult craziness
+207 048408 37 Anatole creek psychic
+208 048409 37 partridges Huffman squabbled
+209 048410 37 brunch Majorca burlesque
+210 048411 37 recruited governing capped
+211 048412 37 dimensions gadfly extracted A
+212 048413 37 Chicana reassigned DiMaggio
+213 048601 37 announced intentness exclamation FAS
+214 048602 37 praised craziness subdirectory
+215 048603 37 employing psychic fangs
+216 048604 37 linear squabbled buyer A
+217 048801 37 quagmire burlesque pithing A
+218 050901 37 western capped transistorizing A
+219 051201 37 relishing extracted nonbiodegradable
+220 056002 37 serving DiMaggio dislocate
+221 056003 37 scheduling exclamation monochromatic FAS
+222 056004 37 lore subdirectory batting
+223 056102 37 eventful fangs postcondition A
+224 056203 37 arteriole buyer catalog FAS
+225 056204 37 disentangle pithing Remus
+226 058003 37 cured transistorizing devices A
+227 058004 37 Fenton nonbiodegradable bike A
+228 058005 37 avoidable dislocate qualify
+229 058006 37 drains monochromatic detained
+230 058007 37 detectably batting commended
+231 058101 37 husky postcondition civilize
+232 058102 37 impelling catalog Elmhurst
+233 058103 37 undoes Remus anesthetizing
+234 058105 37 evened devices deaf
+235 058111 37 squeezes bike Brigham
+236 058112 37 destroyer qualify title
+237 058113 37 rudeness detained coarse
+238 058114 37 beaner commended combinations
+239 058115 37 boorish civilize grayness
+240 058116 37 Everhart Elmhurst innumerable FAS
+241 058117 37 encompass anesthetizing Caroline A
+242 058118 37 mushrooms deaf fatty FAS
+243 058119 37 Alison Brigham eastbound
+244 058120 37 externally title inexperienced
+245 058121 37 pellagra coarse hoarder A
+246 058122 37 cult combinations scotch W
+247 058123 37 creek grayness passport A
+248 058124 37 Huffman innumerable strategic FAS
+249 058125 37 Majorca Caroline gated
+250 058126 37 governing fatty flog
+251 058127 37 gadfly eastbound Pipestone
+252 058128 37 reassigned inexperienced Dar
+253 058201 37 intentness hoarder Corcoran
+254 058202 37 craziness scotch flyers A
+255 058303 37 psychic passport competitions W
+256 058304 37 squabbled strategic suppliers FAS
+257 058602 37 burlesque gated skips
+258 058603 37 capped flog institutes
+259 058604 37 extracted Pipestone troop A
+260 058605 37 DiMaggio Dar connective W
+261 058606 37 exclamation Corcoran denies
+262 058607 37 subdirectory flyers polka
+263 060401 36 fangs competitions observations FAS
+264 061701 36 buyer suppliers askers
+265 066201 36 pithing skips homeless FAS
+266 066501 36 transistorizing institutes Anna
+267 068001 36 nonbiodegradable troop subdirectories W
+268 068002 36 dislocate connective decaying FAS
+269 068005 36 monochromatic denies outwitting W
+270 068006 36 batting polka Harpy W
+271 068007 36 postcondition observations crazed
+272 068008 36 catalog askers suffocate
+273 068009 36 Remus homeless provers FAS
+274 068010 36 devices Anna technically
+275 068011 36 bike subdirectories Franklinizations
+276 068202 36 qualify decaying considered
+277 068302 36 detained outwitting tinnily
+278 068303 36 commended Harpy uninterruptedly
+279 068401 36 civilize crazed whistled A
+280 068501 36 Elmhurst suffocate automate
+281 068502 36 anesthetizing provers gutting W
+282 068503 36 deaf technically surreptitious
+283 068602 36 Brigham Franklinizations Choctaw
+284 068603 36 title considered cooks
+285 068701 36 coarse tinnily millivolt FAS
+286 068702 36 combinations uninterruptedly counterpoise
+287 068703 36 grayness whistled Gothicism
+288 076001 36 innumerable automate feminine
+289 076002 36 Caroline gutting metaphysically W
+290 076101 36 fatty surreptitious sanding A
+291 076102 36 eastbound Choctaw contributorily
+292 076103 36 inexperienced cooks receivers FAS
+293 076302 36 hoarder millivolt adjourn
+294 076303 36 scotch counterpoise straggled A
+295 076304 36 passport Gothicism druggists
+296 076305 36 strategic feminine thanking FAS
+297 076306 36 gated metaphysically ostrich
+298 076307 36 flog sanding hopelessness FAS
+299 076402 36 Pipestone contributorily Eurydice
+300 076501 36 Dar receivers excitation W
+301 076502 36 Corcoran adjourn presumes FAS
+302 076701 36 flyers straggled imaginable FAS
+303 078001 36 competitions druggists concoct W
+304 078002 36 suppliers thanking peering W
+305 078003 36 skips ostrich Phelps FAS
+306 078004 36 institutes hopelessness ferociousness FAS
+307 078005 36 troop Eurydice sentences
+308 078006 36 connective excitation unlocks
+309 078007 36 denies presumes engrossing W
+310 078008 36 polka imaginable Ruth
+311 078101 36 observations concoct tying
+312 078103 36 askers peering exclaimers
+313 078104 36 homeless Phelps synergy
+314 078105 36 Anna ferociousness Huey W
+315 082101 36 subdirectories sentences merging
+316 083401 36 decaying unlocks judges A
+317 084001 36 outwitting engrossing Shylock W
+318 084002 36 Harpy Ruth Miltonism
+319 086001 36 crazed tying hen W
+320 086102 36 suffocate exclaimers honeybee FAS
+321 086201 36 provers synergy towers
+322 088001 36 technically Huey dilutes W
+323 088002 36 Franklinizations merging numerals FAS
+324 088003 36 considered judges democracy FAS
+325 088004 36 tinnily Shylock Ibero-
+326 088101 36 uninterruptedly Miltonism invalids
+327 088102 36 whistled hen behavior
+328 088103 36 automate honeybee accruing
+329 088104 36 gutting towers relics A
+330 088105 36 surreptitious dilutes rackets
+331 088106 36 Choctaw numerals Fischbein W
+332 088201 36 cooks democracy phony W
+333 088203 36 millivolt Ibero- cross FAS
+334 088204 36 counterpoise invalids cleanup
+335 088302 37 Gothicism behavior conspirator
+336 088303 37 feminine accruing label FAS
+337 088305 37 metaphysically relics university
+338 088402 37 sanding rackets cleansed FAS
+339 088501 36 contributorily Fischbein ballgown
+340 088502 36 receivers phony starlet
+341 088503 36 adjourn cross aqueous
+342 098001 58 straggled cleanup portrayal A
+343 098002 58 druggists conspirator despising W
+344 098003 58 thanking label distort W
+345 098004 58 ostrich university palmed
+346 098005 58 hopelessness cleansed faced
+347 098006 58 Eurydice ballgown silverware
+348 141903 29 excitation starlet assessor
+349 098008 58 presumes aqueous spiders
+350 098009 58 imaginable portrayal artificially
+351 098010 58 concoct despising reminiscence
+352 098011 58 peering distort Mexican
+353 098012 58 Phelps palmed obnoxious
+354 098013 58 ferociousness faced fragile
+355 098014 58 sentences silverware apprehensible
+356 098015 58 unlocks assessor births
+357 098016 58 engrossing spiders garages
+358 098017 58 Ruth artificially panty
+359 098018 58 tying reminiscence anteater
+360 098019 58 exclaimers Mexican displacement A
+361 098020 58 synergy obnoxious drovers A
+362 098021 58 Huey fragile patenting A
+363 098022 58 merging apprehensible far A
+364 098023 58 judges births shrieks
+365 098024 58 Shylock garages aligning W
+366 098025 37 Miltonism panty pragmatism
+367 106001 36 hen anteater fevers W
+368 108001 36 honeybee displacement reexamines A
+369 108002 36 towers drovers occupancies
+370 108003 36 dilutes patenting sweats FAS
+371 108004 36 numerals far modulators
+372 108005 36 democracy shrieks demand W
+373 108007 36 Ibero- aligning Madeira
+374 108008 36 invalids pragmatism Viennese W
+375 108009 36 behavior fevers chillier W
+376 108010 36 accruing reexamines wildcats FAS
+377 108011 36 relics occupancies gentle
+378 108012 36 rackets sweats Angles W
+379 108101 36 Fischbein modulators accuracies
+380 108102 36 phony demand toggle
+381 108103 36 cross Madeira Mendelssohn W
+382 108111 50 cleanup Viennese behaviorally
+383 108105 36 conspirator chillier Rochford
+384 108106 36 label wildcats mirror W
+385 108107 36 university gentle Modula
+386 108108 50 cleansed Angles clobbering
+387 108109 36 ballgown accuracies chronography
+388 108110 36 starlet toggle Eskimoizeds
+389 108201 36 aqueous Mendelssohn British W
+390 108202 36 portrayal behaviorally pitfalls
+391 108203 36 despising Rochford verify W
+392 108204 36 distort mirror scatter FAS
+393 108205 36 palmed Modula Aztecan
+394 108301 36 faced clobbering acuity W
+395 108302 36 silverware chronography sinking W
+396 112101 36 assessor Eskimoizeds beasts FAS
+397 112102 36 spiders British Witt W
+398 113701 36 artificially pitfalls physicists FAS
+399 116001 36 reminiscence verify folksong A
+400 116201 36 Mexican scatter strokes FAS
+401 116301 36 obnoxious Aztecan crowder
+402 116302 36 fragile acuity merry
+403 116601 36 apprehensible sinking cadenced
+404 116602 36 births beasts alimony A
+405 116603 36 garages Witt principled A
+406 116701 36 panty physicists golfing
+407 116702 36 anteater folksong undiscovered
+408 118001 36 displacement strokes irritates
+409 118002 36 drovers crowder patriots A
+410 118003 36 patenting merry rooms FAS
+411 118004 36 far cadenced towering W
+412 118005 36 shrieks alimony displease
+413 118006 36 aligning principled photosensitive
+414 118007 36 pragmatism golfing inking
+415 118008 36 fevers undiscovered gainers
+416 118101 36 reexamines irritates leaning A
+417 118102 36 occupancies patriots hydrant A
+418 118103 36 sweats rooms preserve
+419 118202 36 modulators towering blinded A
+420 118203 36 demand displease interactions A
+421 118204 36 Madeira photosensitive Barry
+422 118302 36 Viennese inking whiteness A
+423 118304 36 chillier gainers pastimes W
+424 118305 36 wildcats leaning Edenization
+425 118306 36 gentle hydrant Muscat
+426 118307 36 Angles preserve assassinated
+427 123101 36 accuracies blinded labeled
+428 123102 36 toggle interactions glacial A
+429 123301 36 Mendelssohn Barry implied W
+430 126001 36 behaviorally whiteness bibliographies W
+431 126002 36 Rochford pastimes Buchanan
+432 126003 36 mirror Edenization forgivably FAS
+433 126101 36 Modula Muscat innuendo A
+434 126301 36 clobbering assassinated den FAS
+435 126302 36 chronography labeled submarines W
+436 126402 36 Eskimoizeds glacial mouthful A
+437 126601 36 British implied expiring
+438 126602 36 pitfalls bibliographies unfulfilled FAS
+439 126702 36 verify Buchanan precession
+440 128001 36 scatter forgivably nullified
+441 128002 36 Aztecan innuendo affects
+442 128003 36 acuity den Cynthia
+443 128004 36 sinking submarines Chablis A
+444 128005 36 beasts mouthful betterments FAS
+445 128007 36 Witt expiring advertising
+446 128008 36 physicists unfulfilled rubies A
+447 128009 36 folksong precession southwest FAS
+448 128010 36 strokes nullified superstitious A
+449 128011 36 crowder affects tabernacle W
+450 128012 36 merry Cynthia silk A
+451 128013 36 cadenced Chablis handsomest A
+452 128014 36 alimony betterments Persian A
+453 128015 36 principled advertising analog W
+454 128016 36 golfing rubies complex W
+455 128017 36 undiscovered southwest Taoist
+456 128018 36 irritates superstitious suspend
+457 128019 36 patriots tabernacle relegated
+458 128020 36 rooms silk awesome W
+459 128021 36 towering handsomest Bruxelles
+460 128022 36 displease Persian imprecisely A
+461 128023 36 photosensitive analog televise
+462 128101 36 inking complex braking
+463 128102 36 gainers Taoist true FAS
+464 128103 36 leaning suspend disappointing FAS
+465 128104 36 hydrant relegated navally W
+466 128106 36 preserve awesome circus
+467 128107 36 blinded Bruxelles beetles
+468 128108 36 interactions imprecisely trumps
+469 128202 36 Barry televise fourscore W
+470 128203 36 whiteness braking Blackfoots
+471 128301 36 pastimes true Grady
+472 128302 36 Edenization disappointing quiets FAS
+473 128303 36 Muscat navally floundered FAS
+474 128304 36 assassinated circus profundity W
+475 128305 36 labeled beetles Garrisonian W
+476 128307 36 glacial trumps Strauss
+477 128401 36 implied fourscore cemented FAS
+478 128502 36 bibliographies Blackfoots contrition A
+479 128503 36 Buchanan Grady mutations
+480 128504 36 forgivably quiets exhibits W
+481 128505 36 innuendo floundered tits
+482 128601 36 den profundity mate A
+483 128603 36 submarines Garrisonian arches
+484 128604 36 mouthful Strauss Moll
+485 128702 36 expiring cemented ropers
+486 128703 36 unfulfilled contrition bombast
+487 128704 36 precession mutations difficultly A
+488 138001 36 nullified exhibits adsorption
+489 138002 36 affects tits definiteness FAS
+490 138003 36 Cynthia mate cultivation A
+491 138004 36 Chablis arches heals A
+492 138005 36 betterments Moll Heusen W
+493 138006 36 advertising ropers target FAS
+494 138007 36 rubies bombast cited A
+495 138008 36 southwest difficultly congresswoman W
+496 138009 36 superstitious adsorption Katherine
+497 138102 36 tabernacle definiteness titter A
+498 138103 36 silk cultivation aspire A
+499 138104 36 handsomest heals Mardis
+500 138105 36 Persian Heusen Nadia W
+501 138201 36 analog target estimating FAS
+502 138302 36 complex cited stuck A
+503 138303 36 Taoist congresswoman fifteenth A
+504 138304 36 suspend Katherine Colombo
+505 138401 29 relegated titter survey A
+506 140102 29 awesome aspire staffing
+507 140103 29 Bruxelles Mardis obtain
+508 140104 29 imprecisely Nadia loaded
+509 140105 29 televise estimating slaughtered
+510 140201 29 braking stuck lights A
+511 140701 29 true fifteenth circumference
+512 141501 29 disappointing Colombo dull A
+513 141502 29 navally survey weekly A
+514 141901 29 circus staffing wetness
+515 141902 29 beetles obtain visualized
+516 142101 29 trumps loaded Tannenbaum
+517 142102 29 fourscore slaughtered moribund
+518 142103 29 Blackfoots lights demultiplex
+519 142701 29 Grady circumference lockings
+520 143001 29 quiets dull thugs FAS
+521 143501 29 floundered weekly unnerves
+522 143502 29 profundity wetness abut
+523 148001 29 Garrisonian visualized Chippewa A
+524 148002 29 Strauss Tannenbaum stratifications A
+525 148003 29 cemented moribund signaled
+526 148004 29 contrition demultiplex Italianizes A
+527 148005 29 mutations lockings algorithmic A
+528 148006 29 exhibits thugs paranoid FAS
+529 148007 29 tits unnerves camping A
+530 148009 29 mate abut signifying A
+531 148010 29 arches Chippewa Patrice W
+532 148011 29 Moll stratifications search A
+533 148012 29 ropers signaled Angeles A
+534 148013 29 bombast Italianizes semblance
+535 148023 36 difficultly algorithmic taxed
+536 148015 29 adsorption paranoid Beatrice
+537 148016 29 definiteness camping retrace
+538 148017 29 cultivation signifying lockout
+539 148018 29 heals Patrice grammatic
+540 148019 29 Heusen search helmsman
+541 148020 29 target Angeles uniform W
+542 148021 29 cited semblance hamming
+543 148022 29 congresswoman taxed disobedience
+544 148101 29 Katherine Beatrice captivated A
+545 148102 29 titter retrace transferals A
+546 148201 29 aspire lockout cartographer A
+547 148401 29 Mardis grammatic aims FAS
+548 148402 29 Nadia helmsman Pakistani
+549 148501 29 estimating uniform burglarized FAS
+550 148502 29 stuck hamming saucepans A
+551 148503 29 fifteenth disobedience lacerating A
+552 148504 29 Colombo captivated corny
+553 148601 29 survey transferals megabytes FAS
+554 148602 29 staffing cartographer chancellor
+555 150701 29 obtain aims bulk A
+556 152101 29 loaded Pakistani commits A
+557 152102 29 slaughtered burglarized meson W
+558 155202 36 lights saucepans deputies
+559 155203 29 circumference lacerating northeaster A
+560 155204 29 dull corny dipole
+561 155205 29 weekly megabytes machining 0
+562 156001 29 wetness chancellor therefore
+563 156002 29 visualized bulk Telefunken
+564 156102 29 Tannenbaum commits salvaging
+565 156301 29 moribund meson Corinthianizes A
+566 156302 29 demultiplex deputies restlessly A
+567 156303 29 lockings northeaster bromides
+568 156304 29 thugs dipole generalized A
+569 156305 29 unnerves machining mishaps
+570 156306 29 abut therefore quelling
+571 156501 29 Chippewa Telefunken spiritual A
+572 158001 29 stratifications salvaging beguiles FAS
+573 158002 29 signaled Corinthianizes Trobriand FAS
+574 158101 29 Italianizes restlessly fleeing A
+575 158102 29 algorithmic bromides Armour A
+576 158103 29 paranoid generalized chin A
+577 158201 29 camping mishaps provers A
+578 158202 29 signifying quelling aeronautic A
+579 158203 29 Patrice spiritual voltage W
+580 158204 29 search beguiles sash
+581 158301 29 Angeles Trobriand anaerobic A
+582 158302 29 semblance fleeing simultaneous A
+583 158303 29 taxed Armour accumulating A
+584 158304 29 Beatrice chin Medusan A
+585 158305 29 retrace provers shouted A
+586 158306 29 lockout aeronautic freakish
+587 158501 29 grammatic voltage index FAS
+588 160301 29 helmsman sash commercially
+589 166101 50 uniform anaerobic mistiness A
+590 166102 50 hamming simultaneous endpoint
+591 168001 29 disobedience accumulating straight A
+592 168002 29 captivated Medusan flurried
+593 168003 29 transferals shouted denotative A
+594 168101 29 cartographer freakish coming FAS
+595 168102 29 aims index commencements FAS
+596 168103 29 Pakistani commercially gentleman
+597 168104 29 burglarized mistiness gifted
+598 168202 29 saucepans endpoint Shanghais
+599 168301 29 lacerating straight sportswriting A
+600 168502 29 corny flurried sloping A
+601 168503 29 megabytes denotative navies
+602 168601 29 chancellor coming leaflet A
+603 173001 40 bulk commencements shooter
+604 173701 40 commits gentleman Joplin FAS
+605 173702 40 meson gifted babies
+606 176001 40 deputies Shanghais subdivision FAS
+607 176101 40 northeaster sportswriting burstiness W
+608 176201 40 dipole sloping belted FAS
+609 176401 40 machining navies assails FAS
+610 176501 40 therefore leaflet admiring W
+611 176601 40 Telefunken shooter swaying 0
+612 176602 40 salvaging Joplin Goldstine FAS
+613 176603 40 Corinthianizes babies fitting
+614 178001 40 restlessly subdivision Norwalk W
+615 178002 40 bromides burstiness weakening W
+616 178003 40 generalized belted analogy FAS
+617 178004 40 mishaps assails deludes
+618 178005 40 quelling admiring cokes
+619 178006 40 spiritual swaying Clayton
+620 178007 40 beguiles Goldstine exhausts
+621 178008 40 Trobriand fitting causality
+622 178101 40 fleeing Norwalk sating FAS
+623 178102 40 Armour weakening icon
+624 178103 40 chin analogy throttles
+625 178201 40 provers deludes communicants FAS
+626 178202 40 aeronautic cokes dehydrate FAS
+627 178301 40 voltage Clayton priceless FAS
+628 178302 40 sash exhausts publicly
+629 178401 40 anaerobic causality incidentals FAS
+630 178402 40 simultaneous sating commonplace
+631 178403 40 accumulating icon mumbles
+632 178404 40 Medusan throttles furthermore W
+633 178501 40 shouted communicants cautioned W
+634 186002 37 freakish dehydrate parametrized A
+635 186102 37 index priceless registration A
+636 186201 40 commercially publicly sadly FAS
+637 186202 40 mistiness incidentals positioning
+638 186203 40 endpoint commonplace babysitting
+639 186302 37 straight mumbles eternal A
+640 188007 37 flurried furthermore hoarder
+641 188008 37 denotative cautioned congregates
+642 188009 37 coming parametrized rains
+643 188010 37 commencements registration workers W
+644 188011 37 gentleman sadly sags A
+645 188012 37 gifted positioning unplug W
+646 188013 37 Shanghais babysitting garage A
+647 188014 37 sportswriting eternal boulder A
+648 188015 37 sloping hoarder hollowly A
+649 188016 37 navies congregates specifics
+650 188017 37 leaflet rains Teresa
+651 188102 37 shooter workers Winsett
+652 188103 37 Joplin sags convenient A
+653 188202 37 babies unplug buckboards FAS
+654 188301 40 subdivision garage amenities
+655 188302 40 burstiness boulder resplendent FAS
+656 188303 40 belted hollowly priding FAS
+657 188401 37 assails specifics configurations
+658 188402 37 admiring Teresa untidiness A
+659 188503 37 swaying Winsett Brice W
+660 188504 37 Goldstine convenient sews FAS
+661 188505 37 fitting buckboards participated
+662 190701 37 Norwalk amenities Simon FAS
+663 190703 50 weakening resplendent certificates
+664 191701 37 analogy priding Fitzpatrick
+665 191702 37 deludes configurations Evanston A
+666 191703 37 cokes untidiness misted
+667 196001 37 Clayton Brice textures A
+668 196002 37 exhausts sews save
+669 196003 37 causality participated count
+670 196101 37 sating Simon rightful A
+671 196103 37 icon certificates chaperone
+672 196104 37 throttles Fitzpatrick Lizzy A
+673 196201 37 communicants Evanston clenched A
+674 196202 37 dehydrate misted effortlessly
+675 196203 37 priceless textures accessed
+676 198001 37 publicly save beaters A
+677 198003 37 incidentals count Hornblower FAS
+678 198004 37 commonplace rightful vests A
+679 198005 37 mumbles chaperone indulgences FAS
+680 198006 37 furthermore Lizzy infallibly A
+681 198007 37 cautioned clenched unwilling FAS
+682 198008 37 parametrized effortlessly excrete FAS
+683 198009 37 registration accessed spools A
+684 198010 37 sadly beaters crunches FAS
+685 198011 37 positioning Hornblower overestimating FAS
+686 198012 37 babysitting vests ineffective
+687 198013 37 eternal indulgences humiliation A
+688 198014 37 hoarder infallibly sophomore
+689 198015 37 congregates unwilling star
+690 198017 37 rains excrete rifles
+691 198018 37 workers spools dialysis
+692 198019 37 sags crunches arriving
+693 198020 37 unplug overestimating indulge
+694 198021 37 garage ineffective clockers
+695 198022 37 boulder humiliation languages
+696 198023 50 hollowly sophomore Antarctica A
+697 198024 37 specifics star percentage
+698 198101 37 Teresa rifles ceiling A
+699 198103 37 Winsett dialysis specification
+700 198105 37 convenient arriving regimented A
+701 198106 37 buckboards indulge ciphers
+702 198201 37 amenities clockers pictures A
+703 198204 37 resplendent languages serpents A
+704 198301 53 priding Antarctica allot A
+705 198302 53 configurations percentage realized A
+706 198303 53 untidiness ceiling mayoral A
+707 198304 53 Brice specification opaquely A
+708 198401 37 sews regimented hostess FAS
+709 198402 37 participated ciphers fiftieth
+710 198403 37 Simon pictures incorrectly
+711 202101 37 certificates serpents decomposition FAS
+712 202301 37 Fitzpatrick allot stranglings
+713 202302 37 Evanston realized mixture FAS
+714 202303 37 misted mayoral electroencephalography FAS
+715 202304 37 textures opaquely similarities FAS
+716 202305 37 save hostess charges W
+717 202601 37 count fiftieth freest FAS
+718 202602 37 rightful incorrectly Greenberg FAS
+719 202605 37 chaperone decomposition tinting
+720 202606 37 Lizzy stranglings expelled W
+721 202607 37 clenched mixture warm
+722 202901 37 effortlessly electroencephalography smoothed
+723 202902 37 accessed similarities deductions FAS
+724 202903 37 beaters charges Romano W
+725 202904 37 Hornblower freest bitterroot
+726 202907 37 vests Greenberg corset
+727 202908 37 indulgences tinting securing
+728 203101 37 infallibly expelled environing FAS
+729 203103 37 unwilling warm cute
+730 203104 37 excrete smoothed Crays
+731 203105 37 spools deductions heiress FAS
+732 203401 37 crunches Romano inform FAS
+733 203402 37 overestimating bitterroot avenge
+734 203404 37 ineffective corset universals
+735 203901 37 humiliation securing Kinsey W
+736 203902 37 sophomore environing ravines FAS
+737 203903 37 star cute bestseller
+738 203906 37 rifles Crays equilibrium
+739 203907 37 dialysis heiress extents 0
+740 203908 37 arriving inform relatively
+741 203909 37 indulge avenge pressure FAS
+742 206101 37 clockers universals critiques FAS
+743 206201 37 languages Kinsey befouled
+744 206202 37 Antarctica ravines rightfully FAS
+745 206203 37 percentage bestseller mechanizing FAS
+746 206206 37 ceiling equilibrium Latinizes
+747 206207 37 specification extents timesharing
+748 206208 37 regimented relatively Aden
+749 208001 37 ciphers pressure embassies
+750 208002 37 pictures critiques males FAS
+751 208003 37 serpents befouled shapelessly FAS
+752 208004 37 allot rightfully genres FAS
+753 208008 37 realized mechanizing mastering
+754 208009 37 mayoral Latinizes Newtonian
+755 208010 37 opaquely timesharing finishers FAS
+756 208011 37 hostess Aden abates
+757 208101 37 fiftieth embassies teem
+758 208102 37 incorrectly males kiting FAS
+759 208103 37 decomposition shapelessly stodgy FAS
+760 208104 37 stranglings genres scalps FAS
+761 208105 37 mixture mastering feed FAS
+762 208110 37 electroencephalography Newtonian guitars
+763 208111 37 similarities finishers airships
+764 208112 37 charges abates store
+765 208113 37 freest teem denounces
+766 208201 37 Greenberg kiting Pyle FAS
+767 208203 37 tinting stodgy Saxony
+768 208301 37 expelled scalps serializations FAS
+769 208302 37 warm feed Peruvian FAS
+770 208305 37 smoothed guitars taxonomically FAS
+771 208401 37 deductions airships kingdom A
+772 208402 37 Romano store stint A
+773 208403 37 bitterroot denounces Sault A
+774 208404 37 corset Pyle faithful
+775 208501 37 securing Saxony Ganymede FAS
+776 208502 37 environing serializations tidiness FAS
+777 208503 37 cute Peruvian gainful FAS
+778 208504 37 Crays taxonomically contrary FAS
+779 208505 37 heiress kingdom Tipperary FAS
+780 210101 37 inform stint tropics W
+781 210102 37 avenge Sault theorizers
+782 210103 37 universals faithful renew 0
+783 210104 37 Kinsey Ganymede already
+784 210105 37 ravines tidiness terminal
+785 210106 37 bestseller gainful Hegelian
+786 210107 37 equilibrium contrary hypothesizer
+787 210401 37 extents Tipperary warningly FAS
+788 213201 37 relatively tropics journalizing FAS
+789 213203 37 pressure theorizers nested
+790 213204 37 critiques renew Lars
+791 213205 37 befouled already saplings
+792 213206 37 rightfully terminal foothill
+793 213207 37 mechanizing Hegelian labeled
+794 216101 37 Latinizes hypothesizer imperiously FAS
+795 216103 37 timesharing warningly reporters FAS
+796 218001 37 Aden journalizing furnishings FAS
+797 218002 37 embassies nested precipitable FAS
+798 218003 37 males Lars discounts FAS
+799 218004 37 shapelessly saplings excises FAS
+800 143503 50 genres foothill Stalin
+801 218006 37 mastering labeled despot FAS
+802 218007 37 Newtonian imperiously ripeness FAS
+803 218008 37 finishers reporters Arabia
+804 218009 37 abates furnishings unruly
+805 218010 37 teem precipitable mournfulness
+806 218011 37 kiting discounts boom FAS
+807 218020 37 stodgy excises slaughter A
+808 218021 50 scalps Stalin Sabine
+809 218022 37 feed despot handy FAS
+810 218023 37 guitars ripeness rural
+811 218024 37 airships Arabia organizer
+812 218101 37 store unruly shipyard FAS
+813 218102 37 denounces mournfulness civics FAS
+814 218103 37 Pyle boom inaccuracy FAS
+815 218201 37 Saxony slaughter rules FAS
+816 218202 37 serializations Sabine juveniles FAS
+817 218203 37 Peruvian handy comprised W
+818 218204 37 taxonomically rural investigations
+819 218205 37 kingdom organizer stabilizes A
+820 218301 37 stint shipyard seminaries FAS
+821 218302 37 Sault civics Hunter A
+822 218401 37 faithful inaccuracy sporty FAS
+823 218402 37 Ganymede rules test FAS
+824 218403 37 tidiness juveniles weasels
+825 218404 37 gainful comprised CERN
+826 218407 37 contrary investigations tempering
+827 218408 37 Tipperary stabilizes afore FAS
+828 218409 37 tropics seminaries Galatean
+829 218410 37 theorizers Hunter techniques W
+830 226001 37 renew sporty error
+831 226002 37 already test veranda
+832 226003 37 terminal weasels severely
+833 226004 37 Hegelian CERN Cassites FAS
+834 226005 37 hypothesizer tempering forthcoming
+835 226006 37 warningly afore guides
+836 226007 37 journalizing Galatean vanish FAS
+837 226008 37 nested techniques lied A
+838 226203 37 Lars error sawtooth FAS
+839 226204 37 saplings veranda fated FAS
+840 226205 37 foothill severely gradually
+841 226206 37 labeled Cassites widens
+842 226207 37 imperiously forthcoming preclude
+843 226208 37 reporters guides Jobrel
+844 226209 37 furnishings vanish hooker
+845 226210 37 precipitable lied rainstorm
+846 226211 37 discounts sawtooth disconnects
+847 228001 37 excises fated cruelty
+848 228004 37 Stalin gradually exponentials A
+849 228005 37 despot widens affective A
+850 228006 37 ripeness preclude arteries
+851 228007 37 Arabia Jobrel Crosby FAS
+852 228008 37 unruly hooker acquaint
+853 228009 37 mournfulness rainstorm evenhandedly
+854 228101 37 boom disconnects percentage
+855 228108 37 slaughter cruelty disobedience
+856 228109 37 Sabine exponentials humility
+857 228110 37 handy affective gleaning A
+858 228111 37 rural arteries petted A
+859 228112 37 organizer Crosby bloater A
+860 228113 37 shipyard acquaint minion A
+861 228114 37 civics evenhandedly marginal A
+862 228115 37 inaccuracy percentage apiary A
+863 228116 37 rules disobedience measures
+864 228117 37 juveniles humility precaution
+865 228118 37 comprised gleaning repelled
+866 228119 37 investigations petted primary FAS
+867 228120 37 stabilizes bloater coverings
+868 228121 37 seminaries minion Artemia A
+869 228122 37 Hunter marginal navigate
+870 228201 37 sporty apiary spatial
+871 228206 37 test measures Gurkha
+872 228207 37 weasels precaution meanwhile A
+873 228208 37 CERN repelled Melinda A
+874 228209 37 tempering primary Butterfield
+875 228210 37 afore coverings Aldrich A
+876 228211 37 Galatean Artemia previewing A
+877 228212 37 techniques navigate glut A
+878 228213 37 error spatial unaffected
+879 228214 37 veranda Gurkha inmate
+880 228301 37 severely meanwhile mineral
+881 228305 37 Cassites Melinda impending A
+882 228306 37 forthcoming Butterfield meditation A
+883 228307 37 guides Aldrich ideas
+884 228308 37 vanish previewing miniaturizes W
+885 228309 37 lied glut lewdly
+886 228310 37 sawtooth unaffected title
+887 228311 37 fated inmate youthfulness
+888 228312 37 gradually mineral creak FAS
+889 228313 37 widens impending Chippewa
+890 228314 37 preclude meditation clamored
+891 228401 65 Jobrel ideas freezes
+892 228402 65 hooker miniaturizes forgivably FAS
+893 228403 65 rainstorm lewdly reduce FAS
+894 228404 65 disconnects title McGovern W
+895 228405 65 cruelty youthfulness Nazis W
+896 228406 65 exponentials creak epistle W
+897 228407 65 affective Chippewa socializes W
+898 228408 65 arteries clamored conceptions
+899 228409 65 Crosby freezes Kevin
+900 228410 65 acquaint forgivably uncovering
+901 230301 37 evenhandedly reduce chews FAS
+902 230302 37 percentage McGovern appendixes FAS
+903 230303 37 disobedience Nazis raining
+904 018062 37 humility epistle infest
+905 230501 37 gleaning socializes compartment
+906 230502 37 petted conceptions minting
+907 230503 37 bloater Kevin ducks
+908 230504 37 minion uncovering roped A
+909 230505 37 marginal chews waltz
+910 230506 37 apiary appendixes Lillian
+911 230507 37 measures raining repressions A
+912 230508 37 precaution infest chillingly
+913 230509 37 repelled compartment noncritical
+914 230901 37 primary minting lithograph
+915 230902 37 coverings ducks spongers
+916 230903 37 Artemia roped parenthood
+917 230904 37 navigate waltz posed
+918 230905 37 spatial Lillian instruments
+919 230906 37 Gurkha repressions filial
+920 230907 37 meanwhile chillingly fixedly
+921 230908 37 Melinda noncritical relives
+922 230909 37 Butterfield lithograph Pandora
+923 230910 37 Aldrich spongers watering A
+924 230911 37 previewing parenthood ungrateful
+925 230912 37 glut posed secures
+926 230913 37 unaffected instruments chastisers
+927 230914 37 inmate filial icon
+928 231304 37 mineral fixedly reuniting A
+929 231305 37 impending relives imagining A
+930 231306 37 meditation Pandora abiding A
+931 231307 37 ideas watering omnisciently
+932 231308 37 miniaturizes ungrateful Britannic
+933 231309 37 lewdly secures scholastics A
+934 231310 37 title chastisers mechanics A
+935 231311 37 youthfulness icon humidly A
+936 231312 37 creak reuniting masterpiece
+937 231313 37 Chippewa imagining however
+938 231314 37 clamored abiding Mendelian
+939 231315 37 freezes omnisciently jarred
+940 232102 37 forgivably Britannic scolds
+941 232103 37 reduce scholastics infatuate
+942 232104 37 McGovern mechanics willed A
+943 232105 37 Nazis humidly joyfully
+944 232106 37 epistle masterpiece Microsoft
+945 232107 37 socializes however fibrosities
+946 232108 37 conceptions Mendelian Baltimorean
+947 232601 37 Kevin jarred equestrian
+948 232602 37 uncovering scolds Goodrich
+949 232603 37 chews infatuate apish A
+950 232605 37 appendixes willed Adlerian
+5950 1232605 37 appendixes willed Adlerian
+5951 1232606 37 appendixes willed Adlerian
+5952 1232607 37 appendixes willed Adlerian
+5953 1232608 37 appendixes willed Adlerian
+5954 1232609 37 appendixes willed Adlerian
+951 232606 37 raining joyfully Tropez
+952 232607 37 infest Microsoft nouns
+953 232608 37 compartment fibrosities distracting
+954 232609 37 minting Baltimorean mutton
+955 236104 37 ducks equestrian bridgeable A
+956 236105 37 roped Goodrich stickers A
+957 236106 37 waltz apish transcontinental A
+958 236107 37 Lillian Adlerian amateurish
+959 236108 37 repressions Tropez Gandhian
+960 236109 37 chillingly nouns stratified
+961 236110 37 noncritical distracting chamberlains
+962 236111 37 lithograph mutton creditably
+963 236112 37 spongers bridgeable philosophic
+964 236113 37 parenthood stickers ores
+965 238005 37 posed transcontinental Carleton
+966 238006 37 instruments amateurish tape A
+967 238007 37 filial Gandhian afloat A
+968 238008 37 fixedly stratified goodness A
+969 238009 37 relives chamberlains welcoming
+970 238010 37 Pandora creditably Pinsky FAS
+971 238011 37 watering philosophic halting
+972 238012 37 ungrateful ores bibliography
+973 238013 37 secures Carleton decoding
+974 240401 41 chastisers tape variance A
+975 240402 41 icon afloat allowed A
+976 240901 41 reuniting goodness dire A
+977 240902 41 imagining welcoming dub A
+978 241801 41 abiding Pinsky poisoning
+979 242101 41 omnisciently halting Iraqis A
+980 242102 41 Britannic bibliography heaving
+981 242201 41 scholastics decoding population A
+982 242202 41 mechanics variance bomb A
+983 242501 41 humidly allowed Majorca A
+984 242502 41 masterpiece dire Gershwins
+985 246201 41 however dub explorers
+986 246202 41 Mendelian poisoning libretto A
+987 246203 41 jarred Iraqis occurred
+988 246204 41 scolds heaving Lagos
+989 246205 41 infatuate population rats
+990 246301 41 willed bomb bankruptcies A
+991 246302 41 joyfully Majorca crying
+992 248001 41 Microsoft Gershwins unexpected
+993 248002 41 fibrosities explorers accessed A
+994 248003 41 Baltimorean libretto colorful A
+995 248004 41 equestrian occurred versatility A
+996 248005 41 Goodrich Lagos cosy
+997 248006 41 apish rats Darius A
+998 248007 41 Adlerian bankruptcies mastering A
+999 248008 41 Tropez crying Asiaticizations A
+1000 248009 41 nouns unexpected offerers A
+1001 248010 41 distracting accessed uncles A
+1002 248011 41 mutton colorful sleepwalk
+1003 248012 41 bridgeable versatility Ernestine
+1004 248013 41 stickers cosy checksumming
+1005 248014 41 transcontinental Darius stopped
+1006 248015 41 amateurish mastering sicker
+1007 248016 41 Gandhian Asiaticizations Italianization
+1008 248017 41 stratified offerers alphabetic
+1009 248018 41 chamberlains uncles pharmaceutic
+1010 248019 41 creditably sleepwalk creator
+1011 248020 41 philosophic Ernestine chess
+1012 248021 41 ores checksumming charcoal
+1013 248101 41 Carleton stopped Epiphany A
+1014 248102 41 tape sicker bulldozes A
+1015 248201 41 afloat Italianization Pygmalion A
+1016 248202 41 goodness alphabetic caressing A
+1017 248203 41 welcoming pharmaceutic Palestine A
+1018 248204 41 Pinsky creator regimented A
+1019 248205 41 halting chess scars A
+1020 248206 41 bibliography charcoal realest A
+1021 248207 41 decoding Epiphany diffusing A
+1022 248208 41 variance bulldozes clubroom A
+1023 248209 41 allowed Pygmalion Blythe A
+1024 248210 41 dire caressing ahead
+1025 248211 50 dub Palestine reviver
+1026 250501 34 poisoning regimented retransmitting A
+1027 250502 34 Iraqis scars landslide
+1028 250503 34 heaving realest Eiffel
+1029 250504 34 population diffusing absentee
+1030 250505 34 bomb clubroom aye
+1031 250601 34 Majorca Blythe forked A
+1032 250602 34 Gershwins ahead Peruvianizes
+1033 250603 34 explorers reviver clerked
+1034 250604 34 libretto retransmitting tutor
+1035 250605 34 occurred landslide boulevard
+1036 251001 34 Lagos Eiffel shuttered
+1037 251002 34 rats absentee quotes A
+1038 251003 34 bankruptcies aye Caltech
+1039 251004 34 crying forked Mossberg
+1040 251005 34 unexpected Peruvianizes kept
+1041 251301 34 accessed clerked roundly
+1042 251302 34 colorful tutor features A
+1043 251303 34 versatility boulevard imaginable A
+1044 251304 34 cosy shuttered controller
+1045 251305 34 Darius quotes racial
+1046 251401 34 mastering Caltech uprisings A
+1047 251402 34 Asiaticizations Mossberg narrowed A
+1048 251403 34 offerers kept cannot A
+1049 251404 34 uncles roundly vest
+1050 251405 34 sleepwalk features famine
+1051 251406 34 Ernestine imaginable sugars
+1052 251801 34 checksumming controller exterminated A
+1053 251802 34 stopped racial belays
+1054 252101 34 sicker uprisings Hodges A
+1055 252102 34 Italianization narrowed translatable
+1056 252301 34 alphabetic cannot duality A
+1057 252302 34 pharmaceutic vest recording A
+1058 252303 34 creator famine rouses A
+1059 252304 34 chess sugars poison
+1060 252305 34 charcoal exterminated attitude
+1061 252306 34 Epiphany belays dusted
+1062 252307 34 bulldozes Hodges encompasses
+1063 252308 34 Pygmalion translatable presentation
+1064 252309 34 caressing duality Kantian
+1065 256001 34 Palestine recording imprecision A
+1066 256002 34 regimented rouses saving
+1067 256003 34 scars poison maternal
+1068 256004 34 realest attitude hewed
+1069 256005 34 diffusing dusted kerosene
+1070 258001 34 clubroom encompasses Cubans
+1071 258002 34 Blythe presentation photographers
+1072 258003 34 ahead Kantian nymph A
+1073 258004 34 reviver imprecision bedlam A
+1074 258005 34 retransmitting saving north A
+1075 258006 34 landslide maternal Schoenberg A
+1076 258007 34 Eiffel hewed botany A
+1077 258008 34 absentee kerosene curs
+1078 258009 34 aye Cubans solidification
+1079 258010 34 forked photographers inheritresses
+1080 258011 34 Peruvianizes nymph stiller
+1081 258101 68 clerked bedlam t1 A
+1082 258102 68 tutor north suite A
+1083 258103 34 boulevard Schoenberg ransomer
+1084 258104 68 shuttered botany Willy
+1085 258105 68 quotes curs Rena A
+1086 258106 68 Caltech solidification Seattle A
+1087 258107 68 Mossberg inheritresses relaxes A
+1088 258108 68 kept stiller exclaim
+1089 258109 68 roundly t1 implicated A
+1090 258110 68 features suite distinguish
+1091 258111 68 imaginable ransomer assayed
+1092 258112 68 controller Willy homeowner
+1093 258113 68 racial Rena and
+1094 258201 34 uprisings Seattle stealth
+1095 258202 34 narrowed relaxes coinciding A
+1096 258203 34 cannot exclaim founder A
+1097 258204 34 vest implicated environing
+1098 258205 34 famine distinguish jewelry
+1099 258301 34 sugars assayed lemons A
+1100 258401 34 exterminated homeowner brokenness A
+1101 258402 34 belays and bedpost A
+1102 258403 34 Hodges stealth assurers A
+1103 258404 34 translatable coinciding annoyers
+1104 258405 34 duality founder affixed
+1105 258406 34 recording environing warbling
+1106 258407 34 rouses jewelry seriously
+1107 228123 37 poison lemons boasted
+1108 250606 34 attitude brokenness Chantilly
+1109 208405 37 dusted bedpost Iranizes
+1110 212101 37 encompasses assurers violinist
+1111 218206 37 presentation annoyers extramarital
+1112 150401 37 Kantian affixed spates
+1113 248212 41 imprecision warbling cloakroom
+1114 128026 00 saving seriously gazer
+1115 128024 00 maternal boasted hand
+1116 128027 00 hewed Chantilly tucked
+1117 128025 00 kerosene Iranizes gems
+1118 128109 00 Cubans violinist clinker
+1119 128705 00 photographers extramarital refiner
+1120 126303 00 nymph spates callus
+1121 128308 00 bedlam cloakroom leopards
+1122 128204 00 north gazer comfortingly
+1123 128205 00 Schoenberg hand generically
+1124 128206 00 botany tucked getters
+1125 128207 00 curs gems sexually
+1126 118205 00 solidification clinker spear
+1127 116801 00 inheritresses refiner serums
+1128 116803 00 stiller callus Italianization
+1129 116804 00 t1 leopards attendants
+1130 116802 00 suite comfortingly spies
+1131 128605 00 ransomer generically Anthony
+1132 118308 00 Willy getters planar
+1133 113702 00 Rena sexually cupped
+1134 113703 00 Seattle spear cleanser
+1135 112103 00 relaxes serums commuters
+1136 118009 00 exclaim Italianization honeysuckle
+5136 1118009 00 exclaim Italianization honeysuckle
+1137 138011 00 implicated attendants orphanage
+1138 138010 00 distinguish spies skies
+1139 138012 00 assayed Anthony crushers
+1140 068304 00 homeowner planar Puritan
+1141 078009 00 and cupped squeezer
+1142 108013 00 stealth cleanser bruises
+1143 084004 00 coinciding commuters bonfire
+1144 083402 00 founder honeysuckle Colombo
+1145 084003 00 environing orphanage nondecreasing
+1146 088504 00 jewelry skies innocents
+1147 088005 00 lemons crushers masked
+1148 088007 00 brokenness Puritan file
+1149 088006 00 bedpost squeezer brush
+1150 148025 00 assurers bruises mutilate
+1151 148024 00 annoyers bonfire mommy
+1152 138305 00 affixed Colombo bulkheads
+1153 138306 00 warbling nondecreasing undeclared
+1154 152701 00 seriously innocents displacements
+1155 148505 00 boasted masked nieces
+1156 158003 00 Chantilly file coeducation
+1157 156201 00 Iranizes brush brassy
+1158 156202 00 violinist mutilate authenticator
+1159 158307 00 extramarital mommy Washoe
+1160 158402 00 spates bulkheads penny
+1161 158401 00 cloakroom undeclared Flagler
+1162 068013 00 gazer displacements stoned
+1163 068012 00 hand nieces cranes
+1164 068203 00 tucked coeducation masterful
+1165 088205 00 gems brassy biracial
+1166 068704 00 clinker authenticator steamships
+1167 068604 00 refiner Washoe windmills
+1168 158502 00 callus penny exploit
+1169 123103 00 leopards Flagler riverfront
+1170 148026 00 comfortingly stoned sisterly
+1171 123302 00 generically cranes sharpshoot
+1172 076503 00 getters masterful mittens
+1173 126304 00 sexually biracial interdependency
+1174 068306 00 spear steamships policy
+1175 143504 00 serums windmills unleashing
+1176 160201 00 Italianization exploit pretenders
+1177 148028 00 attendants riverfront overstatements
+1178 148027 00 spies sisterly birthed
+1179 143505 00 Anthony sharpshoot opportunism
+1180 108014 00 planar mittens showroom
+1181 076104 00 cupped interdependency compromisingly
+1182 078106 00 cleanser policy Medicare
+1183 126102 00 commuters unleashing corresponds
+1184 128029 00 honeysuckle pretenders hardware
+1185 128028 00 orphanage overstatements implant
+1186 018410 00 skies birthed Alicia
+1187 128110 00 crushers opportunism requesting
+1188 148506 00 Puritan showroom produced
+1189 123303 00 squeezer compromisingly criticizes
+1190 123304 00 bruises Medicare backer
+1191 068504 00 bonfire corresponds positively
+1192 068305 00 Colombo hardware colicky
+1193 000000 00 nondecreasing implant thrillingly
+1 000001 00 Omaha teethe neat
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+1 000001 00 Omaha teethe neat
+2 011401 37 breaking dreaded Steinberg W
+3 011402 37 Romans scholastics jarring
+4 011403 37 intercepted audiology tinily
+INSERT DELAYED INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
drop table t1, t2;
diff --git a/mysql-test/r/bdb.result b/mysql-test/r/bdb.result
index 473ac0116cc..3570f74065e 100644
--- a/mysql-test/r/bdb.result
+++ b/mysql-test/r/bdb.result
@@ -140,13 +140,13 @@ id parent_id level
1015 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 Using index
+1 SIMPLE t1 ref level level 1 const 6 Using index
explain select level,id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 Using index
+1 SIMPLE t1 ref level level 1 const 6 Using index
explain select level,id,parent_id from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1
+1 SIMPLE t1 ref level level 1 const 6
select level,id from t1 where level=1;
level id
1 1002
@@ -625,7 +625,7 @@ id parent_id level
1016 102 2
explain select level from t1 where level=1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref level level 1 const 1 Using index
+1 SIMPLE t1 ref level level 1 const 6 Using index
select level,id from t1 where level=1;
level id
1 1004
@@ -1284,3 +1284,389 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
id
4
DROP TABLE t1;
+create temporary table t1 (a int, primary key(a)) engine=bdb;
+select * from t1;
+a
+alter table t1 add b int;
+select * from t1;
+a b
+drop table t1;
+set storage_engine=bdb;
+drop table if exists t1,t2,t3;
+--- Testing varchar ---
+--- Testing varchar ---
+create table t1 (v varchar(10), c char(10), t text);
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Warning 1265 Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+ *+*+ *
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Warning 1265 Data truncated for column 't' at row 2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(10) default NULL
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+ *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`),
+ KEY `c` (`c`),
+ KEY `t` (`t`(10))
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where c='a ';
+count(*)
+10
+select count(*) from t1 where t='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const 10 Using where
+explain select count(*) from t1 where c='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c c 11 const 10 Using where
+explain select count(*) from t1 where t='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t t 13 NULL 10 Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL 11 Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL 10 Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL 10 Using where
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+qq
+*a*a*a*
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v,v_2 v 13 const 10 Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(*) from t1 group by c limit 10;
+c count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(*) from t1 group by t limit 10;
+t count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a ');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a '),('a '),('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a ' where a like 'a%';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='abc ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a %';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+drop table t1;
+create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`(5)),
+ KEY `c` (`c`(5)),
+ KEY `t` (`t`(5))
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v char(10) character set utf8);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) character set utf8 default NULL
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(10), c char(10)) row_format=fixed;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+insert into t1 values('a','a'),('a ','a ');
+select concat('*',v,'*',c,'*') from t1;
+concat('*',v,'*',c,'*')
+*a*a*
+*a *a*
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+create table t1 (v varchar(65530), key(v));
+Warnings:
+Warning 1071 Specified key was too long; max key length is 255 bytes
+drop table if exists t1;
+create table t1 (v varchar(65536));
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext character set utf8
+) ENGINE=BerkeleyDB DEFAULT CHARSET=latin1
+drop table t1;
+set storage_engine=MyISAM;
diff --git a/mysql-test/r/binary.result b/mysql-test/r/binary.result
index 405de1158d6..5b5f673b071 100644
--- a/mysql-test/r/binary.result
+++ b/mysql-test/r/binary.result
@@ -134,3 +134,10 @@ select * from t1 where firstname='john' and firstname like binary 'John';
firstname lastname
John Doe
drop table t1;
+create table t1 (a binary);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` binary(1) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
diff --git a/mysql-test/r/bool.result b/mysql-test/r/bool.result
index a054eceec0c..184046a2d6f 100644
--- a/mysql-test/r/bool.result
+++ b/mysql-test/r/bool.result
@@ -33,6 +33,24 @@ a
SELECT * FROM t1 where (1 AND a) IS NULL;
a
NULL
+set sql_mode='high_not_precedence';
+select * from t1 where not a between 2 and 3;
+a
+set sql_mode=default;
+select * from t1 where not a between 2 and 3;
+a
+0
+1
+select a, a is false, a is true, a is unknown from t1;
+a a is false a is true a is unknown
+0 1 0 0
+1 0 1 0
+NULL 0 0 1
+select a, a is not false, a is not true, a is not unknown from t1;
+a a is not false a is not true a is not unknown
+0 0 1 1
+1 1 0 1
+NULL 1 1 0
SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
a
diff --git a/mysql-test/r/case.result b/mysql-test/r/case.result
index 75d0c9a7e3b..5679b1d6838 100644
--- a/mysql-test/r/case.result
+++ b/mysql-test/r/case.result
@@ -96,12 +96,12 @@ CASE WHEN 1 THEN 1.0 END AS c9
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` char(1) character set latin1 collate latin1_danish_ci NOT NULL default '',
- `c2` char(1) character set latin1 collate latin1_danish_ci NOT NULL default '',
- `c3` char(1) NOT NULL default '',
- `c4` char(1) NOT NULL default '',
- `c5` char(3) NOT NULL default '',
- `c6` char(3) NOT NULL default '',
+ `c1` varchar(1) character set latin1 collate latin1_danish_ci NOT NULL default '',
+ `c2` varchar(1) character set latin1 collate latin1_danish_ci NOT NULL default '',
+ `c3` varchar(1) NOT NULL default '',
+ `c4` varchar(1) NOT NULL default '',
+ `c5` varchar(3) NOT NULL default '',
+ `c6` varchar(3) NOT NULL default '',
`c7` double(3,1) NOT NULL default '0.0',
`c8` double(3,1) NOT NULL default '0.0',
`c9` double(3,1) default NULL
@@ -147,10 +147,10 @@ Table Create Table
t1 CREATE TABLE `t1` (
`COALESCE(1)` int(1) NOT NULL default '0',
`COALESCE(1.0)` double(3,1) NOT NULL default '0.0',
- `COALESCE('a')` char(1) NOT NULL default '',
+ `COALESCE('a')` varchar(1) NOT NULL default '',
`COALESCE(1,1.0)` double(3,1) NOT NULL default '0.0',
- `COALESCE(1,'1')` char(1) NOT NULL default '',
- `COALESCE(1.1,'1')` char(3) NOT NULL default '',
- `COALESCE('a' COLLATE latin1_bin,'b')` char(1) character set latin1 collate latin1_bin NOT NULL default ''
+ `COALESCE(1,'1')` varchar(1) NOT NULL default '',
+ `COALESCE(1.1,'1')` varchar(3) NOT NULL default '',
+ `COALESCE('a' COLLATE latin1_bin,'b')` varchar(1) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
diff --git a/mysql-test/r/cast.result b/mysql-test/r/cast.result
index ccf75f68e88..d784460a68d 100644
--- a/mysql-test/r/cast.result
+++ b/mysql-test/r/cast.result
@@ -68,7 +68,7 @@ create table t1 select cast(_koi8r'ÔÅÓÔ' as char character set cp1251) as t;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `t` char(4) character set cp1251 NOT NULL default ''
+ `t` varchar(4) character set cp1251 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select
@@ -87,15 +87,15 @@ cast(_latin1'a ' AS char(2)) as c4,
cast(_latin1'a' AS char(2)) as c5;
select * from t1;
c1 c2 c3 c4 c5
-ab a ab a a
+ab a ab a a
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` binary(2) NOT NULL default '',
- `c2` binary(2) NOT NULL default '',
- `c3` binary(2) NOT NULL default '',
- `c4` binary(2) NOT NULL default '',
- `c5` binary(2) NOT NULL default ''
+ `c1` varchar(2) NOT NULL default '',
+ `c2` varchar(2) NOT NULL default '',
+ `c3` varchar(2) NOT NULL default '',
+ `c4` varchar(2) NOT NULL default '',
+ `c5` varchar(2) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select
@@ -114,15 +114,15 @@ cast(_koi8r'Æ ' AS nchar(2)) as c4,
cast(_koi8r'Æ' AS nchar(2)) as c5;
select * from t1;
c1 c2 c3 c4 c5
-фг ф фг ф ф
+фг ф фг ф ф
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` char(2) character set utf8 NOT NULL default '',
- `c2` char(2) character set utf8 NOT NULL default '',
- `c3` char(2) character set utf8 NOT NULL default '',
- `c4` char(2) character set utf8 NOT NULL default '',
- `c5` char(2) character set utf8 NOT NULL default ''
+ `c1` varchar(2) character set utf8 NOT NULL default '',
+ `c2` varchar(2) character set utf8 NOT NULL default '',
+ `c3` varchar(2) character set utf8 NOT NULL default '',
+ `c4` varchar(2) character set utf8 NOT NULL default '',
+ `c5` varchar(2) character set utf8 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (a binary(10), b char(10) character set koi8r);
diff --git a/mysql-test/r/consistent_snapshot.result b/mysql-test/r/consistent_snapshot.result
new file mode 100644
index 00000000000..90606abbe4e
--- /dev/null
+++ b/mysql-test/r/consistent_snapshot.result
@@ -0,0 +1,15 @@
+drop table if exists t1;
+create table t1 (a int) engine=innodb;
+start transaction with consistent snapshot;
+insert into t1 values(1);
+select * from t1;
+a
+commit;
+delete from t1;
+start transaction;
+insert into t1 values(1);
+select * from t1;
+a
+1
+commit;
+drop table t1;
diff --git a/mysql-test/r/count_distinct.result b/mysql-test/r/count_distinct.result
index 16460580d6c..1bc1ad6a31e 100644
--- a/mysql-test/r/count_distinct.result
+++ b/mysql-test/r/count_distinct.result
@@ -53,3 +53,10 @@ select count(distinct f) from t1;
count(distinct f)
0
drop table t1;
+create table t1 (a char(3), b char(20), primary key (a, b));
+insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English');
+select count(distinct a) from t1 group by b;
+count(distinct a)
+1
+1
+drop table t1;
diff --git a/mysql-test/r/create.result b/mysql-test/r/create.result
index 596e8a4c4da..ce4515f900b 100644
--- a/mysql-test/r/create.result
+++ b/mysql-test/r/create.result
@@ -415,7 +415,7 @@ a int(11) YES NULL
b bigint(11) 0
c bigint(10) 0
d date YES NULL
-e char(1)
+e varchar(1)
f datetime YES NULL
g time YES NULL
h longblob
@@ -442,9 +442,9 @@ t2 CREATE TABLE `t2` (
`ifnull(j,j)` date default NULL,
`ifnull(k,k)` datetime NOT NULL default '0000-00-00 00:00:00',
`ifnull(l,l)` datetime default NULL,
- `ifnull(m,m)` char(1) default NULL,
- `ifnull(n,n)` char(3) default NULL,
- `ifnull(o,o)` char(10) default NULL
+ `ifnull(m,m)` varchar(1) default NULL,
+ `ifnull(n,n)` varchar(3) default NULL,
+ `ifnull(o,o)` varchar(10) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1,t2;
create table t1(str varchar(10) default 'def',strnull varchar(10),intg int default '10',rel double default '3.14');
diff --git a/mysql-test/r/ctype_big5.result b/mysql-test/r/ctype_big5.result
index 44fad0cd96a..789b6e586ad 100644
--- a/mysql-test/r/ctype_big5.result
+++ b/mysql-test/r/ctype_big5.result
@@ -1,10 +1,58 @@
drop table if exists t1;
-SET NAMES big5;
-CREATE TABLE t1 (c CHAR(10) CHARACTER SET big5, KEY(c));
+SET @test_character_set= 'big5';
+SET @test_collation= 'big5_chinese_ci';
+SET @safe_character_set_server= @@character_set_server;
+SET @safe_collation_server= @@collation_server;
+SET character_set_server= @test_character_set;
+SET collation_server= @test_collation;
+CREATE DATABASE d1;
+USE d1;
+CREATE TABLE t1 (c CHAR(10), KEY(c));
+SHOW FULL COLUMNS FROM t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c char(10) big5_chinese_ci YES MUL NULL select,insert,update,references
INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa');
-SELECT * FROM t1 WHERE c LIKE 'aaa%';
-c
+SELECT c as want3results FROM t1 WHERE c LIKE 'aaa%';
+want3results
aaa
aaaa
aaaaa
DROP TABLE t1;
+CREATE TABLE t1 (c1 varchar(15), KEY c1 (c1(2)));
+SHOW FULL COLUMNS FROM t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c1 varchar(15) big5_chinese_ci YES MUL NULL select,insert,update,references
+INSERT INTO t1 VALUES ('location'),('loberge'),('lotre'),('boabab');
+SELECT c1 as want3results from t1 where c1 like 'l%';
+want3results
+location
+loberge
+lotre
+SELECT c1 as want3results from t1 where c1 like 'lo%';
+want3results
+location
+loberge
+lotre
+SELECT c1 as want1result from t1 where c1 like 'loc%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'loca%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locat%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locati%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locatio%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'location%';
+want1result
+location
+DROP TABLE t1;
+DROP DATABASE d1;
+USE test;
+SET character_set_server= @safe_character_set_server;
+SET collation_server= @safe_collation_server;
diff --git a/mysql-test/r/ctype_big5.result.es b/mysql-test/r/ctype_big5.result.es
new file mode 100644
index 00000000000..9b9fcbccbe0
--- /dev/null
+++ b/mysql-test/r/ctype_big5.result.es
@@ -0,0 +1,58 @@
+drop table if exists t1;
+SET @test_character_set= 'big5';
+SET @test_collation= 'big5_chinese_ci';
+SET @safe_character_set_server= @@character_set_server;
+SET @safe_collation_server= @@collation_server;
+SET character_set_server= @test_character_set;
+SET collation_server= @test_collation;
+CREATE DATABASE d1;
+USE d1;
+CREATE TABLE t1 (c CHAR(10), KEY(c));
+SHOW FULL COLUMNS FROM t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c char(10) big5_chinese_ci YES MUL NULL
+INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa');
+SELECT c as want3results FROM t1 WHERE c LIKE 'aaa%';
+want3results
+aaa
+aaaa
+aaaaa
+DROP TABLE t1;
+CREATE TABLE t1 (c1 varchar(15), KEY c1 (c1(2)));
+SHOW FULL COLUMNS FROM t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c1 varchar(15) big5_chinese_ci YES MUL NULL
+INSERT INTO t1 VALUES ('location'),('loberge'),('lotre'),('boabab');
+SELECT c1 as want3results from t1 where c1 like 'l%';
+want3results
+location
+loberge
+lotre
+SELECT c1 as want3results from t1 where c1 like 'lo%';
+want3results
+location
+loberge
+lotre
+SELECT c1 as want1result from t1 where c1 like 'loc%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'loca%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locat%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locati%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locatio%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'location%';
+want1result
+location
+DROP TABLE t1;
+DROP DATABASE d1;
+USE test;
+SET character_set_server= @safe_character_set_server;
+SET collation_server= @safe_collation_server;
diff --git a/mysql-test/r/ctype_latin1.result b/mysql-test/r/ctype_latin1.result
index a8182438ac4..355f53b63a5 100644
--- a/mysql-test/r/ctype_latin1.result
+++ b/mysql-test/r/ctype_latin1.result
@@ -296,3 +296,12 @@ FD C3BD FD 1
FE C3BE FE 1
FF C3BF FF 1
DROP TABLE t1;
+select 'a' regexp 'A' collate latin1_general_ci;
+'a' regexp 'A' collate latin1_general_ci
+1
+select 'a' regexp 'A' collate latin1_general_cs;
+'a' regexp 'A' collate latin1_general_cs
+0
+select 'a' regexp 'A' collate latin1_bin;
+'a' regexp 'A' collate latin1_bin
+0
diff --git a/mysql-test/r/ctype_mb.result b/mysql-test/r/ctype_mb.result
index 5e273b3c800..88941d11aad 100644
--- a/mysql-test/r/ctype_mb.result
+++ b/mysql-test/r/ctype_mb.result
@@ -3,16 +3,16 @@ CREATE TABLE t1 SELECT _utf8'test' as c1, _utf8'теÑÑ‚' as c2;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` char(4) character set utf8 NOT NULL default '',
- `c2` char(4) character set utf8 NOT NULL default ''
+ `c1` varchar(4) character set utf8 NOT NULL default '',
+ `c2` varchar(4) character set utf8 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DELETE FROM t1;
ALTER TABLE t1 ADD c3 CHAR(4) CHARACTER SET utf8;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `c1` char(4) character set utf8 NOT NULL default '',
- `c2` char(4) character set utf8 NOT NULL default '',
+ `c1` varchar(4) character set utf8 NOT NULL default '',
+ `c2` varchar(4) character set utf8 NOT NULL default '',
`c3` char(4) character set utf8 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
INSERT INTO t1 VALUES ('aaaabbbbccccdddd','aaaabbbbccccdddd','aaaabbbbccccdddd');
diff --git a/mysql-test/r/ctype_recoding.result b/mysql-test/r/ctype_recoding.result
index 78d15c21301..7d5f9d5b59a 100644
--- a/mysql-test/r/ctype_recoding.result
+++ b/mysql-test/r/ctype_recoding.result
@@ -174,3 +174,69 @@ Warnings:
Warning 1265 Data truncated for column 'a' at row 1
Warning 1265 Data truncated for column 'b' at row 1
drop table t1;
+set names koi8r;
+create table t1 (a char(10) character set cp1251);
+insert into t1 values (_koi8r'×ÁÓÑ');
+select * from t1 where a=_koi8r'×ÁÓÑ';
+a
+×ÁÓÑ
+select * from t1 where a=concat(_koi8r'×ÁÓÑ');
+ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (koi8r_general_ci,COERCIBLE) for operation '='
+select * from t1 where a=_latin1'×ÁÓÑ';
+ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation '='
+drop table t1;
+set names latin1;
+set names koi8r;
+create table t1 (c1 char(10) character set cp1251);
+insert into t1 values ('ß');
+select c1 from t1 where c1 between 'ß' and 'ß';
+c1
+select ifnull(c1,'ß'), ifnull(null,c1) from t1;
+ifnull(c1,'ß') ifnull(null,c1)
+ß ß
+select if(1,c1,'ö'), if(0,c1,'ö') from t1;
+if(1,c1,'ö') if(0,c1,'ö')
+ß ö
+select coalesce('ö',c1), coalesce(null,c1) from t1;
+coalesce('ö',c1) coalesce(null,c1)
+ö ß
+select least(c1,'ö'), greatest(c1,'ö') from t1;
+least(c1,'ö') greatest(c1,'ö')
+ö ß
+select locate(c1,'ß'), locate('ß',c1) from t1;
+locate(c1,'ß') locate('ß',c1)
+1 1
+select field(c1,'ß'),field('ß',c1) from t1;
+field(c1,'ß') field('ß',c1)
+1 1
+select concat(c1,'ö'), concat('ö',c1) from t1;
+concat(c1,'ö') concat('ö',c1)
+ßö öß
+select concat_ws(c1,'ö','ß'), concat_ws('ö',c1,'ß') from t1;
+concat_ws(c1,'ö','ß') concat_ws('ö',c1,'ß')
+ößß ßöß
+select replace(c1,'ß','ö'), replace('ß',c1,'ö') from t1;
+replace(c1,'ß','ö') replace('ß',c1,'ö')
+ö ö
+select substring_index(c1,'öößß',2) from t1;
+substring_index(c1,'öößß',2)
+select elt(1,c1,'ö'),elt(1,'ö',c1) from t1;
+elt(1,c1,'ö') elt(1,'ö',c1)
+ß ö
+select make_set(3,c1,'ö'), make_set(3,'ö',c1) from t1;
+make_set(3,c1,'ö') make_set(3,'ö',c1)
+ß,ö ö,ß
+select insert(c1,1,2,'ö'),insert('ö',1,2,c1) from t1;
+insert(c1,1,2,'ö') insert('ö',1,2,c1)
+ö ß
+select trim(c1 from 'ß'),trim('ß' from c1) from t1;
+trim(c1 from 'ß') trim('ß' from c1)
+
+select lpad(c1,3,'ö'), lpad('ö',3,c1) from t1;
+lpad(c1,3,'ö') lpad('ö',3,c1)
+ööß ßßö
+select rpad(c1,3,'ö'), rpad('ö',3,c1) from t1;
+rpad(c1,3,'ö') rpad('ö',3,c1)
+ßöö ößß
diff --git a/mysql-test/r/ctype_recoding.result.es b/mysql-test/r/ctype_recoding.result.es
new file mode 100644
index 00000000000..27425a69872
--- /dev/null
+++ b/mysql-test/r/ctype_recoding.result.es
@@ -0,0 +1,242 @@
+SET CHARACTER SET koi8r;
+DROP TABLE IF EXISTS ÔÁÂÌÉÃÁ, t1, t2;
+SET CHARACTER SET koi8r;
+CREATE TABLE t1 (a CHAR(10) CHARACTER SET cp1251) SELECT _koi8r'ÐÒÏÂÁ' AS a;
+CREATE TABLE t2 (a CHAR(10) CHARACTER SET utf8);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) character set cp1251 default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT a FROM t1;
+a
+ÐÒÏÂÁ
+SELECT HEX(a) FROM t1;
+HEX(a)
+EFF0EEE1E0
+INSERT t2 SELECT * FROM t1;
+SELECT HEX(a) FROM t2;
+HEX(a)
+D0BFD180D0BED0B1D0B0
+DROP TABLE t1, t2;
+CREATE TABLE t1 (description text character set cp1250 NOT NULL);
+INSERT INTO t1 (description) VALUES (_latin2'aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddde');
+SELECT description FROM t1;
+description
+aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaasssssssssssaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaabbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbcccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccccddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddddde
+DROP TABLE t1;
+CREATE TABLE t1 (a TEXT CHARACTER SET cp1251) SELECT _koi8r'ÐÒÏÂÁ' AS a;
+CREATE TABLE t2 (a TEXT CHARACTER SET utf8);
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` text character set cp1251
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SELECT HEX(a) FROM t1;
+HEX(a)
+EFF0EEE1E0
+INSERT t2 SELECT * FROM t1;
+SELECT HEX(a) FROM t2;
+HEX(a)
+D0BFD180D0BED0B1D0B0
+DROP TABLE t1, t2;
+CREATE TABLE `ÔÁÂÌÉÃÁ`
+(
+ÐÏÌÅ CHAR(32) CHARACTER SET koi8r NOT NULL COMMENT "ËÏÍÍÅÎÔÁÒÉÊ ÐÏÌÑ"
+) COMMENT "ËÏÍÍÅÎÔÁÒÉÊ ÔÁÂÌÉÃÙ";
+SHOW TABLES;
+Tables_in_test
+ÔÁÂÌÉÃÁ
+SHOW CREATE TABLE ÔÁÂÌÉÃÁ;
+Table Create Table
+ÔÁÂÌÉÃÁ CREATE TABLE `ÔÁÂÌÉÃÁ` (
+ `ÐÏÌÅ` char(32) character set koi8r NOT NULL default '' COMMENT 'ËÏÍÍÅÎÔÁÒÉÊ ÐÏÌÑ'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='ËÏÍÍÅÎÔÁÒÉÊ ÔÁÂÌÉÃÙ'
+SHOW FIELDS FROM ÔÁÂÌÉÃÁ;
+Field Type Null Key Default Extra
+ÐÏÌÅ char(32)
+SET CHARACTER SET cp1251;
+SHOW TABLES;
+Tables_in_test
+òàáëèöà
+SHOW CREATE TABLE òàáëèöà;
+Table Create Table
+òàáëèöà CREATE TABLE `òàáëèöà` (
+ `ïîëå` char(32) character set koi8r NOT NULL default '' COMMENT 'êîììåíòàðèé ïîëÿ'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='êîììåíòàðèé òàáëèöû'
+SHOW FIELDS FROM òàáëèöà;
+Field Type Null Key Default Extra
+ïîëå char(32)
+SET CHARACTER SET utf8;
+SHOW TABLES;
+Tables_in_test
+таблица
+SHOW CREATE TABLE таблица;
+Table Create Table
+таблица CREATE TABLE `таблица` (
+ `поле` char(32) character set koi8r NOT NULL default '' COMMENT 'комментарий полÑ'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 COMMENT='комментарий таблицы'
+SHOW FIELDS FROM таблица;
+Field Type Null Key Default Extra
+поле char(32)
+SET CHARACTER SET koi8r;
+DROP TABLE ÔÁÂÌÉÃÁ;
+SET CHARACTER SET default;
+SET NAMES UTF8;
+CREATE TABLE t1 (t text) DEFAULT CHARSET UTF8;
+INSERT INTO t1 (t) VALUES ('x');
+SELECT 1 FROM t1 WHERE CONCAT(_latin1'x') = t;
+1
+1
+DROP TABLE t1;
+SET CHARACTER SET koi8r;
+CREATE DATABASE ÔÅÓÔ;
+USE ÔÅÓÔ;
+SHOW TABLES;
+Tables_in_теÑÑ‚
+SHOW TABLES IN ÔÅÓÔ;
+Tables_in_теÑÑ‚
+SET CHARACTER SET cp1251;
+SHOW TABLES;
+Tables_in_теÑÑ‚
+SHOW TABLES IN òåñò;
+Tables_in_теÑÑ‚
+SET CHARACTER SET koi8r;
+DROP DATABASE ÔÅÓÔ;
+SET NAMES koi8r;
+SELECT hex('ÔÅÓÔ');
+hex('теÑÑ‚')
+D4C5D3D4
+SET character_set_connection=cp1251;
+SELECT hex('ÔÅÓÔ');
+hex('теÑÑ‚')
+F2E5F1F2
+USE test;
+SET NAMES binary;
+CREATE TABLE `теÑÑ‚` (`теÑÑ‚` int);
+SHOW CREATE TABLE `теÑÑ‚`;
+Table Create Table
+теÑÑ‚ CREATE TABLE `теÑÑ‚` (
+ `теÑÑ‚` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SET NAMES utf8;
+SHOW CREATE TABLE `теÑÑ‚`;
+Table Create Table
+теÑÑ‚ CREATE TABLE `теÑÑ‚` (
+ `теÑÑ‚` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP TABLE `теÑÑ‚`;
+SET NAMES binary;
+SET character_set_connection=utf8;
+SELECT 'теÑÑ‚' as s;
+s
+теÑÑ‚
+SET NAMES utf8;
+SET character_set_connection=binary;
+SELECT 'теÑÑ‚' as s;
+s
+теÑÑ‚
+SET NAMES latin1;
+CREATE TABLE t1 (`ä` CHAR(128) DEFAULT 'ä', `ä1` ENUM('ä1','ä2') DEFAULT 'ä2');
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `ä` char(128) default 'ä',
+ `ä1` enum('ä1','ä2') default 'ä2'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SHOW COLUMNS FROM t1;
+Field Type Null Key Default Extra
+ä char(128) YES ä
+ä1 enum('ä1','ä2') YES ä2
+SET NAMES binary;
+SHOW CREATE TABLE t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `ä` char(128) default 'ä',
+ `ä1` enum('ä1','ä2') default 'ä2'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SHOW COLUMNS FROM t1;
+Field Type Null Key Default Extra
+ä char(128) YES ä
+ä1 enum('ä1','ä2') YES ä2
+DROP TABLE t1;
+SET NAMES binary;
+CREATE TABLE `goodÐÌÏÈÏ` (a int);
+ERROR HY000: Invalid utf8 character string: 'ÐÌÏÈÏ'
+SET NAMES utf8;
+CREATE TABLE `goodÐÌÏÈÏ` (a int);
+ERROR HY000: Invalid utf8 character string: 'ÐÌÏÈÏ` (a int)'
+set names latin1;
+create table t1 (a char(10) character set koi8r, b text character set koi8r);
+insert into t1 values ('test','test');
+insert into t1 values ('ÊÃÕË','ÊÃÕË');
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+Warning 1265 Data truncated for column 'b' at row 1
+drop table t1;
+set names koi8r;
+create table t1 (a char(10) character set cp1251);
+insert into t1 values (_koi8r'×ÁÓÑ');
+select * from t1 where a=_koi8r'×ÁÓÑ';
+a
+×ÁÓÑ
+select * from t1 where a=concat(_koi8r'×ÁÓÑ');
+ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (koi8r_general_ci,COERCIBLE) for operation '='
+select * from t1 where a=_latin1'×ÁÓÑ';
+ERROR HY000: Illegal mix of collations (cp1251_general_ci,IMPLICIT) and (latin1_swedish_ci,COERCIBLE) for operation '='
+drop table t1;
+set names latin1;
+set names koi8r;
+create table t1 (c1 char(10) character set cp1251);
+insert into t1 values ('ß');
+select c1 from t1 where c1 between 'ß' and 'ß';
+c1
+select ifnull(c1,'ß'), ifnull(null,c1) from t1;
+ifnull(c1,'ÑŠ') ifnull(null,c1)
+ß ß
+select if(1,c1,'ö'), if(0,c1,'ö') from t1;
+if(1,c1,'Ж') if(0,c1,'Ж')
+ß ö
+select coalesce('ö',c1), coalesce(null,c1) from t1;
+coalesce('Ж',c1) coalesce(null,c1)
+ö ß
+select least(c1,'ö'), greatest(c1,'ö') from t1;
+least(c1,'Ж') greatest(c1,'Ж')
+ö ß
+select locate(c1,'ß'), locate('ß',c1) from t1;
+locate(c1,'ÑŠ') locate('ÑŠ',c1)
+1 1
+select field(c1,'ß'),field('ß',c1) from t1;
+field(c1,'ÑŠ') field('ÑŠ',c1)
+1 1
+select concat(c1,'ö'), concat('ö',c1) from t1;
+concat(c1,'Ж') concat('Ж',c1)
+ßö öß
+select concat_ws(c1,'ö','ß'), concat_ws('ö',c1,'ß') from t1;
+concat_ws(c1,'Ж','ъ') concat_ws('Ж',c1,'ъ')
+ößß ßöß
+select replace(c1,'ß','ö'), replace('ß',c1,'ö') from t1;
+replace(c1,'ъ','Ж') replace('ъ',c1,'Ж')
+ö ö
+select substring_index(c1,'öößß',2) from t1;
+substring_index(c1,'ЖЖъъ',2)
+select elt(1,c1,'ö'),elt(1,'ö',c1) from t1;
+elt(1,c1,'Ж') elt(1,'Ж',c1)
+ß ö
+select make_set(3,c1,'ö'), make_set(3,'ö',c1) from t1;
+make_set(3,c1,'Ж') make_set(3,'Ж',c1)
+ß,ö ö,ß
+select insert(c1,1,2,'ö'),insert('ö',1,2,c1) from t1;
+insert(c1,1,2,'Ж') insert('Ж',1,2,c1)
+ö ß
+select trim(c1 from 'ß'),trim('ß' from c1) from t1;
+trim(c1 from 'ÑŠ') trim('ÑŠ' from c1)
+
+select lpad(c1,3,'ö'), lpad('ö',3,c1) from t1;
+lpad(c1,3,'Ж') lpad('Ж',3,c1)
+ööß ßßö
+select rpad(c1,3,'ö'), rpad('ö',3,c1) from t1;
+rpad(c1,3,'Ж') rpad('Ж',3,c1)
+ßöö ößß
diff --git a/mysql-test/r/ctype_sjis.result b/mysql-test/r/ctype_sjis.result
index b0edbed1a41..944fa0602a9 100644
--- a/mysql-test/r/ctype_sjis.result
+++ b/mysql-test/r/ctype_sjis.result
@@ -60,3 +60,14 @@ hex(c)
9353
9373
drop table t1;
+SET NAMES sjis;
+CREATE TABLE t1 (
+c char(16) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=sjis;
+insert into t1 values(0xb1),(0xb2),(0xb3);
+select hex(c) from t1;
+hex(c)
+B1
+B2
+B3
+drop table t1;
diff --git a/mysql-test/r/ctype_tis620.result b/mysql-test/r/ctype_tis620.result
index 1fece515f9f..0f29c564fa8 100644
--- a/mysql-test/r/ctype_tis620.result
+++ b/mysql-test/r/ctype_tis620.result
@@ -259,8 +259,8 @@ WU
¡Ñ³°ªÒ
¡Ñ³°Ô¡Ò
¡Ñ³·ÔÁÒ
-¡Ñ¹µì
¡Ñ¹µÔ¡Ã
+¡Ñ¹µì
¡Ñ¹¸ÔªÒ
¡Ñ¹¸ÔÁÒ
¡Ñ¹ÂÒÃѵ¹ì
@@ -272,8 +272,8 @@ WU
¡Ò­¨¹ÇÃó
¡Ò­¨¹Ò
¡Ò¹´Ò
-¡Ò¹µì
¡Ò¹µìÃÇÕ
+¡Ò¹µì
¡ÒÂÊÔ·¸Ôì
¡ÒÃÇÔÍÃ
¡ÒÃØ³Õ
@@ -350,8 +350,8 @@ WU
à¡ÕÂõÔÈÑ¡´Ôì
à¡ÕÂõÔÊÇÑÊ´Ôì
à¡×éÍ¡ÙÅ
-á¡éÇ
á¡éÇã¨
+á¡éÇ
â¡Ážѹ¸ì
â¡àÁÈ
â¡ÅºÍÅ ¤Í¹à¹ç¤ªÑè¹Êì
@@ -368,8 +368,8 @@ WU
¢¨Ãà¡ÕÂõÔ
¢¨ÃÈÃÕ
¢¨ÃÈÑ¡´Ôì
-¢¹Ôɰì
¢¹ÔɰÒ
+¢¹Ôɰì
¢ÇÑ­ã¨
¢ÇÑ­ªÑÂ
¢ÇÑ­à´×͹
@@ -412,8 +412,8 @@ WU
ठÊËÒÂÍÔÁà»ê¡«ì
à¤.«Õ.¾Õ. áÁªªÕ¹à¹ÍÃÕè
षշÕÅÔÊ«Ôè§
-ह áÁ¡«ì (»ÃÐà·Èä·Â)
ह áÁç¡«ì (»ÃÐà·Èä·Â)
+ह áÁ¡«ì (»ÃÐà·Èä·Â)
à¤Ã×ÍÇÑÅÂì
᤹¹Ù ÍÔ¹àµÍÃìà·Ã´
á¤Ð¨éÍÂ
@@ -494,12 +494,12 @@ WU
¨ÓàÃÔ­
¨ÓÅͧ
¨Ô³³ì
-¨Ôµµì
¨Ôµµì¹ÔÉÒ
¨ÔµµÁÒÊ
¨ÔµµÒ
¨ÔµµÔ
¨ÔµµÔ¹¹Ñ¹·ì
+¨Ôµµì
¨ÔµÃÅ´Ò
¨ÔµÃÒ
¨ÔµÃÒÀóì
@@ -627,10 +627,10 @@ WU
ªÇ¹¾ÔÈ
ªÇÅÔµ
ªÇÔÈÒ
-ªèÍ
ªèͩѵÃ
ªèÍ·Ô¾Âì
ªèÍÍÑ­ªÑ­
+ªèÍ
ªÐ¹ÔÅ
ªÐÍé͹
ªÑªªÑÂ
@@ -758,12 +758,12 @@ WU
³¸ÔµÒ
³ÀÑ·Ã
³Àѷáóì
-³Ã§¤ì
³Ã§¤ìªÑÂ
³Ã§¤ì¾ÑªÃì
³Ã§¤ìÄ·¸Ôì
³Ã§¤ìÇÔ·Âì
³Ã§¤ìÈÑ¡´Ôì
+³Ã§¤ì
³Ã§ÃÑ¡Éì
³Ã§Ä·¸Ôì
³Ã§ÈÑ¡´Ôì
@@ -862,11 +862,11 @@ WU
µÐÇѹ
µÑ觨Ñè§ËÅÍ´ä¿
µÒà¿ç´
-µØê
µØê¡µÒ
µØéÁ
µØëÂ
µØÅÒÅѡɳì
+µØê
àµçÁà´ª
àµ×͹ã¨
àµ×͹µÒ
@@ -917,8 +917,8 @@ WU
·Ñº·ÔÁ
·ÑȹÇÃó
·ÑȹվÃ
-·ÑȹÕÂì
·ÑȹÕÂÒ
+·ÑȹÕÂì
·ÑÈÇÃó
·èÒ·ÃÒÂá¨é§ÇѲ¹Ò
·Ô¦ÑÁ¾Ã
@@ -1088,8 +1088,8 @@ WU
¹Ã¾Å
¹ÃÀÑ·Ãì
¹ÃÒ
-¹ÃÔ¹·Ãì
¹ÃÔ¹·Ãìà´ª
+¹ÃÔ¹·Ãì
¹ÃÔÈ
¹ÃÔɰ
¹ÃÕ
@@ -1115,8 +1115,8 @@ WU
¹Ñ·¸Á¹
¹Ñ¹ªÑÂ
¹Ñ¹·ªÑÂ
-¹Ñ¹·¹ì
¹Ñ¹·¹Ò
+¹Ñ¹·¹ì
¹Ñ¹·¾Ã
¹Ñ¹·¾Å
¹Ñ¹·ÁÒÊ
@@ -1148,14 +1148,14 @@ WU
¹Ôà«Ð
¹Ô´
¹Ô´Ò
-¹ÔµÂì
¹ÔµÂÒ
+¹ÔµÂì
¹ÔµÔ
¹ÔµÔ¾§Éì
¹ÔµÔÁÒ
¹Ô·ÃÒ
-¹Ô·Ñȹì
¹Ô·ÑȹÕÂì
+¹Ô·Ñȹì
¹Ô¸ÔÇ´Õ
¹Ô»»Í¹à¾¹µì(»ÃÐà·Èä·Â)
¹Ô¾¹¸ì
@@ -1349,8 +1349,8 @@ WU
»ÃÒ³ÕÂì
»ÃÒâÁ·Âì
»ÃÒö¹Ò
-»ÃÔ­­ì
»ÃÔ­­Ò
+»ÃÔ­­ì
»ÃÔ­´Ò
»ÃÔ³´Ò
»ÃÔ·ÑÈ
@@ -1454,10 +1454,10 @@ WU
¾§ÉìÈÑ¡´Ôì
¾§ÉìÊѹµì
¾§Éì͹ѹµì
-¾¨¹ì
¾¨¹Ò
¾¨¹Òö
¾¨¹ÕÂì
+¾¨¹ì
¾¨ÁÒ¹
¾¨ÁÒÅÂì
¾¹Á
@@ -1504,8 +1504,8 @@ WU
¾ÃÊÇÃäì
¾ÃËÁ¾Ñ²¹ì
¾ÃéÍÁªÑÂ
-¾ÃлÃÐá´§ Î͹´éÒ¤ÒÃìÊì
¾ÃлÃÐá´§ Î͹´éÒ¤ÒÃìÊì ¨Ó¡Ñ´
+¾ÃлÃÐá´§ Î͹´éÒ¤ÒÃìÊì
¾ÃÐÃÒÁ 3 ¤ÒÃìà«ç¹àµÍÃì
¾ÃÐÃÒÁ 3 Î͹´éÒ¤ÒÃìÊì
¾ÃÔéÁà¾ÃÒ
@@ -1604,10 +1604,10 @@ WU
¾Ùŷͧ¾Ãç;à¾ÍÃìµÕé_
¾ÙżÅ
à¾ç§ ¿Ù ËÅÔ¹
-à¾çªÃì
ྪÃÃѵ¹ì
ྪÃÅ´Ò
ྪÃÔ¹·Ãì
+à¾çªÃì
à¾ç­¨Ñ¹·Ãì
à¾ç­·Ô¾Âì
à¾ç­¹ÀÒ
@@ -1831,7 +1831,6 @@ WU
ÃÒàÁÈÃì
ÃÒÂÕ¹
Ã×è¹ÇÃÒËì
-ÃØé§
ÃØè§·Ô¾Âì
ÃØè§·ÔÇÒ
ÃØè§¹ÀÒ
@@ -1840,11 +1839,12 @@ WU
ÃØè§Ãѵ¹ì
ÃØè§ÃÑÈÁÕ
ÃØè§àÃ×ͧ
-ÃØè§âè¹ì
ÃØè§âè¹ì¢¹Êè§
+ÃØè§âè¹ì
ÃØé§ÅÒÇÃó
ÃØè§ÇÔ·Âì
ÃØè§ÍÃØ³
+ÃØé§
ÃØ¨Ò
ÃØ¨ÒÀÒ
ÃØËйÒ
@@ -1861,8 +1861,8 @@ WU
áþᾤ ¤Í¹ÊµÃѤªÑè¹
âç§Ò¹àËÅç¡¡ÃØ§à·¾Ï
âè¹ì»ÃÐàÊÃÔ°
-Ä·¸Ôì
Ä·¸ÔªÑÂ
+Ä·¸Ôì
ÅÅÔ´Ò
ÅÅÔµÒ
ÅÐÁèÍÁ
@@ -2050,8 +2050,8 @@ WU
ÇÔäÅÇÃó
ÇÔÇ
ÇÔÇÃø¹ì
-ÇÔÇѲ¹ì
ÇÔÇѲ¹ìªÑÂ
+ÇÔÇѲ¹ì
ÇÔȹÕ
ÇÔÈÃØµ
ÇÔÈÒÅ
@@ -2146,11 +2146,11 @@ WU
ÈÈÔÇÔÁÅ
ÈÈÔÉÒ
ÈÑ¡´Ò
-ÈÑ¡´Ôì
ÈÑ¡´ÔìªÑÂ
ÈÑ¡´ÔìàªÇ§
ÈÑ¡´Ôì´Ò
ÈÑ¡´ÔìÇÔºÙÅÂì
+ÈÑ¡´Ôì
ÈÑ¡ÃÔ¹·Ãì
ÈѹʹÕÂì
ÈÒ¹µÔᏴì
@@ -2348,18 +2348,18 @@ WU
ÊÓÃÒ­
ÊÓÄ·¸Ôì
ÊÓÅÕ
-ÊÔ§Ëì
ÊÔ§Ëì¾Å
ÊÔ§ËÒ
+ÊÔ§Ëì
ÊԵҹѹ
ÊÔµÒ¾Ã
ÊÔ·¸Ò
-ÊÔ·¸Ôì
ÊÔ·¸ÔªÑÂ
ÊÔ·¸Ôà´ª
ÊÔ·¸Ô¾Ã
ÊÔ·¸Ô¾Ãó
ÊÔ·¸Ô¾Å
+ÊÔ·¸Ôì
ÊÔ¹·ÇÕ
ÊÔÃÔªÑÂ
ÊÔÃÔà´ª
@@ -2393,15 +2393,15 @@ WU
ÊØ¢ÊÇÑÊ´Ôì¡Å¡ÒÃ
ÊØ¢Êѹµì
ÊØ¢ØÁ
-ÊØ¤¹¸ì
ÊØ¤¹¸Ò
+ÊØ¤¹¸ì
ÊØ¨ÒÃÕ
ÊØ¨Ôµ
ÊØ¨ÔµµÒ
ÊØ¨ÔµÃÒ
ÊØ¨Ô¹´Ò
-ÊØ¨Ô¹µì
ÊØ¨Ô¹µ¹ì
+ÊØ¨Ô¹µì
ÊØªÅ
ÊØªÑÂ
ÊØªÒ´Ò
@@ -2443,13 +2443,13 @@ WU
ÊØ¸Ô´Ò
ÊØ¸ÔÈÑ¡´Ôì
ÊØ¸Õ
-ÊØ¸ÕÃì
ÊØ¸ÕÃÒ
+ÊØ¸ÕÃì
ÊØ¹·Ã
ÊØ¹·ÃÕ
ÊØ¹Ñ··Õ
-ÊØ¹Ñ¹·ì
ÊØ¹Ñ¹·Ò
+ÊØ¹Ñ¹·ì
ÊØ¹ÔµÒ
ÊØ¹ÔÈÒ
ÊØ¹ÔÉÒ
@@ -2511,10 +2511,10 @@ WU
ÊØÃÈÑ¡´Ôì
ÊØÃÊÔ·¸Ôì
ÊØÃѪ¹Õ¡Ã
-ÊØÃѵ¹ì
ÊØÃѵ¹Ç´Õ
ÊØÃѵ¹ìÇ´Õ
ÊØÃѵ¹Ò
+ÊØÃѵ¹ì
ÊØÃѵÂÒ
ÊØÃÒ§¤¹Ò
ÊØÃÔªÑÂ
@@ -2529,8 +2529,8 @@ WU
ÊØÃÕ¸Ò¾Ã
ÊØÃÕ¾Ã
ÊØÃÕÁÒÈ
-ÊØÃÕÂì
ÊØÃÕÂì¾Ã
+ÊØÃÕÂì
ÊØÃÕÃѵ¹ì
ÊØÅÑ´´Ò
ÊØÇÀÑ·Ãì
@@ -2540,9 +2540,9 @@ WU
ÊØÇÃóÕ
ÊØÇÃóÕÂì
ÊØÇÃѵ¹ì
-ÊØÇѲ¹ì
ÊØÇѲ¹ìªÑÂ
ÊØÇѲ¹Ò
+ÊØÇѲ¹ì
ÊØÇѵªÑÂ
ÊØÇÒÃÕ
ÊØÇÔªÑÂ
@@ -2623,8 +2623,8 @@ WU
͹¹·ì
͹ÇѪ
͹ѭ­Ò
-͹ѹµì
͹ѹµÈÑ¡´Ôì
+͹ѹµì
͹ءԵÔ
͹ءÙÅ
͹تÒ
@@ -2770,8 +2770,8 @@ WU
ÍÒÃÒ¾Ã
ÍÒÃÔÂÒ
ÍÒÃÕ
-ÍÒÃÕÂì
ÍÒÃÕÂì àÊÁÒ©ÔÁ (ä·Âູ¡Ñ¹
+ÍÒÃÕÂì
ÍÒÃÕÃѵ¹ì
ÍÒÃÕÇÃó
ÍÓ¹ÇÂ
@@ -2899,3 +2899,41 @@ hex(a) STRCMP(a,'a') STRCMP(a,'a ')
6109 -1 -1
61 0 0
DROP TABLE t1;
+CREATE TABLE t1 (
+`id` int(11) NOT NULL auto_increment,
+`url` varchar(200) NOT NULL default '',
+`name` varchar(250) NOT NULL default '',
+`type` int(11) NOT NULL default '0',
+`website` varchar(250) NOT NULL default '',
+`adddate` date NOT NULL default '0000-00-00',
+`size` varchar(20) NOT NULL default '',
+`movieid` int(11) NOT NULL default '0',
+`musicid` int(11) NOT NULL default '0',
+`star` varchar(20) NOT NULL default '',
+`download` int(11) NOT NULL default '0',
+`lastweek` int(11) NOT NULL default '0',
+`thisweek` int(11) NOT NULL default '0',
+`page` varchar(250) NOT NULL default '',
+PRIMARY KEY (`id`),
+UNIQUE KEY `url` (`url`)
+) CHARACTER SET tis620;
+INSERT INTO t1 VALUES
+(1,'http://www.siamzone.com/download/download/000001-frodo_1024.jpg','The Lord
+of the Rings
+Wallpapers',1,'http://www.lordoftherings.net','2002-01-22','',448,0,'',3805,0,0,
+'');
+INSERT INTO t1 VALUES (2,'http://www.othemovie.com/OScreenSaver1.EXE','O
+Screensaver',2,'','2002-01-22','',491,0,'',519,0,0,'');
+INSERT INTO t1 VALUES
+(3,'http://www.siamzone.com/download/download/000003-jasonx2(800x600).jpg','Jaso
+n X Wallpapers',1,'','2002-05-31','',579,0,'',1091,0,0,'');
+select * from t1 order by id;
+id url name type website adddate size movieid musicid star download lastweek thisweek page
+1 http://www.siamzone.com/download/download/000001-frodo_1024.jpg The Lord
+of the Rings
+Wallpapers 1 http://www.lordoftherings.net 2002-01-22 448 0 3805 0 0
+2 http://www.othemovie.com/OScreenSaver1.EXE O
+Screensaver 2 2002-01-22 491 0 519 0 0
+3 http://www.siamzone.com/download/download/000003-jasonx2(800x600).jpg Jaso
+n X Wallpapers 1 2002-05-31 579 0 1091 0 0
+DROP TABLE t1;
diff --git a/mysql-test/r/ctype_uca.result b/mysql-test/r/ctype_uca.result
index 90681795513..cb060ad7ee4 100644
--- a/mysql-test/r/ctype_uca.result
+++ b/mysql-test/r/ctype_uca.result
@@ -19,6 +19,9 @@ select 'a ' = 'a\t', 'a ' < 'a\t', 'a ' > 'a\t';
select 'a a' > 'a', 'a \t' < 'a';
'a a' > 'a' 'a \t' < 'a'
1 1
+select 'c' like '\_' as want0;
+want0
+0
CREATE TABLE t (
c char(20) NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
@@ -2315,3 +2318,60 @@ HEX(CONVERT(col1 USING ucs2))
064A06A9062F064A06AF0631
064A06A9064A
DROP TABLE t1;
+SET @test_character_set= 'utf8';
+SET @test_collation= 'utf8_swedish_ci';
+SET @safe_character_set_server= @@character_set_server;
+SET @safe_collation_server= @@collation_server;
+SET character_set_server= @test_character_set;
+SET collation_server= @test_collation;
+CREATE DATABASE d1;
+USE d1;
+CREATE TABLE t1 (c CHAR(10), KEY(c));
+SHOW FULL COLUMNS FROM t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c char(10) utf8_swedish_ci YES MUL NULL select,insert,update,references
+INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa');
+SELECT c as want3results FROM t1 WHERE c LIKE 'aaa%';
+want3results
+aaa
+aaaa
+aaaaa
+DROP TABLE t1;
+CREATE TABLE t1 (c1 varchar(15), KEY c1 (c1(2)));
+SHOW FULL COLUMNS FROM t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c1 varchar(15) utf8_swedish_ci YES MUL NULL select,insert,update,references
+INSERT INTO t1 VALUES ('location'),('loberge'),('lotre'),('boabab');
+SELECT c1 as want3results from t1 where c1 like 'l%';
+want3results
+location
+loberge
+lotre
+SELECT c1 as want3results from t1 where c1 like 'lo%';
+want3results
+location
+loberge
+lotre
+SELECT c1 as want1result from t1 where c1 like 'loc%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'loca%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locat%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locati%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locatio%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'location%';
+want1result
+location
+DROP TABLE t1;
+DROP DATABASE d1;
+USE test;
+SET character_set_server= @safe_character_set_server;
+SET collation_server= @safe_collation_server;
diff --git a/mysql-test/r/ctype_uca.result.es b/mysql-test/r/ctype_uca.result.es
new file mode 100644
index 00000000000..1f86376def6
--- /dev/null
+++ b/mysql-test/r/ctype_uca.result.es
@@ -0,0 +1,2377 @@
+DROP TABLE IF EXISTS t1;
+set names utf8;
+set collation_connection=utf8_unicode_ci;
+select 'a' = 'a', 'a' = 'a ', 'a ' = 'a';
+'a' = 'a' 'a' = 'a ' 'a ' = 'a'
+1 1 1
+select 'a\t' = 'a' , 'a\t' < 'a' , 'a\t' > 'a';
+'a\t' = 'a' 'a\t' < 'a' 'a\t' > 'a'
+0 1 0
+select 'a\t' = 'a ', 'a\t' < 'a ', 'a\t' > 'a ';
+'a\t' = 'a ' 'a\t' < 'a ' 'a\t' > 'a '
+0 1 0
+select 'a' = 'a\t', 'a' < 'a\t', 'a' > 'a\t';
+'a' = 'a\t' 'a' < 'a\t' 'a' > 'a\t'
+0 0 1
+select 'a ' = 'a\t', 'a ' < 'a\t', 'a ' > 'a\t';
+'a ' = 'a\t' 'a ' < 'a\t' 'a ' > 'a\t'
+0 0 1
+select 'a a' > 'a', 'a \t' < 'a';
+'a a' > 'a' 'a \t' < 'a'
+1 1
+select 'c' like '\_' as want0;
+want0
+0
+CREATE TABLE t (
+c char(20) NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci;
+INSERT INTO t VALUES ('a'),('ab'),('aba');
+ALTER TABLE t ADD INDEX (c);
+SELECT c FROM t WHERE c LIKE 'a%';
+c
+a
+ab
+aba
+DROP TABLE t;
+create table t1 (c1 char(10) character set utf8 collate utf8_bin);
+insert into t1 values ('A'),('a');
+insert into t1 values ('B'),('b');
+insert into t1 values ('C'),('c');
+insert into t1 values ('D'),('d');
+insert into t1 values ('E'),('e');
+insert into t1 values ('F'),('f');
+insert into t1 values ('G'),('g');
+insert into t1 values ('H'),('h');
+insert into t1 values ('I'),('i');
+insert into t1 values ('J'),('j');
+insert into t1 values ('K'),('k');
+insert into t1 values ('L'),('l');
+insert into t1 values ('M'),('m');
+insert into t1 values ('N'),('n');
+insert into t1 values ('O'),('o');
+insert into t1 values ('P'),('p');
+insert into t1 values ('Q'),('q');
+insert into t1 values ('R'),('r');
+insert into t1 values ('S'),('s');
+insert into t1 values ('T'),('t');
+insert into t1 values ('U'),('u');
+insert into t1 values ('V'),('v');
+insert into t1 values ('W'),('w');
+insert into t1 values ('X'),('x');
+insert into t1 values ('Y'),('y');
+insert into t1 values ('Z'),('z');
+insert into t1 values (_ucs2 0x00e0),(_ucs2 0x00c0);
+insert into t1 values (_ucs2 0x00e1),(_ucs2 0x00c1);
+insert into t1 values (_ucs2 0x00e2),(_ucs2 0x00c2);
+insert into t1 values (_ucs2 0x00e3),(_ucs2 0x00c3);
+insert into t1 values (_ucs2 0x00e4),(_ucs2 0x00c4);
+insert into t1 values (_ucs2 0x00e5),(_ucs2 0x00c5);
+insert into t1 values (_ucs2 0x00e6),(_ucs2 0x00c6);
+insert into t1 values (_ucs2 0x00e7),(_ucs2 0x00c7);
+insert into t1 values (_ucs2 0x00e8),(_ucs2 0x00c8);
+insert into t1 values (_ucs2 0x00e9),(_ucs2 0x00c9);
+insert into t1 values (_ucs2 0x00ea),(_ucs2 0x00ca);
+insert into t1 values (_ucs2 0x00eb),(_ucs2 0x00cb);
+insert into t1 values (_ucs2 0x00ec),(_ucs2 0x00cc);
+insert into t1 values (_ucs2 0x00ed),(_ucs2 0x00cd);
+insert into t1 values (_ucs2 0x00ee),(_ucs2 0x00ce);
+insert into t1 values (_ucs2 0x00ef),(_ucs2 0x00cf);
+insert into t1 values (_ucs2 0x00f0),(_ucs2 0x00d0);
+insert into t1 values (_ucs2 0x00f1),(_ucs2 0x00d1);
+insert into t1 values (_ucs2 0x00f2),(_ucs2 0x00d2);
+insert into t1 values (_ucs2 0x00f3),(_ucs2 0x00d3);
+insert into t1 values (_ucs2 0x00f4),(_ucs2 0x00d4);
+insert into t1 values (_ucs2 0x00f5),(_ucs2 0x00d5);
+insert into t1 values (_ucs2 0x00f6),(_ucs2 0x00d6);
+insert into t1 values (_ucs2 0x00f7),(_ucs2 0x00d7);
+insert into t1 values (_ucs2 0x00f8),(_ucs2 0x00d8);
+insert into t1 values (_ucs2 0x00f9),(_ucs2 0x00d9);
+insert into t1 values (_ucs2 0x00fa),(_ucs2 0x00da);
+insert into t1 values (_ucs2 0x00fb),(_ucs2 0x00db);
+insert into t1 values (_ucs2 0x00fc),(_ucs2 0x00dc);
+insert into t1 values (_ucs2 0x00fd),(_ucs2 0x00dd);
+insert into t1 values (_ucs2 0x00fe),(_ucs2 0x00de);
+insert into t1 values (_ucs2 0x00ff),(_ucs2 0x00df);
+insert into t1 values (_ucs2 0x0100),(_ucs2 0x0101),(_ucs2 0x0102),(_ucs2 0x0103);
+insert into t1 values (_ucs2 0x0104),(_ucs2 0x0105),(_ucs2 0x0106),(_ucs2 0x0107);
+insert into t1 values (_ucs2 0x0108),(_ucs2 0x0109),(_ucs2 0x010a),(_ucs2 0x010b);
+insert into t1 values (_ucs2 0x010c),(_ucs2 0x010d),(_ucs2 0x010e),(_ucs2 0x010f);
+insert into t1 values (_ucs2 0x0110),(_ucs2 0x0111),(_ucs2 0x0112),(_ucs2 0x0113);
+insert into t1 values (_ucs2 0x0114),(_ucs2 0x0115),(_ucs2 0x0116),(_ucs2 0x0117);
+insert into t1 values (_ucs2 0x0118),(_ucs2 0x0119),(_ucs2 0x011a),(_ucs2 0x011b);
+insert into t1 values (_ucs2 0x011c),(_ucs2 0x011d),(_ucs2 0x011e),(_ucs2 0x011f);
+insert into t1 values (_ucs2 0x0120),(_ucs2 0x0121),(_ucs2 0x0122),(_ucs2 0x0123);
+insert into t1 values (_ucs2 0x0124),(_ucs2 0x0125),(_ucs2 0x0126),(_ucs2 0x0127);
+insert into t1 values (_ucs2 0x0128),(_ucs2 0x0129),(_ucs2 0x012a),(_ucs2 0x012b);
+insert into t1 values (_ucs2 0x012c),(_ucs2 0x012d),(_ucs2 0x012e),(_ucs2 0x012f);
+insert into t1 values (_ucs2 0x0130),(_ucs2 0x0131),(_ucs2 0x0132),(_ucs2 0x0133);
+insert into t1 values (_ucs2 0x0134),(_ucs2 0x0135),(_ucs2 0x0136),(_ucs2 0x0137);
+insert into t1 values (_ucs2 0x0138),(_ucs2 0x0139),(_ucs2 0x013a),(_ucs2 0x013b);
+insert into t1 values (_ucs2 0x013c),(_ucs2 0x013d),(_ucs2 0x013e),(_ucs2 0x013f);
+insert into t1 values (_ucs2 0x0140),(_ucs2 0x0141),(_ucs2 0x0142),(_ucs2 0x0143);
+insert into t1 values (_ucs2 0x0144),(_ucs2 0x0145),(_ucs2 0x0146),(_ucs2 0x0147);
+insert into t1 values (_ucs2 0x0148),(_ucs2 0x0149),(_ucs2 0x014a),(_ucs2 0x014b);
+insert into t1 values (_ucs2 0x014c),(_ucs2 0x014d),(_ucs2 0x014e),(_ucs2 0x014f);
+insert into t1 values (_ucs2 0x0150),(_ucs2 0x0151),(_ucs2 0x0152),(_ucs2 0x0153);
+insert into t1 values (_ucs2 0x0154),(_ucs2 0x0155),(_ucs2 0x0156),(_ucs2 0x0157);
+insert into t1 values (_ucs2 0x0158),(_ucs2 0x0159),(_ucs2 0x015a),(_ucs2 0x015b);
+insert into t1 values (_ucs2 0x015c),(_ucs2 0x015d),(_ucs2 0x015e),(_ucs2 0x015f);
+insert into t1 values (_ucs2 0x0160),(_ucs2 0x0161),(_ucs2 0x0162),(_ucs2 0x0163);
+insert into t1 values (_ucs2 0x0164),(_ucs2 0x0165),(_ucs2 0x0166),(_ucs2 0x0167);
+insert into t1 values (_ucs2 0x0168),(_ucs2 0x0169),(_ucs2 0x016a),(_ucs2 0x016b);
+insert into t1 values (_ucs2 0x016c),(_ucs2 0x016d),(_ucs2 0x016e),(_ucs2 0x016f);
+insert into t1 values (_ucs2 0x0170),(_ucs2 0x0171),(_ucs2 0x0172),(_ucs2 0x0173);
+insert into t1 values (_ucs2 0x0174),(_ucs2 0x0175),(_ucs2 0x0176),(_ucs2 0x0177);
+insert into t1 values (_ucs2 0x0178),(_ucs2 0x0179),(_ucs2 0x017a),(_ucs2 0x017b);
+insert into t1 values (_ucs2 0x017c),(_ucs2 0x017d),(_ucs2 0x017e),(_ucs2 0x017f);
+insert into t1 values (_ucs2 0x0180),(_ucs2 0x0181),(_ucs2 0x0182),(_ucs2 0x0183);
+insert into t1 values (_ucs2 0x0184),(_ucs2 0x0185),(_ucs2 0x0186),(_ucs2 0x0187);
+insert into t1 values (_ucs2 0x0188),(_ucs2 0x0189),(_ucs2 0x018a),(_ucs2 0x018b);
+insert into t1 values (_ucs2 0x018c),(_ucs2 0x018d),(_ucs2 0x018e),(_ucs2 0x018f);
+insert into t1 values (_ucs2 0x0190),(_ucs2 0x0191),(_ucs2 0x0192),(_ucs2 0x0193);
+insert into t1 values (_ucs2 0x0194),(_ucs2 0x0195),(_ucs2 0x0196),(_ucs2 0x0197);
+insert into t1 values (_ucs2 0x0198),(_ucs2 0x0199),(_ucs2 0x019a),(_ucs2 0x019b);
+insert into t1 values (_ucs2 0x019c),(_ucs2 0x019d),(_ucs2 0x019e),(_ucs2 0x019f);
+insert into t1 values (_ucs2 0x01a0),(_ucs2 0x01a1),(_ucs2 0x01a2),(_ucs2 0x01a3);
+insert into t1 values (_ucs2 0x01a4),(_ucs2 0x01a5),(_ucs2 0x01a6),(_ucs2 0x01a7);
+insert into t1 values (_ucs2 0x01a8),(_ucs2 0x01a9),(_ucs2 0x01aa),(_ucs2 0x01ab);
+insert into t1 values (_ucs2 0x01ac),(_ucs2 0x01ad),(_ucs2 0x01ae),(_ucs2 0x01af);
+insert into t1 values (_ucs2 0x01b0),(_ucs2 0x01b1),(_ucs2 0x01b2),(_ucs2 0x01b3);
+insert into t1 values (_ucs2 0x01b4),(_ucs2 0x01b5),(_ucs2 0x01b6),(_ucs2 0x01b7);
+insert into t1 values (_ucs2 0x01b8),(_ucs2 0x01b9),(_ucs2 0x01ba),(_ucs2 0x01bb);
+insert into t1 values (_ucs2 0x01bc),(_ucs2 0x01bd),(_ucs2 0x01be),(_ucs2 0x01bf);
+insert into t1 values (_ucs2 0x01c0),(_ucs2 0x01c1),(_ucs2 0x01c2),(_ucs2 0x01c3);
+insert into t1 values (_ucs2 0x01c4),(_ucs2 0x01c5),(_ucs2 0x01c6),(_ucs2 0x01c7);
+insert into t1 values (_ucs2 0x01c8),(_ucs2 0x01c9),(_ucs2 0x01ca),(_ucs2 0x01cb);
+insert into t1 values (_ucs2 0x01cc),(_ucs2 0x01cd),(_ucs2 0x01ce),(_ucs2 0x01cf);
+insert into t1 values (_ucs2 0x01d0),(_ucs2 0x01d1),(_ucs2 0x01d2),(_ucs2 0x01d3);
+insert into t1 values (_ucs2 0x01d4),(_ucs2 0x01d5),(_ucs2 0x01d6),(_ucs2 0x01d7);
+insert into t1 values (_ucs2 0x01d8),(_ucs2 0x01d9),(_ucs2 0x01da),(_ucs2 0x01db);
+insert into t1 values (_ucs2 0x01dc),(_ucs2 0x01dd),(_ucs2 0x01de),(_ucs2 0x01df);
+insert into t1 values (_ucs2 0x01e0),(_ucs2 0x01e1),(_ucs2 0x01e2),(_ucs2 0x01e3);
+insert into t1 values (_ucs2 0x01e4),(_ucs2 0x01e5),(_ucs2 0x01e6),(_ucs2 0x01e7);
+insert into t1 values (_ucs2 0x01e8),(_ucs2 0x01e9),(_ucs2 0x01ea),(_ucs2 0x01eb);
+insert into t1 values (_ucs2 0x01ec),(_ucs2 0x01ed),(_ucs2 0x01ee),(_ucs2 0x01ef);
+insert into t1 values (_ucs2 0x01f0),(_ucs2 0x01f1),(_ucs2 0x01f2),(_ucs2 0x01f3);
+insert into t1 values (_ucs2 0x01f4),(_ucs2 0x01f5),(_ucs2 0x01f6),(_ucs2 0x01f7);
+insert into t1 values (_ucs2 0x01f8),(_ucs2 0x01f9),(_ucs2 0x01fa),(_ucs2 0x01fb);
+insert into t1 values (_ucs2 0x01fc),(_ucs2 0x01fd),(_ucs2 0x01fe),(_ucs2 0x01ff);
+insert into t1 values ('AA'),('Aa'),('aa'),('aA');
+insert into t1 values ('CH'),('Ch'),('ch'),('cH');
+insert into t1 values ('DZ'),('Dz'),('dz'),('dZ');
+insert into t1 values ('IJ'),('Ij'),('ij'),('iJ');
+insert into t1 values ('LJ'),('Lj'),('lj'),('lJ');
+insert into t1 values ('LL'),('Ll'),('ll'),('lL');
+insert into t1 values ('NJ'),('Nj'),('nj'),('nJ');
+insert into t1 values ('OE'),('Oe'),('oe'),('oE');
+insert into t1 values ('SS'),('Ss'),('ss'),('sS');
+insert into t1 values ('RR'),('Rr'),('rr'),('rR');
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_unicode_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_icelandic_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Â,Ã,à,â,ã,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Ã,á
+Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ã,ð
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+E,e,È,Ê,Ë,è,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+É,é
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,ÃŽ,Ã,ì,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+Ã,í
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ô,Õ,ò,ô,õ,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ó,ó
+Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Û,Ü,ù,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ú,ú
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,ÿ,Ŷ,ŷ,Ÿ
+Ã,ý
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Þ,þ
+Ä,Æ,ä,æ
+Ö,Ø,ö,ø
+Ã…,Ã¥
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_latvian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,Ċ,ċ
+CH,Ch,cH,ch
+ÄŒ,Ä
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ǧ,ǧ,Ç´,ǵ
+Ä¢,Ä£
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+Y,y
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ǩ,ǩ
+Ķ,ķ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Ļ,ļ
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Ņ,ņ
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ř,ř
+RR,Rr,rR,rr
+Å–,Å—
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż
+Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_romanian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Ã,Ä,Ã…,à,á,ã,ä,Ã¥,Ä€,Ä,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Ă,ă
+Â,â
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,Ã,ì,í,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+Î,î
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Åž,ÅŸ
+Æ©
+ƪ
+T,t,Ť,ť
+ƾ
+Å¢,Å£
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_slovenian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,Ċ,ċ
+CH,Ch,cH,ch
+ÄŒ,Ä
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż
+Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_polish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Ä„,Ä…
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ć,ć
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ě,ě
+Ę,ę
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Ń,ń
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ô,Õ,Ö,ò,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ó,ó
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Åš,Å›
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ž,ž
+Ź,ź
+Ż,ż
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_estonian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ã…,à,á,â,ã,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz
+DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,ò,ó,ô,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Z,z
+Ž,ž
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,ù,ú,û,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+Õ,õ
+Ä,ä
+Ö,ö
+Ü,ü
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Ź,ź,Ż,ż
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_spanish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Ñ,ñ
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_swedish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,à,á,â,ã,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,ò,ó,ô,õ,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,ù,ú,û,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ü,Ã,ü,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ã…,Ã¥
+Ä,Æ,ä,æ
+Ö,Ø,ö,ø
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_turkish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ç,ç
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Äž,ÄŸ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+I,ı
+IJ,Ij
+ƕ,Ƕ
+Ħ,ħ
+i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+iJ,ij,IJ,ij
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,ò,ó,ô,õ,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ö,ö
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Åž,ÅŸ
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,ù,ú,û,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ü,ü
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_czech_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,Ċ,ċ
+cH
+ÄŒ,Ä
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+CH,Ch,ch
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Å”,Å•,Å–,Å—
+RR,Rr,rR,rr
+Ř,ř
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż
+Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_danish_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,à,á,â,ã,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+aA
+Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,ò,ó,ô,õ,ÅŒ,Å,ÅŽ,Å,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,ù,ú,û,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ü,Ã,ü,ý,ÿ,Ű,ű,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ä,Æ,ä,æ
+Ö,Ø,ö,ø,Å,Å‘
+AA,Aa,aa,Ã…,Ã¥
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_lithuanian_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,CH,Ch,c,ch,Ç,ç,Ć,ć,Ĉ,ĉ,Ċ,ċ
+cH
+ÄŒ,Ä
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,Y,i,y,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż
+Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_slovak_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ã…,à,á,â,ã,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Ä,ä
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,Ċ,ċ
+cH
+ÄŒ,Ä
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+CH,Ch,ch
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Õ,Ö,ò,ó,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ô,ô
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å¿
+SS,Ss,sS,ss,ß
+Å ,Å¡
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż
+Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_spanish2_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+cH
+CH,Ch,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,i,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij,IJ,ij
+ı
+Æ—
+Æ–
+J,j,Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj,LJ,Lj,lj
+lL
+LL,Ll,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj,NJ,Nj,nj
+Ñ,ñ
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,RR,Rr,r,rr,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+rR
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+U,u,Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+V,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+select group_concat(c1 order by c1) from t1 group by c1 collate utf8_roman_ci;
+group_concat(c1 order by c1)
+÷
+×
+A,a,À,Ã,Â,Ã,Ä,Ã…,à,á,â,ã,ä,Ã¥,Ä€,Ä,Ä‚,ă,Ä„,Ä…,Ç,ÇŽ,Çž,ÇŸ,Ç ,Ç¡,Ǻ,Ç»
+AA,Aa,aA,aa
+Æ,æ,Ǣ,ǣ,Ǽ,ǽ
+B,b
+Æ€
+Ƃ,ƃ
+C,c,Ç,ç,Ć,ć,Ĉ,ĉ,ÄŠ,Ä‹,ÄŒ,Ä
+CH,Ch,cH,ch
+Ƈ,ƈ
+D,d,ÄŽ,Ä
+DZ,Dz,dZ,dz,DŽ,Dž,dž,DZ,Dz,dz
+Ä,Ä‘
+Ɖ
+ÆŠ
+Ƌ,ƌ
+Ã,ð
+E,e,È,É,Ê,Ë,è,é,ê,ë,Ē,ē,Ĕ,ĕ,Ė,ė,Ę,ę,Ě,ě
+ÆŽ,Ç
+F,f
+Æ‘,Æ’
+G,g,Äœ,Ä,Äž,ÄŸ,Ä ,Ä¡,Ä¢,Ä£,Ǧ,ǧ,Ç´,ǵ
+Ǥ,ǥ
+Æ“
+Æ”
+Æ¢,Æ£
+H,h,Ĥ,ĥ
+ƕ,Ƕ
+Ħ,ħ
+I,J,i,j,ÃŒ,Ã,ÃŽ,Ã,ì,í,î,ï,Ĩ,Ä©,Ī,Ä«,Ĭ,Ä­,Ä®,į,İ,Ç,Ç
+IJ,Ij,iJ,ij
+IJ,ij
+ı
+Æ—
+Æ–
+Ĵ,ĵ,ǰ
+K,k,Ķ,ķ,Ǩ,ǩ
+Ƙ,ƙ
+L,l,Ĺ,ĺ,Ļ,ļ,Ľ,ľ
+Ä¿,Å€
+LJ,Lj,lJ,lj
+LJ,Lj,lj
+LL,Ll,lL,ll
+Å,Å‚
+Æš
+Æ›
+M,m
+N,n,Ñ,ñ,Ń,ń,Ņ,ņ,Ň,ň,Ǹ,ǹ
+NJ,Nj,nJ,nj
+NJ,Nj,nj
+Æž
+ÅŠ,Å‹
+O,o,Ã’,Ó,Ô,Õ,Ö,ò,ó,ô,õ,ö,ÅŒ,Å,ÅŽ,Å,Å,Å‘,Æ ,Æ¡,Ç‘,Ç’,Ǫ,Ç«,Ǭ,Ç­
+OE,Oe,oE,oe,Å’,Å“
+Ø,ø,Ǿ,ǿ
+Ɔ
+ÆŸ
+P,p
+Ƥ,ƥ
+Q,q
+ĸ
+R,r,Ŕ,ŕ,Ŗ,ŗ,Ř,ř
+RR,Rr,rR,rr
+Ʀ
+S,s,Åš,Å›,Åœ,Å,Åž,ÅŸ,Å ,Å¡,Å¿
+SS,Ss,sS,ss,ß
+Æ©
+ƪ
+T,t,Ţ,ţ,Ť,ť
+ƾ
+Ŧ,ŧ
+Æ«
+Ƭ,ƭ
+Æ®
+Ù,Ú,Û,Ü,ù,ú,û,ü,Ũ,ũ,Ū,ū,Ŭ,ŭ,Ů,ů,Ű,ű,Ų,ų,Ư,ư,Ǔ,ǔ,Ǖ,ǖ,Ǘ,ǘ,Ǚ,ǚ,Ǜ,ǜ
+Ɯ
+Ʊ
+U,V,u,v
+Ʋ
+W,w,Ŵ,ŵ
+X,x
+Y,y,Ã,ý,ÿ,Ŷ,Å·,Ÿ
+Ƴ,ƴ
+Z,z,Ź,ź,Ż,ż,Ž,ž
+Ƶ,ƶ
+Ʒ,Ǯ,ǯ
+Ƹ,ƹ
+ƺ
+Þ,þ
+Æ¿,Ç·
+Æ»
+Ƨ,ƨ
+Ƽ,ƽ
+Æ„,Æ…
+ʼn
+Ç€
+Ç‚
+ǃ
+drop table t1;
+SET NAMES utf8;
+CREATE TABLE t1 (c varchar(255) NOT NULL COLLATE utf8_general_ci, INDEX (c));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x039C03C903B403B11F770308 USING utf8));
+SELECT * FROM t1 WHERE c LIKE CONVERT(_ucs2 0x039C0025 USING utf8)
+COLLATE utf8_general_ci;
+c
+Μωδαί̈
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x039C03C903B4 USING utf8));
+SELECT * FROM t1 WHERE c LIKE CONVERT(_ucs2 0x039C0025 USING utf8)
+COLLATE utf8_general_ci ORDER BY c;
+c
+Μωδ
+Μωδαί̈
+DROP TABLE t1;
+CREATE TABLE t1 (c varchar(255) NOT NULL COLLATE ucs2_unicode_ci, INDEX (c));
+INSERT INTO t1 VALUES (_ucs2 0x039C03C903B403B11F770308);
+SELECT * FROM t1 WHERE c LIKE _ucs2 0x039C0025 COLLATE ucs2_unicode_ci;
+c
+Μωδαί̈
+INSERT INTO t1 VALUES (_ucs2 0x039C03C903B4);
+SELECT * FROM t1 WHERE c LIKE _ucs2 0x039C0025
+COLLATE ucs2_unicode_ci ORDER BY c;
+c
+Μωδ
+Μωδαί̈
+DROP TABLE t1;
+CREATE TABLE t1 (c varchar(255) NOT NULL COLLATE utf8_unicode_ci, INDEX (c));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x039C03C903B403B11F770308 USING utf8));
+SELECT * FROM t1 WHERE c LIKE CONVERT(_ucs2 0x039C0025 USING utf8) COLLATE utf8_unicode_ci;
+c
+Μωδαί̈
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x039C03C903B4 USING utf8));
+SELECT * FROM t1 WHERE c LIKE CONVERT(_ucs2 0x039C0025 USING utf8)
+COLLATE utf8_unicode_ci ORDER BY c;
+c
+Μωδ
+Μωδαί̈
+DROP TABLE t1;
+CREATE TABLE t1 (
+col1 CHAR(32) CHARACTER SET utf8 NOT NULL
+);
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0041004100410627 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0041004100410628 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0041004100410647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0041004100410648 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0633064A0651062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062D06330646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A0642064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06320627062F0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062806310627064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064706450647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F062706460634062C0648064A06270646064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06A90647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A06270631064A062E USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062706460642064406270628 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064A0631062706460650 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627062F064806270631062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280631062706480646200C06310627 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062E064806270646062F0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0648 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A062D062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A0623062B064A0631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06220646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0642063106270631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06AF06310641062A0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06270646062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0634062E0635064A0651062A064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0628062706310632 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06270633062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063906A90633 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06270648060C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F0631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062D062F0648062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0628064A0633062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0648067E0646062C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06330627064406AF064A060C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063306270644 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064606450627064A0646062F0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A06280631064A0632 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0645062C06440633 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280648062F060C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0628064A0646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06350641062D0627062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064A0646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06A9062A06270628 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x068606340645 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0645064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062E06480631062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0686064706310647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06420648064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06450635064506510645 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06310627 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0646063406270646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0645064A200C062F0647062F060C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0647063106860646062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06390645064400BB USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06A9064806340634 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0628 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064706500646064A064606AF USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627062D063306270646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064A062706310634062706370631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06450646062A06340631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0634062F0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F0633062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A064806270646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0647064506270646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064806510644 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A0634062E064A0635 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F0627062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280627 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A064106270648062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062D06270644062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A064106A906510631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063A064406280647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F06270631062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064A06A9064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06270632 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063106470628063106270646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064606470636062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064506340631064806370647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064A063106270646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0646064A0632 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064A06A9 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0645062D064206510642 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0637063106270632 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064106310647064606AF USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A0645062F06510646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064A063106270646064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280648062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06A90627063106470627064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06270648 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0639063106350647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064506480631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0633064A06270633064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064A063106270646060C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062D064806320647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063906440645 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F062706460634 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06450642062706440627062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F064A06AF0631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0648064A06980647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0646062706450647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064506480631062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0628062D062B USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0628063106310633064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064606480634062A0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06450646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A064606470627 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0622064606860647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F064806310647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064206270645062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x067E0631062F062706320645 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0698062706460648064A0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0648064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F06390648062A0650 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063306500631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F0646064A0633064F0646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063106270633 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0647064A0626062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0639064406480645200C063406310642064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280639062F0627064B USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0645062F063106330647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062206410631064A06420627064A064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F06270646063406AF06270647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06440646062F0646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x067E064A06480633062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0647064606AF06270645064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x067E0633 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0622063A06270632 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062C064606AF USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062C064706270646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F064806510645 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063406470631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06A9064506280631064A062C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06450646062A06420644 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06A90631062F0646062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06470645 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06310641062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06220646062C0627 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064506270646062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A0627 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062706A9062A06280631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064606380631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F06480644062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F06480628062706310647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064606330628062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0645063306270639062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0634062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06480632064A0631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0645062E062A06270631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06330641064A0631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627064606AF0644064A0633 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A0642064A200C06320627062F0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280627063206AF0634062A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0647064506330631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06220644064506270646064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06270634 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06220645062F0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06A906270631064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x067E0631062F0627062E062A0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063906440645064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x0627062F0628064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062D062F0651 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064606280648062F060C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06480644064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x063906480636060C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06340627064A062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064506470645 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062A0631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06220646060C USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06470645063306310634 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06A90627064606480646 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062E0627064606480627062F06AF064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06AF06310645064A USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280648062C0648062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062206480631062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F0648 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06A90627064506440627064B USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x064A06A9062F064A06AF0631 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06AF USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x062F064406280633062A0647 USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280648062F0646062F USING utf8));
+INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06450647064506270646 USING utf8));
+SELECT HEX(CONVERT(col1 USING ucs2)) FROM t1 ORDER BY col1 COLLATE utf8_persian_ci, col1 COLLATE utf8_bin;
+HEX(CONVERT(col1 USING ucs2))
+0041004100410627
+0041004100410628
+0041004100410648
+0041004100410647
+0622063A06270632
+062206410631064A06420627064A064A
+06220644064506270646064A
+06220645062F0647
+06220646
+06220646060C
+06220646062C0627
+0622064606860647
+062206480631062F
+0627062D063306270646
+0627062F0628064A
+0627062F064806270631062F
+06270632
+06270633062A
+06270634
+0627064206270645062A
+062706A9062A06280631
+0627064506480631
+06270646062F
+062706460642064406270628
+0627064606AF0644064A0633
+06270648
+06270648060C
+0627064806510644
+0627064A
+0627064A063106270646
+0627064A063106270646060C
+0627064A0631062706460650
+0627064A063106270646064A
+0627064A0646
+0628
+06280627
+0628062706310632
+06280627063206AF0634062A
+0628062D062B
+06280631062706480646200C06310627
+062806310627064A
+0628063106310633064A
+06280639062F0627064B
+06280648062C0648062F
+06280648062F
+06280648062F060C
+06280648062F0646062F
+06280647
+0628064A0633062A
+0628064A0646
+067E0631062F0627062E062A0647
+067E0631062F062706320645
+067E0633
+067E064A06480633062A
+062A0627
+062A06270631064A062E
+062A0623062B064A0631
+062A06280631064A0632
+062A062D062A
+062A0631
+062A0634062E064A0635
+062A064106270648062A
+062A064106A906510631
+062A0642064A
+062A0642064A200C06320627062F0647
+062A0645062F06510646
+062A064606470627
+062A064806270646
+062C064606AF
+062C064706270646
+068606340645
+0686064706310647
+062D06270644062A
+062D062F0651
+062D062F0648062F
+062D06330646
+062D064806320647
+062E0627064606480627062F06AF064A
+062E064806270646062F0647
+062E06480631062F
+062F0627062F
+062F06270631062F
+062F062706460634
+062F062706460634062C0648064A06270646064A
+062F06270646063406AF06270647
+062F0631
+062F0633062A
+062F06390648062A0650
+062F064406280633062A0647
+062F0646064A0633064F0646
+062F0648
+062F06480628062706310647
+062F064806310647
+062F06480644062A
+062F064806510645
+062F064A06AF0631
+06310627
+063106270633
+06310641062A
+063106470628063106270646
+06320627062F0647
+0698062706460648064A0647
+063306500631
+063306270644
+06330627064406AF064A060C
+06330641064A0631
+0633064A06270633064A
+0633064A0651062F
+06340627064A062F
+0634062E0635064A0651062A064A
+0634062F
+0634062F0647
+063406470631
+06350641062D0627062A
+0637063106270632
+0639063106350647
+063906A90633
+063906440645
+063906440645064A
+0639064406480645200C063406310642064A
+06390645064400BB
+063906480636060C
+063A064406280647
+064106310647064606AF
+0642063106270631
+06420648064A
+06A90627063106470627064A
+06A906270631064A
+06A90627064506440627064B
+06A90627064606480646
+06A9062A06270628
+06A90631062F0646062F
+06A9064506280631064A062C
+06A9064806340634
+06A90647
+06AF
+06AF06310641062A0647
+06AF06310645064A
+06440646062F0646
+064506270646062F
+0645062C06440633
+0645062D064206510642
+0645062E062A06270631
+0645062F063106330647
+0645063306270639062F
+064506340631064806370647
+06450635064506510645
+06450642062706440627062A
+06450646
+06450646062A06340631
+06450646062A06420644
+064506480631062F
+064506470645
+06450647064506270646
+0645064A
+0645064A200C062F0647062F060C
+0646062706450647
+064606280648062F060C
+064606330628062A
+0646063406270646
+064606380631
+064606450627064A0646062F0647
+064606480634062A0647
+064606470636062A
+0646064A0632
+0648
+0648067E0646062C
+06480632064A0631
+06480644064A
+0648064A
+0648064A06980647
+064706500646064A064606AF
+0647063106860646062F
+06470645
+0647064506270646
+0647064506330631
+06470645063306310634
+064706450647
+0647064606AF06270645064A
+0647064A0626062A
+064A062706310634062706370631
+064A06A9
+064A06A9062F064A06AF0631
+064A06A9064A
+DROP TABLE t1;
+SET @test_character_set= 'utf8';
+SET @test_collation= 'utf8_swedish_ci';
+SET @safe_character_set_server= @@character_set_server;
+SET @safe_collation_server= @@collation_server;
+SET character_set_server= @test_character_set;
+SET collation_server= @test_collation;
+CREATE DATABASE d1;
+USE d1;
+CREATE TABLE t1 (c CHAR(10), KEY(c));
+SHOW FULL COLUMNS FROM t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c char(10) utf8_swedish_ci YES MUL NULL
+INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa');
+SELECT c as want3results FROM t1 WHERE c LIKE 'aaa%';
+want3results
+aaa
+aaaa
+aaaaa
+DROP TABLE t1;
+CREATE TABLE t1 (c1 varchar(15), KEY c1 (c1(2)));
+SHOW FULL COLUMNS FROM t1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c1 varchar(15) utf8_swedish_ci YES MUL NULL
+INSERT INTO t1 VALUES ('location'),('loberge'),('lotre'),('boabab');
+SELECT c1 as want3results from t1 where c1 like 'l%';
+want3results
+location
+loberge
+lotre
+SELECT c1 as want3results from t1 where c1 like 'lo%';
+want3results
+location
+loberge
+lotre
+SELECT c1 as want1result from t1 where c1 like 'loc%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'loca%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locat%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locati%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'locatio%';
+want1result
+location
+SELECT c1 as want1result from t1 where c1 like 'location%';
+want1result
+location
+DROP TABLE t1;
+DROP DATABASE d1;
+USE test;
+SET character_set_server= @safe_character_set_server;
+SET collation_server= @safe_collation_server;
diff --git a/mysql-test/r/ctype_ucs.result b/mysql-test/r/ctype_ucs.result
index a0ac29b7989..c2c1097e1bb 100644
--- a/mysql-test/r/ctype_ucs.result
+++ b/mysql-test/r/ctype_ucs.result
@@ -1,15 +1,46 @@
DROP TABLE IF EXISTS t1;
+SET NAMES latin1;
+SET character_set_connection=ucs2;
+select 'a' = 'a', 'a' = 'a ', 'a ' = 'a';
+'a' = 'a' 'a' = 'a ' 'a ' = 'a'
+1 1 1
+select 'a\0' = 'a', 'a\0' < 'a', 'a\0' > 'a';
+'a\0' = 'a' 'a\0' < 'a' 'a\0' > 'a'
+0 1 0
+select 'a' = 'a\0', 'a' < 'a\0', 'a' > 'a\0';
+'a' = 'a\0' 'a' < 'a\0' 'a' > 'a\0'
+0 0 1
+select 'a\0' = 'a ', 'a\0' < 'a ', 'a\0' > 'a ';
+'a\0' = 'a ' 'a\0' < 'a ' 'a\0' > 'a '
+0 1 0
+select 'a ' = 'a\0', 'a ' < 'a\0', 'a ' > 'a\0';
+'a ' = 'a\0' 'a ' < 'a\0' 'a ' > 'a\0'
+0 0 1
+select 'a a' > 'a', 'a \0' < 'a';
+'a a' > 'a' 'a \0' < 'a'
+1 1
+select binary 'a a' > 'a', binary 'a \0' > 'a', binary 'a\0' > 'a';
+binary 'a a' > 'a' binary 'a \0' > 'a' binary 'a\0' > 'a'
+1 1 1
SET CHARACTER SET koi8r;
-CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2);
-INSERT INTO t1 VALUES (_koi8r'ò'), (X'2004');
+CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004');
SELECT hex(word) FROM t1 ORDER BY word;
hex(word)
0420
2004
+SELECT hex(word2) FROM t1 ORDER BY word2;
+hex(word2)
+0420
+2004
DELETE FROM t1;
-INSERT INTO t1 VALUES (X'042000200020'), (X'200400200020');
+INSERT INTO t1 VALUES (X'042000200020',X'042000200020'), (X'200400200020', X'200400200020');
SELECT hex(word) FROM t1 ORDER BY word;
hex(word)
+042000200020
+200400200020
+SELECT hex(word2) FROM t1 ORDER BY word2;
+hex(word2)
0420
2004
DROP TABLE t1;
@@ -43,8 +74,8 @@ RPAD(_ucs2 X'0420',10,_ucs2 X'0421') r;
SHOW CREATE TABLE t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `l` char(10) character set ucs2 NOT NULL default '',
- `r` char(10) character set ucs2 NOT NULL default ''
+ `l` varchar(10) character set ucs2 NOT NULL default '',
+ `r` varchar(10) character set ucs2 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
DROP TABLE t1;
create table t2(f1 Char(30));
@@ -62,10 +93,10 @@ create table t1 (a varchar(10) character set ucs2, key(a));
insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
explain select * from t1 where a like 'abc%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index a a 21 NULL 5 Using where; Using index
+1 SIMPLE t1 range a a 23 NULL 1 Using where; Using index
explain select * from t1 where a like concat('abc','%');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index a a 21 NULL 5 Using where; Using index
+1 SIMPLE t1 range a a 23 NULL 1 Using where; Using index
select * from t1 where a like "abc%";
a
abc
@@ -290,7 +321,7 @@ aardvark 0
aardvarz 0
EXPLAIN SELECT word FROM t1 ORDER BY word;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL PRIMARY 128 NULL 6 Using index
+1 SIMPLE t1 index NULL PRIMARY 130 NULL 6 Using index
SELECT word FROM t1 ORDER by word;
word
a
@@ -314,7 +345,7 @@ INSERT INTO t1 (word) VALUES ("aardvara");
INSERT INTO t1 (word) VALUES ("aardvarz");
EXPLAIN SELECT * FROM t1 ORDER BY WORD;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL PRIMARY 128 NULL 6 Using index
+1 SIMPLE t1 index NULL PRIMARY 130 NULL 6 Using index
SELECT * FROM t1 ORDER BY word;
word
a
@@ -480,3 +511,27 @@ a 0061
b 0062
c 0063
drop table t1;
+set @ivar= 1234;
+set @str1 = 'select ?';
+set @str2 = convert(@str1 using ucs2);
+prepare stmt1 from @str2;
+execute stmt1 using @ivar;
+?
+1234
+SET TIMESTAMP=10000;
+create table t2 (c char(30)) charset=ucs2;
+set @v=convert('abc' using ucs2);
+reset master;
+insert into t2 values (@v);
+show binlog events from 95;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 95 User var 1 135 @`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci
+master-bin.000001 135 Query 1 218 use `test`; insert into t2 values (@v)
+/*!40019 SET @@session.max_insert_delayed_threads=0*/;
+SET @`v`:=_ucs2 0x006100620063 COLLATE ucs2_general_ci;
+use test;
+SET TIMESTAMP=10000;
+SET @@session.foreign_key_checks=1, @@session.sql_auto_is_null=1, @@session.unique_checks=1;
+SET @@session.sql_mode=0;
+insert into t2 values (@v);
+drop table t2;
diff --git a/mysql-test/r/ctype_ujis.result b/mysql-test/r/ctype_ujis.result
index 7c3ae52cbc9..d02ac0062f8 100644
--- a/mysql-test/r/ctype_ujis.result
+++ b/mysql-test/r/ctype_ujis.result
@@ -126,3 +126,43 @@ Field Type Null Key Default Extra
a char(1)
b enum('¤¢','¤¤') YES NULL
DROP TABLE t1;
+CREATE TABLE t1
+(
+a INTEGER NOT NULL,
+b VARCHAR(50) NOT NULL DEFAULT '',
+PRIMARY KEY (a),
+KEY b (b(10))
+) TYPE=InnoDB CHARACTER SET 'ujis' COLLATE 'ujis_japanese_ci';
+INSERT INTO t1 (a, b) VALUES (0, 'aaabbbcccddd');
+INSERT INTO t1 (a, b) VALUES (1, 'eeefffggghhh');
+INSERT INTO t1 (a, b) VALUES (2, 'iiijjjkkkl');
+SELECT t1.* FROM t1 WHERE b='aaabbbcccddd' ORDER BY a;
+a b
+0 aaabbbcccddd
+SELECT t1.* FROM t1 WHERE b='eeefffggghhh' ORDER BY a;
+a b
+1 eeefffggghhh
+SELECT t1.* FROM t1 WHERE b='iiijjjkkkl' ORDER BY a;
+a b
+2 iiijjjkkkl
+DROP TABLE t1;
+CREATE TABLE t1
+(
+a INTEGER NOT NULL,
+b VARCHAR(50) NOT NULL DEFAULT '',
+PRIMARY KEY (a),
+KEY b (b(10))
+) TYPE=MyISAM CHARACTER SET 'ujis' COLLATE 'ujis_japanese_ci';
+INSERT INTO t1 (a, b) VALUES (0, 'aaabbbcccddd');
+INSERT INTO t1 (a, b) VALUES (1, 'eeefffggghhh');
+INSERT INTO t1 (a, b) VALUES (2, 'iiijjjkkkl');
+SELECT t1.* FROM t1 WHERE b='aaabbbcccddd' ORDER BY a;
+a b
+0 aaabbbcccddd
+SELECT t1.* FROM t1 WHERE b='eeefffggghhh' ORDER BY a;
+a b
+1 eeefffggghhh
+SELECT t1.* FROM t1 WHERE b='iiijjjkkkl' ORDER BY a;
+a b
+2 iiijjjkkkl
+DROP TABLE t1;
diff --git a/mysql-test/r/ctype_utf8.result b/mysql-test/r/ctype_utf8.result
index 945ec8eae99..79e871c4e79 100644
--- a/mysql-test/r/ctype_utf8.result
+++ b/mysql-test/r/ctype_utf8.result
@@ -285,7 +285,7 @@ create table t2 select ifnull(a,a) from t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `ifnull(a,a)` char(5) character set utf8 default NULL
+ `ifnull(a,a)` varchar(5) character set utf8 default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t2;
ifnull(a,a)
@@ -809,8 +809,11 @@ create table t2 select concat(a,_utf8'') as a, concat(b,_utf8'')as b from t1;
show create table t2;
Table Create Table
t2 CREATE TABLE `t2` (
- `a` char(5) character set utf8 NOT NULL default '',
- `b` char(15) character set utf8 NOT NULL default ''
+ `a` varchar(5) character set utf8 NOT NULL default '',
+ `b` varchar(15) character set utf8 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t2;
drop table t1;
+select 'c' like '\_' as want0;
+want0
+0
diff --git a/mysql-test/r/delete.result b/mysql-test/r/delete.result
index 5575ee1bf98..f1fba87c70b 100644
--- a/mysql-test/r/delete.result
+++ b/mysql-test/r/delete.result
@@ -16,12 +16,34 @@ SET AUTOCOMMIT=0;
DELETE from t1;
SET AUTOCOMMIT=1;
drop table t1;
-create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
-insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23);
+create table t1 (
+a bigint not null,
+b bigint not null default 0,
+c bigint not null default 0,
+d bigint not null default 0,
+e bigint not null default 0,
+f bigint not null default 0,
+g bigint not null default 0,
+h bigint not null default 0,
+i bigint not null default 0,
+j bigint not null default 0,
+primary key (a,b,c,d,e,f,g,h,i,j));
+insert into t1 (a) values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23);
delete from t1 where a=26;
drop table t1;
-create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
-insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27);
+create table t1 (
+a bigint not null,
+b bigint not null default 0,
+c bigint not null default 0,
+d bigint not null default 0,
+e bigint not null default 0,
+f bigint not null default 0,
+g bigint not null default 0,
+h bigint not null default 0,
+i bigint not null default 0,
+j bigint not null default 0,
+primary key (a,b,c,d,e,f,g,h,i,j));
+insert into t1 (a) values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27);
delete from t1 where a=27;
drop table t1;
CREATE TABLE `t1` (
diff --git a/mysql-test/r/drop_temp_table.result b/mysql-test/r/drop_temp_table.result
index 08793bcbd57..34c08f08788 100644
--- a/mysql-test/r/drop_temp_table.result
+++ b/mysql-test/r/drop_temp_table.result
@@ -11,8 +11,8 @@ get_lock("a",10)
show binlog events;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 4 Format_desc 1 95 Server ver: VERSION, Binlog ver: 4
-master-bin.000001 95 Query 1 190 use `test`; create database `drop-temp+table-test`
-master-bin.000001 190 Query 1 306 use `drop-temp+table-test`; create temporary table `table:name` (a int)
-master-bin.000001 306 Query 1 457 use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name`
-master-bin.000001 457 Query 1 550 use `drop-temp+table-test`; DO RELEASE_LOCK("a")
+master-bin.000001 95 Query 1 206 create database `drop-temp+table-test`
+master-bin.000001 206 Query 1 322 use `drop-temp+table-test`; create temporary table `table:name` (a int)
+master-bin.000001 322 Query 1 473 use `drop-temp+table-test`; DROP /*!40005 TEMPORARY */ TABLE IF EXISTS `drop-temp+table-test`.`table:name`
+master-bin.000001 473 Query 1 566 use `drop-temp+table-test`; DO RELEASE_LOCK("a")
drop database `drop-temp+table-test`;
diff --git a/mysql-test/r/endspace.result b/mysql-test/r/endspace.result
index 96210a0e16d..b1942409c91 100644
--- a/mysql-test/r/endspace.result
+++ b/mysql-test/r/endspace.result
@@ -43,7 +43,7 @@ teststring
teststring
explain select * from t1 order by text1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL key1 32 NULL 3 Using index
+1 SIMPLE t1 index NULL key1 34 NULL 3 Using index
alter table t1 modify text1 char(32) binary not null;
check table t1;
Table Op Msg_type Msg_text
@@ -99,15 +99,15 @@ concat('|', text1, '|')
explain select concat('|', text1, '|') from t1 where text1='teststring ';
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range key1 key1 22 NULL 2 Using where
-select * from t1 where text1 like 'teststring_%';
-text1
-teststring
-teststring
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
-text1
-teststring
-teststring
-teststring
+select concat('|', text1, '|') from t1 where text1 like 'teststring_%';
+concat('|', text1, '|')
+|teststring |
+|teststring |
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
+concat('|', text1, '|')
+|teststring |
+|teststring|
+|teststring |
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
concat('|', text1, '|')
|teststring|
@@ -121,14 +121,14 @@ concat('|', text1, '|')
drop table t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1)) pack_keys=0;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
-text1
-teststring
-teststring
-select * from t1 where text1='teststring' or text1 >= 'teststring\t';
-text1
-teststring
-teststring
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
+concat('|', text1, '|')
+|teststring |
+|teststring|
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 >= 'teststring\t';
+concat('|', text1, '|')
+|teststring |
+|teststring|
drop table t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 using BTREE (text1)) engine=heap;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
@@ -151,7 +151,7 @@ teststring
teststring
explain select * from t1 order by text1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL key1 32 NULL 3
+1 SIMPLE t1 index NULL key1 34 NULL 3
alter table t1 modify text1 char(32) binary not null;
select * from t1 order by text1;
text1
@@ -200,12 +200,10 @@ teststring
teststring
select text1, length(text1) from t1 where text1='teststring' or text1 like 'teststring_%';
text1 length(text1)
-teststring 10
teststring 11
teststring 11
select text1, length(text1) from t1 where text1='teststring' or text1 >= 'teststring\t';
text1 length(text1)
-teststring 10
teststring 11
teststring 11
select concat('|', text1, '|') from t1 order by text1;
diff --git a/mysql-test/r/flush_block_commit.result b/mysql-test/r/flush_block_commit.result
index 17991f15382..4a7575d8f7a 100644
--- a/mysql-test/r/flush_block_commit.result
+++ b/mysql-test/r/flush_block_commit.result
@@ -20,4 +20,12 @@ commit;
a
1
unlock tables;
+commit;
+begin;
+insert into t1 values(10);
+flush tables with read lock;
+commit;
+unlock tables;
+flush tables with read lock;
+unlock tables;
drop table t1;
diff --git a/mysql-test/r/flush_read_lock_kill.result b/mysql-test/r/flush_read_lock_kill.result
new file mode 100644
index 00000000000..dfdcf51457a
--- /dev/null
+++ b/mysql-test/r/flush_read_lock_kill.result
@@ -0,0 +1,9 @@
+drop table if exists t1;
+create table t1 (kill_id int);
+insert into t1 values(connection_id());
+ flush tables with read lock;
+select ((@id := kill_id) - kill_id) from t1;
+((@id := kill_id) - kill_id)
+0
+kill connection @id;
+drop table t1;
diff --git a/mysql-test/r/fulltext.result b/mysql-test/r/fulltext.result
index 3f4766830b0..a85cfd4181c 100644
--- a/mysql-test/r/fulltext.result
+++ b/mysql-test/r/fulltext.result
@@ -190,6 +190,14 @@ a
select * from t1 where match a against ("+aaa10 +(bbb*)" in boolean mode);
a
aaa10 bbb20
+select * from t1 where match a against ("+(+aaa* +bbb1*)" in boolean mode);
+a
+aaa20 bbb15
+aaa30 bbb10
+select * from t1 where match a against ("(+aaa* +bbb1*)" in boolean mode);
+a
+aaa20 bbb15
+aaa30 bbb10
drop table t1;
CREATE TABLE t1 (
id int(11),
@@ -330,6 +338,9 @@ t1_id name t2_id t1_id name
select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode);
t2_id t1_id name
drop table t1,t2;
+create table t1 (a text, fulltext key (a));
+insert into t1 select "xxxx yyyy zzzz";
+drop table t1;
SET NAMES latin1;
CREATE TABLE t1 (t text character set utf8 not null, fulltext(t));
INSERT t1 VALUES ('Mit freundlichem Grüß'), ('aus Osnabrück');
@@ -352,9 +363,9 @@ t collation(t)
aus Osnabrück utf8_general_ci
SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrueck');
t collation(t)
-SELECT t, collation(t),MATCH t AGAINST ('Osnabruck') FROM t1 WHERE MATCH t AGAINST ('Osnabruck');
-t collation(t) MATCH t AGAINST ('Osnabruck')
-aus Osnabrück utf8_general_ci 1.591139793396
+SELECT t, collation(t),FORMAT(MATCH t AGAINST ('Osnabruck'),6) FROM t1 WHERE MATCH t AGAINST ('Osnabruck');
+t collation(t) FORMAT(MATCH t AGAINST ('Osnabruck'),6)
+aus Osnabrück utf8_general_ci 1.591140
alter table t1 modify t varchar(200) collate latin1_german2_ci not null;
Warnings:
Warning 1265 Data truncated for column 't' at row 3
@@ -379,3 +390,18 @@ s
pära para para
para para para
DROP TABLE t1;
+CREATE TABLE t1 (h text, FULLTEXT (h));
+INSERT INTO t1 VALUES ('Jesses Hasse Ling and his syncopators of Swing');
+REPAIR TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 repair status OK
+select count(*) from t1;
+count(*)
+1
+drop table t1;
+create table t1 (a int primary key, b text, fulltext(b));
+create table t2 (a int, b text);
+insert t1 values (1, "aaaa"), (2, "bbbb");
+insert t2 values (10, "aaaa"), (2, "cccc");
+replace t1 select * from t2;
+drop table t1, t2;
diff --git a/mysql-test/r/fulltext_order_by.result b/mysql-test/r/fulltext_order_by.result
index bfee9eba280..c6c42fa2e8b 100644
--- a/mysql-test/r/fulltext_order_by.result
+++ b/mysql-test/r/fulltext_order_by.result
@@ -6,53 +6,53 @@ FULLTEXT(message)
) comment = 'original testcase by sroussey@network54.com';
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("testbug"),
("steve"),("is"),("cool"),("steve is cool");
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve');
-a MATCH (message) AGAINST ('steve')
-4 0.90587323904037
-7 0.89568990468979
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve');
+a FORMAT(MATCH (message) AGAINST ('steve'),6)
+4 0.905873
+7 0.895690
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve');
a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
4 1
7 1
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
-a MATCH (message) AGAINST ('steve')
-4 0.90587323904037
-7 0.89568990468979
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
+a FORMAT(MATCH (message) AGAINST ('steve'),6)
+4 0.905873
+7 0.895690
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
4 1
7 1
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a;
-a MATCH (message) AGAINST ('steve')
-4 0.90587323904037
-7 0.89568990468979
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a;
+a FORMAT(MATCH (message) AGAINST ('steve'),6)
+4 0.905873
+7 0.895690
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a;
a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
4 1
7 1
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC;
-a MATCH (message) AGAINST ('steve')
-7 0.89568990468979
-4 0.90587323904037
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC;
+a FORMAT(MATCH (message) AGAINST ('steve'),6)
+7 0.895690
+4 0.905873
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a DESC;
a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
7 1
4 1
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1;
-a MATCH (message) AGAINST ('steve')
-7 0.89568990468979
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1;
+a FORMAT(MATCH (message) AGAINST ('steve'),6)
+7 0.895690
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY 1;
a MATCH (message) AGAINST ('steve' IN BOOLEAN MODE)
7 1
-SELECT a, MATCH (message) AGAINST ('steve') as rel FROM t1 ORDER BY rel;
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) as rel FROM t1 ORDER BY rel;
a rel
-1 0
-2 0
-3 0
-5 0
-6 0
-7 0.89568990468979
-4 0.90587323904037
+1 0.000000
+2 0.000000
+3 0.000000
+5 0.000000
+6 0.000000
+7 0.895690
+4 0.905873
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) as rel FROM t1 ORDER BY rel;
a rel
1 0
diff --git a/mysql-test/r/func_compress.result b/mysql-test/r/func_compress.result
index 11dbcca9431..9bc8e417e19 100644
--- a/mysql-test/r/func_compress.result
+++ b/mysql-test/r/func_compress.result
@@ -69,6 +69,6 @@ Error 1259 ZLIB: Input data corrupted
Error 1256 Uncompressed data size too large; the maximum size is 1048576 (probably, length of uncompressed data was corrupted)
drop table t1;
set @@max_allowed_packet=1048576*100;
-select compress(repeat('aaaaaaaaaa', 10000000)) is null;
-compress(repeat('aaaaaaaaaa', 10000000)) is null
+select compress(repeat('aaaaaaaaaa', IF(XXX, 10, 10000000))) is null;
+compress(repeat('aaaaaaaaaa', IF(XXX, 10, 10000000))) is null
0
diff --git a/mysql-test/r/func_gconcat.result b/mysql-test/r/func_gconcat.result
index 22868aa03c4..dfaf5758699 100644
--- a/mysql-test/r/func_gconcat.result
+++ b/mysql-test/r/func_gconcat.result
@@ -457,3 +457,10 @@ group_concat(distinct b order by b)
Warnings:
Warning 1260 2 line(s) were cut by GROUP_CONCAT()
drop table t1;
+create table t1 (a char(3), b char(20), primary key (a, b));
+insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English');
+select group_concat(a) from t1 group by b;
+group_concat(a)
+ABW
+ABW
+drop table t1;
diff --git a/mysql-test/r/func_group.result b/mysql-test/r/func_group.result
index cb9e63c9df5..73fea8ed258 100644
--- a/mysql-test/r/func_group.result
+++ b/mysql-test/r/func_group.result
@@ -639,8 +639,22 @@ create table t1 (a char(10));
insert into t1 values ('a'),('b'),('c');
select coercibility(max(a)) from t1;
coercibility(max(a))
-3
+2
drop table t1;
+create table t1 (a char character set latin2);
+insert into t1 values ('a'),('b');
+select charset(max(a)), coercibility(max(a)),
+charset(min(a)), coercibility(min(a)) from t1;
+charset(max(a)) coercibility(max(a)) charset(min(a)) coercibility(min(a))
+latin2 2 latin2 2
+create table t2 select max(a),min(a) from t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `max(a)` varchar(1) character set latin2 default NULL,
+ `min(a)` varchar(1) character set latin2 default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t2,t1;
create table t1 (a int);
insert into t1 values (1);
select max(a) as b from t1 having b=1;
diff --git a/mysql-test/r/func_in.result b/mysql-test/r/func_in.result
index daf36b00693..fa603fd16d5 100644
--- a/mysql-test/r/func_in.result
+++ b/mysql-test/r/func_in.result
@@ -179,3 +179,9 @@ select 1 in ('1.1',2);
select 1 in ('1.1',2.0);
1 in ('1.1',2.0)
0
+create table t1 (a char(20) character set binary);
+insert into t1 values ('aa'), ('bb');
+select * from t1 where a in (NULL, 'aa');
+a
+aa
+drop table t1;
diff --git a/mysql-test/r/func_like.result b/mysql-test/r/func_like.result
index e9434b1749d..ac8e5eda8e8 100644
--- a/mysql-test/r/func_like.result
+++ b/mysql-test/r/func_like.result
@@ -3,10 +3,10 @@ create table t1 (a varchar(10), key(a));
insert into t1 values ("a"),("abc"),("abcd"),("hello"),("test");
explain select * from t1 where a like 'abc%';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index a a 11 NULL 5 Using where; Using index
+1 SIMPLE t1 index a a 13 NULL 5 Using where; Using index
explain select * from t1 where a like concat('abc','%');
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index a a 11 NULL 5 Using where; Using index
+1 SIMPLE t1 index a a 13 NULL 5 Using where; Using index
select * from t1 where a like "abc%";
a
abc
diff --git a/mysql-test/r/func_str.result b/mysql-test/r/func_str.result
index 1f07ba0484f..e65ddde8aef 100644
--- a/mysql-test/r/func_str.result
+++ b/mysql-test/r/func_str.result
@@ -201,6 +201,9 @@ hex(unhex("1")) hex(unhex("12")) hex(unhex("123")) hex(unhex("1234")) hex(unhex(
select length(unhex(md5("abrakadabra")));
length(unhex(md5("abrakadabra")))
16
+select concat('a', quote(NULL));
+concat('a', quote(NULL))
+aNULL
select reverse("");
reverse("")
@@ -312,7 +315,7 @@ insert into t1 values ('one'),(NULL),('two'),('four');
select a, quote(a), isnull(quote(a)), quote(a) is null, ifnull(quote(a), 'n') from t1;
a quote(a) isnull(quote(a)) quote(a) is null ifnull(quote(a), 'n')
one 'one' 0 0 'one'
-NULL NULL 1 1 n
+NULL NULL 0 0 NULL
two 'two' 0 0 'two'
four 'four' 0 0 'four'
drop table t1;
@@ -578,36 +581,36 @@ Warning 1265 Data truncated for column 'format(130,10)' at row 1
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `bin(130)` char(64) NOT NULL default '',
- `oct(130)` char(64) NOT NULL default '',
- `conv(130,16,10)` char(64) NOT NULL default '',
- `hex(130)` char(6) NOT NULL default '',
- `char(130)` char(1) NOT NULL default '',
- `format(130,10)` char(4) NOT NULL default '',
- `left(_latin2'a',1)` char(1) character set latin2 NOT NULL default '',
- `right(_latin2'a',1)` char(1) character set latin2 NOT NULL default '',
- `lcase(_latin2'a')` char(1) character set latin2 NOT NULL default '',
- `ucase(_latin2'a')` char(1) character set latin2 NOT NULL default '',
- `substring(_latin2'a',1,1)` char(1) character set latin2 NOT NULL default '',
- `concat(_latin2'a',_latin2'b')` char(2) character set latin2 NOT NULL default '',
- `lpad(_latin2'a',4,_latin2'b')` char(4) character set latin2 NOT NULL default '',
- `rpad(_latin2'a',4,_latin2'b')` char(4) character set latin2 NOT NULL default '',
- `concat_ws(_latin2'a',_latin2'b')` char(1) character set latin2 NOT NULL default '',
- `make_set(255,_latin2'a',_latin2'b',_latin2'c')` char(5) character set latin2 NOT NULL default '',
- `export_set(255,_latin2'y',_latin2'n',_latin2' ')` char(127) character set latin2 NOT NULL default '',
- `trim(_latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `ltrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `rtrim(_latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `trim(LEADING _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `trim(TRAILING _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `trim(BOTH _latin2' ' FROM _latin2' a ')` char(3) character set latin2 NOT NULL default '',
- `repeat(_latin2'a',10)` char(10) character set latin2 NOT NULL default '',
- `reverse(_latin2'ab')` char(2) character set latin2 NOT NULL default '',
- `quote(_latin2'ab')` char(6) character set latin2 NOT NULL default '',
- `soundex(_latin2'ab')` char(4) character set latin2 NOT NULL default '',
- `substring(_latin2'ab',1)` char(2) character set latin2 NOT NULL default '',
- `insert(_latin2'abcd',2,3,_latin2'ef')` char(6) character set latin2 NOT NULL default '',
- `replace(_latin2'abcd',_latin2'b',_latin2'B')` char(4) character set latin2 NOT NULL default '',
+ `bin(130)` varchar(64) NOT NULL default '',
+ `oct(130)` varchar(64) NOT NULL default '',
+ `conv(130,16,10)` varchar(64) NOT NULL default '',
+ `hex(130)` varchar(6) NOT NULL default '',
+ `char(130)` varchar(1) NOT NULL default '',
+ `format(130,10)` varchar(4) NOT NULL default '',
+ `left(_latin2'a',1)` varchar(1) character set latin2 NOT NULL default '',
+ `right(_latin2'a',1)` varchar(1) character set latin2 NOT NULL default '',
+ `lcase(_latin2'a')` varchar(1) character set latin2 NOT NULL default '',
+ `ucase(_latin2'a')` varchar(1) character set latin2 NOT NULL default '',
+ `substring(_latin2'a',1,1)` varchar(1) character set latin2 NOT NULL default '',
+ `concat(_latin2'a',_latin2'b')` varchar(2) character set latin2 NOT NULL default '',
+ `lpad(_latin2'a',4,_latin2'b')` varchar(4) character set latin2 NOT NULL default '',
+ `rpad(_latin2'a',4,_latin2'b')` varchar(4) character set latin2 NOT NULL default '',
+ `concat_ws(_latin2'a',_latin2'b')` varchar(1) character set latin2 NOT NULL default '',
+ `make_set(255,_latin2'a',_latin2'b',_latin2'c')` varchar(5) character set latin2 NOT NULL default '',
+ `export_set(255,_latin2'y',_latin2'n',_latin2' ')` varchar(127) character set latin2 NOT NULL default '',
+ `trim(_latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `ltrim(_latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `rtrim(_latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `trim(LEADING _latin2' ' FROM _latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `trim(TRAILING _latin2' ' FROM _latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `trim(BOTH _latin2' ' FROM _latin2' a ')` varchar(3) character set latin2 NOT NULL default '',
+ `repeat(_latin2'a',10)` varchar(10) character set latin2 NOT NULL default '',
+ `reverse(_latin2'ab')` varchar(2) character set latin2 NOT NULL default '',
+ `quote(_latin2'ab')` varchar(6) character set latin2 NOT NULL default '',
+ `soundex(_latin2'ab')` varchar(4) character set latin2 NOT NULL default '',
+ `substring(_latin2'ab',1)` varchar(2) character set latin2 NOT NULL default '',
+ `insert(_latin2'abcd',2,3,_latin2'ef')` varchar(6) character set latin2 NOT NULL default '',
+ `replace(_latin2'abcd',_latin2'b',_latin2'B')` varchar(4) character set latin2 NOT NULL default '',
`encode('abcd','ab')` binary(4) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
diff --git a/mysql-test/r/func_system.result b/mysql-test/r/func_system.result
index d3db2cc5151..0f827913780 100644
--- a/mysql-test/r/func_system.result
+++ b/mysql-test/r/func_system.result
@@ -46,8 +46,8 @@ create table t1 (version char(40)) select database(), user(), version() as 'vers
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `database()` char(34) character set utf8 default NULL,
- `user()` char(77) character set utf8 NOT NULL default '',
+ `database()` varchar(34) character set utf8 default NULL,
+ `user()` varchar(77) character set utf8 NOT NULL default '',
`version` char(40) default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
@@ -61,8 +61,8 @@ create table t1 select charset(_utf8'a'), collation(_utf8'a');
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `charset(_utf8'a')` char(64) character set utf8 NOT NULL default '',
- `collation(_utf8'a')` char(64) character set utf8 NOT NULL default ''
+ `charset(_utf8'a')` varchar(64) character set utf8 NOT NULL default '',
+ `collation(_utf8'a')` varchar(64) character set utf8 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
select TRUE,FALSE,NULL;
diff --git a/mysql-test/r/func_test.result.es b/mysql-test/r/func_test.result.es
new file mode 100644
index 00000000000..380f96835d0
--- /dev/null
+++ b/mysql-test/r/func_test.result.es
@@ -0,0 +1,185 @@
+drop table if exists t1,t2;
+select 0=0,1>0,1>=1,1<0,1<=0,1!=0,strcmp("abc","abcd"),strcmp("b","a"),strcmp("a","a") ;
+0=0 1>0 1>=1 1<0 1<=0 1!=0 strcmp("abc","abcd") strcmp("b","a") strcmp("a","a")
+1 1 1 0 0 1 -1 1 0
+select "a"<"b","a"<="b","b">="a","b">"a","a"="A","a"<>"b";
+"a"<"b" "a"<="b" "b">="a" "b">"a" "a"="A" "a"<>"b"
+1 1 1 1 1 1
+select "a "="A", "A "="a", "a " <= "A b";
+"a "="A" "A "="a" "a " <= "A b"
+1 1 1
+select "abc" like "a%", "abc" not like "%d%", "a%" like "a\%","abc%" like "a%\%","abcd" like "a%b_%d", "a" like "%%a","abcde" like "a%_e","abc" like "abc%";
+"abc" like "a%" "abc" not like "%d%" "a%" like "a\%" "abc%" like "a%\%" "abcd" like "a%b_%d" "a" like "%%a" "abcde" like "a%_e" "abc" like "abc%"
+1 1 1 1 1 1 1 1
+select "a" like "%%b","a" like "%%ab","ab" like "a\%", "ab" like "_", "ab" like "ab_", "abc" like "%_d", "abc" like "abc%d";
+"a" like "%%b" "a" like "%%ab" "ab" like "a\%" "ab" like "_" "ab" like "ab_" "abc" like "%_d" "abc" like "abc%d"
+0 0 0 0 0 0 0
+select '?' like '|%', '?' like '|%' ESCAPE '|', '%' like '|%', '%' like '|%' ESCAPE '|', '%' like '%';
+'?' like '|%' '?' like '|%' ESCAPE '|' '%' like '|%' '%' like '|%' ESCAPE '|' '%' like '%'
+0 0 0 1 1
+select 'abc' like '%c','abcabc' like '%c', "ab" like "", "ab" like "a", "ab" like "ab";
+'abc' like '%c' 'abcabc' like '%c' "ab" like "" "ab" like "a" "ab" like "ab"
+1 1 0 0 1
+select "Det här är svenska" regexp "h[[:alpha:]]+r", "aba" regexp "^(a|b)*$";
+"Det här är svenska" regexp "h[[:alpha:]]+r" "aba" regexp "^(a|b)*$"
+1 1
+select "aba" regexp concat("^","a");
+"aba" regexp concat("^","a")
+1
+select !0,NOT 0=1,!(0=0),1 AND 1,1 && 0,0 OR 1,1 || NULL, 1=1 or 1=1 and 1=0;
+!0 NOT 0=1 !(0=0) 1 AND 1 1 && 0 0 OR 1 1 || NULL 1=1 or 1=1 and 1=0
+1 1 0 1 0 1 1 1
+select 2 between 1 and 3, "monty" between "max" and "my",2=2 and "monty" between "max" and "my" and 3=3;
+2 between 1 and 3 "monty" between "max" and "my" 2=2 and "monty" between "max" and "my" and 3=3
+1 1 1
+select 'b' between 'a' and 'c', 'B' between 'a' and 'c';
+'b' between 'a' and 'c' 'B' between 'a' and 'c'
+1 1
+select 2 in (3,2,5,9,5,1),"monty" in ("david","monty","allan"), 1.2 in (1.4,1.2,1.0);
+2 in (3,2,5,9,5,1) "monty" in ("david","monty","allan") 1.2 in (1.4,1.2,1.0)
+1 1 1
+select -1.49 or -1.49,0.6 or 0.6;
+-1.49 or -1.49 0.6 or 0.6
+1 1
+select 3 ^ 11, 1 ^ 1, 1 ^ 0, 1 ^ NULL, NULL ^ 1;
+3 ^ 11 1 ^ 1 1 ^ 0 1 ^ NULL NULL ^ 1
+8 0 1 NULL NULL
+explain extended select 3 ^ 11, 1 ^ 1, 1 ^ 0, 1 ^ NULL, NULL ^ 1;
+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
+Warnings:
+Note 1003 select (3 ^ 11) AS `3 ^ 11`,(1 ^ 1) AS `1 ^ 1`,(1 ^ 0) AS `1 ^ 0`,(1 ^ NULL) AS `1 ^ NULL`,(NULL ^ 1) AS `NULL ^ 1`
+select 1 XOR 1, 1 XOR 0, 0 XOR 1, 0 XOR 0, NULL XOR 1, 1 XOR NULL, 0 XOR NULL;
+1 XOR 1 1 XOR 0 0 XOR 1 0 XOR 0 NULL XOR 1 1 XOR NULL 0 XOR NULL
+0 1 1 0 NULL NULL NULL
+select 1 like 2 xor 2 like 1;
+1 like 2 xor 2 like 1
+0
+select 10 % 7, 10 mod 7, 10 div 3;
+10 % 7 10 mod 7 10 div 3
+3 3 3
+explain extended select 10 % 7, 10 mod 7, 10 div 3;
+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
+Warnings:
+Note 1003 select (10 % 7) AS `10 % 7`,(10 % 7) AS `10 mod 7`,(10 DIV 3) AS `10 div 3`
+select (1 << 64)-1, ((1 << 64)-1) DIV 1, ((1 << 64)-1) DIV 2;
+(1 << 64)-1 ((1 << 64)-1) DIV 1 ((1 << 64)-1) DIV 2
+18446744073709551615 18446744073709551615 9223372036854775807
+explain extended select (1 << 64)-1, ((1 << 64)-1) DIV 1, ((1 << 64)-1) DIV 2;
+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
+Warnings:
+Note 1003 select ((1 << 64) - 1) AS `(1 << 64)-1`,(((1 << 64) - 1) DIV 1) AS `((1 << 64)-1) DIV 1`,(((1 << 64) - 1) DIV 2) AS `((1 << 64)-1) DIV 2`
+create table t1 (a int);
+insert t1 values (1);
+select * from t1 where 1 xor 1;
+a
+explain extended select * from t1 where 1 xor 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
+Warnings:
+Note 1003 select test.t1.a AS `a` from test.t1 where (1 xor 1)
+select - a from t1;
+- a
+-1
+explain extended select - a from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 system NULL NULL NULL NULL 1
+Warnings:
+Note 1003 select -(test.t1.a) AS `- a` from test.t1
+drop table t1;
+select 5 between 0 and 10 between 0 and 1,(5 between 0 and 10) between 0 and 1;
+5 between 0 and 10 between 0 and 1 (5 between 0 and 10) between 0 and 1
+0 1
+select 1 and 2 between 2 and 10, 2 between 2 and 10 and 1;
+1 and 2 between 2 and 10 2 between 2 and 10 and 1
+1 1
+select 1 and 0 or 2, 2 or 1 and 0;
+1 and 0 or 2 2 or 1 and 0
+1 1
+select _koi8r'a' = _koi8r'A';
+_koi8r'a' = _koi8r'A'
+1
+select _koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci;
+_koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci
+1
+explain extended select _koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci;
+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
+Warnings:
+Note 1003 select (_koi8r'a' = (_koi8r'A' collate _latin1'koi8r_general_ci')) AS `_koi8r'a' = _koi8r'A' COLLATE koi8r_general_ci`
+select _koi8r'a' = _koi8r'A' COLLATE koi8r_bin;
+_koi8r'a' = _koi8r'A' COLLATE koi8r_bin
+0
+select _koi8r'a' COLLATE koi8r_general_ci = _koi8r'A';
+_koi8r'a' COLLATE koi8r_general_ci = _koi8r'A'
+1
+select _koi8r'a' COLLATE koi8r_bin = _koi8r'A';
+_koi8r'a' COLLATE koi8r_bin = _koi8r'A'
+0
+select _koi8r'a' COLLATE koi8r_bin = _koi8r'A' COLLATE koi8r_general_ci;
+ERROR HY000: Illegal mix of collations (koi8r_bin,EXPLICIT) and (koi8r_general_ci,EXPLICIT) for operation '='
+select _koi8r'a' = _latin1'A';
+ERROR HY000: Illegal mix of collations (koi8r_general_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation '='
+select strcmp(_koi8r'a', _koi8r'A');
+strcmp(_koi8r'a', _koi8r'A')
+0
+select strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_general_ci);
+strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_general_ci)
+0
+select strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_bin);
+strcmp(_koi8r'a', _koi8r'A' COLLATE koi8r_bin)
+1
+select strcmp(_koi8r'a' COLLATE koi8r_general_ci, _koi8r'A');
+strcmp(_koi8r'a' COLLATE koi8r_general_ci, _koi8r'A')
+0
+select strcmp(_koi8r'a' COLLATE koi8r_bin, _koi8r'A');
+strcmp(_koi8r'a' COLLATE koi8r_bin, _koi8r'A')
+1
+select strcmp(_koi8r'a' COLLATE koi8r_general_ci, _koi8r'A' COLLATE koi8r_bin);
+ERROR HY000: Illegal mix of collations (koi8r_general_ci,EXPLICIT) and (koi8r_bin,EXPLICIT) for operation 'strcmp'
+select strcmp(_koi8r'a', _latin1'A');
+ERROR HY000: Illegal mix of collations (koi8r_general_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation 'strcmp'
+select _koi8r'a' LIKE _koi8r'A';
+_koi8r'a' LIKE _koi8r'A'
+1
+select _koi8r'a' LIKE _koi8r'A' COLLATE koi8r_general_ci;
+_koi8r'a' LIKE _koi8r'A' COLLATE koi8r_general_ci
+1
+select _koi8r'a' LIKE _koi8r'A' COLLATE koi8r_bin;
+_koi8r'a' LIKE _koi8r'A' COLLATE koi8r_bin
+0
+select _koi8r'a' COLLATE koi8r_general_ci LIKE _koi8r'A';
+_koi8r'a' COLLATE koi8r_general_ci LIKE _koi8r'A'
+1
+select _koi8r'a' COLLATE koi8r_bin LIKE _koi8r'A';
+_koi8r'a' COLLATE koi8r_bin LIKE _koi8r'A'
+0
+select _koi8r'a' COLLATE koi8r_general_ci LIKE _koi8r'A' COLLATE koi8r_bin;
+ERROR HY000: Illegal mix of collations (koi8r_general_ci,EXPLICIT) and (koi8r_bin,EXPLICIT) for operation 'like'
+select _koi8r'a' LIKE _latin1'A';
+ERROR HY000: Illegal mix of collations (koi8r_general_ci,COERCIBLE) and (latin1_swedish_ci,COERCIBLE) for operation 'like'
+CREATE TABLE t1 ( faq_group_id int(11) NOT NULL default '0', faq_id int(11) NOT NULL default '0', title varchar(240) default NULL, keywords text, description longblob, solution longblob, status tinyint(4) NOT NULL default '0', access_id smallint(6) default NULL, lang_id smallint(6) NOT NULL default '0', created datetime NOT NULL default '0000-00-00 00:00:00', updated datetime default NULL, last_access datetime default NULL, last_notify datetime default NULL, solved_count int(11) NOT NULL default '0', static_solved int(11) default NULL, solved_1 int(11) default NULL, solved_2 int(11) default NULL, solved_3 int(11) default NULL, solved_4 int(11) default NULL, solved_5 int(11) default NULL, expires datetime default NULL, notes text, assigned_to smallint(6) default NULL, assigned_group smallint(6) default NULL, last_edited_by smallint(6) default NULL, orig_ref_no varchar(15) binary default NULL, c$fundstate smallint(6) default NULL, c$contributor smallint(6) default NULL, UNIQUE KEY t1$faq_id (faq_id), KEY t1$group_id$faq_id (faq_group_id,faq_id), KEY t1$c$fundstate (c$fundstate) ) ENGINE=MyISAM;
+INSERT INTO t1 VALUES (82,82,'How to use the DynaVox Usage Counts Feature','usages count, number, corner, white, box, button','<as-html>\r\n<table width=\"100%\" border=\"0\">\r\n <tr>\r\n <td width=\"3%\"> </td>\r\n <td width=\"97%\">\r\n <h3><font face=\"Verdana, Arial, Helvetica, sans-serif\" color=\"#000000\">How \r\n To</font><!-- #BeginEditable \"CS_troubleshoot_question\" --><font face=\"Verdana, Arial, Helvetica, sans-serif\" color=\"#000099\"><font color=\"#000000\">: \r\n Display or Hide the Usage Counts to find out how many times each button is being selected. </font></font><!-- #EndEditable --></h3>\r\n </td>\r\n </tr>\r\n</table>','<as-html>\r\n <table width=\"100%\" border=\"0\">\r\n <tr>\r\n <td width=\"3%\"> </td>\r\n \r\n<td width=\"97%\"><!-- #BeginEditable \"CS_troubleshoot_answer\" --> \r\n \r\n<p><font color=\"#000000\" face=\"Verdana, Arial, Helvetica, sans-serif\">1. Select \r\n the <i>On/Setup</i> button to access the DynaVox Setup Menu.<br>\r\n 2. Select <b>Button Features.</b><br>\r\n 3. Below the <b>OK</b> button is the <b>Usage Counts</b> button.<br>\r\n a. If it says \"Hidden\" then the Usage Counts will not be displayed.<br>\r\n b. If it says \"Displayed\" then the Usage Counts will be shown.<br>\r\n c. Select the <b>Usage Counts</b> Option Ring once and it will toggle \r\n to the alternative option.<br>\r\n 4. Once the correct setting has been chosen, select <b>OK</b> to leave the <i>Button \r\n Features</i> menu.<br>\r\n 5. Select <b>OK</b> out of the <i>Setup</i> menu and return to the communication \r\n page.</font></p>\r\n <p><font color=\"#000000\" face=\"Verdana, Arial, Helvetica, sans-serif\">For \r\n further information on <i>Usage Counts,</i> see the <i>Button Features \r\n Menu Entry</i> in the DynaVox/DynaMyte Reference Manual.</font></p>\r\n<!-- #EndEditable --></td>\r\n </tr>\r\n</table>',4,1,1,'2001-11-16 16:43:34','2002-11-25 12:09:43','2003-07-24 01:04:48',NULL,11,NULL,0,0,0,0,0,NULL,NULL,NULL,NULL,11,NULL,NULL,NULL);
+CREATE TABLE t2 ( access_id smallint(6) NOT NULL default '0', name varchar(20) binary default NULL, rank smallint(6) NOT NULL default '0', KEY t2$access_id (access_id) ) ENGINE=MyISAM;
+INSERT INTO t2 VALUES (1,'Everyone',2),(2,'Help',3),(3,'Customer Support',1);
+SELECT f_acc.rank, a1.rank, a2.rank FROM t1 LEFT JOIN t1 f1 ON (f1.access_id=1 AND f1.faq_group_id = t1.faq_group_id) LEFT JOIN t2 a1 ON (a1.access_id = f1.access_id) LEFT JOIN t1 f2 ON (f2.access_id=3 AND f2.faq_group_id = t1.faq_group_id) LEFT JOIN t2 a2 ON (a2.access_id = f2.access_id), t2 f_acc WHERE LEAST(a1.rank,a2.rank) = f_acc.rank;
+rank rank rank
+2 2 NULL
+DROP TABLE t1,t2;
+CREATE TABLE t1 (d varchar(6), k int);
+INSERT INTO t1 VALUES (NULL, 2);
+SELECT GREATEST(d,d) FROM t1 WHERE k=2;
+GREATEST(d,d)
+NULL
+DROP TABLE t1;
+select 1197.90 mod 50;
+1197.90 mod 50
+47.90
+select 5.1 mod 3, 5.1 mod -3, -5.1 mod 3, -5.1 mod -3;
+5.1 mod 3 5.1 mod -3 -5.1 mod 3 -5.1 mod -3
+2.1 2.1 -2.1 -2.1
+select 5 mod 3, 5 mod -3, -5 mod 3, -5 mod -3;
+5 mod 3 5 mod -3 -5 mod 3 -5 mod -3
+2 2 -2 -2
diff --git a/mysql-test/r/func_time.result b/mysql-test/r/func_time.result
index 678ad9c9fdc..131496f3d9f 100644
--- a/mysql-test/r/func_time.result
+++ b/mysql-test/r/func_time.result
@@ -474,6 +474,12 @@ unix_timestamp(@a)
select unix_timestamp('1969-12-01 19:00:01');
unix_timestamp('1969-12-01 19:00:01')
0
+select from_unixtime(0);
+from_unixtime(0)
+NULL
+select from_unixtime(2145916800);
+from_unixtime(2145916800)
+NULL
CREATE TABLE t1 (datetime datetime, timestamp timestamp, date date, time time);
INSERT INTO t1 values ("2001-01-02 03:04:05", "2002-01-02 03:04:05", "2003-01-02", "06:07:08");
SELECT * from t1;
diff --git a/mysql-test/r/gis.result b/mysql-test/r/gis.result
index c013a01b51b..ee0a30e27d0 100644
--- a/mysql-test/r/gis.result
+++ b/mysql-test/r/gis.result
@@ -581,3 +581,77 @@ t1 CREATE TABLE `t1` (
`POINT(1,3)` longblob NOT NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
+CREATE TABLE `t1` (`object_id` bigint(20) unsigned NOT NULL default '0', `geo`
+geometry NOT NULL default '') ENGINE=MyISAM ;
+insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363
+36.305435,-114.992394 36.305202,-114.991219 36.305975,-114.991163
+36.306845,-114.989432 36.309452,-114.978275 36.312642,-114.977363
+36.311978,-114.975327 36.312344,-114.96502 36.31597,-114.963364
+36.313629,-114.961723 36.313721,-114.956398 36.316057,-114.951882
+36.320979,-114.947073 36.323475,-114.945207 36.326451,-114.945207
+36.326451,-114.944132 36.326061,-114.94003 36.326588,-114.924017
+36.334484,-114.923281 36.334146,-114.92564 36.331504,-114.94072
+36.319282,-114.945348 36.314812,-114.948091 36.314762,-114.951755
+36.316211,-114.952446 36.313883,-114.952644 36.309488,-114.944725
+36.313083,-114.93706 36.32043,-114.932478 36.323497,-114.924556
+36.327708,-114.922608 36.329715,-114.92009 36.328695,-114.912105
+36.323566,-114.901647 36.317952,-114.897436 36.313968,-114.895344
+36.309573,-114.891699 36.304398,-114.890569 36.303551,-114.886356
+36.302702,-114.885141 36.301351,-114.885709 36.297391,-114.892499
+36.290893,-114.902142 36.288974,-114.904941 36.288838,-114.905308
+36.289845,-114.906325 36.290395,-114.909916 36.289549,-114.914527
+36.287535,-114.918797 36.284423,-114.922982 36.279731,-114.924113
+36.277282,-114.924057 36.275817,-114.927733 36.27053,-114.929354
+36.269029,-114.929354 36.269029,-114.950856 36.268715,-114.950768
+36.264324,-114.960206 36.264293,-114.960301 36.268943,-115.006662
+36.268929,-115.008583 36.265619,-115.00665 36.264247,-115.006659
+36.246873,-115.006659 36.246873,-115.006838 36.247697,-115.010764
+36.247774,-115.015609 36.25113,-115.015765 36.254505,-115.029517
+36.254619,-115.038573 36.249317,-115.038573 36.249317,-115.023403
+36.25841,-115.023873 36.258994,-115.031845 36.259829,-115.03183
+36.261053,-115.025561 36.261095,-115.036417 36.274632,-115.033729
+36.276041,-115.032217 36.274851,-115.029845 36.273959,-115.029934
+36.274966,-115.025763 36.274896,-115.025406 36.281044,-115.028731
+36.284471,-115.036497 36.290377,-115.042071 36.291039,-115.026759
+36.298478,-115.008995 36.301966,-115.006363 36.305435),(-115.079835
+36.244369,-115.079735 36.260186,-115.076435 36.262369,-115.069758
+36.265,-115.070235 36.268757,-115.064542 36.268655,-115.061843
+36.269857,-115.062676 36.270693,-115.06305 36.272344,-115.059051
+36.281023,-115.05918 36.283008,-115.060591 36.285246,-115.061913
+36.290022,-115.062499 36.306353,-115.062499 36.306353,-115.060918
+36.30642,-115.06112 36.289779,-115.05713 36.2825,-115.057314
+36.279446,-115.060779 36.274659,-115.061366 36.27209,-115.057858
+36.26557,-115.055805 36.262883,-115.054688 36.262874,-115.047335
+36.25037,-115.044234 36.24637,-115.052434 36.24047,-115.061734
+36.23507,-115.061934 36.22677,-115.061934 36.22677,-115.061491
+36.225267,-115.062024 36.218194,-115.060134 36.218278,-115.060133
+36.210771,-115.057833 36.210771,-115.057433 36.196271,-115.062233
+36.196271,-115.062233 36.190371,-115.062233 36.190371,-115.065533
+36.190371,-115.071333 36.188571,-115.098331 36.188275,-115.098331
+36.188275,-115.098435 36.237569,-115.097535 36.240369,-115.097535
+36.240369,-115.093235 36.240369,-115.089135 36.240469,-115.083135
+36.240569,-115.083135 36.240569,-115.079835
+36.244369)))')),('85998',GeomFromText('MULTIPOLYGON(((-115.333107
+36.264587,-115.333168 36.280638,-115.333168 36.280638,-115.32226
+36.280643,-115.322538 36.274311,-115.327222 36.274258,-115.32733
+36.263026,-115.330675 36.262984,-115.332132 36.264673,-115.333107
+36.264587),(-115.247239 36.247066,-115.247438 36.218267,-115.247438
+36.218267,-115.278525 36.219263,-115.278525 36.219263,-115.301545
+36.219559,-115.332748 36.219197,-115.332757 36.220041,-115.332757
+36.220041,-115.332895 36.233514,-115.349023 36.233479,-115.351489
+36.234475,-115.353681 36.237021,-115.357106 36.239789,-115.36519
+36.243331,-115.368156 36.243487,-115.367389 36.244902,-115.364553
+36.246014,-115.359219 36.24616,-115.356186 36.248025,-115.353347
+36.248004,-115.350813 36.249507,-115.339673 36.25387,-115.333069
+36.255018,-115.333069 36.255018,-115.333042 36.247767,-115.279039
+36.248666,-115.263639 36.247466,-115.263839 36.252766,-115.261439
+36.252666,-115.261439 36.247366,-115.247239 36.247066)))'));
+select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
+t1 where object_id=85998;
+object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
+85998 MULTIPOLYGON 0 POINT(115.31877315203 -36.237472821022)
+select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
+t1 where object_id=85984;
+object_id geometrytype(geo) ISSIMPLE(GEO) ASTEXT(centroid(geo))
+85984 MULTIPOLYGON 0 POINT(-114.87787186923 36.33101763469)
+drop table t1;
diff --git a/mysql-test/r/grant.result b/mysql-test/r/grant.result
index d5b4aea81f6..b69ba9702a6 100644
--- a/mysql-test/r/grant.result
+++ b/mysql-test/r/grant.result
@@ -134,6 +134,31 @@ ERROR HY000: Incorrect usage of DB GRANT and GLOBAL PRIVILEGES
select 1;
1
1
+insert into mysql.user (host, user) values ('localhost', 'test11');
+insert into mysql.db (host, db, user, select_priv) values
+('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
+alter table mysql.db order by db asc;
+flush privileges;
+show grants for test11@localhost;
+Grants for test11@localhost
+GRANT USAGE ON *.* TO 'test11'@'localhost'
+GRANT SELECT ON `ab%`.* TO 'test11'@'localhost'
+GRANT SELECT ON `a%`.* TO 'test11'@'localhost'
+alter table mysql.db order by db desc;
+flush privileges;
+show grants for test11@localhost;
+Grants for test11@localhost
+GRANT USAGE ON *.* TO 'test11'@'localhost'
+GRANT SELECT ON `ab%`.* TO 'test11'@'localhost'
+GRANT SELECT ON `a%`.* TO 'test11'@'localhost'
+delete from mysql.user where user='test11';
+delete from mysql.db where user='test11';
+create database mysqltest1;
+grant usage on mysqltest1.* to test6123 identified by 'magic123';
+select host,db,user,select_priv,insert_priv from mysql.db where db="mysqltest1";
+host db user select_priv insert_priv
+delete from mysql.user where user='test6123';
+drop database mysqltest1;
create table t1 (a int);
grant ALL PRIVILEGES on *.* to drop_user2@localhost with GRANT OPTION;
show grants for drop_user2@localhost;
@@ -193,17 +218,19 @@ grant select on test.* to drop_user3@localhost;
grant select on *.* to drop_user4@localhost;
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
-ERROR HY000: Can't drop one or more of the requested users
revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
drop_user3@localhost, drop_user4@localhost;
+ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
+ERROR HY000: Operation DROP USER failed for 'drop_user1'@'localhost','drop_user2'@'localhost','drop_user3'@'localhost','drop_user4'@'localhost'
drop table t1;
grant usage on *.* to mysqltest_1@localhost identified by "password";
-grant select, update, insert on test.* to mysqltest@localhost;
+grant select, update, insert on test.* to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
Grants for mysqltest_1@localhost
GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'
+GRANT SELECT, INSERT, UPDATE ON `test`.* TO 'mysqltest_1'@'localhost'
drop user mysqltest_1@localhost;
SET NAMES koi8r;
CREATE DATABASE ÂÄ;
@@ -227,27 +254,9 @@ Grants for ÀÚÅÒ@localhost
GRANT USAGE ON *.* TO 'ÀÚÅÒ'@'localhost'
GRANT SELECT (ËÏÌ) ON `ÂÄ`.`ÔÁÂ` TO 'ÀÚÅÒ'@'localhost'
REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost;
+DROP USER ÀÚÅÒ@localhost;
DROP DATABASE ÂÄ;
SET NAMES latin1;
-insert into mysql.user (host, user) values ('localhost', 'test11');
-insert into mysql.db (host, db, user, select_priv) values
-('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
-alter table mysql.db order by db asc;
-flush privileges;
-show grants for test11@localhost;
-Grants for test11@localhost
-GRANT USAGE ON *.* TO 'test11'@'localhost'
-GRANT SELECT ON `ab%`.* TO 'test11'@'localhost'
-GRANT SELECT ON `a%`.* TO 'test11'@'localhost'
-alter table mysql.db order by db desc;
-flush privileges;
-show grants for test11@localhost;
-Grants for test11@localhost
-GRANT USAGE ON *.* TO 'test11'@'localhost'
-GRANT SELECT ON `ab%`.* TO 'test11'@'localhost'
-GRANT SELECT ON `a%`.* TO 'test11'@'localhost'
-delete from mysql.user where user='test11';
-delete from mysql.db where user='test11';
USE test;
CREATE TABLE t1 (a int );
CREATE TABLE t2 LIKE t1;
@@ -315,6 +324,26 @@ DROP DATABASE testdb7;
DROP DATABASE testdb8;
DROP DATABASE testdb9;
DROP DATABASE testdb10;
+create table t1(a int, b int, c int, d int);
+grant insert(b), insert(c), insert(d), insert(a) on t1 to grant_user@localhost;
+show grants for grant_user@localhost;
+Grants for grant_user@localhost
+GRANT USAGE ON *.* TO 'grant_user'@'localhost'
+GRANT INSERT (a, d, c, b) ON `test`.`t1` TO 'grant_user'@'localhost'
+select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv;
+Host Db User Table_name Column_name Column_priv
+localhost test grant_user t1 b Insert
+localhost test grant_user t1 d Insert
+localhost test grant_user t1 a Insert
+localhost test grant_user t1 c Insert
+revoke ALL PRIVILEGES on t1 from grant_user@localhost;
+show grants for grant_user@localhost;
+Grants for grant_user@localhost
+GRANT USAGE ON *.* TO 'grant_user'@'localhost'
+select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv;
+Host Db User Table_name Column_name Column_priv
+drop user grant_user@localhost;
+drop table t1;
SHOW PRIVILEGES;
Privilege Context Comment
Alter Tables To alter the table
diff --git a/mysql-test/r/grant2.result b/mysql-test/r/grant2.result
index 9e1e5d50f31..edfd1a07680 100644
--- a/mysql-test/r/grant2.result
+++ b/mysql-test/r/grant2.result
@@ -60,3 +60,165 @@ use test;
delete from mysql.user where user like 'mysqltest\_%';
delete from mysql.db where user like 'mysqltest\_%';
flush privileges;
+set sql_mode='maxdb';
+drop table if exists t1, t2;
+create table t1(c1 int);
+create table t2(c1 int, c2 int);
+create user 'mysqltest_1';
+create user 'mysqltest_1';
+ERROR HY000: Operation CREATE USER failed for 'mysqltest_1'@'%'
+create user 'mysqltest_2' identified by 'Mysqltest-2';
+create user 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff';
+grant select on *.* to 'mysqltest_2';
+grant insert on test.* to 'mysqltest_2';
+grant update on test.t1 to 'mysqltest_2';
+grant update (c2) on test.t2 to 'mysqltest_2';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+host user password
+% mysqltest_1
+% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1
+% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+host db user
+% test mysqltest_2
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+host db user table_name
+% test mysqltest_2 t1
+% test mysqltest_2 t2
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+host db user table_name column_name
+% test mysqltest_2 t2 c2
+show grants for 'mysqltest_1';
+Grants for mysqltest_1@%
+GRANT USAGE ON *.* TO 'mysqltest_1'@'%'
+show grants for 'mysqltest_2';
+Grants for mysqltest_2@%
+GRANT SELECT ON *.* TO 'mysqltest_2'@'%' IDENTIFIED BY PASSWORD '*BD447CBA355AF58578D3AE33BA2E2CD388BA08D1'
+GRANT INSERT ON "test".* TO 'mysqltest_2'@'%'
+GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_2'@'%'
+GRANT UPDATE ON "test"."t1" TO 'mysqltest_2'@'%'
+drop user 'mysqltest_1';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+host user password
+% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1
+% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+host db user
+% test mysqltest_2
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+host db user table_name
+% test mysqltest_2 t1
+% test mysqltest_2 t2
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+host db user table_name column_name
+% test mysqltest_2 t2 c2
+show grants for 'mysqltest_1';
+ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
+rename user 'mysqltest_2' to 'mysqltest_1';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+host user password
+% mysqltest_1 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1
+% mysqltest_3 fffffffffffffffffffffffffffffffffffffffff
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+host db user
+% test mysqltest_1
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+host db user table_name
+% test mysqltest_1 t1
+% test mysqltest_1 t2
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+host db user table_name column_name
+% test mysqltest_1 t2 c2
+show grants for 'mysqltest_1';
+Grants for mysqltest_1@%
+GRANT SELECT ON *.* TO 'mysqltest_1'@'%' IDENTIFIED BY PASSWORD '*BD447CBA355AF58578D3AE33BA2E2CD388BA08D1'
+GRANT INSERT ON "test".* TO 'mysqltest_1'@'%'
+GRANT UPDATE (c2) ON "test"."t2" TO 'mysqltest_1'@'%'
+GRANT UPDATE ON "test"."t1" TO 'mysqltest_1'@'%'
+drop user 'mysqltest_1', 'mysqltest_3';
+grant all on test.t1 to 'mysqltest_1';
+ERROR 42000: 'root'@'localhost' is not allowed to create new users
+drop user 'mysqltest_1';
+ERROR HY000: Operation DROP USER failed for 'mysqltest_1'@'%'
+drop table t1, t2;
+insert into mysql.db set user='mysqltest_1', db='%', host='%';
+flush privileges;
+show grants for 'mysqltest_1';
+ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
+revoke all privileges, grant option from 'mysqltest_1';
+ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
+drop user 'mysqltest_1';
+select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user;
+host db user
+insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1';
+flush privileges;
+show grants for 'mysqltest_1';
+ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
+drop user 'mysqltest_1';
+select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name;
+host db user table_name
+insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1';
+flush privileges;
+show grants for 'mysqltest_1';
+ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host '%'
+drop user 'mysqltest_1';
+select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name;
+host db user table_name column_name
+create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+create user 'mysqltest_1', 'mysqltest_2' identified by 'Mysqltest-2', 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff';
+rename user 'mysqltest_1' to 'mysqltest_1a', 'mysqltest_2' TO 'mysqltest_2a', 'mysqltest_3' TO 'mysqltest_3a';
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+ERROR HY000: Operation DROP USER failed for 'mysqltest_1'@'%','mysqltest_2'@'%','mysqltest_3'@'%'
+drop user 'mysqltest_1a', 'mysqltest_2a', 'mysqltest_3a';
+create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+create user 'mysqltest_1a', 'mysqltest_2', 'mysqltest_3a';
+ERROR HY000: Operation CREATE USER failed for 'mysqltest_2'@'%'
+rename user 'mysqltest_1a' to 'mysqltest_1b', 'mysqltest_2a' TO 'mysqltest_2b', 'mysqltest_3a' TO 'mysqltest_3b';
+ERROR HY000: Operation RENAME USER failed for 'mysqltest_2a'@'%'
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+drop user 'mysqltest_1b', 'mysqltest_2b', 'mysqltest_3b';
+ERROR HY000: Operation DROP USER failed for 'mysqltest_2b'@'%'
+create user 'mysqltest_2' identified by 'Mysqltest-2';
+drop user 'mysqltest_2' identified by 'Mysqltest-2';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'identified by 'Mysqltest-2'' at line 1
+create user '%@b'@'b';
+show grants for '%@b'@'b';
+Grants for %@b@b
+GRANT USAGE ON *.* TO '%@b'@'b'
+grant select on mysql.* to '%@b'@'b';
+show grants for '%@b'@'b';
+Grants for %@b@b
+GRANT USAGE ON *.* TO '%@b'@'b'
+GRANT SELECT ON "mysql".* TO '%@b'@'b'
+rename user '%@b'@'b' to '%@a'@'a';
+show grants for '%@b'@'b';
+ERROR 42000: There is no such grant defined for user '%@b' on host 'b'
+show grants for '%@a'@'a';
+Grants for %@a@a
+GRANT USAGE ON *.* TO '%@a'@'a'
+GRANT SELECT ON "mysql".* TO '%@a'@'a'
+drop user '%@a'@'a';
+create user mysqltest_2@localhost;
+grant usage on *.* to mysqltest_2@localhost with grant option;
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+ERROR 42000: Access denied for user 'mysqltest_2'@'localhost' to database 'mysql'
+create user mysqltest_A@'%';
+rename user mysqltest_A@'%' to mysqltest_B@'%';
+drop user mysqltest_B@'%';
+drop user mysqltest_2@localhost;
+create user mysqltest_3@localhost;
+grant all privileges on mysql.* to mysqltest_3@localhost;
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+host user password
+% mysqltest_2 *BD447CBA355AF58578D3AE33BA2E2CD388BA08D1
+localhost mysqltest_3
+insert into mysql.user set host='%', user='mysqltest_B';
+create user mysqltest_A@'%';
+ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql'
+rename user mysqltest_B@'%' to mysqltest_C@'%';
+ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql'
+drop user mysqltest_B@'%';
+ERROR 42000: Access denied for user 'mysqltest_3'@'localhost' to database 'mysql'
+drop user mysqltest_B@'%';
+drop user mysqltest_3@localhost;
diff --git a/mysql-test/r/group_min_max.result b/mysql-test/r/group_min_max.result
index c291599b078..006e7052376 100644
--- a/mysql-test/r/group_min_max.result
+++ b/mysql-test/r/group_min_max.result
@@ -1365,7 +1365,7 @@ where exists ( select * from t2 where t2.c > 'b1' )
group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY t1 range NULL idx_t1_1 147 NULL 17 Using index for group-by
-2 SUBQUERY t2 index NULL idx_t2_1 163 NULL 164 Using index
+2 SUBQUERY t2 index NULL idx_t2_1 163 NULL 164 Using where; Using index
explain select a1,a2,b,min(c),max(c) from t1 where (a1 >= 'c' or a2 < 'b') and (b > 'a') group by a1,a2,b;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 range idx_t1_0,idx_t1_1,idx_t1_2 idx_t1_1 147 NULL 17 Using where; Using index for group-by
diff --git a/mysql-test/r/have_moscow_leap_timezone.require b/mysql-test/r/have_moscow_leap_timezone.require
new file mode 100644
index 00000000000..f27452d7770
--- /dev/null
+++ b/mysql-test/r/have_moscow_leap_timezone.require
@@ -0,0 +1,2 @@
+from_unixtime(1072904422)
+2004-01-01 00:00:00
diff --git a/mysql-test/r/have_openssl_1.require b/mysql-test/r/have_openssl_1.require
index 032b60d544a..b33a1d2854f 100644
--- a/mysql-test/r/have_openssl_1.require
+++ b/mysql-test/r/have_openssl_1.require
@@ -1,2 +1,2 @@
Variable_name Value
-Ssl_cipher EDH-RSA-DES-CBC3-SHA
+Ssl_cipher DHE-RSA-AES256-SHA
diff --git a/mysql-test/r/having.result b/mysql-test/r/having.result
index 2e94974e953..86c9adf8cf6 100644
--- a/mysql-test/r/having.result
+++ b/mysql-test/r/having.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
create table t1 (a int);
select count(a) as b from t1 where a=0 having b > 0;
b
@@ -128,3 +128,203 @@ id description c
1 test 0
2 test2 0
drop table t1,t2,t3;
+create table t1 (col1 int, col2 varchar(5), col_t1 int);
+create table t2 (col1 int, col2 varchar(5), col_t2 int);
+create table t3 (col1 int, col2 varchar(5), col_t3 int);
+insert into t1 values(10,'hello',10);
+insert into t1 values(20,'hello',20);
+insert into t1 values(30,'hello',30);
+insert into t1 values(10,'bye',10);
+insert into t1 values(10,'sam',10);
+insert into t1 values(10,'bob',10);
+insert into t2 select * from t1;
+insert into t3 select * from t1;
+select count(*) from t1 group by col1 having col1 = 10;
+count(*)
+4
+select count(*) as count_col1 from t1 group by col1 having col1 = 10;
+count_col1
+4
+select count(*) as count_col1 from t1 as tmp1 group by col1 having col1 = 10;
+count_col1
+4
+select count(*) from t1 group by col2 having col2 = 'hello';
+count(*)
+3
+select count(*) from t1 group by col2 having col1 = 10;
+ERROR 42S22: Unknown column 'col1' in 'having clause'
+select col1 as count_col1 from t1 as tmp1 group by col1 having col1 = 10;
+count_col1
+10
+select col1 as count_col1 from t1 as tmp1 group by col1 having count_col1 = 10;
+count_col1
+10
+select col1 as count_col1 from t1 as tmp1 group by count_col1 having col1 = 10;
+count_col1
+10
+select col1 as count_col1 from t1 as tmp1 group by count_col1 having count_col1 = 10;
+count_col1
+10
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col1 = 10;
+count_col1 col2
+10 bob
+10 bye
+10 hello
+10 sam
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having count_col1 = 10;
+count_col1 col2
+10 bob
+10 bye
+10 hello
+10 sam
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col2 = 'hello';
+count_col1 col2
+10 hello
+20 hello
+30 hello
+select col1 as count_col1,col2 as group_col2 from t1 as tmp1 group by col1,col2 having group_col2 = 'hello';
+count_col1 group_col2
+10 hello
+20 hello
+30 hello
+select sum(col1) as co12 from t1 group by col2 having col2 10;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '10' at line 1
+select sum(col1) as co2, count(col2) as cc from t1 group by col1 having col1 =10;
+co2 cc
+40 4
+select t2.col2 from t2 group by t2.col1, t2.col2 having t1.col1 <= 10;
+ERROR 42S22: Unknown column 't1.col1' in 'having clause'
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having t2.col1 <= 10);
+col1
+10
+20
+30
+10
+10
+10
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2
+having t2.col1 <=
+(select min(t3.col1) from t3));
+col1
+10
+20
+30
+10
+10
+10
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having t1.col1 <= 10);
+col1
+10
+10
+10
+10
+select t1.col1 as tmp_col from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having tmp_col <= 10);
+tmp_col
+10
+10
+10
+10
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having col_t1 <= 10);
+col1
+10
+10
+10
+10
+select sum(col1) from t1
+group by col_t1
+having (select col_t1 from t2 where col_t1 = col_t2 order by col_t2 limit 1);
+sum(col1)
+40
+20
+30
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having col_t1 <= 10)
+having col_t1 <= 20;
+ERROR 42S22: Unknown column 'col_t1' in 'having clause'
+select t1.col1 from t1
+where t1.col2 in
+(select t2.col2 from t2
+group by t2.col1, t2.col2 having col_t1 <= 10)
+group by col_t1
+having col_t1 <= 20;
+col1
+10
+select col_t1, sum(col1) from t1
+group by col_t1
+having col_t1 > 10 and
+exists (select sum(t2.col1) from t2
+group by t2.col2 having t2.col2 > 'b');
+col_t1 sum(col1)
+20 20
+30 30
+select sum(col1) from t1
+group by col_t1
+having col_t1 in (select sum(t2.col1) from t2
+group by t2.col2, t2.col1 having t2.col1 = t1.col1);
+ERROR 42S22: Unknown column 't1.col1' in 'having clause'
+select sum(col1) from t1
+group by col_t1
+having col_t1 in (select sum(t2.col1) from t2
+group by t2.col2, t2.col1 having t2.col1 = col_t1);
+sum(col1)
+40
+20
+30
+select t1.col1, t2.col1 from t1, t2 where t1.col1 = t2.col1
+group by t1.col1, t2.col1 having col1 = 2;
+ERROR 23000: Column 'col1' in having clause is ambiguous
+select t1.col1*10+t2.col1 from t1,t2 where t1.col1=t2.col1
+group by t1.col1, t2.col1 having col1 = 2;
+ERROR 23000: Column 'col1' in having clause is ambiguous
+drop table t1, t2, t3;
+create table t1 (s1 int);
+insert into t1 values (1),(2),(3);
+select count(*) from t1 group by s1 having s1 is null;
+count(*)
+select s1*0 as s1 from t1 group by s1 having s1 <> 0;
+s1
+0
+0
+0
+Warnings:
+Warning 1052 Column 's1' in having clause is ambiguous
+select s1*0 from t1 group by s1 having s1 = 0;
+s1*0
+select s1 from t1 group by 1 having 1 = 0;
+s1
+select count(s1) from t1 group by s1 having count(1+1)=2;
+count(s1)
+select count(s1) from t1 group by s1 having s1*0=0;
+count(s1)
+1
+1
+1
+select * from t1 a, t1 b group by a.s1 having s1 is null;
+ERROR 23000: Column 's1' in having clause is ambiguous
+drop table t1;
+create table t1 (s1 char character set latin1 collate latin1_german1_ci);
+insert into t1 values ('ü'),('y');
+Warnings:
+Warning 1265 Data truncated for column 's1' at row 1
+select s1,count(s1) from t1
+group by s1 collate latin1_swedish_ci having s1 = 'y';
+s1 count(s1)
+y 1
+drop table t1;
diff --git a/mysql-test/r/heap.result b/mysql-test/r/heap.result
index 0432faaab9d..7c4ce234d58 100644
--- a/mysql-test/r/heap.result
+++ b/mysql-test/r/heap.result
@@ -1,10 +1,10 @@
-drop table if exists t1;
+drop table if exists t1,t2,t3;
create table t1 (a int not null,b int not null, primary key (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
insert into t1 values(1,1),(2,2),(3,3),(4,4);
delete from t1 where a=1 or a=0;
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
-t1 0 PRIMARY 1 a NULL NULL NULL NULL HASH
+t1 0 PRIMARY 1 a NULL 3 NULL NULL HASH
select * from t1;
a b
2 2
@@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL btn NULL NULL NULL 11 Using where
explain select * from t1 where btn="a" and new_col="a";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref btn btn 11 const,const 10 Using where
+1 SIMPLE t1 ref btn btn 11 const,const 1 Using where
drop table t1;
CREATE TABLE t1 (
a int default NULL,
@@ -182,7 +182,7 @@ SELECT * FROM t1 WHERE a=NULL;
a b
explain SELECT * FROM t1 WHERE a IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 5 const 10 Using where
+1 SIMPLE t1 ref a a 5 const 1 Using where
SELECT * FROM t1 WHERE a<=>NULL;
a b
NULL 99
@@ -204,7 +204,7 @@ key a (a)
INSERT INTO t1 VALUES (10), (10), (10);
EXPLAIN SELECT * FROM t1 WHERE a=10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 5 const 10 Using where
+1 SIMPLE t1 ref a a 5 const 3 Using where
SELECT * FROM t1 WHERE a=10;
a
10
@@ -233,3 +233,435 @@ SELECT * FROM t1 WHERE B is not null;
a B
1 1
DROP TABLE t1;
+CREATE TABLE t1 (pseudo char(35) PRIMARY KEY, date int(10) unsigned NOT NULL) ENGINE=HEAP;
+INSERT INTO t1 VALUES ('massecot',1101106491),('altec',1101106492),('stitch+',1101106304),('Seb Corgan',1101106305),('beerfilou',1101106263),('flaker',1101106529),('joce8',5),('M4vrick',1101106418),('gabay008',1101106525),('Vamp irX',1101106291),('ZoomZip',1101106546),('rip666',1101106502),('CBP ',1101106397),('guezpard',1101106496);
+DELETE FROM t1 WHERE date<1101106546;
+SELECT * FROM t1;
+pseudo date
+ZoomZip 1101106546
+DROP TABLE t1;
+create table t1(a char(2)) engine=memory;
+insert into t1 values (NULL), (NULL);
+delete from t1 where a is null;
+insert into t1 values ('2'), ('3');
+select * from t1;
+a
+3
+2
+drop table t1;
+set storage_engine=HEAP;
+create table t1 (v varchar(10), c char(10), t varchar(50));
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Warning 1265 Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+ *+*+ *
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(50) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Warning 1265 Data truncated for column 't' at row 2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(10) default NULL
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+ *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL,
+ KEY `v` (`v`),
+ KEY `c` (`c`),
+ KEY `t` (`t`(10))
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where c='a ';
+count(*)
+10
+select count(*) from t1 where t='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const 9 Using where
+explain select count(*) from t1 where c='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c c 11 const 9 Using where
+explain select count(*) from t1 where t='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref t t 13 const 9 Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL v NULL NULL NULL 271 Using where
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*'));
+qq
+*a*a*a*
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const 9 Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(*) from t1 group by c limit 10;
+c count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(*) from t1 group by t limit 10;
+t count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a '),('a '),('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a ' where a like 'a ';
+update t1 set a='a ' where a like 'a ';
+drop table t1;
+create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using btree (c), key using btree (t(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL,
+ KEY `v` TYPE BTREE (`v`),
+ KEY `c` TYPE BTREE (`c`),
+ KEY `t` TYPE BTREE (`t`(10))
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where c='a ';
+count(*)
+10
+select count(*) from t1 where t='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const # Using where
+explain select count(*) from t1 where c='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c c 11 const # Using where
+explain select count(*) from t1 where t='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref t t 13 const # Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL # Using where
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*'));
+qq
+*a*a*a*
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const 7 Using where
+drop table t1;
+create table t1 (a char(10), unique using btree (a)) engine=heap;
+insert into t1 values ('a');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a '),('a '),('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a ' where a like 'a ';
+update t1 set a='a ' where a like 'a ';
+drop table t1;
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` varchar(50) default NULL,
+ KEY `v` (`v`(5)),
+ KEY `c` (`c`(5)),
+ KEY `t` (`t`(5))
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(65530) default NULL,
+ KEY `v` (`v`(10))
+) ENGINE=HEAP DEFAULT CHARSET=latin1
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+set storage_engine=MyISAM;
diff --git a/mysql-test/r/heap_hash.result b/mysql-test/r/heap_hash.result
index ba02328d1ba..287e17a264d 100644
--- a/mysql-test/r/heap_hash.result
+++ b/mysql-test/r/heap_hash.result
@@ -1,10 +1,10 @@
-drop table if exists t1;
+drop table if exists t1,t2;
create table t1 (a int not null,b int not null, primary key using HASH (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
insert into t1 values(1,1),(2,2),(3,3),(4,4);
delete from t1 where a=1 or a=0;
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
-t1 0 PRIMARY 1 a NULL NULL NULL NULL HASH
+t1 0 PRIMARY 1 a NULL 3 NULL NULL HASH
select * from t1;
a b
2 2
@@ -169,7 +169,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ALL btn NULL NULL NULL 11 Using where
explain select * from t1 where btn="a" and new_col="a";
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref btn btn 11 const,const 10 Using where
+1 SIMPLE t1 ref btn btn 11 const,const 1 Using where
drop table t1;
CREATE TABLE t1 (
a int default NULL,
@@ -182,7 +182,7 @@ SELECT * FROM t1 WHERE a=NULL;
a b
explain SELECT * FROM t1 WHERE a IS NULL;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref a a 5 const 10 Using where
+1 SIMPLE t1 ref a a 5 const 1 Using where
SELECT * FROM t1 WHERE a<=>NULL;
a b
NULL 99
@@ -203,3 +203,155 @@ DELETE from t1 where a < 100;
SELECT * from t1;
a
DROP TABLE t1;
+create table t1
+(
+a char(8) not null,
+b char(20) not null,
+c int not null,
+key (a)
+) engine=heap;
+insert into t1 values ('aaaa', 'prefill-hash=5',0);
+insert into t1 values ('aaab', 'prefill-hash=0',0);
+insert into t1 values ('aaac', 'prefill-hash=7',0);
+insert into t1 values ('aaad', 'prefill-hash=2',0);
+insert into t1 values ('aaae', 'prefill-hash=1',0);
+insert into t1 values ('aaaf', 'prefill-hash=4',0);
+insert into t1 values ('aaag', 'prefill-hash=3',0);
+insert into t1 values ('aaah', 'prefill-hash=6',0);
+explain select * from t1 where a='aaaa';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+explain select * from t1 where a='aaab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+explain select * from t1 where a='aaac';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+explain select * from t1 where a='aaad';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+insert into t1 select * from t1;
+explain select * from t1 where a='aaaa';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+explain select * from t1 where a='aaab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+explain select * from t1 where a='aaac';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+explain select * from t1 where a='aaad';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+flush tables;
+explain select * from t1 where a='aaaa';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 2 Using where
+explain select * from t1 where a='aaab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 2 Using where
+explain select * from t1 where a='aaac';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 2 Using where
+explain select * from t1 where a='aaad';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 2 Using where
+create table t2 as select * from t1;
+delete from t1;
+insert into t1 select * from t2;
+explain select * from t1 where a='aaaa';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+explain select * from t1 where a='aaab';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+explain select * from t1 where a='aaac';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+explain select * from t1 where a='aaad';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 8 const 1 Using where
+drop table t1, t2;
+create table t1 (
+id int unsigned not null primary key auto_increment,
+name varchar(20) not null,
+index heap_idx(name),
+index btree_idx using btree(name)
+) engine=heap;
+create table t2 (
+id int unsigned not null primary key auto_increment,
+name varchar(20) not null,
+index btree_idx using btree(name),
+index heap_idx(name)
+) engine=heap;
+insert into t1 (name) values ('Matt'), ('Lilu'), ('Corbin'), ('Carly'),
+('Suzy'), ('Hoppy'), ('Burrito'), ('Mimi'), ('Sherry'), ('Ben'), ('Phil'),
+('Emily'), ('Mike');
+insert into t2 select * from t1;
+explain select * from t1 where name='matt';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where
+explain select * from t2 where name='matt';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where
+explain select * from t1 where name='Lilu';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where
+explain select * from t2 where name='Lilu';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where
+explain select * from t1 where name='Phil';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where
+explain select * from t2 where name='Phil';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where
+explain select * from t1 where name='Lilu';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref heap_idx,btree_idx heap_idx 22 const 1 Using where
+explain select * from t2 where name='Lilu';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref btree_idx,heap_idx btree_idx 22 const 1 Using where
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+flush tables;
+select count(*) from t1 where name='Matt';
+count(*)
+7
+explain select * from t1 ignore index (btree_idx) where name='matt';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 id NULL 91 NULL NULL HASH
+t1 1 heap_idx 1 name NULL 13 NULL NULL HASH
+t1 1 btree_idx 1 name A NULL NULL NULL BTREE
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 id NULL 91 NULL NULL HASH
+t1 1 heap_idx 1 name NULL 13 NULL NULL HASH
+t1 1 btree_idx 1 name A NULL NULL NULL BTREE
+create table t3
+(
+a varchar(20) not null,
+b varchar(20) not null,
+key (a,b)
+) engine=heap;
+insert into t3 select name, name from t1;
+show index from t3;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t3 1 a 1 a NULL NULL NULL NULL HASH
+t3 1 a 2 b NULL 15 NULL NULL HASH
+show index from t3;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t3 1 a 1 a NULL NULL NULL NULL HASH
+t3 1 a 2 b NULL 15 NULL NULL HASH
+explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t3 ref a a 44 const,const 6 Using where
+1 SIMPLE t1 ref heap_idx heap_idx 22 const 7 Using where
+drop table t1, t2, t3;
diff --git a/mysql-test/r/index_merge_ror_cpk.result b/mysql-test/r/index_merge_ror_cpk.result
index 7acfb8dc93b..ba8efe42bd6 100644
--- a/mysql-test/r/index_merge_ror_cpk.result
+++ b/mysql-test/r/index_merge_ror_cpk.result
@@ -74,7 +74,7 @@ id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 index_merge PRIMARY,key1,pktail2ok pktail2ok,key1 8,4 NULL 199 Using sort_union(pktail2ok,key1); Using where
explain select * from t1 where pktail3bad=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref key1,pktail3bad pktail3bad 4 const 98 Using where
+1 SIMPLE t1 ref key1,pktail3bad pktail3bad 4 const ROWS Using where
explain select * from t1 where pktail4bad=1 and key1=10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref key1,pktail4bad pktail4bad 4 const 99 Using where
diff --git a/mysql-test/r/information_schema.result b/mysql-test/r/information_schema.result
new file mode 100644
index 00000000000..f716d90a073
--- /dev/null
+++ b/mysql-test/r/information_schema.result
@@ -0,0 +1,536 @@
+grant all privileges on test.* to mysqltest_1@localhost;
+select * from information_schema.SCHEMATA where schema_name > 'm';
+CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME SQL_PATH
+NULL mysql latin1 NULL
+NULL test latin1 NULL
+select schema_name from information_schema.schemata;
+schema_name
+mysql
+test
+show databases *;
+CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME SQL_PATH
+NULL mysql latin1 NULL
+NULL test latin1 NULL
+show databases like 't%';
+Database (t%)
+test
+show databases;
+Database
+mysql
+test
+show databases * where schema_name like 't%';
+CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME SQL_PATH
+NULL test latin1 NULL
+show databases * where schema_name = 't%';
+CATALOG_NAME SCHEMA_NAME DEFAULT_CHARACTER_SET_NAME SQL_PATH
+create database testtets;
+create table testtets.t1(a int, b VARCHAR(30), KEY string_data (b));
+create table test.t2(a int);
+create table t3(a int, KEY a_data (a));
+create table testtets.t4(a int);
+create view v1 (c) as select table_name from information_schema.TABLES;
+select * from v1;
+c
+columns_priv
+db
+func
+help_category
+help_keyword
+help_relation
+help_topic
+host
+proc
+tables_priv
+time_zone
+time_zone_leap_second
+time_zone_name
+time_zone_transition
+time_zone_transition_type
+user
+t2
+t3
+v1
+t1
+t4
+select c,table_name from v1
+left join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+c table_name
+tables_priv tables_priv
+time_zone time_zone
+time_zone_leap_second time_zone_leap_second
+time_zone_name time_zone_name
+time_zone_transition time_zone_transition
+time_zone_transition_type time_zone_transition_type
+t2 t2
+t3 t3
+t1 t1
+t4 t4
+select c, v2.table_name from v1
+right join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+c table_name
+tables_priv tables_priv
+time_zone time_zone
+time_zone_leap_second time_zone_leap_second
+time_zone_name time_zone_name
+time_zone_transition time_zone_transition
+time_zone_transition_type time_zone_transition_type
+t2 t2
+t3 t3
+t1 t1
+t4 t4
+select table_name from information_schema.TABLES
+where table_schema = "testtets" and table_name like "t%";
+table_name
+t1
+t4
+select * from information_schema.STATISTICS where TABLE_SCHEMA = "testtets";
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT
+NULL testtets t1 1 testtets string_data 1 b A NULL NULL NULL YES BTREE
+show keys * where TABLE_SCHEMA Like "test%";
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME NON_UNIQUE INDEX_SCHEMA INDEX_NAME SEQ_IN_INDEX COLUMN_NAME COLLATION CARDINALITY SUB_PART PACKED NULLABLE INDEX_TYPE COMMENT
+NULL test t3 1 test a_data 1 a A NULL NULL NULL YES BTREE
+NULL testtets t1 1 testtets string_data 1 b A NULL NULL NULL YES BTREE
+show keys where INDEX_NAME = "a_data";
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t3 1 a_data 1 a A NULL NULL NULL YES BTREE
+show tables like 't%';
+Tables_in_test (t%)
+t2
+t3
+show tables * from test where table_name like 't%';
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME TABLE_TYPE
+NULL test t2
+NULL test t3
+show table status;
+Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
+t2 MyISAM 9 Fixed 0 0 0 21474836479 1024 0 NULL # # NULL latin1_swedish_ci NULL
+t3 MyISAM 9 Fixed 0 0 0 21474836479 1024 0 NULL # # NULL latin1_swedish_ci NULL
+v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view
+show full columns from t3 like "a%";
+Field Type Collation Null Key Default Extra Privileges Comment
+a int(11) NULL YES MUL NULL select,insert,update,references
+show full columns from mysql.db like "Insert%";
+Field Type Collation Null Key Default Extra Privileges Comment
+Insert_priv enum('N','Y') utf8_bin N select,insert,update,references
+show full columns from v1;
+Field Type Collation Null Key Default Extra Privileges Comment
+c varchar(64) utf8_general_ci select,insert,update,references
+select * from information_schema.COLUMNS where table_name="t1"
+and column_name= "a";
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT
+NULL testtets t1 a 1 NULL YES int 11 11 11 0 NULL NULL int(11) select,insert,update,references
+show columns * where table_name = "t1";
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION COLUMN_DEFAULT IS_NULLABLE DATA_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE CHARACTER_SET_NAME COLLATION_NAME COLUMN_TYPE COLUMN_KEY EXTRA PRIVILEGES COLUMN_COMMENT
+NULL testtets t1 a 1 NULL YES int 11 11 11 0 NULL NULL int(11) select,insert,update,references
+NULL testtets t1 b 2 NULL YES varchar 30 30 NULL NULL latin1 latin1_swedish_ci varchar(30) MUL select,insert,update,references
+drop view v1;
+drop tables testtets.t4, testtets.t1, t2, t3;
+drop database testtets;
+select * from information_schema.CHARACTER_SETS
+where CHARACTER_SET_NAME like 'latin1%';
+CHARACTER_SET_NAME DESCRIPTION DEFAULT_COLLATE_NAME MAXLEN
+latin1 ISO 8859-1 West European latin1_swedish_ci 1
+SHOW CHARACTER SET LIKE 'latin1%';
+Charset Description Default collation Maxlen
+latin1 ISO 8859-1 West European latin1_swedish_ci 1
+SHOW CHARACTER SET * LIKE 'latin1%';
+CHARACTER_SET_NAME DESCRIPTION DEFAULT_COLLATE_NAME MAXLEN
+latin1 ISO 8859-1 West European latin1_swedish_ci 1
+SHOW CHARACTER SET WHERE CHARACTER_SET_NAME like 'latin1%';
+Charset Description Default collation Maxlen
+latin1 ISO 8859-1 West European latin1_swedish_ci 1
+SHOW CHARACTER SET CHARACTER_SET_NAME WHERE CHARACTER_SET_NAME like 'latin1%';
+CHARACTER_SET_NAME
+latin1
+SHOW CHARACTER SET * WHERE CHARACTER_SET_NAME like 'latin1%';
+CHARACTER_SET_NAME DESCRIPTION DEFAULT_COLLATE_NAME MAXLEN
+latin1 ISO 8859-1 West European latin1_swedish_ci 1
+select * from information_schema.COLLATIONS
+where COLLATION_NAME like 'latin1%';
+COLLATION_NAME CHARSET ID DEFAULT COMPILED SORTLEN
+latin1_german1_ci latin1 5 0
+latin1_swedish_ci latin1 8 Yes Yes 1
+latin1_danish_ci latin1 15 0
+latin1_german2_ci latin1 31 Yes 2
+latin1_bin latin1 47 Yes 1
+latin1_general_ci latin1 48 0
+latin1_general_cs latin1 49 0
+latin1_spanish_ci latin1 94 0
+SHOW COLLATION LIKE 'latin1%';
+Collation Charset Id Default Compiled Sortlen
+latin1_german1_ci latin1 5 0
+latin1_swedish_ci latin1 8 Yes Yes 1
+latin1_danish_ci latin1 15 0
+latin1_german2_ci latin1 31 Yes 2
+latin1_bin latin1 47 Yes 1
+latin1_general_ci latin1 48 0
+latin1_general_cs latin1 49 0
+latin1_spanish_ci latin1 94 0
+SHOW COLLATION * LIKE 'latin1%';
+COLLATION_NAME CHARSET ID DEFAULT COMPILED SORTLEN
+latin1_german1_ci latin1 5 0
+latin1_swedish_ci latin1 8 Yes Yes 1
+latin1_danish_ci latin1 15 0
+latin1_german2_ci latin1 31 Yes 2
+latin1_bin latin1 47 Yes 1
+latin1_general_ci latin1 48 0
+latin1_general_cs latin1 49 0
+latin1_spanish_ci latin1 94 0
+SHOW COLLATION WHERE COLLATION_NAME like 'latin1%';
+Collation Charset Id Default Compiled Sortlen
+latin1_german1_ci latin1 5 0
+latin1_swedish_ci latin1 8 Yes Yes 1
+latin1_danish_ci latin1 15 0
+latin1_german2_ci latin1 31 Yes 2
+latin1_bin latin1 47 Yes 1
+latin1_general_ci latin1 48 0
+latin1_general_cs latin1 49 0
+latin1_spanish_ci latin1 94 0
+SHOW COLLATION COLLATION_NAME WHERE COLLATION_NAME like 'latin1%';
+COLLATION_NAME
+latin1_german1_ci
+latin1_swedish_ci
+latin1_danish_ci
+latin1_german2_ci
+latin1_bin
+latin1_general_ci
+latin1_general_cs
+latin1_spanish_ci
+SHOW COLLATION * WHERE COLLATION_NAME like 'latin1%';
+COLLATION_NAME CHARSET ID DEFAULT COMPILED SORTLEN
+latin1_german1_ci latin1 5 0
+latin1_swedish_ci latin1 8 Yes Yes 1
+latin1_danish_ci latin1 15 0
+latin1_german2_ci latin1 31 Yes 2
+latin1_bin latin1 47 Yes 1
+latin1_general_ci latin1 48 0
+latin1_general_cs latin1 49 0
+latin1_spanish_ci latin1 94 0
+select * from information_schema.COLLATION_CHARACTER_SET_APPLICABILITY
+where COLLATION_NAME like 'latin1%';
+COLLATION_NAME CHARACTER_SET_NAME
+latin1_german1_ci latin1
+latin1_swedish_ci latin1
+latin1_danish_ci latin1
+latin1_german2_ci latin1
+latin1_bin latin1
+latin1_general_ci latin1
+latin1_general_cs latin1
+latin1_spanish_ci latin1
+create function sub1(i int) returns int
+return i+1;
+create procedure sel2()
+begin
+select * from t1;
+select * from t2;
+end|
+show procedure status;
+Db Name Type Definer Modified Created Security_type Comment
+test sel2 PROCEDURE root@localhost # # DEFINER
+show function status;
+Db Name Type Definer Modified Created Security_type Comment
+test sub1 FUNCTION root@localhost # # DEFINER
+select a.ROUTINE_NAME from information_schema.ROUTINES a,
+information_schema.SCHEMATA b where
+a.ROUTINE_SCHEMA = b.SCHEMA_NAME;
+ROUTINE_NAME
+sel2
+sub1
+explain select a.ROUTINE_NAME from information_schema.ROUTINES a,
+information_schema.SCHEMATA b where
+a.ROUTINE_SCHEMA = b.SCHEMA_NAME;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE # ALL NULL NULL NULL NULL 2
+1 SIMPLE # ALL NULL NULL NULL NULL 2 Using where
+select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a,
+mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8);
+ROUTINE_NAME name
+sub1 sub1
+sel2 sel2
+select count(*) from information_schema.ROUTINES;
+count(*)
+2
+create view v0 (c) as select schema_name from information_schema.schemata;
+select * from v0;
+c
+mysql
+test
+explain select * from v0;
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY # ALL NULL NULL NULL NULL 2
+create view v1 (c) as select table_name from information_schema.tables
+where table_name="v1";
+select * from v1;
+c
+v1
+create view v2 (c) as select column_name from information_schema.columns
+where table_name="v2";
+select * from v2;
+c
+c
+create view v3 (c) as select CHARACTER_SET_NAME from information_schema.character_sets
+where CHARACTER_SET_NAME like "latin1%";
+select * from v3;
+c
+latin1
+create view v4 (c) as select COLLATION_NAME from information_schema.collations
+where COLLATION_NAME like "latin1%";
+select * from v4;
+c
+latin1_german1_ci
+latin1_swedish_ci
+latin1_danish_ci
+latin1_german2_ci
+latin1_bin
+latin1_general_ci
+latin1_general_cs
+latin1_spanish_ci
+show keys from v4;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+select * from information_schema.views where TABLE_NAME like "v%";
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE
+NULL test v0 select `schemata`.`SCHEMA_NAME` AS `c` from `information_schema`.`schemata` NONE NO
+NULL test v1 select `tables`.`TABLE_NAME` AS `c` from `information_schema`.`tables` where (`tables`.`TABLE_NAME` = _utf8'v1') NONE NO
+NULL test v2 select `columns`.`COLUMN_NAME` AS `c` from `information_schema`.`columns` where (`columns`.`TABLE_NAME` = _utf8'v2') NONE NO
+NULL test v3 select `character_sets`.`CHARACTER_SET_NAME` AS `c` from `information_schema`.`character_sets` where (`character_sets`.`CHARACTER_SET_NAME` like _utf8'latin1%') NONE NO
+NULL test v4 select `collations`.`COLLATION_NAME` AS `c` from `information_schema`.`collations` where (`collations`.`COLLATION_NAME` like _utf8'latin1%') NONE NO
+drop view v0, v1, v2, v3, v4;
+create table t1 (a int);
+grant select,update,insert on t1 to mysqltest_1@localhost;
+grant select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
+grant all on test.* to mysqltest_1@localhost with grant option;
+select * from information_schema.USER_PRIVILEGES where grantee like '%mysqltest_1%';
+GRANTEE TABLE_CATALOG PRIVILEGE_TYPE IS_GRANTABLE
+'mysqltest_1'@'localhost' NULL USAGE NO
+select * from information_schema.SCHEMA_PRIVILEGES where grantee like '%mysqltest_1%';
+GRANTEE TABLE_CATALOG TABLE_SCHEMA PRIVILEGE_TYPE IS_GRANTABLE
+'mysqltest_1'@'localhost' NULL test SELECT YES
+'mysqltest_1'@'localhost' NULL test INSERT YES
+'mysqltest_1'@'localhost' NULL test UPDATE YES
+'mysqltest_1'@'localhost' NULL test DELETE YES
+'mysqltest_1'@'localhost' NULL test CREATE YES
+'mysqltest_1'@'localhost' NULL test DROP YES
+'mysqltest_1'@'localhost' NULL test REFERENCES YES
+'mysqltest_1'@'localhost' NULL test INDEX YES
+'mysqltest_1'@'localhost' NULL test ALTER YES
+'mysqltest_1'@'localhost' NULL test CREATE TEMPORARY TABLES YES
+'mysqltest_1'@'localhost' NULL test LOCK TABLES YES
+'mysqltest_1'@'localhost' NULL test CREATE VIEW YES
+'mysqltest_1'@'localhost' NULL test SHOW VIEW YES
+select * from information_schema.TABLE_PRIVILEGES where grantee like '%mysqltest_1%';
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'mysqltest_1'@'localhost' NULL test t1 SELECT NO
+'mysqltest_1'@'localhost' NULL test t1 INSERT NO
+'mysqltest_1'@'localhost' NULL test t1 UPDATE NO
+select * from information_schema.COLUMN_PRIVILEGES where grantee like '%mysqltest_1%';
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'mysqltest_1'@'localhost' NULL test t1 a SELECT NO
+'mysqltest_1'@'localhost' NULL test t1 a INSERT NO
+'mysqltest_1'@'localhost' NULL test t1 a UPDATE NO
+'mysqltest_1'@'localhost' NULL test t1 a REFERENCES NO
+delete from mysql.user where user='mysqltest_1';
+delete from mysql.db where user='mysqltest_1';
+delete from mysql.tables_priv where user='mysqltest_1';
+delete from mysql.columns_priv where user='mysqltest_1';
+flush privileges;
+drop table t1;
+create table t1 (a int null, primary key(a));
+alter table t1 add constraint constraint_1 unique (a);
+alter table t1 add constraint unique key_1(a);
+alter table t1 add constraint constraint_2 unique key_2(a);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) NOT NULL default '0',
+ PRIMARY KEY (`a`),
+ UNIQUE KEY `constraint_1` (`a`),
+ UNIQUE KEY `key_1` (`a`),
+ UNIQUE KEY `key_2` (`a`)
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_SCHEMA= "test";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE CONSTRAINT_METHOD
+NULL test PRIMARY test t1 PRIMARY KEY NULL
+NULL test constraint_1 test t1 UNIQUE NULL
+NULL test key_1 test t1 UNIQUE NULL
+NULL test key_2 test t1 UNIQUE NULL
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_SCHEMA= "test";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME
+NULL test PRIMARY NULL test t1 a 1 NULL NULL NULL
+NULL test constraint_1 NULL test t1 a 1 NULL NULL NULL
+NULL test key_1 NULL test t1 a 1 NULL NULL NULL
+NULL test key_2 NULL test t1 a 1 NULL NULL NULL
+select table_name from information_schema.TABLES where table_schema like "test%";
+table_name
+t1
+select table_name,column_name from information_schema.COLUMNS where table_schema like "test%";
+table_name column_name
+t1 a
+select ROUTINE_NAME from information_schema.ROUTINES;
+ROUTINE_NAME
+sel2
+sub1
+delete from mysql.user where user='mysqltest_1';
+drop table t1;
+drop procedure sel2;
+drop function sub1;
+create table t1(a int);
+create view v1 (c) as select a from t1 with check option;
+create view v2 (c) as select a from t1 WITH LOCAL CHECK OPTION;
+create view v3 (c) as select a from t1 WITH CASCADED CHECK OPTION;
+select * from information_schema.views;
+TABLE_CATALOG TABLE_SCHEMA TABLE_NAME VIEW_DEFINITION CHECK_OPTION IS_UPDATABLE
+NULL test v1 select `test`.`t1`.`a` AS `c` from `test`.`t1` WITH CASCADED CHECK OPTION YES
+NULL test v2 select `test`.`t1`.`a` AS `c` from `test`.`t1` WITH LOCAL CHECK OPTION YES
+NULL test v3 select `test`.`t1`.`a` AS `c` from `test`.`t1` WITH CASCADED CHECK OPTION YES
+grant select (a) on test.t1 to joe@localhost with grant option;
+select * from INFORMATION_SCHEMA.COLUMN_PRIVILEGES;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'joe'@'localhost' NULL test t1 a SELECT YES
+select * from INFORMATION_SCHEMA.TABLE_PRIVILEGES;
+GRANTEE TABLE_CATALOG TABLE_SCHEMA TABLE_NAME PRIVILEGE_TYPE IS_GRANTABLE
+'joe'@'localhost' NULL test t1 USAGE YES
+drop view v1, v2, v3;
+drop table t1;
+delete from mysql.user where user='joe';
+delete from mysql.db where user='joe';
+delete from mysql.tables_priv where user='joe';
+delete from mysql.columns_priv where user='joe';
+flush privileges;
+create procedure px5 ()
+begin
+declare v int;
+declare c cursor for select version from
+information_schema.tables;
+open c;
+fetch c into v;
+select v;
+close c;
+end;//
+call px5()//
+v
+9
+call px5()//
+v
+9
+select sql_mode from information_schema.ROUTINES;
+sql_mode
+
+drop procedure px5;
+create table t1 (a int not null auto_increment,b int, primary key (a));
+insert into t1 values (1,1),(NULL,3),(NULL,4);
+select AUTO_INCREMENT from information_schema.tables where table_name = 't1';
+AUTO_INCREMENT
+4
+drop table t1;
+create table t1 (s1 int);
+insert into t1 values (0),(9),(0);
+select s1 from t1 where s1 in (select version from
+information_schema.tables) union select version from
+information_schema.tables;
+s1
+9
+10
+drop table t1;
+SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
+Table Create Table
+character_sets CREATE TEMPORARY TABLE `character_sets` (
+ `CHARACTER_SET_NAME` varchar(30) NOT NULL default '',
+ `DESCRIPTION` varchar(60) NOT NULL default '',
+ `DEFAULT_COLLATE_NAME` varchar(60) NOT NULL default '',
+ `MAXLEN` bigint(3) NOT NULL default '0'
+) ENGINE=HEAP DEFAULT CHARSET=utf8 MAX_ROWS=2252
+set names latin2;
+SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
+Table Create Table
+character_sets CREATE TEMPORARY TABLE `character_sets` (
+ `CHARACTER_SET_NAME` varchar(30) NOT NULL default '',
+ `DESCRIPTION` varchar(60) NOT NULL default '',
+ `DEFAULT_COLLATE_NAME` varchar(60) NOT NULL default '',
+ `MAXLEN` bigint(3) NOT NULL default '0'
+) ENGINE=HEAP DEFAULT CHARSET=utf8 MAX_ROWS=2252
+set names latin1;
+create table t1 select * from information_schema.CHARACTER_SETS
+where CHARACTER_SET_NAME like "latin1";
+select * from t1;
+CHARACTER_SET_NAME DESCRIPTION DEFAULT_COLLATE_NAME MAXLEN
+latin1 ISO 8859-1 West European latin1_swedish_ci 1
+alter table t1 default character set utf8;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `CHARACTER_SET_NAME` varchar(30) NOT NULL default '',
+ `DESCRIPTION` varchar(60) NOT NULL default '',
+ `DEFAULT_COLLATE_NAME` varchar(60) NOT NULL default '',
+ `MAXLEN` bigint(3) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=utf8
+drop table t1;
+create view v1 as select * from information_schema.TABLES;
+drop view v1;
+create table t1(a NUMERIC(5,3), b NUMERIC(5,1), c float(5,2),
+d NUMERIC(6,4), e float, f DECIMAL(6,3), g int(11), h DOUBLE(10,3),
+i DOUBLE);
+select COLUMN_NAME,COLUMN_TYPE, CHARACTER_MAXIMUM_LENGTH,
+CHARACTER_OCTET_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE
+from information_schema.columns where table_name= 't1';
+COLUMN_NAME COLUMN_TYPE CHARACTER_MAXIMUM_LENGTH CHARACTER_OCTET_LENGTH NUMERIC_PRECISION NUMERIC_SCALE
+a decimal(5,3) 7 7 5 3
+b decimal(5,1) 7 7 5 1
+c float(5,2) 5 5 5 2
+d decimal(6,4) 8 8 6 4
+e float 12 12 12 NULL
+f decimal(6,3) 8 8 6 3
+g int(11) 11 11 11 0
+h double(10,3) 10 10 10 3
+i double 22 22 22 NULL
+drop table t1;
+create table t115 as select table_name, column_name, column_type
+from information_schema.columns where table_name = 'proc';
+select * from t115;
+table_name column_name column_type
+proc db char(64)
+proc name char(64)
+proc type enum('FUNCTION','PROCEDURE')
+proc specific_name char(64)
+proc language enum('SQL')
+proc sql_data_access enum('CONTAINS_SQL','NO_SQL','READS_SQL_DATA','MODIFIES_SQL_DATA')
+proc is_deterministic enum('YES','NO')
+proc security_type enum('INVOKER','DEFINER')
+proc param_list blob
+proc returns char(64)
+proc body blob
+proc definer char(77)
+proc created timestamp
+proc modified timestamp
+proc sql_mode set('REAL_AS_FLOAT','PIPES_AS_CONCAT','ANSI_QUOTES','IGNORE_SPACE','NOT_USED','ONLY_FULL_GROUP_BY','NO_UNSIGNED_SUBTRACTION','NO_DIR_IN_CREATE','POSTGRESQL','ORACLE','MSSQL','DB2','MAXDB','NO_KEY_OPTIONS','NO_TABLE_OPTIONS','NO_FIELD_OPTIONS','MYSQL323','MYSQL40','ANSI','NO_AUTO_VALUE_ON_ZERO')
+proc comment char(64)
+drop table t115;
+create view vk as select count(*) from information_schema.tables a;
+select * from vk;
+count(*)
+17
+drop view vk;
+create procedure p108 () begin declare c cursor for select data_type
+from information_schema.columns; open c; open c; end;//
+call p108()//
+ERROR 24000: Cursor is already open
+drop procedure p108;
+create view v1 as select A1.table_name from information_schema.TABLES A1
+where table_name= "user";
+select * from v1;
+table_name
+user
+drop view v1;
+create view vo as select 'a' union select 'a';
+show index from vo;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_NAME= "vo";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE CONSTRAINT_METHOD
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_NAME= "vo";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME
+drop view vo;
diff --git a/mysql-test/r/information_schema_inno.result b/mysql-test/r/information_schema_inno.result
new file mode 100644
index 00000000000..e6dcda2c15d
--- /dev/null
+++ b/mysql-test/r/information_schema_inno.result
@@ -0,0 +1,19 @@
+CREATE TABLE t1 (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id),
+FOREIGN KEY (t1_id) REFERENCES t1(id) ON DELETE CASCADE,
+FOREIGN KEY (t1_id) REFERENCES t1(id) ON UPDATE CASCADE) ENGINE=INNODB;
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_SCHEMA= "test";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_SCHEMA TABLE_NAME CONSTRAINT_TYPE CONSTRAINT_METHOD
+NULL test PRIMARY test t1 PRIMARY KEY NULL
+NULL test PRIMARY test t2 PRIMARY KEY NULL
+NULL test t2_ibfk_1 test t2 FOREIGN KEY ON DELETE CASCADE
+NULL test t2_ibfk_2 test t2 FOREIGN KEY ON UPDATE CASCADE
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_SCHEMA= "test";
+CONSTRAINT_CATALOG CONSTRAINT_SCHEMA CONSTRAINT_NAME TABLE_CATALOG TABLE_SCHEMA TABLE_NAME COLUMN_NAME ORDINAL_POSITION REFERENCED_TABLE_SCHEMA REFERENCED_TABLE_NAME REFERENCED_COLUMN_NAME
+NULL test PRIMARY NULL test t1 id 1 NULL NULL NULL
+NULL test PRIMARY NULL test t2 id 1 NULL NULL NULL
+NULL test t2_ibfk_1 NULL test t2 t1_id 1 NULL id
+NULL test t2_ibfk_2 NULL test t2 t1_id 1 NULL id
+drop table t2, t1;
diff --git a/mysql-test/r/innodb.result b/mysql-test/r/innodb.result
index 40767a40b82..60028763b17 100644
--- a/mysql-test/r/innodb.result
+++ b/mysql-test/r/innodb.result
@@ -1421,19 +1421,19 @@ insert t2 select * from t1;
insert t3 select * from t1;
checksum table t1, t2, t3, t4 quick;
Table Checksum
-test.t1 968604391
+test.t1 272226711
test.t2 NULL
test.t3 NULL
test.t4 NULL
checksum table t1, t2, t3, t4;
Table Checksum
-test.t1 968604391
+test.t1 272226711
test.t2 968604391
test.t3 968604391
test.t4 NULL
checksum table t1, t2, t3, t4 extended;
Table Checksum
-test.t1 968604391
+test.t1 272226711
test.t2 968604391
test.t3 968604391
test.t4 NULL
@@ -1664,3 +1664,41 @@ select count(*) from t1 where x = 18446744073709551601;
count(*)
1
drop table t1;
+create table t1 (c char(10), index (c,c)) engine=innodb;
+ERROR 42S21: Duplicate column name 'c'
+create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1)) engine=innodb;
+ERROR 42S21: Duplicate column name 'c1'
+create table t1 (c1 char(10), c2 char(10), index (c1,c1,c2)) engine=innodb;
+ERROR 42S21: Duplicate column name 'c1'
+create table t1 (c1 char(10), c2 char(10), index (c2,c1,c1)) engine=innodb;
+ERROR 42S21: Duplicate column name 'c1'
+create table t1 (c1 char(10), c2 char(10)) engine=innodb;
+alter table t1 add key (c1,c1);
+ERROR 42S21: Duplicate column name 'c1'
+alter table t1 add key (c2,c1,c1);
+ERROR 42S21: Duplicate column name 'c1'
+alter table t1 add key (c1,c2,c1);
+ERROR 42S21: Duplicate column name 'c1'
+alter table t1 add key (c1,c1,c2);
+ERROR 42S21: Duplicate column name 'c1'
+drop table t1;
+show status like "Innodb_buffer_pool_pages_total";
+Variable_name Value
+Innodb_buffer_pool_pages_total 512
+show status like "Innodb_page_size";
+Variable_name Value
+Innodb_page_size 16384
+show status like "Innodb_rows_deleted";
+Variable_name Value
+Innodb_rows_deleted 2078
+show status like "Innodb_rows_inserted";
+Variable_name Value
+Innodb_rows_inserted 31706
+show status like "Innodb_rows_read";
+Variable_name Value
+Innodb_rows_read 80161
+show status like "Innodb_rows_updated";
+Variable_name Value
+Innodb_rows_updated 29530
+create table t1 (v varchar(16384)) engine=innodb;
+ERROR 42000: Column length too big for column 'v' (max = 255); use BLOB instead
diff --git a/mysql-test/r/innodb.result.es b/mysql-test/r/innodb.result.es
new file mode 100644
index 00000000000..602a034bc16
--- /dev/null
+++ b/mysql-test/r/innodb.result.es
@@ -0,0 +1,1653 @@
+drop table if exists t1,t2,t3,t4;
+drop database if exists mysqltest;
+create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) engine=innodb;
+insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David'), (2, 'Erik'), (3, 'Sasha'), (3, 'Jeremy'), (4, 'Matt');
+select id, code, name from t1 order by id;
+id code name
+1 1 Tim
+2 1 Monty
+3 2 David
+4 2 Erik
+5 3 Sasha
+6 3 Jeremy
+7 4 Matt
+update ignore t1 set id = 8, name = 'Sinisa' where id < 3;
+select id, code, name from t1 order by id;
+id code name
+2 1 Monty
+3 2 David
+4 2 Erik
+5 3 Sasha
+6 3 Jeremy
+7 4 Matt
+8 1 Sinisa
+update ignore t1 set id = id + 10, name = 'Ralph' where id < 4;
+select id, code, name from t1 order by id;
+id code name
+3 2 David
+4 2 Erik
+5 3 Sasha
+6 3 Jeremy
+7 4 Matt
+8 1 Sinisa
+12 1 Ralph
+drop table t1;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+parent_id int(11) DEFAULT '0' NOT NULL,
+level tinyint(4) DEFAULT '0' NOT NULL,
+PRIMARY KEY (id),
+KEY parent_id (parent_id),
+KEY level (level)
+) engine=innodb;
+INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),(24,4,2),(28,5,2),(29,5,2),(30,5,2),(31,6,2),(32,6,2),(33,6,2),(203,7,2),(202,7,2),(20,3,2),(157,0,0),(193,5,2),(40,7,2),(2,1,1),(15,2,2),(6,1,1),(34,6,2),(35,6,2),(16,3,2),(7,1,1),(36,7,2),(18,3,2),(26,5,2),(27,5,2),(183,4,2),(38,7,2),(25,5,2),(37,7,2),(21,4,2),(19,3,2),(5,1,1),(179,5,2);
+update t1 set parent_id=parent_id+100;
+select * from t1 where parent_id=102;
+id parent_id level
+8 102 2
+9 102 2
+15 102 2
+update t1 set id=id+1000;
+update t1 set id=1024 where id=1009;
+Got one of the listed errors
+select * from t1;
+id parent_id level
+1001 100 0
+1002 101 1
+1003 101 1
+1004 101 1
+1005 101 1
+1006 101 1
+1007 101 1
+1008 102 2
+1009 102 2
+1015 102 2
+1016 103 2
+1017 103 2
+1018 103 2
+1019 103 2
+1020 103 2
+1021 104 2
+1022 104 2
+1024 104 2
+1025 105 2
+1026 105 2
+1027 105 2
+1028 105 2
+1029 105 2
+1030 105 2
+1031 106 2
+1032 106 2
+1033 106 2
+1034 106 2
+1035 106 2
+1036 107 2
+1037 107 2
+1038 107 2
+1040 107 2
+1157 100 0
+1179 105 2
+1183 104 2
+1193 105 2
+1202 107 2
+1203 107 2
+update ignore t1 set id=id+1;
+select * from t1;
+id parent_id level
+1001 100 0
+1002 101 1
+1003 101 1
+1004 101 1
+1005 101 1
+1006 101 1
+1007 101 1
+1008 102 2
+1010 102 2
+1015 102 2
+1016 103 2
+1017 103 2
+1018 103 2
+1019 103 2
+1020 103 2
+1021 104 2
+1023 104 2
+1024 104 2
+1025 105 2
+1026 105 2
+1027 105 2
+1028 105 2
+1029 105 2
+1030 105 2
+1031 106 2
+1032 106 2
+1033 106 2
+1034 106 2
+1035 106 2
+1036 107 2
+1037 107 2
+1039 107 2
+1041 107 2
+1158 100 0
+1180 105 2
+1184 104 2
+1194 105 2
+1202 107 2
+1204 107 2
+update ignore t1 set id=1023 where id=1010;
+select * from t1 where parent_id=102;
+id parent_id level
+1008 102 2
+1010 102 2
+1015 102 2
+explain select level from t1 where level=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const # Using where; Using index
+explain select level,id from t1 where level=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const # Using where; Using index
+explain select level,id,parent_id from t1 where level=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const # Using where
+select level,id from t1 where level=1;
+level id
+1 1002
+1 1003
+1 1004
+1 1005
+1 1006
+1 1007
+select level,id,parent_id from t1 where level=1;
+level id parent_id
+1 1002 101
+1 1003 101
+1 1004 101
+1 1005 101
+1 1006 101
+1 1007 101
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 id A # NULL NULL BTREE
+t1 1 parent_id 1 parent_id A # NULL NULL BTREE
+t1 1 level 1 level A # NULL NULL BTREE
+drop table t1;
+CREATE TABLE t1 (
+gesuchnr int(11) DEFAULT '0' NOT NULL,
+benutzer_id int(11) DEFAULT '0' NOT NULL,
+PRIMARY KEY (gesuchnr,benutzer_id)
+) engine=innodb;
+replace into t1 (gesuchnr,benutzer_id) values (2,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+replace into t1 (gesuchnr,benutzer_id) values (1,1);
+select * from t1;
+gesuchnr benutzer_id
+1 1
+2 1
+drop table t1;
+create table t1 (a int) engine=innodb;
+insert into t1 values (1), (2);
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+delete from t1 where a = 1;
+select * from t1;
+a
+2
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
+create table t1 (a int,b varchar(20)) engine=innodb;
+insert into t1 values (1,""), (2,"testing");
+delete from t1 where a = 1;
+select * from t1;
+a b
+2 testing
+create index skr on t1 (a);
+insert into t1 values (3,""), (4,"testing");
+analyze table t1;
+Table Op Msg_type Msg_text
+test.t1 analyze status OK
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 1 skr 1 a A # NULL NULL YES BTREE
+drop table t1;
+create table t1 (a int,b varchar(20),key(a)) engine=innodb;
+insert into t1 values (1,""), (2,"testing");
+select * from t1 where a = 1;
+a b
+1
+drop table t1;
+create table t1 (n int not null primary key) engine=innodb;
+set autocommit=0;
+insert into t1 values (4);
+rollback;
+select n, "after rollback" from t1;
+n after rollback
+insert into t1 values (4);
+commit;
+select n, "after commit" from t1;
+n after commit
+4 after commit
+commit;
+insert into t1 values (5);
+insert into t1 values (4);
+ERROR 23000: Duplicate entry '4' for key 1
+commit;
+select n, "after commit" from t1;
+n after commit
+4 after commit
+5 after commit
+set autocommit=1;
+insert into t1 values (6);
+insert into t1 values (4);
+ERROR 23000: Duplicate entry '4' for key 1
+select n from t1;
+n
+4
+5
+6
+rollback;
+drop table t1;
+create table t1 (n int not null primary key) engine=innodb;
+start transaction;
+insert into t1 values (4);
+flush tables with read lock;
+commit;
+unlock tables;
+commit;
+select * from t1;
+n
+4
+drop table t1;
+create table t1 ( id int NOT NULL PRIMARY KEY, nom varchar(64)) engine=innodb;
+begin;
+insert into t1 values(1,'hamdouni');
+select id as afterbegin_id,nom as afterbegin_nom from t1;
+afterbegin_id afterbegin_nom
+1 hamdouni
+rollback;
+select id as afterrollback_id,nom as afterrollback_nom from t1;
+afterrollback_id afterrollback_nom
+set autocommit=0;
+insert into t1 values(2,'mysql');
+select id as afterautocommit0_id,nom as afterautocommit0_nom from t1;
+afterautocommit0_id afterautocommit0_nom
+2 mysql
+rollback;
+select id as afterrollback_id,nom as afterrollback_nom from t1;
+afterrollback_id afterrollback_nom
+set autocommit=1;
+drop table t1;
+CREATE TABLE t1 (id char(8) not null primary key, val int not null) engine=innodb;
+insert into t1 values ('pippo', 12);
+insert into t1 values ('pippo', 12);
+ERROR 23000: Duplicate entry 'pippo' for key 1
+delete from t1;
+delete from t1 where id = 'pippo';
+select * from t1;
+id val
+insert into t1 values ('pippo', 12);
+set autocommit=0;
+delete from t1;
+rollback;
+select * from t1;
+id val
+pippo 12
+delete from t1;
+commit;
+select * from t1;
+id val
+drop table t1;
+create table t1 (a integer) engine=innodb;
+start transaction;
+rename table t1 to t2;
+create table t1 (b integer) engine=innodb;
+insert into t1 values (1);
+rollback;
+drop table t1;
+rename table t2 to t1;
+drop table t1;
+set autocommit=1;
+CREATE TABLE t1 (ID INTEGER NOT NULL PRIMARY KEY, NAME VARCHAR(64)) ENGINE=innodb;
+INSERT INTO t1 VALUES (1, 'Jochen');
+select * from t1;
+ID NAME
+1 Jochen
+drop table t1;
+CREATE TABLE t1 ( _userid VARCHAR(60) NOT NULL PRIMARY KEY) ENGINE=innodb;
+set autocommit=0;
+INSERT INTO t1 SET _userid='marc@anyware.co.uk';
+COMMIT;
+SELECT * FROM t1;
+_userid
+marc@anyware.co.uk
+SELECT _userid FROM t1 WHERE _userid='marc@anyware.co.uk';
+_userid
+marc@anyware.co.uk
+drop table t1;
+set autocommit=1;
+CREATE TABLE t1 (
+user_id int(10) DEFAULT '0' NOT NULL,
+name varchar(100),
+phone varchar(100),
+ref_email varchar(100) DEFAULT '' NOT NULL,
+detail varchar(200),
+PRIMARY KEY (user_id,ref_email)
+)engine=innodb;
+INSERT INTO t1 VALUES (10292,'sanjeev','29153373','sansh777@hotmail.com','xxx'),(10292,'shirish','2333604','shirish@yahoo.com','ddsds'),(10292,'sonali','323232','sonali@bolly.com','filmstar');
+select * from t1 where user_id=10292;
+user_id name phone ref_email detail
+10292 sanjeev 29153373 sansh777@hotmail.com xxx
+10292 shirish 2333604 shirish@yahoo.com ddsds
+10292 sonali 323232 sonali@bolly.com filmstar
+INSERT INTO t1 VALUES (10291,'sanjeev','29153373','sansh777@hotmail.com','xxx'),(10293,'shirish','2333604','shirish@yahoo.com','ddsds');
+select * from t1 where user_id=10292;
+user_id name phone ref_email detail
+10292 sanjeev 29153373 sansh777@hotmail.com xxx
+10292 shirish 2333604 shirish@yahoo.com ddsds
+10292 sonali 323232 sonali@bolly.com filmstar
+select * from t1 where user_id>=10292;
+user_id name phone ref_email detail
+10292 sanjeev 29153373 sansh777@hotmail.com xxx
+10292 shirish 2333604 shirish@yahoo.com ddsds
+10292 sonali 323232 sonali@bolly.com filmstar
+10293 shirish 2333604 shirish@yahoo.com ddsds
+select * from t1 where user_id>10292;
+user_id name phone ref_email detail
+10293 shirish 2333604 shirish@yahoo.com ddsds
+select * from t1 where user_id<10292;
+user_id name phone ref_email detail
+10291 sanjeev 29153373 sansh777@hotmail.com xxx
+drop table t1;
+CREATE TABLE t1 (a int not null, b int not null,c int not null,
+key(a),primary key(a,b), unique(c),key(a),unique(b));
+show index from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A # NULL NULL BTREE
+t1 0 PRIMARY 2 b A # NULL NULL BTREE
+t1 0 c 1 c A # NULL NULL BTREE
+t1 0 b 1 b A # NULL NULL BTREE
+t1 1 a 1 a A # NULL NULL BTREE
+t1 1 a_2 1 a A # NULL NULL BTREE
+drop table t1;
+create table t1 (col1 int not null, col2 char(4) not null, primary key(col1));
+alter table t1 engine=innodb;
+insert into t1 values ('1','1'),('5','2'),('2','3'),('3','4'),('4','4');
+select * from t1;
+col1 col2
+1 1
+2 3
+3 4
+4 4
+5 2
+update t1 set col2='7' where col1='4';
+select * from t1;
+col1 col2
+1 1
+2 3
+3 4
+4 7
+5 2
+alter table t1 add co3 int not null;
+select * from t1;
+col1 col2 co3
+1 1 0
+2 3 0
+3 4 0
+4 7 0
+5 2 0
+update t1 set col2='9' where col1='2';
+select * from t1;
+col1 col2 co3
+1 1 0
+2 9 0
+3 4 0
+4 7 0
+5 2 0
+drop table t1;
+create table t1 (a int not null , b int, primary key (a)) engine = innodb;
+create table t2 (a int not null , b int, primary key (a)) engine = myisam;
+insert into t1 VALUES (1,3) , (2,3), (3,3);
+select * from t1;
+a b
+1 3
+2 3
+3 3
+insert into t2 select * from t1;
+select * from t2;
+a b
+1 3
+2 3
+3 3
+delete from t1 where b = 3;
+select * from t1;
+a b
+insert into t1 select * from t2;
+select * from t1;
+a b
+1 3
+2 3
+3 3
+select * from t2;
+a b
+1 3
+2 3
+3 3
+drop table t1,t2;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+ggid varchar(32) binary DEFAULT '' NOT NULL,
+email varchar(64) DEFAULT '' NOT NULL,
+passwd varchar(32) binary DEFAULT '' NOT NULL,
+PRIMARY KEY (id),
+UNIQUE ggid (ggid)
+) ENGINE=innodb;
+insert into t1 (ggid,passwd) values ('test1','xxx');
+insert into t1 (ggid,passwd) values ('test2','yyy');
+insert into t1 (ggid,passwd) values ('test2','this will fail');
+ERROR 23000: Duplicate entry 'test2' for key 2
+insert into t1 (ggid,id) values ('this will fail',1);
+ERROR 23000: Duplicate entry '1' for key 1
+select * from t1 where ggid='test1';
+id ggid email passwd
+1 test1 xxx
+select * from t1 where passwd='xxx';
+id ggid email passwd
+1 test1 xxx
+select * from t1 where id=2;
+id ggid email passwd
+2 test2 yyy
+replace into t1 (ggid,id) values ('this will work',1);
+replace into t1 (ggid,passwd) values ('test2','this will work');
+update t1 set id=100,ggid='test2' where id=1;
+ERROR 23000: Duplicate entry 'test2' for key 2
+select * from t1;
+id ggid email passwd
+1 this will work
+3 test2 this will work
+select * from t1 where id=1;
+id ggid email passwd
+1 this will work
+select * from t1 where id=999;
+id ggid email passwd
+drop table t1;
+CREATE TABLE t1 (
+user_name varchar(12),
+password text,
+subscribed char(1),
+user_id int(11) DEFAULT '0' NOT NULL,
+quota bigint(20),
+weight double,
+access_date date,
+access_time time,
+approved datetime,
+dummy_primary_key int(11) NOT NULL auto_increment,
+PRIMARY KEY (dummy_primary_key)
+) ENGINE=innodb;
+INSERT INTO t1 VALUES ('user_0','somepassword','N',0,0,0,'2000-09-07','23:06:59','2000-09-07 23:06:59',1);
+INSERT INTO t1 VALUES ('user_1','somepassword','Y',1,1,1,'2000-09-07','23:06:59','2000-09-07 23:06:59',2);
+INSERT INTO t1 VALUES ('user_2','somepassword','N',2,2,1.4142135623731,'2000-09-07','23:06:59','2000-09-07 23:06:59',3);
+INSERT INTO t1 VALUES ('user_3','somepassword','Y',3,3,1.7320508075689,'2000-09-07','23:06:59','2000-09-07 23:06:59',4);
+INSERT INTO t1 VALUES ('user_4','somepassword','N',4,4,2,'2000-09-07','23:06:59','2000-09-07 23:06:59',5);
+select user_name, password , subscribed, user_id, quota, weight, access_date, access_time, approved, dummy_primary_key from t1 order by user_name;
+user_name password subscribed user_id quota weight access_date access_time approved dummy_primary_key
+user_0 somepassword N 0 0 0 2000-09-07 23:06:59 2000-09-07 23:06:59 1
+user_1 somepassword Y 1 1 1 2000-09-07 23:06:59 2000-09-07 23:06:59 2
+user_2 somepassword N 2 2 1.4142135623731 2000-09-07 23:06:59 2000-09-07 23:06:59 3
+user_3 somepassword Y 3 3 1.7320508075689 2000-09-07 23:06:59 2000-09-07 23:06:59 4
+user_4 somepassword N 4 4 2 2000-09-07 23:06:59 2000-09-07 23:06:59 5
+drop table t1;
+CREATE TABLE t1 (
+id int(11) NOT NULL auto_increment,
+parent_id int(11) DEFAULT '0' NOT NULL,
+level tinyint(4) DEFAULT '0' NOT NULL,
+KEY (id),
+KEY parent_id (parent_id),
+KEY level (level)
+) engine=innodb;
+INSERT INTO t1 VALUES (1,0,0),(3,1,1),(4,1,1),(8,2,2),(9,2,2),(17,3,2),(22,4,2),(24,4,2),(28,5,2),(29,5,2),(30,5,2),(31,6,2),(32,6,2),(33,6,2),(203,7,2),(202,7,2),(20,3,2),(157,0,0),(193,5,2),(40,7,2),(2,1,1),(15,2,2),(6,1,1),(34,6,2),(35,6,2),(16,3,2),(7,1,1),(36,7,2),(18,3,2),(26,5,2),(27,5,2),(183,4,2),(38,7,2),(25,5,2),(37,7,2),(21,4,2),(19,3,2),(5,1,1);
+INSERT INTO t1 values (179,5,2);
+update t1 set parent_id=parent_id+100;
+select * from t1 where parent_id=102;
+id parent_id level
+8 102 2
+9 102 2
+15 102 2
+update t1 set id=id+1000;
+update t1 set id=1024 where id=1009;
+select * from t1;
+id parent_id level
+1001 100 0
+1003 101 1
+1004 101 1
+1008 102 2
+1024 102 2
+1017 103 2
+1022 104 2
+1024 104 2
+1028 105 2
+1029 105 2
+1030 105 2
+1031 106 2
+1032 106 2
+1033 106 2
+1203 107 2
+1202 107 2
+1020 103 2
+1157 100 0
+1193 105 2
+1040 107 2
+1002 101 1
+1015 102 2
+1006 101 1
+1034 106 2
+1035 106 2
+1016 103 2
+1007 101 1
+1036 107 2
+1018 103 2
+1026 105 2
+1027 105 2
+1183 104 2
+1038 107 2
+1025 105 2
+1037 107 2
+1021 104 2
+1019 103 2
+1005 101 1
+1179 105 2
+update ignore t1 set id=id+1;
+select * from t1;
+id parent_id level
+1002 100 0
+1004 101 1
+1005 101 1
+1009 102 2
+1025 102 2
+1018 103 2
+1023 104 2
+1025 104 2
+1029 105 2
+1030 105 2
+1031 105 2
+1032 106 2
+1033 106 2
+1034 106 2
+1204 107 2
+1203 107 2
+1021 103 2
+1158 100 0
+1194 105 2
+1041 107 2
+1003 101 1
+1016 102 2
+1007 101 1
+1035 106 2
+1036 106 2
+1017 103 2
+1008 101 1
+1037 107 2
+1019 103 2
+1027 105 2
+1028 105 2
+1184 104 2
+1039 107 2
+1026 105 2
+1038 107 2
+1022 104 2
+1020 103 2
+1006 101 1
+1180 105 2
+update ignore t1 set id=1023 where id=1010;
+select * from t1 where parent_id=102;
+id parent_id level
+1009 102 2
+1025 102 2
+1016 102 2
+explain select level from t1 where level=1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref level level 1 const # Using where; Using index
+select level,id from t1 where level=1;
+level id
+1 1004
+1 1005
+1 1003
+1 1007
+1 1008
+1 1006
+select level,id,parent_id from t1 where level=1;
+level id parent_id
+1 1004 101
+1 1005 101
+1 1003 101
+1 1007 101
+1 1008 101
+1 1006 101
+select level,id from t1 where level=1 order by id;
+level id
+1 1003
+1 1004
+1 1005
+1 1006
+1 1007
+1 1008
+delete from t1 where level=1;
+select * from t1;
+id parent_id level
+1002 100 0
+1009 102 2
+1025 102 2
+1018 103 2
+1023 104 2
+1025 104 2
+1029 105 2
+1030 105 2
+1031 105 2
+1032 106 2
+1033 106 2
+1034 106 2
+1204 107 2
+1203 107 2
+1021 103 2
+1158 100 0
+1194 105 2
+1041 107 2
+1016 102 2
+1035 106 2
+1036 106 2
+1017 103 2
+1037 107 2
+1019 103 2
+1027 105 2
+1028 105 2
+1184 104 2
+1039 107 2
+1026 105 2
+1038 107 2
+1022 104 2
+1020 103 2
+1180 105 2
+drop table t1;
+CREATE TABLE t1 (
+sca_code char(6) NOT NULL,
+cat_code char(6) NOT NULL,
+sca_desc varchar(50),
+lan_code char(2) NOT NULL,
+sca_pic varchar(100),
+sca_sdesc varchar(50),
+sca_sch_desc varchar(16),
+PRIMARY KEY (sca_code, cat_code, lan_code),
+INDEX sca_pic (sca_pic)
+) engine = innodb ;
+INSERT INTO t1 ( sca_code, cat_code, sca_desc, lan_code, sca_pic, sca_sdesc, sca_sch_desc) VALUES ( 'PD', 'J', 'PENDANT', 'EN', NULL, NULL, 'PENDANT'),( 'RI', 'J', 'RING', 'EN', NULL, NULL, 'RING'),( 'QQ', 'N', 'RING', 'EN', 'not null', NULL, 'RING');
+select count(*) from t1 where sca_code = 'PD';
+count(*)
+1
+select count(*) from t1 where sca_code <= 'PD';
+count(*)
+1
+select count(*) from t1 where sca_pic is null;
+count(*)
+2
+alter table t1 drop index sca_pic, add index sca_pic (cat_code, sca_pic);
+select count(*) from t1 where sca_code='PD' and sca_pic is null;
+count(*)
+1
+select count(*) from t1 where cat_code='E';
+count(*)
+0
+alter table t1 drop index sca_pic, add index (sca_pic, cat_code);
+select count(*) from t1 where sca_code='PD' and sca_pic is null;
+count(*)
+1
+select count(*) from t1 where sca_pic >= 'n';
+count(*)
+1
+select sca_pic from t1 where sca_pic is null;
+sca_pic
+NULL
+NULL
+update t1 set sca_pic="test" where sca_pic is null;
+delete from t1 where sca_code='pd';
+drop table t1;
+set @a:=now();
+CREATE TABLE t1 (a int not null, b timestamp not null, primary key (a)) engine=innodb;
+insert into t1 (a) values(1),(2),(3);
+select t1.a from t1 natural join t1 as t2 where t1.b >= @a order by t1.a;
+a
+1
+2
+3
+update t1 set a=5 where a=1;
+select a from t1;
+a
+2
+3
+5
+drop table t1;
+create table t1 (a varchar(100) not null, primary key(a), b int not null) engine=innodb;
+insert into t1 values("hello",1),("world",2);
+select * from t1 order by b desc;
+a b
+world 2
+hello 1
+optimize table t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status OK
+show keys from t1;
+Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
+t1 0 PRIMARY 1 a A # NULL NULL BTREE
+drop table t1;
+create table t1 (i int, j int ) ENGINE=innodb;
+insert into t1 values (1,2);
+select * from t1 where i=1 and j=2;
+i j
+1 2
+create index ax1 on t1 (i,j);
+select * from t1 where i=1 and j=2;
+i j
+1 2
+drop table t1;
+CREATE TABLE t1 (
+a int3 unsigned NOT NULL,
+b int1 unsigned NOT NULL,
+UNIQUE (a, b)
+) ENGINE = innodb;
+INSERT INTO t1 VALUES (1, 1);
+SELECT MIN(B),MAX(b) FROM t1 WHERE t1.a = 1;
+MIN(B) MAX(b)
+1 1
+drop table t1;
+CREATE TABLE t1 (a int unsigned NOT NULL) engine=innodb;
+INSERT INTO t1 VALUES (1);
+SELECT * FROM t1;
+a
+1
+DROP TABLE t1;
+create table t1 (a int primary key,b int, c int, d int, e int, f int, g int, h int, i int, j int, k int, l int, m int, n int, o int, p int, q int, r int, s int, t int, u int, v int, w int, x int, y int, z int, a1 int, a2 int, a3 int, a4 int, a5 int, a6 int, a7 int, a8 int, a9 int, b1 int, b2 int, b3 int, b4 int, b5 int, b6 int) engine = innodb;
+insert into t1 values (1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1);
+explain select * from t1 where a > 0 and a < 50;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range PRIMARY PRIMARY 4 NULL # Using where
+drop table t1;
+create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) engine=innodb;
+insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
+LOCK TABLES t1 WRITE;
+insert into t1 values (99,1,2,'D'),(1,1,2,'D');
+ERROR 23000: Duplicate entry '1-1' for key 1
+select id from t1;
+id
+0
+1
+2
+select id from t1;
+id
+0
+1
+2
+UNLOCK TABLES;
+DROP TABLE t1;
+create table t1 (id int NOT NULL,id2 int NOT NULL,id3 int NOT NULL,dummy1 char(30),primary key (id,id2),index index_id3 (id3)) engine=innodb;
+insert into t1 values (0,0,0,'ABCDEFGHIJ'),(2,2,2,'BCDEFGHIJK'),(1,1,1,'CDEFGHIJKL');
+LOCK TABLES t1 WRITE;
+begin;
+insert into t1 values (99,1,2,'D'),(1,1,2,'D');
+ERROR 23000: Duplicate entry '1-1' for key 1
+select id from t1;
+id
+0
+1
+2
+insert ignore into t1 values (100,1,2,'D'),(1,1,99,'D');
+commit;
+select id,id3 from t1;
+id id3
+0 0
+1 1
+2 2
+100 2
+UNLOCK TABLES;
+DROP TABLE t1;
+create table t1 (a char(20), unique (a(5))) engine=innodb;
+drop table t1;
+create table t1 (a char(20), index (a(5))) engine=innodb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(20) default NULL,
+ KEY `a` (`a`(5))
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t1;
+create temporary table t1 (a int not null auto_increment, primary key(a)) engine=innodb;
+insert into t1 values (NULL),(NULL),(NULL);
+delete from t1 where a=3;
+insert into t1 values (NULL);
+select * from t1;
+a
+1
+2
+4
+alter table t1 add b int;
+select * from t1;
+a b
+1 NULL
+2 NULL
+4 NULL
+drop table t1;
+create table t1
+(
+id int auto_increment primary key,
+name varchar(32) not null,
+value text not null,
+uid int not null,
+unique key(name,uid)
+) engine=innodb;
+insert into t1 values (1,'one','one value',101),
+(2,'two','two value',102),(3,'three','three value',103);
+set insert_id=5;
+replace into t1 (value,name,uid) values ('other value','two',102);
+delete from t1 where uid=102;
+set insert_id=5;
+replace into t1 (value,name,uid) values ('other value','two',102);
+set insert_id=6;
+replace into t1 (value,name,uid) values ('other value','two',102);
+select * from t1;
+id name value uid
+1 one one value 101
+3 three three value 103
+6 two other value 102
+drop table t1;
+create database mysqltest;
+create table mysqltest.t1 (a int not null) engine= innodb;
+insert into mysqltest.t1 values(1);
+create table mysqltest.t2 (a int not null) engine= myisam;
+insert into mysqltest.t2 values(1);
+create table mysqltest.t3 (a int not null) engine= heap;
+insert into mysqltest.t3 values(1);
+commit;
+drop database mysqltest;
+show tables from mysqltest;
+Got one of the listed errors
+set autocommit=0;
+create table t1 (a int not null) engine= innodb;
+insert into t1 values(1),(2);
+truncate table t1;
+ERROR HY000: Can't execute the given command because you have active locked tables or an active transaction
+commit;
+truncate table t1;
+select * from t1;
+a
+insert into t1 values(1),(2);
+delete from t1;
+select * from t1;
+a
+commit;
+drop table t1;
+set autocommit=1;
+create table t1 (a int not null) engine= innodb;
+insert into t1 values(1),(2);
+truncate table t1;
+insert into t1 values(1),(2);
+select * from t1;
+a
+1
+2
+truncate table t1;
+insert into t1 values(1),(2);
+delete from t1;
+select * from t1;
+a
+drop table t1;
+create table t1 (a int not null, b int not null, c int not null, primary key (a),key(b)) engine=innodb;
+insert into t1 values (3,3,3),(1,1,1),(2,2,2),(4,4,4);
+explain select * from t1 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL #
+explain select * from t1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL b 4 NULL #
+explain select * from t1 order by c;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL # Using filesort
+explain select a from t1 order by a;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 4 NULL # Using index
+explain select b from t1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL b 4 NULL # Using index
+explain select a,b from t1 order by b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL b 4 NULL # Using index
+explain select a,b from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL b 4 NULL # Using index
+explain select a,b,c from t1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL #
+drop table t1;
+create table t1 (t int not null default 1, key (t)) engine=innodb;
+desc t1;
+Field Type Null Key Default Extra
+t int(11) MUL 1
+drop table t1;
+CREATE TABLE t1 (
+number bigint(20) NOT NULL default '0',
+cname char(15) NOT NULL default '',
+carrier_id smallint(6) NOT NULL default '0',
+privacy tinyint(4) NOT NULL default '0',
+last_mod_date timestamp(14) NOT NULL,
+last_mod_id smallint(6) NOT NULL default '0',
+last_app_date timestamp(14) NOT NULL,
+last_app_id smallint(6) default '-1',
+version smallint(6) NOT NULL default '0',
+assigned_scps int(11) default '0',
+status tinyint(4) default '0'
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES (4077711111,'SeanWheeler',90,2,20020111112846,500,00000000000000,-1,2,3,1);
+INSERT INTO t1 VALUES (9197722223,'berry',90,3,20020111112809,500,20020102114532,501,4,10,0);
+INSERT INTO t1 VALUES (650,'San Francisco',0,0,20011227111336,342,00000000000000,-1,1,24,1);
+INSERT INTO t1 VALUES (302467,'Sue\'s Subshop',90,3,20020109113241,500,20020102115111,501,7,24,0);
+INSERT INTO t1 VALUES (6014911113,'SudzCarwash',520,1,20020102115234,500,20020102115259,501,33,32768,0);
+INSERT INTO t1 VALUES (333,'tubs',99,2,20020109113440,501,20020109113440,500,3,10,0);
+CREATE TABLE t2 (
+number bigint(20) NOT NULL default '0',
+cname char(15) NOT NULL default '',
+carrier_id smallint(6) NOT NULL default '0',
+privacy tinyint(4) NOT NULL default '0',
+last_mod_date timestamp(14) NOT NULL,
+last_mod_id smallint(6) NOT NULL default '0',
+last_app_date timestamp(14) NOT NULL,
+last_app_id smallint(6) default '-1',
+version smallint(6) NOT NULL default '0',
+assigned_scps int(11) default '0',
+status tinyint(4) default '0'
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES (4077711111,'SeanWheeler',0,2,20020111112853,500,00000000000000,-1,2,3,1);
+INSERT INTO t2 VALUES (9197722223,'berry',90,3,20020111112818,500,20020102114532,501,4,10,0);
+INSERT INTO t2 VALUES (650,'San Francisco',90,0,20020109113158,342,00000000000000,-1,1,24,1);
+INSERT INTO t2 VALUES (333,'tubs',99,2,20020109113453,501,20020109113453,500,3,10,0);
+select * from t1;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+4077711111 SeanWheeler 90 2 2002-01-11 11:28:46 500 0000-00-00 00:00:00 -1 2 3 1
+9197722223 berry 90 3 2002-01-11 11:28:09 500 2002-01-02 11:45:32 501 4 10 0
+650 San Francisco 0 0 2001-12-27 11:13:36 342 0000-00-00 00:00:00 -1 1 24 1
+302467 Sue's Subshop 90 3 2002-01-09 11:32:41 500 2002-01-02 11:51:11 501 7 24 0
+6014911113 SudzCarwash 520 1 2002-01-02 11:52:34 500 2002-01-02 11:52:59 501 33 32768 0
+333 tubs 99 2 2002-01-09 11:34:40 501 2002-01-09 11:34:40 500 3 10 0
+select * from t2;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+4077711111 SeanWheeler 0 2 2002-01-11 11:28:53 500 0000-00-00 00:00:00 -1 2 3 1
+9197722223 berry 90 3 2002-01-11 11:28:18 500 2002-01-02 11:45:32 501 4 10 0
+650 San Francisco 90 0 2002-01-09 11:31:58 342 0000-00-00 00:00:00 -1 1 24 1
+333 tubs 99 2 2002-01-09 11:34:53 501 2002-01-09 11:34:53 500 3 10 0
+delete t1, t2 from t1 left join t2 on t1.number=t2.number where (t1.carrier_id=90 and t1.number=t2.number) or (t2.carrier_id=90 and t1.number=t2.number) or (t1.carrier_id=90 and t2.number is null);
+select * from t1;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+6014911113 SudzCarwash 520 1 2002-01-02 11:52:34 500 2002-01-02 11:52:59 501 33 32768 0
+333 tubs 99 2 2002-01-09 11:34:40 501 2002-01-09 11:34:40 500 3 10 0
+select * from t2;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+333 tubs 99 2 2002-01-09 11:34:53 501 2002-01-09 11:34:53 500 3 10 0
+select * from t2;
+number cname carrier_id privacy last_mod_date last_mod_id last_app_date last_app_id version assigned_scps status
+333 tubs 99 2 2002-01-09 11:34:53 501 2002-01-09 11:34:53 500 3 10 0
+drop table t1,t2;
+create table t1 (id int unsigned not null auto_increment, code tinyint unsigned not null, name char(20) not null, primary key (id), key (code), unique (name)) engine=innodb;
+BEGIN;
+SET SESSION TRANSACTION ISOLATION LEVEL SERIALIZABLE;
+SELECT @@tx_isolation,@@global.tx_isolation;
+@@tx_isolation @@global.tx_isolation
+SERIALIZABLE REPEATABLE-READ
+insert into t1 (code, name) values (1, 'Tim'), (1, 'Monty'), (2, 'David');
+select id, code, name from t1 order by id;
+id code name
+1 1 Tim
+2 1 Monty
+3 2 David
+COMMIT;
+BEGIN;
+SET SESSION TRANSACTION ISOLATION LEVEL REPEATABLE READ;
+insert into t1 (code, name) values (2, 'Erik'), (3, 'Sasha');
+select id, code, name from t1 order by id;
+id code name
+1 1 Tim
+2 1 Monty
+3 2 David
+4 2 Erik
+5 3 Sasha
+COMMIT;
+BEGIN;
+SET SESSION TRANSACTION ISOLATION LEVEL READ UNCOMMITTED;
+insert into t1 (code, name) values (3, 'Jeremy'), (4, 'Matt');
+select id, code, name from t1 order by id;
+id code name
+1 1 Tim
+2 1 Monty
+3 2 David
+4 2 Erik
+5 3 Sasha
+6 3 Jeremy
+7 4 Matt
+COMMIT;
+DROP TABLE t1;
+create table t1 (n int(10), d int(10)) engine=innodb;
+create table t2 (n int(10), d int(10)) engine=innodb;
+insert into t1 values(1,1),(1,2);
+insert into t2 values(1,10),(2,20);
+UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
+select * from t1;
+n d
+1 10
+1 10
+select * from t2;
+n d
+1 30
+2 20
+drop table t1,t2;
+create table t1 (a int, b int) engine=innodb;
+insert into t1 values(20,null);
+select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
+t2.b=t3.a;
+b ifnull(t2.b,"this is null")
+NULL this is null
+select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
+t2.b=t3.a order by 1;
+b ifnull(t2.b,"this is null")
+NULL this is null
+insert into t1 values(10,null);
+select t2.b, ifnull(t2.b,"this is null") from t1 as t2 left join t1 as t3 on
+t2.b=t3.a order by 1;
+b ifnull(t2.b,"this is null")
+NULL this is null
+NULL this is null
+drop table t1;
+create table t1 (a varchar(10) not null) engine=myisam;
+create table t2 (b varchar(10) not null unique) engine=innodb;
+select t1.a from t1,t2 where t1.a=t2.b;
+a
+drop table t1,t2;
+create table t1 (a int not null, b int, primary key (a)) engine = innodb;
+create table t2 (a int not null, b int, primary key (a)) engine = innodb;
+insert into t1 values (10, 20);
+insert into t2 values (10, 20);
+update t1, t2 set t1.b = 150, t2.b = t1.b where t2.a = t1.a and t1.a = 10;
+drop table t1,t2;
+CREATE TABLE t1 (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id), FOREIGN KEY (t1_id) REFERENCES t1(id) ON DELETE CASCADE ) ENGINE=INNODB;
+insert into t1 set id=1;
+insert into t2 set id=1, t1_id=1;
+delete t1,t2 from t1,t2 where t1.id=t2.t1_id;
+select * from t1;
+id
+select * from t2;
+id t1_id
+drop table t2,t1;
+CREATE TABLE t1(id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TABLE t2(id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id) ) ENGINE=INNODB;
+INSERT INTO t1 VALUES(1);
+INSERT INTO t2 VALUES(1, 1);
+SELECT * from t1;
+id
+1
+UPDATE t1,t2 SET t1.id=t1.id+1, t2.t1_id=t1.id+1;
+SELECT * from t1;
+id
+2
+UPDATE t1,t2 SET t1.id=t1.id+1 where t1.id!=t2.id;
+SELECT * from t1;
+id
+3
+DROP TABLE t1,t2;
+set autocommit=0;
+CREATE TABLE t1 (id CHAR(15) NOT NULL, value CHAR(40) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;
+CREATE TABLE t2 (id CHAR(15) NOT NULL, value CHAR(40) NOT NULL, PRIMARY KEY(id)) ENGINE=InnoDB;
+CREATE TABLE t3 (id1 CHAR(15) NOT NULL, id2 CHAR(15) NOT NULL, PRIMARY KEY(id1, id2)) ENGINE=InnoDB;
+INSERT INTO t3 VALUES("my-test-1", "my-test-2");
+COMMIT;
+INSERT INTO t1 VALUES("this-key", "will disappear");
+INSERT INTO t2 VALUES("this-key", "will also disappear");
+DELETE FROM t3 WHERE id1="my-test-1";
+SELECT * FROM t1;
+id value
+this-key will disappear
+SELECT * FROM t2;
+id value
+this-key will also disappear
+SELECT * FROM t3;
+id1 id2
+ROLLBACK;
+SELECT * FROM t1;
+id value
+SELECT * FROM t2;
+id value
+SELECT * FROM t3;
+id1 id2
+my-test-1 my-test-2
+SELECT * FROM t3 WHERE id1="my-test-1" LOCK IN SHARE MODE;
+id1 id2
+my-test-1 my-test-2
+COMMIT;
+set autocommit=1;
+DROP TABLE t1,t2,t3;
+CREATE TABLE t1 (a int not null primary key, b int not null, unique (b)) engine=innodb;
+INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+UPDATE t1 set a=a+100 where b between 2 and 3 and a < 1000;
+SELECT * from t1;
+a b
+1 1
+102 2
+103 3
+4 4
+5 5
+6 6
+7 7
+8 8
+9 9
+drop table t1;
+CREATE TABLE t1 (a int not null primary key, b int not null, key (b)) engine=innodb;
+CREATE TABLE t2 (a int not null primary key, b int not null, key (b)) engine=innodb;
+INSERT INTO t1 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9),(10,10),(11,11),(12,12);
+INSERT INTO t2 values (1,1),(2,2),(3,3),(4,4),(5,5),(6,6),(7,7),(8,8),(9,9);
+update t1,t2 set t1.a=t1.a+100;
+select * from t1;
+a b
+101 1
+102 2
+103 3
+104 4
+105 5
+106 6
+107 7
+108 8
+109 9
+110 10
+111 11
+112 12
+update t1,t2 set t1.a=t1.a+100 where t1.a=101;
+select * from t1;
+a b
+201 1
+102 2
+103 3
+104 4
+105 5
+106 6
+107 7
+108 8
+109 9
+110 10
+111 11
+112 12
+update t1,t2 set t1.b=t1.b+10 where t1.b=2;
+select * from t1;
+a b
+201 1
+103 3
+104 4
+105 5
+106 6
+107 7
+108 8
+109 9
+110 10
+111 11
+102 12
+112 12
+update t1,t2 set t1.b=t1.b+2,t2.b=t1.b+10 where t1.b between 3 and 5 and t1.a=t2.a+100;
+select * from t1;
+a b
+201 1
+103 5
+104 6
+106 6
+105 7
+107 7
+108 8
+109 9
+110 10
+111 11
+102 12
+112 12
+select * from t2;
+a b
+1 1
+2 2
+6 6
+7 7
+8 8
+9 9
+3 13
+4 14
+5 15
+drop table t1,t2;
+CREATE TABLE t2 ( NEXT_T BIGINT NOT NULL PRIMARY KEY) ENGINE=MyISAM;
+CREATE TABLE t1 ( B_ID INTEGER NOT NULL PRIMARY KEY) ENGINE=InnoDB;
+SET AUTOCOMMIT=0;
+INSERT INTO t1 ( B_ID ) VALUES ( 1 );
+INSERT INTO t2 ( NEXT_T ) VALUES ( 1 );
+ROLLBACK;
+Warnings:
+Warning 1196 Some non-transactional changed tables couldn't be rolled back
+SELECT * FROM t1;
+B_ID
+drop table t1,t2;
+create table t1 ( pk int primary key, parent int not null, child int not null, index (parent) ) engine = innodb;
+insert into t1 values (1,0,4), (2,1,3), (3,2,1), (4,1,2);
+select distinct parent,child from t1 order by parent;
+parent child
+0 4
+1 2
+1 3
+2 1
+drop table t1;
+create table t1 (a int not null auto_increment primary key, b int, c int, key(c)) engine=innodb;
+create table t2 (a int not null auto_increment primary key, b int);
+insert into t1 (b) values (null),(null),(null),(null),(null),(null),(null);
+insert into t2 (a) select b from t1;
+insert into t1 (b) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+insert into t2 (a) select b from t1;
+insert into t1 (a) select b from t2;
+select count(*) from t1;
+count(*)
+29267
+explain select * from t1 where c between 1 and 10000;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range c c 5 NULL # Using where
+update t1 set c=a;
+explain select * from t1 where c between 1 and 10000;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL c NULL NULL NULL # Using where
+drop table t1,t2;
+create table t1 (id int primary key auto_increment, fk int, index index_fk (fk)) engine=innodb;
+insert into t1 (id) values (null),(null),(null),(null),(null);
+update t1 set fk=69 where fk is null order by id limit 1;
+SELECT * from t1;
+id fk
+2 NULL
+3 NULL
+4 NULL
+5 NULL
+1 69
+drop table t1;
+create table t1 (a int not null, b int not null, key (a));
+insert into t1 values (1,1),(1,2),(1,3),(3,1),(3,2),(3,3),(3,1),(3,2),(3,3),(2,1),(2,2),(2,3);
+SET @tmp=0;
+update t1 set b=(@tmp:=@tmp+1) order by a;
+update t1 set b=99 where a=1 order by b asc limit 1;
+update t1 set b=100 where a=1 order by b desc limit 2;
+update t1 set a=a+10+b where a=1 order by b;
+select * from t1 order by a,b;
+a b
+2 4
+2 5
+2 6
+3 7
+3 8
+3 9
+3 10
+3 11
+3 12
+13 2
+111 100
+111 100
+drop table t1;
+create table t1 ( c char(8) not null ) engine=innodb;
+insert into t1 values ('0'),('1'),('2'),('3'),('4'),('5'),('6'),('7'),('8'),('9');
+insert into t1 values ('A'),('B'),('C'),('D'),('E'),('F');
+alter table t1 add b char(8) not null;
+alter table t1 add a char(8) not null;
+alter table t1 add primary key (a,b,c);
+update t1 set a=c, b=c;
+create table t2 (c char(8) not null, b char(8) not null, a char(8) not null, primary key(a,b,c)) engine=innodb;
+insert into t2 select * from t1;
+delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
+drop table t1,t2;
+SET AUTOCOMMIT=1;
+create table t1 (a integer auto_increment primary key) engine=innodb;
+insert into t1 (a) values (NULL),(NULL);
+truncate table t1;
+insert into t1 (a) values (NULL),(NULL);
+SELECT * from t1;
+a
+3
+4
+drop table t1;
+CREATE TABLE t1 (`id 1` INT NOT NULL, PRIMARY KEY (`id 1`)) ENGINE=INNODB;
+CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id), FOREIGN KEY (`t1_id`) REFERENCES `t1`(`id 1`) ON DELETE CASCADE ) ENGINE=INNODB;
+drop table t2,t1;
+create table `t1` (`id` int( 11 ) not null ,primary key ( `id` )) engine = innodb;
+insert into `t1`values ( 1 ) ;
+create table `t2` (`id` int( 11 ) not null default '0',unique key `id` ( `id` ) ,constraint `t1_id_fk` foreign key ( `id` ) references `t1` (`id` )) engine = innodb;
+insert into `t2`values ( 1 ) ;
+create table `t3` (`id` int( 11 ) not null default '0',key `id` ( `id` ) ,constraint `t2_id_fk` foreign key ( `id` ) references `t2` (`id` )) engine = innodb;
+insert into `t3`values ( 1 ) ;
+delete t3,t2,t1 from t1,t2,t3 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+update t1,t2,t3 set t3.id=5, t2.id=6, t1.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+update t3 set t3.id=7 where t1.id =1 and t2.id = t1.id and t3.id = t2.id;
+ERROR 42S02: Unknown table 't1' in where clause
+drop table t3,t2,t1;
+create table t1(
+id int primary key,
+pid int,
+index(pid),
+foreign key(pid) references t1(id) on delete cascade) engine=innodb;
+insert into t1 values(0,0),(1,0),(2,1),(3,2),(4,3),(5,4),(6,5),(7,6),
+(8,7),(9,8),(10,9),(11,10),(12,11),(13,12),(14,13),(15,14);
+delete from t1 where id=0;
+ERROR 23000: Cannot delete or update a parent row: a foreign key constraint fails
+delete from t1 where id=15;
+delete from t1 where id=0;
+drop table t1;
+CREATE TABLE t1 (col1 int(1))ENGINE=InnoDB;
+CREATE TABLE t2 (col1 int(1),stamp TIMESTAMP,INDEX stamp_idx
+(stamp))ENGINE=InnoDB;
+insert into t1 values (1),(2),(3);
+insert into t2 values (1, 20020204130000),(2, 20020204130000),(4,20020204310000 ),(5,20020204230000);
+Warnings:
+Warning 1265 Data truncated for column 'stamp' at row 3
+SELECT col1 FROM t1 UNION SELECT col1 FROM t2 WHERE stamp <
+'20020204120000' GROUP BY col1;
+col1
+1
+2
+3
+4
+drop table t1,t2;
+CREATE TABLE t1 (
+`id` int(10) unsigned NOT NULL auto_increment,
+`id_object` int(10) unsigned default '0',
+`id_version` int(10) unsigned NOT NULL default '1',
+label varchar(100) NOT NULL default '',
+`description` text,
+PRIMARY KEY (`id`),
+KEY `id_object` (`id_object`),
+KEY `id_version` (`id_version`)
+) ENGINE=InnoDB;
+INSERT INTO t1 VALUES("6", "3382", "9", "Test", NULL), ("7", "102", "5", "Le Pekin (Test)", NULL),("584", "1794", "4", "Test de resto", NULL),("837", "1822", "6", "Test 3", NULL),("1119", "3524", "1", "Societe Test", NULL),("1122", "3525", "1", "Fournisseur Test", NULL);
+CREATE TABLE t2 (
+`id` int(10) unsigned NOT NULL auto_increment,
+`id_version` int(10) unsigned NOT NULL default '1',
+PRIMARY KEY (`id`),
+KEY `id_version` (`id_version`)
+) ENGINE=InnoDB;
+INSERT INTO t2 VALUES("3524", "1"),("3525", "1"),("1794", "4"),("102", "5"),("1822", "6"),("3382", "9");
+SELECT t2.id, t1.label FROM t2 INNER JOIN
+(SELECT t1.id_object as id_object FROM t1 WHERE t1.label LIKE '%test%') AS lbl
+ON (t2.id = lbl.id_object) INNER JOIN t1 ON (t2.id = t1.id_object);
+id label
+3382 Test
+102 Le Pekin (Test)
+1794 Test de resto
+1822 Test 3
+3524 Societe Test
+3525 Fournisseur Test
+drop table t1,t2;
+create table t1 (c1 char(5) unique not null, c2 int, stamp timestamp) engine=innodb;
+select * from t1;
+c1 c2 stamp
+replace delayed into t1 (c1, c2) values ( "text1","11"),( "text2","12");
+select * from t1;
+c1 c2 stamp
+text1 11 2004-12-01 13:23:14
+text2 12 2004-12-01 13:23:14
+replace delayed into t1 (c1, c2) values ( "text1","12"),( "text2","13"),( "text3","14", "a" ),( "text4","15", "b" );
+ERROR 21S01: Column count doesn't match value count at row 3
+select * from t1;
+c1 c2 stamp
+text1 11 2004-12-01 13:23:14
+text2 12 2004-12-01 13:23:14
+drop table t1;
+create table t1 (a int, b varchar(200), c text not null) checksum=1 engine=myisam;
+create table t2 (a int, b varchar(200), c text not null) checksum=0 engine=innodb;
+create table t3 (a int, b varchar(200), c text not null) checksum=1 engine=innodb;
+insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
+insert t2 select * from t1;
+insert t3 select * from t1;
+checksum table t1, t2, t3, t4 quick;
+Table Checksum
+test.t1 968604391
+test.t2 NULL
+test.t3 NULL
+test.t4 NULL
+checksum table t1, t2, t3, t4;
+Table Checksum
+test.t1 968604391
+test.t2 968604391
+test.t3 968604391
+test.t4 NULL
+checksum table t1, t2, t3, t4 extended;
+Table Checksum
+test.t1 968604391
+test.t2 968604391
+test.t3 968604391
+test.t4 NULL
+drop table t1,t2,t3;
+create table t1 (id int, name char(10) not null, name2 char(10) not null) engine=innodb;
+insert into t1 values(1,'first','fff'),(2,'second','sss'),(3,'third','ttt');
+select name2 from t1 union all select name from t1 union all select id from t1;
+name2
+fff
+sss
+ttt
+first
+second
+third
+1
+2
+3
+drop table t1;
+create table t1 (a int) engine=innodb;
+create table t2 like t1;
+drop table t1,t2;
+create table t1 (id int(11) not null, id2 int(11) not null, unique (id,id2)) engine=innodb;
+create table t2 (id int(11) not null, constraint t1_id_fk foreign key ( id ) references t1 (id)) engine = innodb;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `id` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL default '0',
+ UNIQUE KEY `id` (`id`,`id2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ KEY `t1_id_fk` (`id`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+create index id on t2 (id);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ KEY `id` (`id`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+create index id2 on t2 (id);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ KEY `id` (`id`),
+ KEY `id2` (`id`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop index id2 on t2;
+drop index id on t2;
+Got one of the listed errors
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ KEY `id` (`id`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2;
+create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id,id2) references t1 (id,id2)) engine = innodb;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL default '0',
+ KEY `t1_id_fk` (`id`,`id2`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`, `id2`) REFERENCES `t1` (`id`, `id2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+create unique index id on t2 (id,id2);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL default '0',
+ UNIQUE KEY `id` (`id`,`id2`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`, `id2`) REFERENCES `t1` (`id`, `id2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2;
+create table t2 (id int(11) not null, id2 int(11) not null, unique (id,id2),constraint t1_id_fk foreign key (id2,id) references t1 (id,id2)) engine = innodb;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL default '0',
+ UNIQUE KEY `id` (`id`,`id2`),
+ KEY `t1_id_fk` (`id2`,`id`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id2`, `id`) REFERENCES `t1` (`id`, `id2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2;
+create table t2 (id int(11) not null, id2 int(11) not null, unique (id,id2), constraint t1_id_fk foreign key (id) references t1 (id)) engine = innodb;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL default '0',
+ UNIQUE KEY `id` (`id`,`id2`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2;
+create table t2 (id int(11) not null, id2 int(11) not null, unique (id,id2),constraint t1_id_fk foreign key (id2,id) references t1 (id,id2)) engine = innodb;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL default '0',
+ `id2` int(11) NOT NULL default '0',
+ UNIQUE KEY `id` (`id`,`id2`),
+ KEY `t1_id_fk` (`id2`,`id`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id2`, `id`) REFERENCES `t1` (`id`, `id2`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2;
+create table t2 (id int(11) not null auto_increment, id2 int(11) not null, constraint t1_id_fk foreign key (id) references t1 (id), primary key (id), index (id,id2)) engine = innodb;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL auto_increment,
+ `id2` int(11) NOT NULL default '0',
+ PRIMARY KEY (`id`),
+ KEY `id` (`id`,`id2`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2;
+create table t2 (id int(11) not null auto_increment, id2 int(11) not null, constraint t1_id_fk foreign key (id) references t1 (id)) engine= innodb;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL auto_increment,
+ `id2` int(11) NOT NULL default '0',
+ KEY `t1_id_fk` (`id`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+alter table t2 add index id_test (id), add index id_test2 (id,id2);
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `id` int(11) NOT NULL auto_increment,
+ `id2` int(11) NOT NULL default '0',
+ KEY `id_test` (`id`),
+ KEY `id_test2` (`id`,`id2`),
+ CONSTRAINT `t1_id_fk` FOREIGN KEY (`id`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2;
+create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
+ERROR HY000: Can't create table '/home/hf/work/mysql-4.1.clean/mysql-test/var/master-data/test/t2.frm' (errno: 150)
+create table t2 (a int auto_increment primary key, b int, index(b), foreign key (b) references t1(id), unique(b)) engine=innodb;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) NOT NULL auto_increment,
+ `b` int(11) default NULL,
+ PRIMARY KEY (`a`),
+ UNIQUE KEY `b_2` (`b`),
+ KEY `b` (`b`),
+ CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2;
+create table t2 (a int auto_increment primary key, b int, foreign key (b) references t1(id), foreign key (b) references t1(id), unique(b)) engine=innodb;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) NOT NULL auto_increment,
+ `b` int(11) default NULL,
+ PRIMARY KEY (`a`),
+ UNIQUE KEY `b` (`b`),
+ CONSTRAINT `t2_ibfk_1` FOREIGN KEY (`b`) REFERENCES `t1` (`id`),
+ CONSTRAINT `t2_ibfk_2` FOREIGN KEY (`b`) REFERENCES `t1` (`id`)
+) ENGINE=InnoDB DEFAULT CHARSET=latin1
+drop table t2, t1;
+show status like "binlog_cache_use";
+Variable_name Value
+Binlog_cache_use 24
+show status like "binlog_cache_disk_use";
+Variable_name Value
+Binlog_cache_disk_use 0
+create table t1 (a int) engine=innodb;
+show status like "binlog_cache_use";
+Variable_name Value
+Binlog_cache_use 25
+show status like "binlog_cache_disk_use";
+Variable_name Value
+Binlog_cache_disk_use 1
+begin;
+delete from t1;
+commit;
+show status like "binlog_cache_use";
+Variable_name Value
+Binlog_cache_use 26
+show status like "binlog_cache_disk_use";
+Variable_name Value
+Binlog_cache_disk_use 1
+drop table t1;
+create table t1 (c char(10), index (c,c)) engine=innodb;
+ERROR 42S21: Duplicate column name 'c'
+create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1)) engine=innodb;
+ERROR 42S21: Duplicate column name 'c1'
+create table t1 (c1 char(10), c2 char(10), index (c1,c1,c2)) engine=innodb;
+ERROR 42S21: Duplicate column name 'c1'
+create table t1 (c1 char(10), c2 char(10), index (c2,c1,c1)) engine=innodb;
+ERROR 42S21: Duplicate column name 'c1'
+create table t1 (c1 char(10), c2 char(10)) engine=innodb;
+alter table t1 add key (c1,c1);
+ERROR 42S21: Duplicate column name 'c1'
+alter table t1 add key (c2,c1,c1);
+ERROR 42S21: Duplicate column name 'c1'
+alter table t1 add key (c1,c2,c1);
+ERROR 42S21: Duplicate column name 'c1'
+alter table t1 add key (c1,c1,c2);
+ERROR 42S21: Duplicate column name 'c1'
+drop table t1;
diff --git a/mysql-test/r/insert_select.result b/mysql-test/r/insert_select.result
index 323302128da..94d33f8090b 100644
--- a/mysql-test/r/insert_select.result
+++ b/mysql-test/r/insert_select.result
@@ -81,6 +81,15 @@ a
1
2
drop table t1, t2;
+create table t1(a int);
+insert into t1 values(1),(1);
+reset master;
+create table t2(unique(a)) select a from t1;
+ERROR 23000: Duplicate entry '1' for key 1
+show binlog events;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 4 Format_desc 1 95 Server ver: VERSION, Binlog ver: 4
+drop table t1;
create table t1 (a int not null);
create table t2 (a int not null);
insert into t1 values (1);
diff --git a/mysql-test/r/join_outer.result b/mysql-test/r/join_outer.result
index 35226c56dab..2f420905195 100644
--- a/mysql-test/r/join_outer.result
+++ b/mysql-test/r/join_outer.result
@@ -745,6 +745,71 @@ player_id match_1_h * match_id home UUX
7 4 * 1 2 2
3 3 * 1 2 1
drop table t1, t2;
+create table t1 (a int, b int, unique index idx (a, b));
+create table t2 (a int, b int, c int, unique index idx (a, b));
+insert into t1 values (1, 10), (1,11), (2,10), (2,11);
+insert into t2 values (1,10,3);
+select t1.a, t1.b, t2.c from t1 left join t2
+on t1.a=t2.a and t1.b=t2.b and t2.c=3
+where t1.a=1 and t2.c is null;
+a b c
+1 11 NULL
+drop table t1, t2;
+CREATE TABLE t1 (
+ts_id bigint(20) default NULL,
+inst_id tinyint(4) default NULL,
+flag_name varchar(64) default NULL,
+flag_value text,
+UNIQUE KEY ts_id (ts_id,inst_id,flag_name)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+CREATE TABLE t2 (
+ts_id bigint(20) default NULL,
+inst_id tinyint(4) default NULL,
+flag_name varchar(64) default NULL,
+flag_value text,
+UNIQUE KEY ts_id (ts_id,inst_id,flag_name)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+INSERT INTO t1 VALUES
+(111056548820001, 0, 'flag1', NULL),
+(111056548820001, 0, 'flag2', NULL),
+(2, 0, 'other_flag', NULL);
+INSERT INTO t2 VALUES
+(111056548820001, 3, 'flag1', 'sss');
+SELECT t1.flag_name,t2.flag_value
+FROM t1 LEFT JOIN t2
+ON (t1.ts_id = t2.ts_id AND t1.flag_name = t2.flag_name AND
+t2.inst_id = 3)
+WHERE t1.inst_id = 0 AND t1.ts_id=111056548820001 AND
+t2.flag_value IS NULL;
+flag_name flag_value
+flag2 NULL
+DROP TABLE t1,t2;
+CREATE TABLE invoice (
+id int(11) unsigned NOT NULL auto_increment,
+text_id int(10) unsigned default NULL,
+PRIMARY KEY (id)
+);
+INSERT INTO invoice VALUES("1", "0");
+INSERT INTO invoice VALUES("2", "10");
+CREATE TABLE text_table (
+text_id char(3) NOT NULL default '',
+language_id char(3) NOT NULL default '',
+text_data text,
+PRIMARY KEY (text_id,language_id)
+);
+INSERT INTO text_table VALUES("0", "EN", "0-EN");
+INSERT INTO text_table VALUES("0", "SV", "0-SV");
+INSERT INTO text_table VALUES("10", "EN", "10-EN");
+INSERT INTO text_table VALUES("10", "SV", "10-SV");
+SELECT invoice.id, invoice.text_id, text_table.text_data
+FROM invoice LEFT JOIN text_table
+ON invoice.text_id = text_table.text_id
+AND text_table.language_id = 'SV'
+ WHERE (invoice.id LIKE '%' OR text_table.text_data LIKE '%');
+id text_id text_data
+1 0 0-SV
+2 10 10-SV
+DROP TABLE invoice, text_table;
CREATE TABLE t0 (a0 int PRIMARY KEY);
CREATE TABLE t1 (a1 int PRIMARY KEY);
CREATE TABLE t2 (a2 int);
diff --git a/mysql-test/r/key.result b/mysql-test/r/key.result
index b11969ab6d7..98e8851bb7e 100644
--- a/mysql-test/r/key.result
+++ b/mysql-test/r/key.result
@@ -311,3 +311,21 @@ test.t1 check status OK
drop table t1;
create table t1 (c char(10), index (c(0)));
ERROR HY000: Key part 'c' length cannot be 0
+create table t1 (c char(10), index (c,c));
+ERROR 42S21: Duplicate column name 'c'
+create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1));
+ERROR 42S21: Duplicate column name 'c1'
+create table t1 (c1 char(10), c2 char(10), index (c1,c1,c2));
+ERROR 42S21: Duplicate column name 'c1'
+create table t1 (c1 char(10), c2 char(10), index (c2,c1,c1));
+ERROR 42S21: Duplicate column name 'c1'
+create table t1 (c1 char(10), c2 char(10));
+alter table t1 add key (c1,c1);
+ERROR 42S21: Duplicate column name 'c1'
+alter table t1 add key (c2,c1,c1);
+ERROR 42S21: Duplicate column name 'c1'
+alter table t1 add key (c1,c2,c1);
+ERROR 42S21: Duplicate column name 'c1'
+alter table t1 add key (c1,c1,c2);
+ERROR 42S21: Duplicate column name 'c1'
+drop table t1;
diff --git a/mysql-test/r/key_cache.result b/mysql-test/r/key_cache.result
index fe8708f882d..79b5a6e84b2 100644
--- a/mysql-test/r/key_cache.result
+++ b/mysql-test/r/key_cache.result
@@ -277,3 +277,13 @@ Key_blocks_unused KEY_BLOCKS_UNUSED
set global keycache2.key_buffer_size=0;
set global keycache3.key_buffer_size=100;
set global keycache3.key_buffer_size=0;
+create table t1 (mytext text, FULLTEXT (mytext));
+insert t1 values ('aaabbb');
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+set GLOBAL key_cache_block_size=2048;
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+drop table t1;
diff --git a/mysql-test/r/lock_multi.result b/mysql-test/r/lock_multi.result
index 4eb4ff6cdc2..9eedbf50064 100644
--- a/mysql-test/r/lock_multi.result
+++ b/mysql-test/r/lock_multi.result
@@ -26,7 +26,7 @@ lock table t1 read;
update t1,t2 set c=a where b=d;
select c from t2;
c
-1
+2
drop table t1;
drop table t2;
create table t1 (a int);
diff --git a/mysql-test/r/lowercase_table2.result b/mysql-test/r/lowercase_table2.result
index 228c7d325e5..3be73f6cc6a 100644
--- a/mysql-test/r/lowercase_table2.result
+++ b/mysql-test/r/lowercase_table2.result
@@ -4,11 +4,11 @@ DROP DATABASE IF EXISTS `test_$1`;
CREATE TABLE T1 (a int);
INSERT INTO T1 VALUES (1);
SHOW TABLES LIKE "T1";
-Tables_in_test (T1) table_type
-T1 BASE TABLE
+Tables_in_test (T1)
+T1
SHOW TABLES LIKE "t1";
-Tables_in_test (t1) table_type
-T1 BASE TABLE
+Tables_in_test (t1)
+T1
SHOW CREATE TABLE T1;
Table Create Table
T1 CREATE TABLE `T1` (
@@ -16,37 +16,37 @@ T1 CREATE TABLE `T1` (
) ENGINE=MyISAM DEFAULT CHARSET=latin1
RENAME TABLE T1 TO T2;
SHOW TABLES LIKE "T2";
-Tables_in_test (T2) table_type
-T2 BASE TABLE
+Tables_in_test (T2)
+T2
SELECT * FROM t2;
a
1
RENAME TABLE T2 TO t3;
SHOW TABLES LIKE "T3";
-Tables_in_test (T3) table_type
-t3 BASE TABLE
+Tables_in_test (T3)
+t3
RENAME TABLE T3 TO T1;
SHOW TABLES LIKE "T1";
-Tables_in_test (T1) table_type
-T1 BASE TABLE
+Tables_in_test (T1)
+T1
ALTER TABLE T1 add b int;
SHOW TABLES LIKE "T1";
-Tables_in_test (T1) table_type
-T1 BASE TABLE
+Tables_in_test (T1)
+T1
ALTER TABLE T1 RENAME T2;
SHOW TABLES LIKE "T2";
-Tables_in_test (T2) table_type
-T2 BASE TABLE
+Tables_in_test (T2)
+T2
LOCK TABLE T2 WRITE;
ALTER TABLE T2 drop b;
SHOW TABLES LIKE "T2";
-Tables_in_test (T2) table_type
-T2 BASE TABLE
+Tables_in_test (T2)
+T2
UNLOCK TABLES;
RENAME TABLE T2 TO T1;
SHOW TABLES LIKE "T1";
-Tables_in_test (T1) table_type
-T1 BASE TABLE
+Tables_in_test (T1)
+T1
SELECT * from T1;
a
1
@@ -59,11 +59,11 @@ DROP DATABASE `test_$1`;
CREATE TABLE T1 (a int) engine=innodb;
INSERT INTO T1 VALUES (1);
SHOW TABLES LIKE "T1";
-Tables_in_test (T1) table_type
-T1 BASE TABLE
+Tables_in_test (T1)
+T1
SHOW TABLES LIKE "t1";
-Tables_in_test (t1) table_type
-T1 BASE TABLE
+Tables_in_test (t1)
+T1
SHOW CREATE TABLE T1;
Table Create Table
T1 CREATE TABLE `T1` (
@@ -71,37 +71,37 @@ T1 CREATE TABLE `T1` (
) ENGINE=InnoDB DEFAULT CHARSET=latin1
RENAME TABLE T1 TO T2;
SHOW TABLES LIKE "T2";
-Tables_in_test (T2) table_type
-t2 BASE TABLE
+Tables_in_test (T2)
+t2
SELECT * FROM t2;
a
1
RENAME TABLE T2 TO t3;
SHOW TABLES LIKE "T3";
-Tables_in_test (T3) table_type
-t3 BASE TABLE
+Tables_in_test (T3)
+t3
RENAME TABLE T3 TO T1;
SHOW TABLES LIKE "T1";
-Tables_in_test (T1) table_type
-t1 BASE TABLE
+Tables_in_test (T1)
+t1
ALTER TABLE T1 add b int;
SHOW TABLES LIKE "T1";
-Tables_in_test (T1) table_type
-t1 BASE TABLE
+Tables_in_test (T1)
+t1
ALTER TABLE T1 RENAME T2;
SHOW TABLES LIKE "T2";
-Tables_in_test (T2) table_type
-t2 BASE TABLE
+Tables_in_test (T2)
+t2
LOCK TABLE T2 WRITE;
ALTER TABLE T2 drop b;
SHOW TABLES LIKE "T2";
-Tables_in_test (T2) table_type
-t2 BASE TABLE
+Tables_in_test (T2)
+t2
UNLOCK TABLES;
RENAME TABLE T2 TO T1;
SHOW TABLES LIKE "T1";
-Tables_in_test (T1) table_type
-t1 BASE TABLE
+Tables_in_test (T1)
+t1
SELECT * from T1;
a
1
@@ -124,10 +124,10 @@ drop table T1;
create table T1 (A int);
alter table T1 add index (A);
show tables like 'T1%';
-Tables_in_test (T1%) table_type
-T1 BASE TABLE
+Tables_in_test (T1%)
+T1
alter table t1 add index (A);
show tables like 't1%';
-Tables_in_test (t1%) table_type
-t1 BASE TABLE
+Tables_in_test (t1%)
+t1
drop table t1;
diff --git a/mysql-test/r/lowercase_table3.result b/mysql-test/r/lowercase_table3.result
index a645e46be9e..8182d07c26b 100644
--- a/mysql-test/r/lowercase_table3.result
+++ b/mysql-test/r/lowercase_table3.result
@@ -6,5 +6,5 @@ drop table t1;
flush tables;
CREATE TABLE t1 (a int) ENGINE=INNODB;
SELECT * from T1;
-ERROR HY000: Can't open file: 'T1.InnoDB' (errno: 1)
+ERROR HY000: Can't open file: 'T1.ibd' (errno: 1)
drop table t1;
diff --git a/mysql-test/r/lowercase_view.result b/mysql-test/r/lowercase_view.result
index 64b40389690..0644b32015c 100644
--- a/mysql-test/r/lowercase_view.result
+++ b/mysql-test/r/lowercase_view.result
@@ -22,3 +22,19 @@ insert into v2aA values ((select max(col1) from v1aA));
ERROR HY000: You can't specify target table 'v2aa' for update in FROM clause
drop view v2Aa,v1Aa;
drop table t1Aa,t2Aa;
+create table t1Aa (col1 int);
+create view v1Aa as select col1 from t1Aa as AaA;
+show create view v1AA;
+View Create View
+v1aa CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1aa` AS select `aaa`.`col1` AS `col1` from `test`.`t1aa` `AaA`
+drop view v1AA;
+select Aaa.col1 from t1Aa as AaA;
+col1
+create view v1Aa as select Aaa.col1 from t1Aa as AaA;
+drop view v1AA;
+create view v1Aa as select AaA.col1 from t1Aa as AaA;
+show create view v1AA;
+View Create View
+v1aa CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1aa` AS select `aaa`.`col1` AS `col1` from `test`.`t1aa` `AaA`
+drop view v1AA;
+drop table t1Aa;
diff --git a/mysql-test/r/merge.result b/mysql-test/r/merge.result
index b115b926f88..a9d90813660 100644
--- a/mysql-test/r/merge.result
+++ b/mysql-test/r/merge.result
@@ -614,19 +614,19 @@ KEY files (fileset_id,fileset_root_id)
EXPLAIN SELECT * FROM t2 IGNORE INDEX (files) WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range PRIMARY PRIMARY 33 NULL 5 Using where
+1 SIMPLE t2 range PRIMARY PRIMARY 35 NULL 5 Using where
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 range PRIMARY,files PRIMARY 33 NULL 5 Using where
+1 SIMPLE t2 range PRIMARY,files PRIMARY 35 NULL 5 Using where
EXPLAIN SELECT * FROM t1 WHERE fileset_id = 2
AND file_code BETWEEN '0000000115' AND '0000000120' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range PRIMARY,files PRIMARY 33 NULL 5 Using where
+1 SIMPLE t1 range PRIMARY,files PRIMARY 35 NULL 5 Using where
EXPLAIN SELECT * FROM t2 WHERE fileset_id = 2
AND file_code = '0000000115' LIMIT 1;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t2 const PRIMARY,files PRIMARY 33 const,const 1
+1 SIMPLE t2 ref PRIMARY,files PRIMARY 35 const,const 1 Using where
DROP TABLE t2, t1;
create table t1 (x int, y int, index xy(x, y));
create table t2 (x int, y int, index xy(x, y));
diff --git a/mysql-test/r/metadata.result b/mysql-test/r/metadata.result
index ced3ca61f80..bd3b7ad5c25 100644
--- a/mysql-test/r/metadata.result
+++ b/mysql-test/r/metadata.result
@@ -4,8 +4,8 @@ Catalog Database Table Table_alias Column Column_alias Name Type Length Max leng
def 1 8 1 1 N 32769 0 8
def 1.0 5 3 3 N 32769 1 8
def -1 8 1 2 N 32769 0 8
-def hello 254 5 5 N 1 31 8
-def NULL 6 0 0 Y 32768 0 8
+def hello 253 5 5 N 1 31 8
+def NULL 6 0 0 Y 32896 0 63
1 1.0 -1 hello NULL
1 1.0 -1 hello NULL
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, l datetime, m enum('a','b'), n set('a','b'), o char(10));
diff --git a/mysql-test/r/mix_innodb_myisam_binlog.result b/mysql-test/r/mix_innodb_myisam_binlog.result
index 11bc9772276..abcb451df65 100644
--- a/mysql-test/r/mix_innodb_myisam_binlog.result
+++ b/mysql-test/r/mix_innodb_myisam_binlog.result
@@ -180,4 +180,25 @@ master-bin.000001 95 Query 1 # use `test`; BEGIN
master-bin.000001 157 Query 1 # use `test`; insert into t1 values(16)
master-bin.000001 239 Query 1 # use `test`; insert into t1 values(18)
master-bin.000001 321 Query 1 # use `test`; COMMIT
+delete from t1;
+delete from t2;
+alter table t2 type=MyISAM;
+insert into t1 values (1);
+begin;
+select * from t1 for update;
+a
+1
+select (@before:=unix_timestamp())*0;
+(@before:=unix_timestamp())*0
+0
+begin;
+ select * from t1 for update;
+insert into t2 values (20);
+ERROR HY000: Lock wait timeout exceeded; try restarting transaction
+select (@after:=unix_timestamp())*0;
+(@after:=unix_timestamp())*0
+0
+select (@after-@before) >= 2;
+(@after-@before) >= 2
+1
drop table t1,t2;
diff --git a/mysql-test/r/multi_update.result b/mysql-test/r/multi_update.result
index df642b00673..b853b05f153 100644
--- a/mysql-test/r/multi_update.result
+++ b/mysql-test/r/multi_update.result
@@ -155,7 +155,6 @@ ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
-ERROR HY000: Table 't2' was locked with a READ lock and can't be updated
unlock tables;
LOCK TABLES t1 write, t2 write;
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
@@ -461,6 +460,7 @@ drop table t1, t2, t3;
create table t1 (col1 int);
create table t2 (col1 int);
update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
+ERROR HY000: You can't specify target table 't1' for update in FROM clause
delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1;
ERROR HY000: You can't specify target table 't1' for update in FROM clause
drop table t1,t2;
@@ -490,3 +490,24 @@ insert into t2 select * from t1;
delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
set @@storage_engine=@ttype_save;
drop table t1,t2;
+create table t1 (a int, b int);
+insert into t1 values (1, 2), (2, 3), (3, 4);
+create table t2 (a int);
+insert into t2 values (10), (20), (30);
+create view v1 as select a as b, a/10 as a from t2;
+lock table t1 write;
+ alter table t1 add column c int default 100 after a;
+ update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
+unlock tables;
+select * from t1;
+a c b
+1 100 13
+2 100 25
+3 100 37
+select * from t2;
+a
+10
+20
+30
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/r/myisam-blob.result.es b/mysql-test/r/myisam-blob.result.es
new file mode 100644
index 00000000000..4031b9cfd1c
--- /dev/null
+++ b/mysql-test/r/myisam-blob.result.es
@@ -0,0 +1,59 @@
+drop table if exists t1;
+CREATE TABLE t1 (data LONGBLOB) ENGINE=myisam;
+INSERT INTO t1 (data) VALUES (NULL);
+UPDATE t1 set data=repeat('a',18*1024*1024);
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (24) - truncated
+select length(data) from t1;
+length(data)
+NULL
+delete from t1 where left(data,1)='a';
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+truncate table t1;
+INSERT INTO t1 (data) VALUES (repeat('a',1*1024*1024));
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (24) - truncated
+INSERT INTO t1 (data) VALUES (repeat('b',16*1024*1024-1024));
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (24) - truncated
+delete from t1 where left(data,1)='b';
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+UPDATE t1 set data=repeat('c',17*1024*1024);
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (24) - truncated
+Warning 1301 Result of repeat() was larger than max_allowed_packet (24) - truncated
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+delete from t1 where left(data,1)='c';
+check table t1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+INSERT INTO t1 set data=repeat('a',18*1024*1024);
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (24) - truncated
+select length(data) from t1;
+length(data)
+NULL
+NULL
+NULL
+alter table t1 modify data blob;
+select length(data) from t1;
+length(data)
+NULL
+NULL
+NULL
+drop table t1;
+CREATE TABLE t1 (data BLOB) ENGINE=myisam;
+INSERT INTO t1 (data) VALUES (NULL);
+UPDATE t1 set data=repeat('a',18*1024*1024);
+Warnings:
+Warning 1301 Result of repeat() was larger than max_allowed_packet (24) - truncated
+select length(data) from t1;
+length(data)
+NULL
+drop table t1;
diff --git a/mysql-test/r/myisam.result b/mysql-test/r/myisam.result
index 26dcce43d08..0074b2672fc 100644
--- a/mysql-test/r/myisam.result
+++ b/mysql-test/r/myisam.result
@@ -408,8 +408,8 @@ Table Op Msg_type Msg_text
test.t1 repair status OK
select concat(a,'.') from t1 where a='aaa';
concat(a,'.')
-aaa.
aaa .
+aaa.
select concat(a,'.') from t1 where binary a='aaa';
concat(a,'.')
aaa.
@@ -461,20 +461,27 @@ concat(a,'.')
a .
drop table t1;
create table t1 (a int not null auto_increment primary key, b text not null, unique b (b(20)));
-insert into t1 (b) values ('a'),('a '),('a ');
+insert into t1 (b) values ('a'),('b'),('c');
select concat(b,'.') from t1;
concat(b,'.')
a.
-a .
-a .
+b.
+c.
update t1 set b='b ' where a=2;
update t1 set b='b ' where a > 1;
ERROR 23000: Duplicate entry 'b ' for key 2
+insert into t1 (b) values ('b');
+ERROR 23000: Duplicate entry 'b' for key 2
+select * from t1;
+a b
+1 a
+2 b
+3 c
delete from t1 where b='b';
select a,concat(b,'.') from t1;
a concat(b,'.')
1 a.
-3 a .
+3 c.
drop table t1;
create table t1 (a int not null);
create table t2 (a int not null, primary key (a));
@@ -506,18 +513,18 @@ insert t1 values (1, "aaa", "bbb"), (NULL, "", "ccccc"), (0, NULL, "");
insert t2 select * from t1;
checksum table t1, t2, t3 quick;
Table Checksum
-test.t1 968604391
+test.t1 272226711
test.t2 NULL
test.t3 NULL
checksum table t1, t2, t3;
Table Checksum
-test.t1 968604391
-test.t2 968604391
+test.t1 272226711
+test.t2 272226711
test.t3 NULL
checksum table t1, t2, t3 extended;
Table Checksum
-test.t1 968604391
-test.t2 968604391
+test.t1 272226711
+test.t2 272226711
test.t3 NULL
drop table t1,t2;
create table t1 (a int, key (a));
@@ -529,6 +536,7 @@ show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
t1 1 a 1 a A NULL NULL NULL YES BTREE disabled
create table t2 (a int);
+set @@rand_seed1=31415926,@@rand_seed2=2718281828;
insert t1 select * from t2;
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
@@ -543,7 +551,7 @@ Warnings:
Note 1031 Table storage engine for 't1' doesn't have this option
show keys from t1;
Table Non_unique Key_name Seq_in_index Column_name Collation Cardinality Sub_part Packed Null Index_type Comment
-t1 1 a 1 a NULL NULL NULL NULL YES HASH
+t1 1 a 1 a NULL 1000 NULL NULL YES HASH
drop table t1,t2;
create table t1 ( a tinytext, b char(1), index idx (a(1),b) );
insert into t1 values (null,''), (null,'');
@@ -554,3 +562,384 @@ select count(*) from t1 where a is null;
count(*)
2
drop table t1;
+set storage_engine=MyISAM;
+drop table if exists t1,t2,t3;
+--- Testing varchar ---
+--- Testing varchar ---
+create table t1 (v varchar(10), c char(10), t text);
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+Warnings:
+Warning 1265 Data truncated for column 'v' at row 1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+ *+*+ *
+*+ *+*+ *
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t2 like t1;
+show create table t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+create table t3 select * from t1;
+show create table t3;
+Table Create Table
+t3 CREATE TABLE `t3` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify c varchar(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify v char(10);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+alter table t1 modify t varchar(10);
+Warnings:
+Warning 1265 Data truncated for column 't' at row 2
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) default NULL,
+ `c` varchar(10) default NULL,
+ `t` varchar(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select concat('*',v,'*',c,'*',t,'*') from t1;
+concat('*',v,'*',c,'*',t,'*')
+*+*+*+ *
+*+*+*+ *
+drop table t1,t2,t3;
+create table t1 (v varchar(10), c char(10), t text, key(v), key(c), key(t(10)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`),
+ KEY `c` (`c`),
+ KEY `t` (`t`(10))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select count(*) from t1;
+count(*)
+270
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+count(*)
+10
+select count(*) from t1 where c='a';
+count(*)
+10
+select count(*) from t1 where t='a';
+count(*)
+10
+select count(*) from t1 where v='a ';
+count(*)
+10
+select count(*) from t1 where c='a ';
+count(*)
+10
+select count(*) from t1 where t='a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ';
+count(*)
+10
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+count(*)
+10
+select count(*) from t1 where v like 'a%';
+count(*)
+11
+select count(*) from t1 where c like 'a%';
+count(*)
+11
+select count(*) from t1 where t like 'a%';
+count(*)
+11
+select count(*) from t1 where v like 'a %';
+count(*)
+9
+explain select count(*) from t1 where v='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v v 13 const 9 Using where; Using index
+explain select count(*) from t1 where c='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref c c 11 const 9 Using where; Using index
+explain select count(*) from t1 where t='a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range t t 13 NULL 9 Using where
+explain select count(*) from t1 where v like 'a%';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL 10 Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL 9 Using where; Using index
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range v v 13 NULL 9 Using where; Using index
+alter table t1 add unique(v);
+ERROR 23000: Duplicate entry '{ ' for key 1
+alter table t1 add key(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a';
+qq
+*a*a*a*
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+*a *a*a *
+explain select * from t1 where v='a';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref v,v_2 v_2 13 const 7 Using where
+select v,count(*) from t1 group by v limit 10;
+v count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(t) from t1 group by v limit 10;
+v count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result v,count(c) from t1 group by v limit 10;
+v count(c)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(*) from t1 group by c limit 10;
+c count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result c,count(t) from t1 group by c limit 10;
+c count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(*) from t1 group by t limit 10;
+t count(*)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+select sql_big_result t,count(t) from t1 group by t limit 10;
+t count(t)
+a 1
+a 10
+b 10
+c 10
+d 10
+e 10
+f 10
+g 10
+h 10
+i 10
+drop table t1;
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a ');
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a' for key 1
+alter table t1 modify a varchar(10);
+insert into t1 values ('a '),('a '),('a '),('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+insert into t1 values ('a ');
+ERROR 23000: Duplicate entry 'a ' for key 1
+update t1 set a='a ' where a like 'a%';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='abc ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a %';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+update t1 set a='a ' where a like 'a ';
+select concat(a,'.') from t1;
+concat(a,'.')
+a .
+drop table t1;
+create table t1 (v varchar(10), c char(10), t text, key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL,
+ `t` text,
+ KEY `v` (`v`(5)),
+ KEY `c` (`c`(5)),
+ KEY `t` (`t`(5))
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v char(10) character set utf8);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` char(10) character set utf8 default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(10), c char(10)) row_format=fixed;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(10) default NULL,
+ `c` char(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1 ROW_FORMAT=FIXED
+insert into t1 values('a','a'),('a ','a ');
+select concat('*',v,'*',c,'*') from t1;
+concat('*',v,'*',c,'*')
+*a*a*
+*a *a*
+drop table t1;
+create table t1 (v varchar(65530), key(v(10)));
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+length(v)
+65530
+drop table t1;
+create table t1 (v varchar(65530), key(v));
+Warnings:
+Warning 1071 Specified key was too long; max key length is 1000 bytes
+drop table if exists t1;
+create table t1 (v varchar(65536));
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 (v varchar(65530) character set utf8);
+Warnings:
+Note 1246 Converting column 'v' from VARCHAR to TEXT
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` mediumtext character set utf8
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+set storage_engine=MyISAM;
+create table t1 (v varchar(65535));
+ERROR 42000: Row size too large. The maximum row size for the used table type, not counting BLOBs, is 65535. You have to change some columns to TEXT or BLOBs
diff --git a/mysql-test/r/mysqldump.result b/mysql-test/r/mysqldump.result
index 2c8b8816da5..62b7bdb9fb1 100644
--- a/mysql-test/r/mysqldump.result
+++ b/mysql-test/r/mysqldump.result
@@ -106,7 +106,7 @@ INSERT INTO t1 VALUES (1, "test", "tes"), (2, "TEST", "TES");
<table_structure name="t1">
<field Field="a" Type="int(11)" Null="YES" Key="" Extra="" />
<field Field="b" Type="text" Null="YES" Key="" Extra="" />
- <field Field="c" Type="char(3)" Null="YES" Key="" Extra="" />
+ <field Field="c" Type="varchar(3)" Null="YES" Key="" Extra="" />
</table_structure>
<table_data name="t1">
<row>
@@ -367,3 +367,45 @@ CREATE ALGORITHM=UNDEFINED VIEW `test`.`v1` AS select `test`.`t1`.`a` AS `a` fro
drop view v1;
drop table t1;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO" */;
+
+CREATE DATABASE /*!32312 IF NOT EXISTS*/ `test` /*!40100 DEFAULT CHARACTER SET latin1 */;
+
+USE `test`;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+
+create database mysqldump_test_db character set latin2 collate latin2_bin;
+
+/*!40101 SET @OLD_CHARACTER_SET_CLIENT=@@CHARACTER_SET_CLIENT */;
+/*!40101 SET @OLD_CHARACTER_SET_RESULTS=@@CHARACTER_SET_RESULTS */;
+/*!40101 SET @OLD_COLLATION_CONNECTION=@@COLLATION_CONNECTION */;
+/*!40101 SET NAMES utf8 */;
+/*!40014 SET @OLD_UNIQUE_CHECKS=@@UNIQUE_CHECKS, UNIQUE_CHECKS=0 */;
+/*!40014 SET @OLD_FOREIGN_KEY_CHECKS=@@FOREIGN_KEY_CHECKS, FOREIGN_KEY_CHECKS=0 */;
+/*!40101 SET @OLD_SQL_MODE=@@SQL_MODE, SQL_MODE="NO_AUTO_VALUE_ON_ZERO" */;
+
+CREATE DATABASE /*!32312 IF NOT EXISTS*/ `mysqldump_test_db` /*!40100 DEFAULT CHARACTER SET latin2 COLLATE latin2_bin */;
+
+USE `mysqldump_test_db`;
+
+/*!40101 SET SQL_MODE=@OLD_SQL_MODE */;
+/*!40014 SET FOREIGN_KEY_CHECKS=@OLD_FOREIGN_KEY_CHECKS */;
+/*!40014 SET UNIQUE_CHECKS=@OLD_UNIQUE_CHECKS */;
+/*!40101 SET CHARACTER_SET_CLIENT=@OLD_CHARACTER_SET_CLIENT */;
+/*!40101 SET CHARACTER_SET_RESULTS=@OLD_CHARACTER_SET_RESULTS */;
+/*!40101 SET COLLATION_CONNECTION=@OLD_COLLATION_CONNECTION */;
+
+drop database mysqldump_test_db;
diff --git a/mysql-test/r/mysqltest.result b/mysql-test/r/mysqltest.result
index 4e30d5bc110..d75dbd5d00c 100644
--- a/mysql-test/r/mysqltest.result
+++ b/mysql-test/r/mysqltest.result
@@ -1,14 +1,12 @@
+select -1 as "before_use_test" ;
+before_use_test
+-1
select otto from (select 1 as otto) as t1;
otto
1
select otto from (select 1 as otto) as t1;
otto
1
-select otto from (select 1 as otto) as t1;
-otto
-1
-select friedrich from (select 1 as otto) as t1;
-ERROR 42S22: Unknown column 'friedrich' in 'field list'
select friedrich from (select 1 as otto) as t1;
ERROR 42S22: Unknown column 'friedrich' in 'field list'
select otto from (select 1 as otto) as t1;
@@ -21,3 +19,126 @@ select friedrich from (select 1 as otto) as t1;
ERROR 42S22: Unknown column 'friedrich' in 'field list'
select friedrich from (select 1 as otto) as t1;
ERROR 42S22: Unknown column 'friedrich' in 'field list'
+select otto from (select 1 as otto) as t1;
+otto
+1
+select 0 as "after_successful_stmt_errno" ;
+after_successful_stmt_errno
+0
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+select 1064 as "after_wrong_syntax_errno" ;
+after_wrong_syntax_errno
+1064
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+select 1064 as "after_let_var_equal_value" ;
+after_let_var_equal_value
+1064
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+set @my_var= 'abc' ;
+select 0 as "after_set_var_equal_value" ;
+after_set_var_equal_value
+0
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+select 1064 as "after_disable_warnings_command" ;
+after_disable_warnings_command
+1064
+drop table if exists t1 ;
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+drop table if exists t1 ;
+select 0 as "after_disable_warnings" ;
+after_disable_warnings
+0
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+select 3 from t1 ;
+ERROR 42S02: Table 'test.t1' doesn't exist
+select 1146 as "after_minus_masked" ;
+after_minus_masked
+1146
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+select 3 from t1 ;
+ERROR 42S02: Table 'test.t1' doesn't exist
+select 1146 as "after_!_masked" ;
+after_!_masked
+1146
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+select -1 as "after_let_errno_equal_value" ;
+after_let_errno_equal_value
+-1
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+prepare stmt from "select 3 from t1" ;
+ERROR 42S02: Table 'test.t1' doesn't exist
+select 1146 as "after_failing_prepare" ;
+after_failing_prepare
+1146
+create table t1 ( f1 char(10));
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+prepare stmt from "select 3 from t1" ;
+select 0 as "after_successful_prepare" ;
+after_successful_prepare
+0
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+execute stmt;
+3
+select 0 as "after_successful_execute" ;
+after_successful_execute
+0
+drop table t1;
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+execute stmt;
+ERROR 42S02: Table 'test.t1' doesn't exist
+select 1146 as "after_failing_execute" ;
+after_failing_execute
+1146
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+execute __stmt_;
+ERROR HY000: Unknown prepared statement handler (__stmt_) given to EXECUTE
+select 1243 as "after_failing_execute" ;
+after_failing_execute
+1243
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+deallocate prepare stmt;
+select 0 as "after_successful_deallocate" ;
+after_successful_deallocate
+0
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+deallocate prepare __stmt_;
+ERROR HY000: Unknown prepared statement handler (__stmt_) given to DEALLOCATE PREPARE
+select 1243 as "after_failing_deallocate" ;
+after_failing_deallocate
+1243
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+select 1064 as "after_--disable_abort_on_error" ;
+after_--disable_abort_on_error
+1064
+select 3 from t1 ;
+ERROR 42S02: Table 'test.t1' doesn't exist
+select 3 from t1 ;
+ERROR 42S02: Table 'test.t1' doesn't exist
+select 3 from t1 ;
+ERROR 42S02: Table 'test.t1' doesn't exist
+select 1146 as "after_!errno_masked_error" ;
+after_!errno_masked_error
+1146
+garbage ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'garbage' at line 1
+select 1064 as "after_--enable_abort_on_error" ;
+after_--enable_abort_on_error
+1064
+select 3 from t1 ;
+ERROR 42S02: Table 'test.t1' doesn't exist
diff --git a/mysql-test/r/ndb_alter_table.result b/mysql-test/r/ndb_alter_table.result
index ab651646c15..d3f60ba4650 100644
--- a/mysql-test/r/ndb_alter_table.result
+++ b/mysql-test/r/ndb_alter_table.result
@@ -18,13 +18,13 @@ col5 enum('PENDING', 'ACTIVE', 'DISABLED') not null,
col6 int not null, to_be_deleted int) ENGINE=ndbcluster;
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ndbcluster 9 Dynamic 0 0 0 NULL 0 0 1 NULL NULL NULL latin1_swedish_ci NULL
+t1 ndbcluster 9 Dynamic 0 0 0 0 0 0 1 NULL NULL NULL latin1_swedish_ci NULL
SET SQL_MODE=NO_AUTO_VALUE_ON_ZERO;
insert into t1 values
(0,4,3,5,"PENDING",1,7),(NULL,4,3,5,"PENDING",1,7),(31,4,3,5,"PENDING",1,7), (7,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7), (100,4,3,5,"PENDING",1,7), (99,4,3,5,"PENDING",1,7), (8,4,3,5,"PENDING",1,7), (NULL,4,3,5,"PENDING",1,7);
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ndbcluster 9 Dynamic 9 0 0 NULL 0 0 101 NULL NULL NULL latin1_swedish_ci NULL
+t1 ndbcluster 9 Dynamic 9 0 0 0 0 0 101 NULL NULL NULL latin1_swedish_ci NULL
select * from t1 order by col1;
col1 col2 col3 col4 col5 col6 to_be_deleted
0 4 3 5 PENDING 1 7
@@ -44,7 +44,7 @@ change column col2 fourth varchar(30) not null after col3,
modify column col6 int not null first;
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ndbcluster 9 Dynamic 9 0 0 NULL 0 0 102 NULL NULL NULL latin1_swedish_ci NULL
+t1 ndbcluster 9 Dynamic 9 0 0 0 0 0 102 NULL NULL NULL latin1_swedish_ci NULL
select * from t1 order by col1;
col6 col1 col3 fourth col4 col4_5 col5 col7 col8
1 0 3 4 5 PENDING 0000-00-00 00:00:00
@@ -59,7 +59,7 @@ col6 col1 col3 fourth col4 col4_5 col5 col7 col8
insert into t1 values (2, NULL,4,3,5,99,"PENDING","EXTRA",'2004-01-01 00:00:00');
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 ndbcluster 9 Dynamic 10 0 0 NULL 0 0 103 NULL NULL NULL latin1_swedish_ci NULL
+t1 ndbcluster 9 Dynamic 10 0 0 0 0 0 103 NULL NULL NULL latin1_swedish_ci NULL
select * from t1 order by col1;
col6 col1 col3 fourth col4 col4_5 col5 col7 col8
1 0 3 4 5 PENDING 0000-00-00 00:00:00
diff --git a/mysql-test/r/ndb_autodiscover.result b/mysql-test/r/ndb_autodiscover.result
index 4925aac8ac1..82ff4072378 100644
--- a/mysql-test/r/ndb_autodiscover.result
+++ b/mysql-test/r/ndb_autodiscover.result
@@ -1,4 +1,4 @@
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
flush status;
create table t1(
id int not null primary key,
@@ -363,3 +363,8 @@ a int NOT NULL PRIMARY KEY,
b int
) engine=ndb;
insert t9 values(1, 2), (2,3), (3, 4), (4, 5);
+create table t10 (
+a int not null primary key,
+b blob
+) engine=ndb;
+insert into t10 values (1, 'kalle');
diff --git a/mysql-test/r/ndb_autodiscover2.result b/mysql-test/r/ndb_autodiscover2.result
index 08803d997a5..91f018b5d02 100644
--- a/mysql-test/r/ndb_autodiscover2.result
+++ b/mysql-test/r/ndb_autodiscover2.result
@@ -8,3 +8,6 @@ show status like 'handler_discover%';
Variable_name Value
Handler_discover 1
drop table t9;
+select * from t10;
+ERROR HY000: Got error 4263 'Invalid blob attributes or invalid blob parts table' from ndbcluster
+drop table t10;
diff --git a/mysql-test/r/ndb_basic.result b/mysql-test/r/ndb_basic.result
index abe1b98b536..6ec5338acbe 100644
--- a/mysql-test/r/ndb_basic.result
+++ b/mysql-test/r/ndb_basic.result
@@ -40,6 +40,11 @@ SELECT * FROM t1 ORDER BY pk1;
pk1 attr1 attr2 attr3
3 1 NULL 9412
9412 9413 17 9413
+UPDATE t1 SET pk1=4 WHERE pk1 = 3;
+SELECT * FROM t1 ORDER BY pk1;
+pk1 attr1 attr2 attr3
+4 1 NULL 9412
+9412 9413 17 9413
DELETE FROM t1;
SELECT * FROM t1;
pk1 attr1 attr2 attr3
@@ -395,6 +400,13 @@ b attr1
9413 9412
drop table test.t1, t2;
drop database mysqltest;
+drop database if exists ndbtest1;
+create database ndbtest1;
+use ndbtest1;
+create table t1(id int) engine=ndbcluster;
+drop database ndbtest1;
+drop database ndbtest1;
+ERROR HY000: Can't drop database 'ndbtest1'; database doesn't exist
use test;
create table t1 (a int primary key, b char(0));
insert into t1 values (1,"");
@@ -414,3 +426,150 @@ select * from t1 where b IS NOT NULL;
a b
1
drop table t1;
+create table t1 (
+c1 int,
+c2 int,
+c3 int,
+c4 int,
+c5 int,
+c6 int,
+c7 int,
+c8 int,
+c9 int,
+c10 int,
+c11 int,
+c12 int,
+c13 int,
+c14 int,
+c15 int,
+c16 int,
+c17 int,
+c18 int,
+c19 int,
+c20 int,
+c21 int,
+c22 int,
+c23 int,
+c24 int,
+c25 int,
+c26 int,
+c27 int,
+c28 int,
+c29 int,
+c30 int,
+c31 int,
+c32 int,
+c33 int,
+c34 int,
+c35 int,
+c36 int,
+c37 int,
+c38 int,
+c39 int,
+c40 int,
+c41 int,
+c42 int,
+c43 int,
+c44 int,
+c45 int,
+c46 int,
+c47 int,
+c48 int,
+c49 int,
+c50 int,
+c51 int,
+c52 int,
+c53 int,
+c54 int,
+c55 int,
+c56 int,
+c57 int,
+c58 int,
+c59 int,
+c60 int,
+c61 int,
+c62 int,
+c63 int,
+c64 int,
+c65 int,
+c66 int,
+c67 int,
+c68 int,
+c69 int,
+c70 int,
+c71 int,
+c72 int,
+c73 int,
+c74 int,
+c75 int,
+c76 int,
+c77 int,
+c78 int,
+c79 int,
+c80 int,
+c81 int,
+c82 int,
+c83 int,
+c84 int,
+c85 int,
+c86 int,
+c87 int,
+c88 int,
+c89 int,
+c90 int,
+c91 int,
+c92 int,
+c93 int,
+c94 int,
+c95 int,
+c96 int,
+c97 int,
+c98 int,
+c99 int,
+c100 int,
+c101 int,
+c102 int,
+c103 int,
+c104 int,
+c105 int,
+c106 int,
+c107 int,
+c108 int,
+c109 int,
+c110 int,
+c111 int,
+c112 int,
+c113 int,
+c114 int,
+c115 int,
+c116 int,
+c117 int,
+c118 int,
+c119 int,
+c120 int,
+c121 int,
+c122 int,
+c123 int,
+c124 int,
+c125 int,
+c126 int,
+c127 int,
+c128 int,
+primary key(c1)) engine=ndb;
+drop table t1;
+create table t1 (
+a1234567890123456789012345678901234567890 int primary key,
+a12345678901234567890123456789a1234567890 int,
+index(a12345678901234567890123456789a1234567890)
+) engine=ndb;
+show tables;
+Tables_in_test
+t1
+insert into t1 values (1,1),(2,1),(3,1),(4,1),(5,2),(6,1),(7,1);
+explain select * from t1 where a12345678901234567890123456789a1234567890=2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a12345678901234567890123456789a1234567890 a12345678901234567890123456789a1234567890 5 const 10 Using where
+select * from t1 where a12345678901234567890123456789a1234567890=2;
+a1234567890123456789012345678901234567890 a12345678901234567890123456789a1234567890
+5 2
+drop table t1;
diff --git a/mysql-test/r/ndb_blob.result b/mysql-test/r/ndb_blob.result
index 25da313c67e..44109dabbc8 100644
--- a/mysql-test/r/ndb_blob.result
+++ b/mysql-test/r/ndb_blob.result
@@ -1,25 +1,5 @@
drop table if exists t1;
-drop database if exists mysqltest;
-create table t1 (
-a int not null primary key,
-b tinytext
-) engine=ndbcluster;
-insert into t1 values(1, 'x');
-update t1 set b = 'y';
-select * from t1;
-a b
-1 y
-delete from t1;
-drop table t1;
-create table t1 (
-a int not null primary key,
-b text not null
-) engine=ndbcluster;
-insert into t1 values(1, '');
-select * from t1;
-a b
-1
-drop table t1;
+drop database if exists test2;
set autocommit=0;
create table t1 (
a int not null primary key,
@@ -102,6 +82,53 @@ commit;
select count(*) from t1;
count(*)
0
+replace t1 set a=1,b=@b1,c=111,d=@d1;
+replace t1 set a=2,b=@b2,c=222,d=@d2;
+commit;
+explain select * from t1 where a = 1;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1
+select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3)
+from t1 where a=1;
+a length(b) substr(b,1+2*900,2) length(d) substr(d,1+3*900,3)
+1 2256 b1 3000 dd1
+select a,length(b),substr(b,1+2*9000,2),length(d),substr(d,1+3*9000,3)
+from t1 where a=2;
+a length(b) substr(b,1+2*9000,2) length(d) substr(d,1+3*9000,3)
+2 20000 b2 30000 dd2
+replace t1 set a=1,b=@b2,c=111,d=@d2;
+replace t1 set a=2,b=@b1,c=222,d=@d1;
+commit;
+select a,length(b),substr(b,1+2*9000,2),length(d),substr(d,1+3*9000,3)
+from t1 where a=1;
+a length(b) substr(b,1+2*9000,2) length(d) substr(d,1+3*9000,3)
+1 20000 b2 30000 dd2
+select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3)
+from t1 where a=2;
+a length(b) substr(b,1+2*900,2) length(d) substr(d,1+3*900,3)
+2 2256 b1 3000 dd1
+replace t1 set a=1,b=concat(@b2,@b2),c=111,d=concat(@d2,@d2);
+replace t1 set a=2,b=concat(@b1,@b1),c=222,d=concat(@d1,@d1);
+commit;
+select a,length(b),substr(b,1+4*9000,2),length(d),substr(d,1+6*9000,3)
+from t1 where a=1;
+a length(b) substr(b,1+4*9000,2) length(d) substr(d,1+6*9000,3)
+1 40000 b2 60000 dd2
+select a,length(b),substr(b,1+4*900,2),length(d),substr(d,1+6*900,3)
+from t1 where a=2;
+a length(b) substr(b,1+4*900,2) length(d) substr(d,1+6*900,3)
+2 4512 b1 6000 dd1
+replace t1 set a=1,b='xyz',c=111,d=null;
+commit;
+select a,b from t1 where d is null;
+a b
+1 xyz
+delete from t1 where a=1;
+delete from t1 where a=2;
+commit;
+select count(*) from t1;
+count(*)
+0
insert into t1 values(1,@b1,111,@d1);
insert into t1 values(2,@b2,222,@d2);
commit;
@@ -241,90 +268,6 @@ a b c d
7 7xb7 777 7xdd7
8 8xb8 888 8xdd8
9 9xb9 999 9xdd9
-select * from t1 order by a;
-a b c d
-1 1xb1 111 1xdd1
-2 2xb2 222 2xdd2
-3 3xb3 333 3xdd3
-4 4xb4 444 4xdd4
-5 5xb5 555 5xdd5
-6 6xb6 666 6xdd6
-7 7xb7 777 7xdd7
-8 8xb8 888 8xdd8
-9 9xb9 999 9xdd9
-alter table t1 add x int;
-select * from t1 order by a;
-a b c d x
-1 1xb1 111 1xdd1 NULL
-2 2xb2 222 2xdd2 NULL
-3 3xb3 333 3xdd3 NULL
-4 4xb4 444 4xdd4 NULL
-5 5xb5 555 5xdd5 NULL
-6 6xb6 666 6xdd6 NULL
-7 7xb7 777 7xdd7 NULL
-8 8xb8 888 8xdd8 NULL
-9 9xb9 999 9xdd9 NULL
-alter table t1 drop x;
-select * from t1 order by a;
-a b c d
-1 1xb1 111 1xdd1
-2 2xb2 222 2xdd2
-3 3xb3 333 3xdd3
-4 4xb4 444 4xdd4
-5 5xb5 555 5xdd5
-6 6xb6 666 6xdd6
-7 7xb7 777 7xdd7
-8 8xb8 888 8xdd8
-9 9xb9 999 9xdd9
-create database mysqltest;
-use mysqltest;
-CREATE TABLE t2 (
-a bigint unsigned NOT NULL PRIMARY KEY,
-b int unsigned not null,
-c int unsigned
-) engine=ndbcluster;
-insert into t2 values (1,1,1),(2,2,2);
-select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a;
-a b c d a b c
-1 1xb1 111 1xdd1 1 1 1
-2 2xb2 222 2xdd2 2 2 2
-drop table t2;
-use test;
-select * from t1 order by a;
-a b c d
-1 1xb1 111 1xdd1
-2 2xb2 222 2xdd2
-3 3xb3 333 3xdd3
-4 4xb4 444 4xdd4
-5 5xb5 555 5xdd5
-6 6xb6 666 6xdd6
-7 7xb7 777 7xdd7
-8 8xb8 888 8xdd8
-9 9xb9 999 9xdd9
-alter table t1 add x int;
-select * from t1 order by a;
-a b c d x
-1 1xb1 111 1xdd1 NULL
-2 2xb2 222 2xdd2 NULL
-3 3xb3 333 3xdd3 NULL
-4 4xb4 444 4xdd4 NULL
-5 5xb5 555 5xdd5 NULL
-6 6xb6 666 6xdd6 NULL
-7 7xb7 777 7xdd7 NULL
-8 8xb8 888 8xdd8 NULL
-9 9xb9 999 9xdd9 NULL
-alter table t1 drop x;
-select * from t1 order by a;
-a b c d
-1 1xb1 111 1xdd1
-2 2xb2 222 2xdd2
-3 3xb3 333 3xdd3
-4 4xb4 444 4xdd4
-5 5xb5 555 5xdd5
-6 6xb6 666 6xdd6
-7 7xb7 777 7xdd7
-8 8xb8 888 8xdd8
-9 9xb9 999 9xdd9
delete from t1 where c >= 100;
commit;
select count(*) from t1;
@@ -375,8 +318,128 @@ rollback;
select count(*) from t1;
count(*)
0
+insert into t1 values(1,'b1',111,'dd1');
+insert into t1 values(2,'b2',222,'dd2');
+insert into t1 values(3,'b3',333,'dd3');
+insert into t1 values(4,'b4',444,'dd4');
+insert into t1 values(5,'b5',555,'dd5');
+insert into t1 values(6,'b6',666,'dd6');
+insert into t1 values(7,'b7',777,'dd7');
+insert into t1 values(8,'b8',888,'dd8');
+insert into t1 values(9,'b9',999,'dd9');
+commit;
+select * from t1 order by a;
+a b c d
+1 b1 111 dd1
+2 b2 222 dd2
+3 b3 333 dd3
+4 b4 444 dd4
+5 b5 555 dd5
+6 b6 666 dd6
+7 b7 777 dd7
+8 b8 888 dd8
+9 b9 999 dd9
+alter table t1 add x int;
+select * from t1 order by a;
+a b c d x
+1 b1 111 dd1 NULL
+2 b2 222 dd2 NULL
+3 b3 333 dd3 NULL
+4 b4 444 dd4 NULL
+5 b5 555 dd5 NULL
+6 b6 666 dd6 NULL
+7 b7 777 dd7 NULL
+8 b8 888 dd8 NULL
+9 b9 999 dd9 NULL
+alter table t1 drop x;
+select * from t1 order by a;
+a b c d
+1 b1 111 dd1
+2 b2 222 dd2
+3 b3 333 dd3
+4 b4 444 dd4
+5 b5 555 dd5
+6 b6 666 dd6
+7 b7 777 dd7
+8 b8 888 dd8
+9 b9 999 dd9
+create database test2;
+use test2;
+CREATE TABLE t2 (
+a bigint unsigned NOT NULL PRIMARY KEY,
+b int unsigned not null,
+c int unsigned
+) engine=ndbcluster;
+insert into t2 values (1,1,1),(2,2,2);
+select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a;
+a b c d a b c
+1 b1 111 dd1 1 1 1
+2 b2 222 dd2 2 2 2
+drop table t2;
+use test;
+select * from t1 order by a;
+a b c d
+1 b1 111 dd1
+2 b2 222 dd2
+3 b3 333 dd3
+4 b4 444 dd4
+5 b5 555 dd5
+6 b6 666 dd6
+7 b7 777 dd7
+8 b8 888 dd8
+9 b9 999 dd9
+alter table t1 add x int;
+select * from t1 order by a;
+a b c d x
+1 b1 111 dd1 NULL
+2 b2 222 dd2 NULL
+3 b3 333 dd3 NULL
+4 b4 444 dd4 NULL
+5 b5 555 dd5 NULL
+6 b6 666 dd6 NULL
+7 b7 777 dd7 NULL
+8 b8 888 dd8 NULL
+9 b9 999 dd9 NULL
+alter table t1 drop x;
+select * from t1 order by a;
+a b c d
+1 b1 111 dd1
+2 b2 222 dd2
+3 b3 333 dd3
+4 b4 444 dd4
+5 b5 555 dd5
+6 b6 666 dd6
+7 b7 777 dd7
+8 b8 888 dd8
+9 b9 999 dd9
+drop table t1;
+drop database test2;
+set autocommit=0;
+create table t1 (
+a int not null primary key,
+b tinytext
+) engine=ndbcluster;
+insert into t1 values(1, 'x');
+update t1 set b = 'y';
+select * from t1;
+a b
+1 y
+delete from t1;
+select * from t1;
+a b
+commit;
+drop table t1;
+set autocommit=0;
+create table t1 (
+a int not null primary key,
+b text not null
+) engine=ndbcluster;
+insert into t1 values(1, '');
+select * from t1;
+a b
+1
+commit;
drop table t1;
-drop database mysqltest;
set autocommit=1;
use test;
CREATE TABLE t1 (
@@ -397,6 +460,7 @@ select * from t1 order by a;
a b
1 AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA
2 BBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBBB
+set autocommit=1;
alter table t1 engine=myisam;
select * from t1 order by a;
a b
diff --git a/mysql-test/r/ndb_charset.result b/mysql-test/r/ndb_charset.result
index 93429a1fcb0..00bc36a7c0d 100644
--- a/mysql-test/r/ndb_charset.result
+++ b/mysql-test/r/ndb_charset.result
@@ -78,9 +78,9 @@ unique key(a)
) engine=ndb;
insert into t1 values(1, 'aAa');
insert into t1 values(2, 'aaa');
-ERROR 23000: Can't write, because of unique constraint, to table 't1'
+ERROR 23000: Duplicate entry '2' for key 1
insert into t1 values(3, 'AAA');
-ERROR 23000: Can't write, because of unique constraint, to table 't1'
+ERROR 23000: Duplicate entry '3' for key 1
select * from t1 order by p;
p a
1 aAa
@@ -189,3 +189,13 @@ p a
5 aaa
6 AAA
drop table t1;
+create table t1 (
+a varchar(10) primary key
+) engine=ndb;
+insert into t1 values ('jonas % ');
+replace into t1 values ('jonas % ');
+replace into t1 values ('jonas % ');
+select * from t1;
+a
+jonas %
+drop table t1;
diff --git a/mysql-test/r/ndb_grant.result b/mysql-test/r/ndb_grant.result
new file mode 100644
index 00000000000..6192a7cace5
--- /dev/null
+++ b/mysql-test/r/ndb_grant.result
@@ -0,0 +1,444 @@
+drop table if exists t1;
+SET NAMES binary;
+use mysql;
+alter table columns_priv engine=ndb;
+alter table db engine=ndb;
+alter table func engine=ndb;
+alter table help_category engine=ndb;
+alter table help_keyword engine=ndb;
+alter table help_relation engine=ndb;
+alter table help_topic engine=ndb;
+alter table host engine=ndb;
+alter table tables_priv engine=ndb;
+alter table time_zone engine=ndb;
+alter table time_zone_leap_second engine=ndb;
+alter table time_zone_name engine=ndb;
+alter table time_zone_transition engine=ndb;
+alter table time_zone_transition_type engine=ndb;
+alter table user engine=ndb;
+use test;
+delete from mysql.user where user='mysqltest_1';
+delete from mysql.db where user='mysqltest_1';
+flush privileges;
+begin;
+grant select on mysqltest.* to mysqltest_1@localhost require cipher "EDH-RSA-DES-CBC3-SHA";
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
+GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+begin;
+grant delete on mysqltest.* to mysqltest_1@localhost;
+commit;
+select * from mysql.user where user="mysqltest_1";
+Host User Password Select_priv Insert_priv Update_priv Delete_priv Create_priv Drop_priv Reload_priv Shutdown_priv Process_priv File_priv Grant_priv References_priv Index_priv Alter_priv Show_db_priv Super_priv Create_tmp_table_priv Lock_tables_priv Execute_priv Repl_slave_priv Repl_client_priv Create_view_priv Show_view_priv ssl_type ssl_cipher x509_issuer x509_subject max_questions max_updates max_connections
+localhost mysqltest_1 N N N N N N N N N N N N N N N N N N N N N 0 0 0
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
+GRANT SELECT, DELETE ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+begin;
+revoke delete on mysqltest.* from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE CIPHER 'EDH-RSA-DES-CBC3-SHA'
+GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+begin;
+grant select on mysqltest.* to mysqltest_1@localhost require NONE;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+begin;
+grant USAGE on mysqltest.* to mysqltest_1@localhost require cipher "EDH-RSA-DES-CBC3-SHA" AND SUBJECT "testsubject" ISSUER "MySQL AB";
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE ISSUER 'MySQL AB' SUBJECT 'testsubject' CIPHER 'EDH-RSA-DES-CBC3-SHA'
+GRANT SELECT ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+begin;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' REQUIRE ISSUER 'MySQL AB' SUBJECT 'testsubject' CIPHER 'EDH-RSA-DES-CBC3-SHA'
+delete from mysql.user where user='mysqltest_1';
+flush privileges;
+begin;
+grant CREATE TEMPORARY TABLES, LOCK TABLES on mysqltest.* to mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT CREATE TEMPORARY TABLES, LOCK TABLES ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+flush privileges;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT CREATE TEMPORARY TABLES, LOCK TABLES ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+begin;
+revoke CREATE TEMPORARY TABLES on mysqltest.* from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT LOCK TABLES ON `mysqltest`.* TO 'mysqltest_1'@'localhost'
+begin;
+grant ALL PRIVILEGES on mysqltest.* to mysqltest_1@localhost with GRANT OPTION;
+commit;
+flush privileges;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT ALL PRIVILEGES ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
+begin;
+revoke LOCK TABLES, ALTER on mysqltest.* from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT SELECT, INSERT, UPDATE, DELETE, CREATE, DROP, REFERENCES, INDEX, CREATE TEMPORARY TABLES, CREATE VIEW, SHOW VIEW ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
+begin;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+commit;
+delete from mysql.user where user='mysqltest_1';
+flush privileges;
+begin;
+grant usage on test.* to mysqltest_1@localhost with grant option;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT USAGE ON `mysqltest`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
+GRANT USAGE ON `test`.* TO 'mysqltest_1'@'localhost' WITH GRANT OPTION
+delete from mysql.user where user='mysqltest_1';
+delete from mysql.db where user='mysqltest_1';
+delete from mysql.tables_priv where user='mysqltest_1';
+delete from mysql.columns_priv where user='mysqltest_1';
+flush privileges;
+show grants for mysqltest_1@localhost;
+ERROR 42000: There is no such grant defined for user 'mysqltest_1' on host 'localhost'
+create table t1 (a int);
+begin;
+GRANT select,update,insert on t1 to mysqltest_1@localhost;
+GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT SELECT, SELECT (a), INSERT, INSERT (a), UPDATE, UPDATE (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
+select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
+table_priv column_priv
+Select,Insert,Update Select,Insert,Update,References
+begin;
+REVOKE select (a), update on t1 from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT SELECT, INSERT, INSERT (a), REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
+begin;
+REVOKE select,update,insert,insert (a) on t1 from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost'
+GRANT REFERENCES (a) ON `test`.`t1` TO 'mysqltest_1'@'localhost'
+begin;
+GRANT select,references on t1 to mysqltest_1@localhost;
+commit;
+select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
+table_priv column_priv
+Select,References References
+begin;
+grant all on test.* to mysqltest_3@localhost with grant option;
+revoke all on test.* from mysqltest_3@localhost;
+commit;
+show grants for mysqltest_3@localhost;
+Grants for mysqltest_3@localhost
+GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost'
+GRANT USAGE ON `test`.* TO 'mysqltest_3'@'localhost' WITH GRANT OPTION
+begin;
+revoke grant option on test.* from mysqltest_3@localhost;
+commit;
+show grants for mysqltest_3@localhost;
+Grants for mysqltest_3@localhost
+GRANT USAGE ON *.* TO 'mysqltest_3'@'localhost'
+begin;
+grant all on test.t1 to mysqltest_2@localhost with grant option;
+revoke all on test.t1 from mysqltest_2@localhost;
+commit;
+show grants for mysqltest_2@localhost;
+Grants for mysqltest_2@localhost
+GRANT USAGE ON *.* TO 'mysqltest_2'@'localhost'
+GRANT USAGE ON `test`.`t1` TO 'mysqltest_2'@'localhost' WITH GRANT OPTION
+begin;
+revoke grant option on test.t1 from mysqltest_2@localhost;
+commit;
+show grants for mysqltest_2@localhost;
+Grants for mysqltest_2@localhost
+GRANT USAGE ON *.* TO 'mysqltest_2'@'localhost'
+delete from mysql.user where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3";
+delete from mysql.db where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3";
+delete from mysql.tables_priv where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3";
+delete from mysql.columns_priv where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3";
+flush privileges;
+drop table t1;
+begin;
+GRANT FILE on mysqltest.* to mysqltest_1@localhost;
+ERROR HY000: Incorrect usage of DB GRANT and GLOBAL PRIVILEGES
+commit;
+select 1;
+1
+1
+create database mysqltest1;
+begin;
+grant usage on mysqltest1.* to test6123 identified by 'magic123';
+commit;
+select host,db,user,select_priv,insert_priv from mysql.db where db="mysqltest1";
+host db user select_priv insert_priv
+delete from mysql.user where user='test6123';
+drop database mysqltest1;
+create table t1 (a int);
+begin;
+grant ALL PRIVILEGES on *.* to drop_user2@localhost with GRANT OPTION;
+commit;
+show grants for drop_user2@localhost;
+Grants for drop_user2@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user2'@'localhost' WITH GRANT OPTION
+begin;
+revoke all privileges, grant option from drop_user2@localhost;
+commit;
+drop user drop_user2@localhost;
+begin;
+grant ALL PRIVILEGES on *.* to drop_user@localhost with GRANT OPTION;
+grant ALL PRIVILEGES on test.* to drop_user@localhost with GRANT OPTION;
+grant select(a) on test.t1 to drop_user@localhost;
+commit;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON `test`.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON `test`.`t1` TO 'drop_user'@'localhost'
+set sql_mode=ansi_quotes;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON "test".* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON "test"."t1" TO 'drop_user'@'localhost'
+set sql_mode=default;
+set sql_quote_show_create=0;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON test.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON test.t1 TO 'drop_user'@'localhost'
+set sql_mode="ansi_quotes";
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON test.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON test.t1 TO 'drop_user'@'localhost'
+set sql_quote_show_create=1;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON "test".* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON "test"."t1" TO 'drop_user'@'localhost'
+set sql_mode="";
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT ALL PRIVILEGES ON *.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT ALL PRIVILEGES ON `test`.* TO 'drop_user'@'localhost' WITH GRANT OPTION
+GRANT SELECT (a) ON `test`.`t1` TO 'drop_user'@'localhost'
+revoke all privileges, grant option from drop_user@localhost;
+show grants for drop_user@localhost;
+Grants for drop_user@localhost
+GRANT USAGE ON *.* TO 'drop_user'@'localhost'
+drop user drop_user@localhost;
+begin;
+revoke all privileges, grant option from drop_user@localhost;
+ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
+commit;
+begin;
+grant select(a) on test.t1 to drop_user1@localhost;
+commit;
+flush privileges;
+begin;
+grant select on test.t1 to drop_user2@localhost;
+grant select on test.* to drop_user3@localhost;
+grant select on *.* to drop_user4@localhost;
+commit;
+flush privileges;
+drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
+drop_user4@localhost;
+begin;
+revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
+drop_user3@localhost, drop_user4@localhost;
+ERROR HY000: Can't revoke all privileges, grant for one or more of the requested users
+commit;
+flush privileges;
+drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
+drop_user4@localhost;
+drop table t1;
+begin;
+grant usage on *.* to mysqltest_1@localhost identified by "password";
+grant select, update, insert on test.* to mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+Grants for mysqltest_1@localhost
+GRANT USAGE ON *.* TO 'mysqltest_1'@'localhost' IDENTIFIED BY PASSWORD '*2470C0C06DEE42FD1618BB99005ADCA2EC9D1E19'
+GRANT SELECT, INSERT, UPDATE ON `test`.* TO 'mysqltest_1'@'localhost'
+drop user mysqltest_1@localhost;
+SET NAMES koi8r;
+CREATE DATABASE ÂÄ;
+USE ÂÄ;
+CREATE TABLE ÔÁÂ (ËÏÌ int);
+begin;
+GRANT SELECT ON ÂÄ.* TO ÀÚÅÒ@localhost;
+commit;
+SHOW GRANTS FOR ÀÚÅÒ@localhost;
+Grants for ÀÚÅÒ@localhost
+GRANT USAGE ON *.* TO 'ÀÚÅÒ'@'localhost'
+GRANT SELECT ON `ÂÄ`.* TO 'ÀÚÅÒ'@'localhost'
+begin;
+REVOKE SELECT ON ÂÄ.* FROM ÀÚÅÒ@localhost;
+commit;
+begin;
+GRANT SELECT ON ÂÄ.ÔÁÂ TO ÀÚÅÒ@localhost;
+commit;
+SHOW GRANTS FOR ÀÚÅÒ@localhost;
+Grants for ÀÚÅÒ@localhost
+GRANT USAGE ON *.* TO 'ÀÚÅÒ'@'localhost'
+GRANT SELECT ON `ÂÄ`.`ÔÁÂ` TO 'ÀÚÅÒ'@'localhost'
+begin;
+REVOKE SELECT ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost;
+commit;
+begin;
+GRANT SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ TO ÀÚÅÒ@localhost;
+commit;
+SHOW GRANTS FOR ÀÚÅÒ@localhost;
+Grants for ÀÚÅÒ@localhost
+GRANT USAGE ON *.* TO 'ÀÚÅÒ'@'localhost'
+GRANT SELECT (ËÏÌ) ON `ÂÄ`.`ÔÁÂ` TO 'ÀÚÅÒ'@'localhost'
+begin;
+REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost;
+commit;
+DROP DATABASE ÂÄ;
+SET NAMES latin1;
+USE test;
+CREATE TABLE t1 (a int );
+CREATE TABLE t2 LIKE t1;
+CREATE TABLE t3 LIKE t1;
+CREATE TABLE t4 LIKE t1;
+CREATE TABLE t5 LIKE t1;
+CREATE TABLE t6 LIKE t1;
+CREATE TABLE t7 LIKE t1;
+CREATE TABLE t8 LIKE t1;
+CREATE TABLE t9 LIKE t1;
+CREATE TABLE t10 LIKE t1;
+CREATE DATABASE testdb1;
+CREATE DATABASE testdb2;
+CREATE DATABASE testdb3;
+CREATE DATABASE testdb4;
+CREATE DATABASE testdb5;
+CREATE DATABASE testdb6;
+CREATE DATABASE testdb7;
+CREATE DATABASE testdb8;
+CREATE DATABASE testdb9;
+CREATE DATABASE testdb10;
+begin;
+GRANT ALL ON testdb1.* TO testuser@localhost;
+GRANT ALL ON testdb2.* TO testuser@localhost;
+GRANT ALL ON testdb3.* TO testuser@localhost;
+GRANT ALL ON testdb4.* TO testuser@localhost;
+GRANT ALL ON testdb5.* TO testuser@localhost;
+GRANT ALL ON testdb6.* TO testuser@localhost;
+GRANT ALL ON testdb7.* TO testuser@localhost;
+GRANT ALL ON testdb8.* TO testuser@localhost;
+GRANT ALL ON testdb9.* TO testuser@localhost;
+GRANT ALL ON testdb10.* TO testuser@localhost;
+GRANT SELECT ON test.t1 TO testuser@localhost;
+GRANT SELECT ON test.t2 TO testuser@localhost;
+GRANT SELECT ON test.t3 TO testuser@localhost;
+GRANT SELECT ON test.t4 TO testuser@localhost;
+GRANT SELECT ON test.t5 TO testuser@localhost;
+GRANT SELECT ON test.t6 TO testuser@localhost;
+GRANT SELECT ON test.t7 TO testuser@localhost;
+GRANT SELECT ON test.t8 TO testuser@localhost;
+GRANT SELECT ON test.t9 TO testuser@localhost;
+GRANT SELECT ON test.t10 TO testuser@localhost;
+GRANT SELECT (a) ON test.t1 TO testuser@localhost;
+GRANT SELECT (a) ON test.t2 TO testuser@localhost;
+GRANT SELECT (a) ON test.t3 TO testuser@localhost;
+GRANT SELECT (a) ON test.t4 TO testuser@localhost;
+GRANT SELECT (a) ON test.t5 TO testuser@localhost;
+GRANT SELECT (a) ON test.t6 TO testuser@localhost;
+GRANT SELECT (a) ON test.t7 TO testuser@localhost;
+GRANT SELECT (a) ON test.t8 TO testuser@localhost;
+GRANT SELECT (a) ON test.t9 TO testuser@localhost;
+GRANT SELECT (a) ON test.t10 TO testuser@localhost;
+commit;
+begin;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM testuser@localhost;
+commit;
+SHOW GRANTS FOR testuser@localhost;
+Grants for testuser@localhost
+GRANT USAGE ON *.* TO 'testuser'@'localhost'
+DROP USER testuser@localhost;
+DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+DROP DATABASE testdb1;
+DROP DATABASE testdb2;
+DROP DATABASE testdb3;
+DROP DATABASE testdb4;
+DROP DATABASE testdb5;
+DROP DATABASE testdb6;
+DROP DATABASE testdb7;
+DROP DATABASE testdb8;
+DROP DATABASE testdb9;
+DROP DATABASE testdb10;
+SHOW PRIVILEGES;
+Privilege Context Comment
+Alter Tables To alter the table
+Create Databases,Tables,Indexes To create new databases and tables
+Create temporary tables Databases To use CREATE TEMPORARY TABLE
+Create view Tables To create new views
+Delete Tables To delete existing rows
+Drop Databases,Tables To drop databases, tables, and views
+File File access on server To read and write files on the server
+Grant option Databases,Tables To give to other users those privileges you possess
+Index Tables To create or drop indexes
+Insert Tables To insert data into tables
+Lock tables Databases To use LOCK TABLES (together with SELECT privilege)
+Process Server Admin To view the plain text of currently executing queries
+References Databases,Tables To have references on tables
+Reload Server Admin To reload or refresh tables, logs and privileges
+Replication client Server Admin To ask where the slave or master servers are
+Replication slave Server Admin To read binary log events from the master
+Select Tables To retrieve rows from table
+Show databases Server Admin To see all databases with SHOW DATABASES
+Show view Tables To see views with SHOW CREATE VIEW
+Shutdown Server Admin To shut down the server
+Super Server Admin To use KILL thread, SET GLOBAL, CHANGE MASTER, etc.
+Update Tables To update existing rows
+Usage Server Admin No privileges - allow connect only
+use mysql;
+alter table columns_priv engine=myisam;
+alter table db engine=myisam;
+alter table func engine=myisam;
+alter table help_category engine=myisam;
+alter table help_keyword engine=myisam;
+alter table help_relation engine=myisam;
+alter table help_topic engine=myisam;
+alter table host engine=myisam;
+alter table tables_priv engine=myisam;
+alter table time_zone engine=myisam;
+alter table time_zone_leap_second engine=myisam;
+alter table time_zone_name engine=myisam;
+alter table time_zone_transition engine=myisam;
+alter table time_zone_transition_type engine=myisam;
+alter table user engine=myisam;
+use test;
+flush privileges;
diff --git a/mysql-test/r/ndb_index_ordered.result b/mysql-test/r/ndb_index_ordered.result
index 2dc260ec43d..50f904af750 100644
--- a/mysql-test/r/ndb_index_ordered.result
+++ b/mysql-test/r/ndb_index_ordered.result
@@ -1,4 +1,4 @@
-drop table if exists t1;
+drop table if exists t1, test1, test2;
CREATE TABLE t1 (
a int unsigned NOT NULL PRIMARY KEY,
b int unsigned not null,
@@ -275,3 +275,38 @@ a b c
1 1 1
4 4 NULL
drop table t1;
+CREATE TABLE test1 (
+SubscrID int(11) NOT NULL auto_increment,
+UsrID int(11) NOT NULL default '0',
+PRIMARY KEY (SubscrID),
+KEY idx_usrid (UsrID)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+INSERT INTO test1 VALUES (2,224),(3,224),(1,224);
+CREATE TABLE test2 (
+SbclID int(11) NOT NULL auto_increment,
+SbcrID int(11) NOT NULL default '0',
+PRIMARY KEY (SbclID),
+KEY idx_sbcrid (SbcrID)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+INSERT INTO test2 VALUES (3,2),(1,1),(2,1),(4,2);
+select * from test1 order by 1;
+SubscrID UsrID
+1 224
+2 224
+3 224
+select * from test2 order by 1;
+SbclID SbcrID
+1 1
+2 1
+3 2
+4 2
+SELECT s.SubscrID,l.SbclID FROM test1 s left JOIN test2 l ON
+l.SbcrID=s.SubscrID WHERE s.UsrID=224 order by 1, 2;
+SubscrID SbclID
+1 1
+1 2
+2 3
+2 4
+3 NULL
+drop table test1;
+drop table test2;
diff --git a/mysql-test/r/ndb_index_unique.result b/mysql-test/r/ndb_index_unique.result
index f1407dfe78d..f9cc89ee4cc 100644
--- a/mysql-test/r/ndb_index_unique.result
+++ b/mysql-test/r/ndb_index_unique.result
@@ -22,7 +22,7 @@ select * from t1 where b = 4 order by a;
a b c
3 4 6
insert into t1 values(8, 2, 3);
-ERROR 23000: Can't write, because of unique constraint, to table 't1'
+ERROR 23000: Duplicate entry '8' for key 1
select * from t1 order by a;
a b c
1 2 3
@@ -44,6 +44,53 @@ a b c
7 8 3
8 2 3
drop table t1;
+CREATE TABLE t1 (
+a int unsigned NOT NULL PRIMARY KEY,
+b int unsigned,
+c int unsigned,
+UNIQUE bc(b,c)
+) engine = ndb;
+insert into t1 values(1,1,1),(2,NULL,2),(3,NULL,NULL),(4,4,NULL);
+select * from t1 use index (bc) where b IS NULL order by a;
+a b c
+2 NULL 2
+3 NULL NULL
+select * from t1 use index (bc)order by a;
+a b c
+1 1 1
+2 NULL 2
+3 NULL NULL
+4 4 NULL
+select * from t1 use index (bc) order by a;
+a b c
+1 1 1
+2 NULL 2
+3 NULL NULL
+4 4 NULL
+select * from t1 use index (PRIMARY) where b IS NULL order by a;
+a b c
+2 NULL 2
+3 NULL NULL
+select * from t1 use index (bc) where b IS NULL order by a;
+a b c
+2 NULL 2
+3 NULL NULL
+select * from t1 use index (bc) where b IS NULL and c IS NULL order by a;
+a b c
+3 NULL NULL
+select * from t1 use index (bc) where b IS NULL and c = 2 order by a;
+a b c
+2 NULL 2
+select * from t1 use index (bc) where b < 4 order by a;
+a b c
+1 1 1
+select * from t1 use index (bc) where b IS NOT NULL order by a;
+a b c
+1 1 1
+4 4 NULL
+insert into t1 values(5,1,1);
+ERROR 23000: Duplicate entry '5' for key 1
+drop table t1;
CREATE TABLE t2 (
a int unsigned NOT NULL PRIMARY KEY,
b int unsigned not null,
@@ -65,7 +112,7 @@ select * from t2 where b = 4 order by a;
a b c
3 4 6
insert into t2 values(8, 2, 3);
-ERROR 23000: Can't write, because of unique constraint, to table 't2'
+ERROR 23000: Duplicate entry '8' for key 1
select * from t2 order by a;
a b c
1 2 3
@@ -87,6 +134,13 @@ a b c
7 8 3
8 2 3
drop table t2;
+CREATE TABLE t2 (
+a int unsigned NOT NULL PRIMARY KEY,
+b int unsigned not null,
+c int unsigned,
+UNIQUE USING HASH (b, c)
+) engine=ndbcluster;
+ERROR 42000: Column 'c' is used with UNIQUE or INDEX but is not defined as NOT NULL
CREATE TABLE t3 (
a int unsigned NOT NULL,
b int unsigned not null,
@@ -123,7 +177,7 @@ pk a
3 NULL
4 4
insert into t1 values (5,0);
-ERROR 23000: Can't write, because of unique constraint, to table 't1'
+ERROR 23000: Duplicate entry '5' for key 1
select * from t1 order by pk;
pk a
-1 NULL
@@ -156,7 +210,7 @@ pk a b c
0 NULL 18 NULL
1 3 19 abc
insert into t2 values(2,3,19,'abc');
-ERROR 23000: Can't write, because of unique constraint, to table 't2'
+ERROR 23000: Duplicate entry '2' for key 1
select * from t2 order by pk;
pk a b c
-1 1 17 NULL
@@ -522,3 +576,39 @@ uid gid rid cid
1 1 2 3
1 1 2 4
drop table t1,t2,t3,t4,t5,t6,t7;
+CREATE TABLE t1 (
+a int unsigned NOT NULL PRIMARY KEY,
+b int unsigned,
+c int unsigned,
+UNIQUE bc(b,c) ) engine = ndb;
+insert into t1 values(1,1,1),(2,NULL,2),(3,NULL,NULL),(4,4,NULL);
+select * from t1 where b=1 and c=1;
+a b c
+1 1 1
+select * from t1 where b is null and c is null;
+a b c
+3 NULL NULL
+select * from t1 where b is null and c = 2;
+a b c
+2 NULL 2
+select * from t1 where b = 4 and c is null;
+a b c
+4 4 NULL
+create table t8 as
+select * from t1 where (b = 1 and c = 1)
+or (b is null and c is null)
+or (b is null and c = 2)
+or (b = 4 and c is null);
+select * from t8 order by a;
+a b c
+1 1 1
+2 NULL 2
+3 NULL NULL
+4 4 NULL
+select * from t1 order by a;
+a b c
+1 1 1
+2 NULL 2
+3 NULL NULL
+4 4 NULL
+drop table t1, t8;
diff --git a/mysql-test/r/ndb_insert.result b/mysql-test/r/ndb_insert.result
index cdc445558b9..7503010a66b 100644
--- a/mysql-test/r/ndb_insert.result
+++ b/mysql-test/r/ndb_insert.result
@@ -535,25 +535,73 @@ count(*)
2000
insert into t1 select * from t1 where b < 10 order by pk1;
ERROR 23000: Duplicate entry '9' for key 1
+DELETE FROM t1 WHERE pk1=2;
begin;
-INSERT IGNORE INTO t1 VALUES(1,2,3);
-ERROR HY000: Table storage engine for 't1' doesn't have this option
-commit;
-select * from t1 where pk1=1;
+INSERT IGNORE INTO t1 VALUES(1,2,3),(2,3,4);
+select * from t1 where pk1 < 3 order by pk1;
pk1 b c
+0 0 0
1 1 1
-INSERT IGNORE INTO t1 VALUES(1,2,3);
-ERROR HY000: Table storage engine for 't1' doesn't have this option
-select * from t1 where pk1=1;
+2 3 4
+rollback;
+INSERT IGNORE INTO t1 VALUES(1,2,3),(2,3,4);
+select * from t1 where pk1 < 3 order by pk1;
pk1 b c
+0 0 0
1 1 1
-REPLACE INTO t1 values(1, 2, 3);
+2 3 4
+REPLACE INTO t1 values(1, 78, 3);
select * from t1 where pk1=1;
pk1 b c
-1 2 3
-INSERT INTO t1 VALUES(1,1,1) ON DUPLICATE KEY UPDATE b=79;
-ERROR HY000: Table storage engine for 't1' doesn't have this option
-select * from t1 where pk1=1;
+1 78 3
+INSERT INTO t1 VALUES(1,1,1),(3,4,5) ON DUPLICATE KEY UPDATE b=79;
+select * from t1 where pk1 < 4 order by pk1;
pk1 b c
-1 2 3
+0 0 0
+1 79 3
+2 3 4
+3 79 3
+INSERT INTO t1 VALUES(1,1,1),(3,4,5) ON DUPLICATE KEY UPDATE b=pk1+c;
+select * from t1 where pk1 < 4 order by pk1;
+pk1 b c
+0 0 0
+1 4 3
+2 3 4
+3 6 3
+DELETE FROM t1 WHERE pk1 = 2 OR pk1 = 4 OR pk1 = 6;
+INSERT INTO t1 VALUES(1,1,1),(2,2,17),(3,4,5) ON DUPLICATE KEY UPDATE pk1=b;
+select * from t1 where pk1 = b and b != c order by pk1;
+pk1 b c
+2 2 17
+4 4 3
+6 6 3
+DROP TABLE t1;
+CREATE TABLE t1(a INT) ENGINE=ndb;
+INSERT IGNORE INTO t1 VALUES (1);
+INSERT IGNORE INTO t1 VALUES (1);
+INSERT IGNORE INTO t1 SELECT a FROM t1;
+INSERT IGNORE INTO t1 SELECT a FROM t1;
+INSERT IGNORE INTO t1 SELECT a FROM t1;
+INSERT IGNORE INTO t1 VALUES (1);
+INSERT IGNORE INTO t1 VALUES (1);
+SELECT * FROM t1;
+a
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
+1
DROP TABLE t1;
diff --git a/mysql-test/r/null.result b/mysql-test/r/null.result
index f39bd0c6f6c..9f05703e69e 100644
--- a/mysql-test/r/null.result
+++ b/mysql-test/r/null.result
@@ -184,3 +184,97 @@ select count(*) from t1 where i=2 or i is null;
count(*)
9
drop table t1;
+set names latin2;
+create table t1 select
+null as c00,
+if(1, null, 'string') as c01,
+if(0, null, 'string') as c02,
+ifnull(null, 'string') as c03,
+ifnull('string', null) as c04,
+case when 0 then null else 'string' end as c05,
+case when 1 then null else 'string' end as c06,
+coalesce(null, 'string') as c07,
+coalesce('string', null) as c08,
+least('string',null) as c09,
+least(null, 'string') as c10,
+greatest('string',null) as c11,
+greatest(null, 'string') as c12,
+nullif('string', null) as c13,
+nullif(null, 'string') as c14,
+trim('string' from null) as c15,
+trim(null from 'string') as c16,
+substring_index('string', null, 1) as c17,
+substring_index(null, 'string', 1) as c18,
+elt(1, null, 'string') as c19,
+elt(1, 'string', null) as c20,
+concat('string', null) as c21,
+concat(null, 'string') as c22,
+concat_ws('sep', 'string', null) as c23,
+concat_ws('sep', null, 'string') as c24,
+concat_ws(null, 'string', 'string') as c25,
+make_set(3, 'string', null) as c26,
+make_set(3, null, 'string') as c27,
+export_set(3, null, 'off', 'sep') as c29,
+export_set(3, 'on', null, 'sep') as c30,
+export_set(3, 'on', 'off', null) as c31,
+replace(null, 'from', 'to') as c32,
+replace('str', null, 'to') as c33,
+replace('str', 'from', null) as c34,
+insert('str', 1, 2, null) as c35,
+insert(null, 1, 2, 'str') as c36,
+lpad('str', 10, null) as c37,
+rpad(null, 10, 'str') as c38;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `c00` binary(0) default NULL,
+ `c01` varchar(6) character set latin2 default NULL,
+ `c02` varchar(6) character set latin2 default NULL,
+ `c03` varchar(6) character set latin2 NOT NULL default '',
+ `c04` varchar(6) character set latin2 default NULL,
+ `c05` varchar(6) character set latin2 default NULL,
+ `c06` varchar(6) character set latin2 default NULL,
+ `c07` varchar(6) character set latin2 default NULL,
+ `c08` varchar(6) character set latin2 default NULL,
+ `c09` varchar(6) character set latin2 NOT NULL default '',
+ `c10` varchar(6) character set latin2 NOT NULL default '',
+ `c11` varchar(6) character set latin2 NOT NULL default '',
+ `c12` varchar(6) character set latin2 NOT NULL default '',
+ `c13` varchar(6) character set latin2 default NULL,
+ `c14` char(0) character set latin2 default NULL,
+ `c15` char(0) character set latin2 default NULL,
+ `c16` varchar(6) character set latin2 default NULL,
+ `c17` varchar(6) character set latin2 default NULL,
+ `c18` char(0) character set latin2 default NULL,
+ `c19` varchar(6) character set latin2 default NULL,
+ `c20` varchar(6) character set latin2 default NULL,
+ `c21` varchar(6) character set latin2 default NULL,
+ `c22` varchar(6) character set latin2 default NULL,
+ `c23` varchar(9) character set latin2 default NULL,
+ `c24` varchar(9) character set latin2 default NULL,
+ `c25` varchar(12) character set latin2 default NULL,
+ `c26` varchar(7) character set latin2 default NULL,
+ `c27` varchar(7) character set latin2 default NULL,
+ `c29` varchar(381) character set latin2 default NULL,
+ `c30` varchar(317) character set latin2 default NULL,
+ `c31` varchar(192) character set latin2 default NULL,
+ `c32` char(0) character set latin2 default NULL,
+ `c33` varchar(3) character set latin2 default NULL,
+ `c34` varchar(3) character set latin2 default NULL,
+ `c35` varchar(3) character set latin2 default NULL,
+ `c36` varchar(3) character set latin2 default NULL,
+ `c37` varchar(10) character set latin2 default NULL,
+ `c38` varchar(10) character set latin2 default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+select
+case 'str' when 'STR' then 'str' when null then 'null' end as c01,
+case 'str' when null then 'null' when 'STR' then 'str' end as c02,
+field(null, 'str1', 'str2') as c03,
+field('str1','STR1', null) as c04,
+field('str1', null, 'STR1') as c05,
+'string' in ('STRING', null) as c08,
+'string' in (null, 'STRING') as c09;
+c01 c02 c03 c04 c05 c08 c09
+str str 0 1 2 1 1
+set names latin1;
diff --git a/mysql-test/r/openssl_1.result b/mysql-test/r/openssl_1.result
index a87d0c33559..f7cb17a1a74 100644
--- a/mysql-test/r/openssl_1.result
+++ b/mysql-test/r/openssl_1.result
@@ -2,9 +2,9 @@ drop table if exists t1;
create table t1(f1 int);
insert into t1 values (5);
grant select on test.* to ssl_user1@localhost require SSL;
-grant select on test.* to ssl_user2@localhost require cipher "EDH-RSA-DES-CBC3-SHA";
-grant select on test.* to ssl_user3@localhost require cipher "EDH-RSA-DES-CBC3-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com";
-grant select on test.* to ssl_user4@localhost require cipher "EDH-RSA-DES-CBC3-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com";
+grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA";
+grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com";
+grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com";
flush privileges;
select * from t1;
f1
diff --git a/mysql-test/r/order_by.result b/mysql-test/r/order_by.result
index 15643f29513..6744ffa889f 100644
--- a/mysql-test/r/order_by.result
+++ b/mysql-test/r/order_by.result
@@ -272,7 +272,7 @@ create table t1 (a int not null, b int, c varchar(10), key (a, b, c));
insert into t1 values (1, NULL, NULL), (1, NULL, 'b'), (1, 1, NULL), (1, 1, 'b'), (1, 1, 'b'), (2, 1, 'a'), (2, 1, 'b'), (2, 2, 'a'), (2, 2, 'b'), (2, 3, 'c'),(1,3,'b');
explain select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index a a 20 NULL 11 Using where; Using index
+1 SIMPLE t1 index a a 22 NULL 11 Using where; Using index
select * from t1 where (a = 1 and b is null and c = 'b') or (a > 2) order by a desc;
a b c
1 NULL b
@@ -348,7 +348,7 @@ Warning 1265 Data truncated for column 'b' at row 2
Warning 1265 Data truncated for column 'c' at row 3
explain select * from t1 order by a, b, c;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 18 NULL 11 Using index
+1 SIMPLE t1 index NULL a 20 NULL 11 Using index
select * from t1 order by a, b, c;
a b c
1 0
@@ -364,7 +364,7 @@ a b c
2 3 c
explain select * from t1 order by a desc, b desc, c desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL a 18 NULL 11 Using index
+1 SIMPLE t1 index NULL a 20 NULL 11 Using index
select * from t1 order by a desc, b desc, c desc;
a b c
2 3 c
@@ -380,7 +380,7 @@ a b c
1 0
explain select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range a a 18 NULL 3 Using where; Using index
+1 SIMPLE t1 range a a 20 NULL 3 Using where; Using index
select * from t1 where (a = 1 and b = 1 and c = 'b') or (a > 2) order by a desc;
a b c
1 1 b
@@ -574,7 +574,7 @@ KEY StringField (FieldKey,StringVal(32))
INSERT INTO t1 VALUES ('0',3,'0'),('0',2,'1'),('0',1,'2'),('1',2,'1'),('1',1,'3'), ('1',0,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('2',3,'0'),('2',2,'1'),('2',1,'2'),('3',2,'1'),('3',1,'2'),('3','3','3');
EXPLAIN SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 36 const 3 Using where
+1 SIMPLE t1 ref FieldKey,LongField,StringField LongField 38 const 3 Using where
SELECT * FROM t1 WHERE FieldKey = '1' ORDER BY LongVal;
FieldKey LongVal StringVal
1 0 2
@@ -582,7 +582,7 @@ FieldKey LongVal StringVal
1 2 1
EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range FieldKey,LongField,StringField FieldKey 36 NULL 4 Using where; Using filesort
+1 SIMPLE t1 range FieldKey,LongField,StringField FieldKey 38 NULL 4 Using where; Using filesort
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY LongVal;
FieldKey LongVal StringVal
3 1 2
@@ -590,7 +590,7 @@ FieldKey LongVal StringVal
3 3 3
EXPLAIN SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 range FieldKey,LongField,StringField LongField 36 NULL 4 Using where
+1 SIMPLE t1 range FieldKey,LongField,StringField LongField 38 NULL 4 Using where
SELECT * FROM t1 WHERE FieldKey > '2' ORDER BY FieldKey, LongVal;
FieldKey LongVal StringVal
3 1 2
@@ -733,3 +733,10 @@ xxxxxxxxxxxxxxxxxxxaa
xxxxxxxxxxxxxxxxxxxx
xxxxxxxxxxxxxxxxxxxz
drop table t1;
+create table t1 (a int not null, b int not null, c int not null);
+insert t1 values (1,1,1),(1,1,2),(1,2,1);
+select a, b from t1 group by a, b order by sum(c);
+a b
+1 2
+1 1
+drop table t1;
diff --git a/mysql-test/r/ps.result b/mysql-test/r/ps.result
index 82e59835cf9..1e31b6e9ae7 100644
--- a/mysql-test/r/ps.result
+++ b/mysql-test/r/ps.result
@@ -106,12 +106,6 @@ ERROR 42000: You have an error in your SQL syntax; check the manual that corresp
set @fvar= 123.4567;
prepare stmt1 from @fvar;
ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '123.4567' at line 1
-set @str1 = 'select ?';
-set @str2 = convert(@str1 using ucs2);
-prepare stmt1 from @str2;
-execute stmt1 using @ivar;
-?
-1234
drop table t1,t2;
PREPARE stmt1 FROM "select _utf8 'A' collate utf8_bin = ?";
set @var='A';
@@ -213,10 +207,10 @@ create table t1 ( a int primary key, b varchar(30)) engine = MYISAM ;
prepare stmt1 from ' show table status from test like ''t1%'' ';
execute stmt1;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MyISAM 9 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
+t1 MyISAM 10 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
show table status from test like 't1%' ;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MyISAM 9 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
+t1 MyISAM 10 Dynamic 0 0 0 4294967295 1024 0 NULL # # # latin1_swedish_ci NULL
deallocate prepare stmt1 ;
drop table t1;
create table t1(a varchar(2), b varchar(3));
@@ -456,3 +450,29 @@ PREPARE stmt FROM 'UPDATE t1 AS P1 INNER JOIN (SELECT N FROM t1 GROUP BY N HAVIN
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+prepare stmt from "select ? is null, ? is not null, ?";
+select @no_such_var is null, @no_such_var is not null, @no_such_var;
+@no_such_var is null @no_such_var is not null @no_such_var
+1 0 NULL
+execute stmt using @no_such_var, @no_such_var, @no_such_var;
+? is null ? is not null ?
+1 0 NULL
+set @var='abc';
+select @var is null, @var is not null, @var;
+@var is null @var is not null @var
+0 1 abc
+execute stmt using @var, @var, @var;
+? is null ? is not null ?
+0 1 abc
+set @var=null;
+select @var is null, @var is not null, @var;
+@var is null @var is not null @var
+1 0 NULL
+execute stmt using @var, @var, @var;
+? is null ? is not null ?
+1 0 NULL
+create table t1 (a varchar(20));
+insert into t1 values ('foo');
+prepare stmt FROM 'SELECT char_length (a) FROM t1';
+ERROR 42000: FUNCTION test.char_length does not exist
+drop table t1;
diff --git a/mysql-test/r/ps_10nestset.result b/mysql-test/r/ps_10nestset.result
index 68f58a03674..ff63485a5f9 100644
--- a/mysql-test/r/ps_10nestset.result
+++ b/mysql-test/r/ps_10nestset.result
@@ -62,4 +62,15 @@ id emp salary l r
4 Donna 1064.80 5 6
5 Eddie 931.70 7 8
6 Fred 798.60 9 10
+prepare st_round from 'update t1 set salary = salary + ? - ( salary MOD ? )';
+set @arg_round= 50;
+execute st_round using @arg_round, @arg_round;
+select * from t1;
+id emp salary l r
+1 Jerry 1350.00 1 12
+2 Bert 1200.00 2 3
+3 Chuck 1250.00 4 11
+4 Donna 1100.00 5 6
+5 Eddie 950.00 7 8
+6 Fred 800.00 9 10
drop table t1;
diff --git a/mysql-test/r/ps_1general.result b/mysql-test/r/ps_1general.result
index fe7aa623023..0868ec3a364 100644
--- a/mysql-test/r/ps_1general.result
+++ b/mysql-test/r/ps_1general.result
@@ -1,4 +1,5 @@
-use test;
+drop table if exists t5, t6, t7, t8;
+drop database if exists mysqltest ;
test_sequence
------ basic tests ------
drop table if exists t1, t9 ;
@@ -276,7 +277,7 @@ t2 MyISAM 9 Fixed 0 0 0 64424509439 1024 0 NULL # # # latin1_swedish_ci NULL
prepare stmt4 from ' show table status from test like ''t9%'' ';
execute stmt4;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t9 MyISAM 9 Dynamic 2 220 440 4294967295 2048 0 NULL # # # latin1_swedish_ci NULL
+t9 MyISAM 10 Dynamic 2 222 444 4294967295 2048 0 NULL # # # latin1_swedish_ci NULL
prepare stmt4 from ' show status like ''Threads_running'' ';
execute stmt4;
Variable_name Value
@@ -290,7 +291,7 @@ execute stmt4;
prepare stmt4 from ' show full processlist ';
execute stmt4;
Id User Host db Command Time State Info
-number root localhost test Query 0 NULL show full processlist
+number root localhost test Query seconds NULL show full processlist
prepare stmt4 from ' show grants for user ';
prepare stmt4 from ' show create table t2 ';
ERROR HY000: This command is not supported in the prepared statement protocol yet
@@ -553,7 +554,6 @@ execute stmt3;
ERROR 42S01: Table 'new_t2' already exists
rename table new_t2 to t2;
drop table t2;
-drop table if exists t5, t6, t7, t8 ;
prepare stmt1 from ' rename table t5 to t6, t7 to t8 ' ;
create table t5 (a int) ;
execute stmt1 ;
@@ -805,21 +805,24 @@ test_sequence
------ grant/revoke/drop affects a parallel session test ------
show grants for second_user@localhost ;
ERROR 42000: There is no such grant defined for user 'second_user' on host 'localhost'
-grant usage on test.* to second_user@localhost
+create database mysqltest;
+use mysqltest;
+use test;
+grant usage on mysqltest.* to second_user@localhost
identified by 'looser' ;
-grant select on test.t9 to second_user@localhost
+grant select on mysqltest.t9 to second_user@localhost
identified by 'looser' ;
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `test`.`t9` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
select current_user();
current_user()
second_user@localhost
show grants for current_user();
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `test`.`t9` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
prepare s_t9 from 'select c1 as my_col
from t9 where c1= 1' ;
execute s_t9 ;
@@ -827,24 +830,24 @@ my_col
1
select a as my_col from t1;
ERROR 42000: select command denied to user 'second_user'@'localhost' for table 't1'
-grant select on test.t1 to second_user@localhost
+grant select on mysqltest.t1 to second_user@localhost
identified by 'looser' ;
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `test`.`t1` TO 'second_user'@'localhost'
-GRANT SELECT ON `test`.`t9` TO 'second_user'@'localhost'
-drop table t9 ;
+GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
+drop table mysqltest.t9 ;
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `test`.`t1` TO 'second_user'@'localhost'
-GRANT SELECT ON `test`.`t9` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `test`.`t1` TO 'second_user'@'localhost'
-GRANT SELECT ON `test`.`t9` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t1` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
prepare s_t1 from 'select a as my_col from t1' ;
execute s_t1 ;
my_col
@@ -853,17 +856,17 @@ my_col
3
4
execute s_t9 ;
-ERROR 42S02: Table 'test.t9' doesn't exist
-revoke all privileges on test.t1 from second_user@localhost
+ERROR 42S02: Table 'mysqltest.t9' doesn't exist
+revoke all privileges on mysqltest.t1 from second_user@localhost
identified by 'looser' ;
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `test`.`t9` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
show grants for second_user@localhost ;
Grants for second_user@localhost
GRANT USAGE ON *.* TO 'second_user'@'localhost' IDENTIFIED BY PASSWORD '*13843FE600B19A81E32AF50D4A6FED25875FF1F3'
-GRANT SELECT ON `test`.`t9` TO 'second_user'@'localhost'
+GRANT SELECT ON `mysqltest`.`t9` TO 'second_user'@'localhost'
execute s_t1 ;
ERROR 42000: select command denied to user 'second_user'@'localhost' for table 't1'
revoke all privileges, grant option from second_user@localhost ;
@@ -874,4 +877,5 @@ drop user second_user@localhost ;
commit ;
show grants for second_user@localhost ;
ERROR 42000: There is no such grant defined for user 'second_user' on host 'localhost'
-drop table t1 ;
+drop table t1,t9 ;
+drop database mysqltest;
diff --git a/mysql-test/r/ps_2myisam.result b/mysql-test/r/ps_2myisam.result
index 1a096a58252..1d1ee8a8561 100644
--- a/mysql-test/r/ps_2myisam.result
+++ b/mysql-test/r/ps_2myisam.result
@@ -69,7 +69,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -1580,7 +1580,9 @@ a b
1200 x1000_1updatedupdated
delete from t1 where a >= 1000 ;
prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
-ERROR HY000: This command is not supported in the prepared statement protocol yet
+execute stmt1;
+execute stmt1;
+execute stmt1;
test_sequence
------ multi table tests ------
delete from t1 ;
@@ -1703,8 +1705,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@@ -1722,8 +1724,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
drop table t2;
drop table if exists t5 ;
@@ -1771,7 +1773,7 @@ t5 CREATE TABLE `t5` (
`param02` double default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
@@ -1787,10 +1789,10 @@ t5 CREATE TABLE `t5` (
`param10` bigint(20) default NULL,
`const11` int(4) default NULL,
`param11` bigint(20) default NULL,
- `const12` char(0) default NULL,
+ `const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
`param13` double default NULL,
- `param14` longblob,
+ `param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t5 ;
@@ -1801,9 +1803,9 @@ def test t5 t5 const02 const02 5 3 3 N 32769 1 63
def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
def test t5 t5 const03 const03 5 23 1 N 32769 31 63
def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
@@ -1817,10 +1819,10 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63
def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
-def test t5 t5 const12 const12 254 0 0 Y 0 0 8
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
-def test t5 t5 param14 param14 252 16777215 0 Y 144 0 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
param01 8
@@ -1907,38 +1909,38 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -1954,38 +1956,38 @@ from t9 where c1= 0 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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
@@ -2004,38 +2006,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
@@ -2044,38 +2046,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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" ;
@@ -2092,38 +2094,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -2136,38 +2138,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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,
@@ -2182,76 +2184,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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_2myisam.result.es b/mysql-test/r/ps_2myisam.result.es
new file mode 100644
index 00000000000..3f17b4cdcd0
--- /dev/null
+++ b/mysql-test/r/ps_2myisam.result.es
@@ -0,0 +1,3130 @@
+use test;
+drop table if exists t1, t9 ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+create table t9
+(
+c1 tinyint, c2 smallint, c3 mediumint, c4 int,
+c5 integer, c6 bigint, c7 float, c8 double,
+c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
+c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c17 year, c18 bit, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
+c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'MYISAM' ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+test_sequence
+------ simple select tests ------
+prepare stmt1 from ' select * from t9 order by c1 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t9 t9 c1 c1 1 4 1 N 49155 0 63
+def test t9 t9 c2 c2 2 6 1 Y 32768 0 63
+def test t9 t9 c3 c3 9 9 1 Y 32768 0 63
+def test t9 t9 c4 c4 3 11 1 Y 32768 0 63
+def test t9 t9 c5 c5 3 11 1 Y 32768 0 63
+def test t9 t9 c6 c6 8 20 1 Y 32768 0 63
+def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
+def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
+def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
+def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
+def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c13 c13 10 10 10 Y 128 0 63
+def test t9 t9 c14 c14 12 19 19 Y 128 0 63
+def test t9 t9 c15 c15 7 19 19 N 1249 0 63
+def test t9 t9 c16 c16 11 8 8 Y 128 0 63
+def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
+def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
+def test t9 t9 c20 c20 254 1 1 Y 0 0 8
+def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c22 c22 253 30 30 Y 0 0 8
+def test t9 t9 c23 c23 252 255 8 Y 144 0 63
+def test t9 t9 c24 c24 252 255 8 Y 16 0 8
+def test t9 t9 c25 c25 252 65535 4 Y 144 0 63
+def test t9 t9 c26 c26 252 65535 4 Y 16 0 8
+def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63
+def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8
+def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63
+def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8
+def test t9 t9 c31 c31 254 5 3 Y 256 0 8
+def test t9 t9 c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00=null ;
+select @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select @arg00 + 1 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? + 1 as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select 1 + @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select 1 + ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 order by a;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 order by a ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b order by a) from t1
+group by 'a' ;
+group_concat(@arg00,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00 order by a) from t1
+group by 'a' ;
+group_concat(b,@arg00 order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,? order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists t5 ;
+create table t5 (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+1 ii
+2 hh
+drop table t5 ;
+drop table if exists t5 ;
+create table t5(session_id char(9) not null) ;
+insert into t5 values ('abc') ;
+prepare stmt1 from ' select * from t5
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table t5 ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01) order by a;
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+set @arg00= 'one' ;
+set @arg01= 'two' ;
+set @arg02= 'five' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
+execute stmt1 using @arg00, @arg01, @arg02 ;
+b
+one
+two
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00=null ;
+insert into t9 set c1= 0, c5 = NULL ;
+select c5 from t9 where c5 > NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 > ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 < NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 < ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 = NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 = ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 <=> NULL ;
+c5
+NULL
+prepare stmt1 from ' select c5 from t9 where c5 <=> ? ';
+execute stmt1 using @arg00 ;
+c5
+NULL
+delete from t9 where c1= 0 ;
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 order by a ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? order by a ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1 ;
+execute stmt1 using @arg00;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=0 ;
+execute stmt1 using @arg00;
+ERROR 42S22: Unknown column '?' in 'order clause'
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1 order by a
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a order by a1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a order by a1 ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02
+order by second.a, first.a;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ?
+ order by second.a, first.a';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+drop table if exists t2 ;
+create table t2 as select * from t1 ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
+the join statement is:
+SELECT * FROM t2 right join t1 using(a) order by t2.a
+prepare stmt1 from @query9 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural right join t1 order by t2.a
+prepare stmt1 from @query8 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query7 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 using(a) order by t2.a
+prepare stmt1 from @query6 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural left join t1 order by t2.a
+prepare stmt1 from @query5 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query4 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 join t1 using(a) order by t2.a
+prepare stmt1 from @query3 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural join t1 order by t2.a
+prepare stmt1 from @query2 ;
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+the join statement is:
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
+prepare stmt1 from @query1 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+drop table t2 ;
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) order by a ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t1;
+prepare stmt1 from ' select a in (select a from t2) from t1 ' ;
+execute stmt1 ;
+a in (select a from t2)
+1
+1
+1
+1
+drop table if exists t5, t6, t7 ;
+create table t5 (a int , b int) ;
+create table t6 like t5 ;
+create table t7 like t5 ;
+insert into t5 values (0, 100), (1, 2), (1, 3), (2, 2), (2, 7),
+(2, -1), (3, 10) ;
+insert into t6 values (0, 0), (1, 1), (2, 1), (3, 1), (4, 1) ;
+insert into t7 values (3, 3), (2, 2), (1, 1) ;
+prepare stmt1 from ' select a, (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1) from t7 ' ;
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+drop table t5, t6, t7 ;
+drop table if exists t2 ;
+create table t2 as select * from t9;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t9.c2 - 0e-3) = t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t9.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t9.c2-?)=t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t9.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+drop table t2 ;
+select 1 < (select a from t1) ;
+ERROR 21000: Subquery returns more than 1 row
+prepare stmt1 from ' select 1 < (select a from t1) ' ;
+execute stmt1 ;
+ERROR 21000: Subquery returns more than 1 row
+select 1 as my_col ;
+my_col
+1
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+prepare stmt1 from ' SELECT 1, 2 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT 1, 2 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT * from t1 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT * from t1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' explain select * from t9 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 6 N 1 31 33
+def table 253 64 2 N 1 31 33
+def type 253 10 3 N 1 31 33
+def possible_keys 253 4096 0 Y 0 31 33
+def key 253 64 0 Y 0 31 33
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 33
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 0 N 1 31 33
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t9 ALL NULL NULL NULL NULL 2
+drop table if exists t2 ;
+create table t2 (s varchar(25), fulltext(s))
+ENGINE = 'MYISAM' ;
+insert into t2 values ('Gravedigger'), ('Greed'),('Hollow Dogs') ;
+commit ;
+prepare stmt1 from ' select s from t2 where match (s) against (?) ' ;
+set @arg00='Dogs' ;
+execute stmt1 using @arg00 ;
+s
+Hollow Dogs
+prepare stmt1 from ' SELECT s FROM t2
+where match (s) against (concat(?,''digger'')) ';
+set @arg00='Grave' ;
+execute stmt1 using @arg00 ;
+s
+Gravedigger
+drop table t2 ;
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+select a,b from t1 order by a;
+a b
+0 two
+1 one
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 order by a;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+create table t2
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+insert into t2(a,b) select a, b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @NULL= null ;
+set @arg00= 'abc' ;
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg00 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg00 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 abc
+10002 abc
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @NULL ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @NULL ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 NULL
+10002 NULL
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 10 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 9 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 8 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 7 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 6 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 5 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 4 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 3 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg01 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 10001
+10002 10002
+10003 10003
+10004 10004
+10005 10005
+10006 10006
+10007 10007
+10008 10008
+10009 10009
+10010 10010
+delete from t1 where a > 10000 ;
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1 order by a;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+8 eight
+9 nine
+81 8-1
+82 8-2
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+drop table if exists t2 ;
+create table t2 (id int auto_increment primary key)
+ENGINE= 'MYISAM' ;
+prepare stmt1 from ' select last_insert_id() ' ;
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+1
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+2
+drop table t2 ;
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+execute stmt1;
+execute stmt1;
+execute stmt1;
+test_sequence
+------ multi table tests ------
+delete from t1 ;
+delete from t9 ;
+insert into t1(a,b) values (1, 'one'), (2, 'two'), (3, 'three') ;
+insert into t9 (c1,c21)
+values (1, 'one'), (2, 'two'), (3, 'three') ;
+prepare stmt_delete from " delete t1, t9
+ from t1, t9 where t1.a=t9.c1 and t1.b='updated' ";
+prepare stmt_update from " update t1, t9
+ set t1.b='updated', t9.c21='updated'
+ where t1.a=t9.c1 and t1.a=? ";
+prepare stmt_select1 from " select a, b from t1 order by a" ;
+prepare stmt_select2 from " select c1, c21 from t9 order by c1" ;
+set @arg00= 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+2 two
+3 three
+execute stmt_select2 ;
+c1 c21
+2 two
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+3 three
+execute stmt_select2 ;
+c1 c21
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+execute stmt_select2 ;
+c1 c21
+set @arg00= @arg00 + 1 ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t1 values(0,NULL) ;
+set @duplicate='duplicate ' ;
+set @1000=1000 ;
+set @5=5 ;
+select a,b from t1 where a < 5 order by a ;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+insert into t1 select a + @1000, concat(@duplicate,b) from t1
+where a < @5 ;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' insert into t1 select a + ?, concat(?,b) from t1
+where a < ? ' ;
+execute stmt1 using @1000, @duplicate, @5;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+set @float=1.00;
+set @five='five' ;
+drop table if exists t2;
+create table t2 like t1 ;
+insert into t2 (b,a)
+select @duplicate, sum(first.a) from t1 first, t1 second
+where first.a <> @5 and second.b = first.b
+and second.b <> @five
+group by second.b
+having sum(second.a) > @2
+union
+select b, a + @100 from t1
+where (a,b) in ( select sqrt(a+@1)+CAST(@float AS signed),b
+from t1);
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 0
+select a,b from t2 order by a ;
+a b
+3 duplicate
+4 duplicate
+103 three
+delete from t2 ;
+prepare stmt1 from ' insert into t2 (b,a)
+select ?, sum(first.a)
+ from t1 first, t1 second
+ where first.a <> ? and second.b = first.b and second.b <> ?
+ group by second.b
+ having sum(second.a) > ?
+union
+select b, a + ? from t1
+ where (a,b) in ( select sqrt(a+?)+CAST(? AS signed),b
+ from t1 ) ' ;
+execute stmt1 using @duplicate, @5, @five, @2, @100, @1, @float ;
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 0
+select a,b from t2 order by a ;
+a b
+3 duplicate
+4 duplicate
+103 three
+drop table t2;
+drop table if exists t5 ;
+set @arg01= 8;
+set @arg02= 8.0;
+set @arg03= 80.00000000000e-1;
+set @arg04= 'abc' ;
+set @arg05= CAST('abc' as binary) ;
+set @arg06= '1991-08-05' ;
+set @arg07= CAST('1991-08-05' as date);
+set @arg08= '1991-08-05 01:01:01' ;
+set @arg09= CAST('1991-08-05 01:01:01' as datetime) ;
+set @arg10= unix_timestamp('1991-01-01 01:01:01');
+set @arg11= YEAR('1991-01-01 01:01:01');
+set @arg12= 8 ;
+set @arg12= NULL ;
+set @arg13= 8.0 ;
+set @arg13= NULL ;
+set @arg14= 'abc';
+set @arg14= NULL ;
+set @arg15= CAST('abc' as binary) ;
+set @arg15= NULL ;
+create table t5 as select
+8 as const01, @arg01 as param01,
+8.0 as const02, @arg02 as param02,
+80.00000000000e-1 as const03, @arg03 as param03,
+'abc' as const04, @arg04 as param04,
+CAST('abc' as binary) as const05, @arg05 as param05,
+'1991-08-05' as const06, @arg06 as param06,
+CAST('1991-08-05' as date) as const07, @arg07 as param07,
+'1991-08-05 01:01:01' as const08, @arg08 as param08,
+CAST('1991-08-05 01:01:01' as datetime) as const09, @arg09 as param09,
+unix_timestamp('1991-01-01 01:01:01') as const10, @arg10 as param10,
+YEAR('1991-01-01 01:01:01') as const11, @arg11 as param11,
+NULL as const12, @arg12 as param12,
+@arg13 as param13,
+@arg14 as param14,
+@arg15 as param15;
+show create table t5 ;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `const01` bigint(1) NOT NULL default '0',
+ `param01` bigint(20) default NULL,
+ `const02` double(3,1) NOT NULL default '0.0',
+ `param02` double default NULL,
+ `const03` double NOT NULL default '0',
+ `param03` double default NULL,
+ `const04` char(3) NOT NULL default '',
+ `param04` longtext,
+ `const05` binary(3) NOT NULL default '',
+ `param05` longblob,
+ `const06` varchar(10) NOT NULL default '',
+ `param06` longtext,
+ `const07` date default NULL,
+ `param07` longblob,
+ `const08` varchar(19) NOT NULL default '',
+ `param08` longtext,
+ `const09` datetime default NULL,
+ `param09` longblob,
+ `const10` int(10) NOT NULL default '0',
+ `param10` bigint(20) default NULL,
+ `const11` int(4) default NULL,
+ `param11` bigint(20) default NULL,
+ `const12` binary(0) default NULL,
+ `param12` bigint(20) default NULL,
+ `param13` double default NULL,
+ `param14` longtext,
+ `param15` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t5 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t5 t5 const01 const01 8 1 1 N 32769 0 63
+def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
+def test t5 t5 const02 const02 5 3 3 N 32769 1 63
+def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
+def test t5 t5 const03 const03 5 23 1 N 32769 31 63
+def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
+def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
+def test t5 t5 const06 const06 253 10 10 N 1 0 8
+def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
+def test t5 t5 const07 const07 10 10 10 Y 128 0 63
+def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
+def test t5 t5 const08 const08 253 19 19 N 1 0 8
+def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
+def test t5 t5 const09 const09 12 19 19 Y 128 0 63
+def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63
+def test t5 t5 const10 const10 3 10 9 N 32769 0 63
+def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
+def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
+def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
+def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
+def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
+def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
+const01 8
+param01 8
+const02 8.0
+param02 8
+const03 8
+param03 8
+const04 abc
+param04 abc
+const05 abc
+param05 abc
+const06 1991-08-05
+param06 1991-08-05
+const07 1991-08-05
+param07 1991-08-05
+const08 1991-08-05 01:01:01
+param08 1991-08-05 01:01:01
+const09 1991-08-05 01:01:01
+param09 1991-08-05 01:01:01
+const10 662680861
+param10 662680861
+const11 1991
+param11 1991
+const12 NULL
+param12 NULL
+param13 NULL
+param14 NULL
+param15 NULL
+drop table t5 ;
+test_sequence
+------ data type conversion tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t9 set c1= 0, c15= '1991-01-01 01:01:01' ;
+select * from t9 order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ select @parameter:= column ------
+prepare full_info from "select @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" ;
+select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 1 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 0 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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
+ @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+ @arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+ @arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+ @arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+ @arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+ @arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+ @arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+ @arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':= c1 from t9 where c1= 1' at line 1
+test_sequence
+------ select column, .. into @parm,.. ------
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 1 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 0 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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,
+ c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+ c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t9 where c1= 1' at line 1
+test_sequence
+-- insert into numeric columns --
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 ) ;
+set @arg00= 21 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22 )" ;
+execute stmt1 ;
+set @arg00= 23;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0,
+30.0, 30.0, 30.0 ) ;
+set @arg00= 31.0 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0,
+ 32.0, 32.0, 32.0 )" ;
+execute stmt1 ;
+set @arg00= 33.0;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( '40', '40', '40', '40', '40', '40', '40', '40',
+'40', '40', '40' ) ;
+set @arg00= '41' ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( '42', '42', '42', '42', '42', '42', '42', '42',
+ '42', '42', '42' )" ;
+execute stmt1 ;
+set @arg00= '43';
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary) ) ;
+set @arg00= CAST('51' as binary) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary) )" ;
+execute stmt1 ;
+set @arg00= CAST('53' as binary) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 2 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 60, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, NULL ) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 61, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 62, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL )" ;
+execute stmt1 ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 63, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 8.0 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 71, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 73, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 'abc' ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 81, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 83, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c1 >= 20
+order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c12
+20 20 20 20 20 20 20 20 20 20 20.0000
+21 21 21 21 21 21 21 21 21 21 21.0000
+22 22 22 22 22 22 22 22 22 22 22.0000
+23 23 23 23 23 23 23 23 23 23 23.0000
+30 30 30 30 30 30 30 30 30 30 30.0000
+31 31 31 31 31 31 31 31 31 31 31.0000
+32 32 32 32 32 32 32 32 32 32 32.0000
+33 33 33 33 33 33 33 33 33 33 33.0000
+40 40 40 40 40 40 40 40 40 40 40.0000
+41 41 41 41 41 41 41 41 41 41 41.0000
+42 42 42 42 42 42 42 42 42 42 42.0000
+43 43 43 43 43 43 43 43 43 43 43.0000
+50 50 50 50 50 50 50 50 50 50 50.0000
+51 51 51 51 51 51 51 51 51 51 51.0000
+52 52 52 52 52 52 52 52 52 52 52.0000
+53 53 53 53 53 53 53 53 53 53 53.0000
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where numeric column = .. --
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+and c8= 20 and c9= 20 and c10= 20 and c12= 20;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+ and c8= 20 and c9= 20 and c10= 20 and c12= 20 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+ and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20';
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20' ";
+execute stmt1 ;
+found
+true
+set @arg00= '20';
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+c12= CAST('20' as binary);
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+ c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+ c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+ c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+ c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+ c12= CAST('20' as binary) ";
+execute stmt1 ;
+found
+true
+set @arg00= CAST('20' as binary) ;
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- some numeric overflow experiments --
+prepare my_insert from "insert into t9
+ ( c21, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 'O', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+prepare my_select from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c21 = 'O' ";
+prepare my_delete from "delete from t9 where c21 = 'O' ";
+set @arg00= 9223372036854775807 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= '9223372036854775807' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= -9223372036854775808 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-9223372036854775808' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= 1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= '1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 1
+c2 1
+c3 1
+c4 1
+c5 1
+c6 1
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= -1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -1
+c2 -1
+c3 -1
+c4 -1
+c5 -1
+c6 -1
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+test_sequence
+-- insert into string columns --
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+select c1, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30
+from t9 where c1 >= 20
+order by c1 ;
+c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
+20 2 20 20 20 20 20 20 20 20 20 20
+21 2 21 21 21 21 21 21 21 21 21 21
+22 2 22 22 22 22 22 22 22 22 22 22
+23 2 23 23 23 23 23 23 23 23 23 23
+30 3 30 30 30 30 30 30 30 30 30 30
+31 3 31 31 31 31 31 31 31 31 31 31
+32 3 32 32 32 32 32 32 32 32 32 32
+33 3 33 33 33 33 33 33 33 33 33 33
+40 4 40 40 40 40 40 40 40 40 40 40
+41 4 41 41 41 41 41 41 41 41 41 41
+42 4 42 42 42 42 42 42 42 42 42 42
+43 4 43 43 43 43 43 43 43 43 43 43
+50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
+51 5 51 51 51 51 51 51 51 51 51 51
+52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
+53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
+55 5 55 55 55 55 55 55 55 55 55 55
+56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
+57 6 57 57 57.00 57.00 57.00 57.00 57.00 57.00 57.00 57.00
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where string column = .. --
+set @arg00= '20';
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+c27= '20' and c28= '20' and c29= '20' and c30= '20' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+ c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+ c27= '20' and c28= '20' and c29= '20' and c30= '20'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('20' as binary);
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+= CAST('20' as binary) and c21= CAST('20' as binary)
+and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+c30= CAST('20' as binary) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20))) = @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and
+c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+ = CAST('20' as binary) and c21= CAST('20' as binary)
+ and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+ c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+ c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+ c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+ c30= CAST('20' as binary)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20))) = ? and c21= ? and
+ c22= ? and c23= ? and c25= ? and c26= ? and c27= ? and c28= ? and
+ c29= ? and c30= ?";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+c27= 20 and c28= 20 and c29= 20 and c30= 20 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+ c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+ c27= 20 and c28= 20 and c29= 20 and c30= 20" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+ c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+ c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- insert into date/time columns --
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
+c1 c13 c14 c15 c16 c17
+20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+21 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+22 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+23 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+30 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+31 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+32 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+33 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+40 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+41 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+42 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+43 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+50 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+51 0010-00-00 0010-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+52 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+53 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+60 NULL NULL 1991-01-01 01:01:01 NULL NULL
+61 NULL NULL 1991-01-01 01:01:01 NULL NULL
+62 NULL NULL 1991-01-01 01:01:01 NULL NULL
+63 NULL NULL 1991-01-01 01:01:01 NULL NULL
+71 NULL NULL 1991-01-01 01:01:01 NULL NULL
+73 NULL NULL 1991-01-01 01:01:01 NULL NULL
+81 NULL NULL 1991-01-01 01:01:01 NULL NULL
+83 NULL NULL 1991-01-01 01:01:01 NULL NULL
+test_sequence
+-- select .. where date/time column = .. --
+set @arg00= '1991-01-01 01:01:01' ;
+select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+c17= '1991-01-01 01:01:01' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+ c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+ c17= '1991-01-01 01:01:01'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('1991-01-01 01:01:01' as datetime) ;
+select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+c14= CAST('1991-01-01 01:01:01' as datetime) and
+c15= CAST('1991-01-01 01:01:01' as datetime) and
+c16= CAST('1991-01-01 01:01:01' as datetime) and
+c17= CAST('1991-01-01 01:01:01' as datetime) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+ c14= CAST('1991-01-01 01:01:01' as datetime) and
+ c15= CAST('1991-01-01 01:01:01' as datetime) and
+ c16= CAST('1991-01-01 01:01:01' as datetime) and
+ c17= CAST('1991-01-01 01:01:01' as datetime)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 1991 ;
+select 'true' as found from t9
+where c1= 20 and c17= 1991 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= 1991" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= ?" ;
+execute stmt1 using @arg00 ;
+found
+true
+set @arg00= 1.991e+3 ;
+select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and abs(c17 - @arg00) < 0.01 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - ?) < 0.01" ;
+execute stmt1 using @arg00 ;
+found
+true
+drop table t1, t9;
diff --git a/mysql-test/r/ps_3innodb.result b/mysql-test/r/ps_3innodb.result
index 5c22beeb56b..888b8f57764 100644
--- a/mysql-test/r/ps_3innodb.result
+++ b/mysql-test/r/ps_3innodb.result
@@ -69,8 +69,8 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
-def test t9 t9 c22 c22 253 30 30 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
+def test t9 t9 c22 c22 254 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
def test t9 t9 c25 c25 252 65535 4 Y 144 0 63
@@ -1563,7 +1563,9 @@ a b
1200 x1000_1updatedupdated
delete from t1 where a >= 1000 ;
prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
-ERROR HY000: This command is not supported in the prepared statement protocol yet
+execute stmt1;
+execute stmt1;
+execute stmt1;
test_sequence
------ multi table tests ------
delete from t1 ;
@@ -1754,7 +1756,7 @@ t5 CREATE TABLE `t5` (
`param02` double default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
@@ -1770,10 +1772,10 @@ t5 CREATE TABLE `t5` (
`param10` bigint(20) default NULL,
`const11` int(4) default NULL,
`param11` bigint(20) default NULL,
- `const12` char(0) default NULL,
+ `const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
`param13` double default NULL,
- `param14` longblob,
+ `param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t5 ;
@@ -1784,9 +1786,9 @@ def test t5 t5 const02 const02 5 3 3 N 32769 1 63
def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
def test t5 t5 const03 const03 5 23 1 N 32769 31 63
def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
@@ -1800,10 +1802,10 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63
def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
-def test t5 t5 const12 const12 254 0 0 Y 0 0 8
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
-def test t5 t5 param14 param14 252 16777215 0 Y 144 0 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
param01 8
@@ -1890,38 +1892,38 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -1937,38 +1939,38 @@ from t9 where c1= 0 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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
@@ -1987,38 +1989,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
@@ -2027,38 +2029,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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" ;
@@ -2075,38 +2077,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -2119,38 +2121,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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,
@@ -2165,76 +2167,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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.es b/mysql-test/r/ps_3innodb.result.es
new file mode 100644
index 00000000000..9386f18a4df
--- /dev/null
+++ b/mysql-test/r/ps_3innodb.result.es
@@ -0,0 +1,3113 @@
+use test;
+drop table if exists t1, t9 ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'InnoDB' ;
+create table t9
+(
+c1 tinyint, c2 smallint, c3 mediumint, c4 int,
+c5 integer, c6 bigint, c7 float, c8 double,
+c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
+c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c17 year, c18 bit, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
+c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'InnoDB' ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+test_sequence
+------ simple select tests ------
+prepare stmt1 from ' select * from t9 order by c1 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t9 t9 c1 c1 1 4 1 N 49155 0 63
+def test t9 t9 c2 c2 2 6 1 Y 32768 0 63
+def test t9 t9 c3 c3 9 9 1 Y 32768 0 63
+def test t9 t9 c4 c4 3 11 1 Y 32768 0 63
+def test t9 t9 c5 c5 3 11 1 Y 32768 0 63
+def test t9 t9 c6 c6 8 20 1 Y 32768 0 63
+def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
+def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
+def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
+def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
+def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c13 c13 10 10 10 Y 128 0 63
+def test t9 t9 c14 c14 12 19 19 Y 128 0 63
+def test t9 t9 c15 c15 7 19 19 N 1249 0 63
+def test t9 t9 c16 c16 11 8 8 Y 128 0 63
+def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
+def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
+def test t9 t9 c20 c20 254 1 1 Y 0 0 8
+def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c22 c22 253 30 30 Y 0 0 8
+def test t9 t9 c23 c23 252 255 8 Y 144 0 63
+def test t9 t9 c24 c24 252 255 8 Y 16 0 8
+def test t9 t9 c25 c25 252 65535 4 Y 144 0 63
+def test t9 t9 c26 c26 252 65535 4 Y 16 0 8
+def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63
+def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8
+def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63
+def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8
+def test t9 t9 c31 c31 254 5 3 Y 256 0 8
+def test t9 t9 c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00=null ;
+select @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select @arg00 + 1 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? + 1 as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select 1 + @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select 1 + ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 order by a;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 order by a ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b order by a) from t1
+group by 'a' ;
+group_concat(@arg00,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00 order by a) from t1
+group by 'a' ;
+group_concat(b,@arg00 order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,? order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists t5 ;
+create table t5 (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+1 ii
+2 hh
+drop table t5 ;
+drop table if exists t5 ;
+create table t5(session_id char(9) not null) ;
+insert into t5 values ('abc') ;
+prepare stmt1 from ' select * from t5
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table t5 ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01) order by a;
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+set @arg00= 'one' ;
+set @arg01= 'two' ;
+set @arg02= 'five' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
+execute stmt1 using @arg00, @arg01, @arg02 ;
+b
+one
+two
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00=null ;
+insert into t9 set c1= 0, c5 = NULL ;
+select c5 from t9 where c5 > NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 > ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 < NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 < ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 = NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 = ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 <=> NULL ;
+c5
+NULL
+prepare stmt1 from ' select c5 from t9 where c5 <=> ? ';
+execute stmt1 using @arg00 ;
+c5
+NULL
+delete from t9 where c1= 0 ;
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 order by a ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? order by a ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1 ;
+execute stmt1 using @arg00;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=0 ;
+execute stmt1 using @arg00;
+ERROR 42S22: Unknown column '?' in 'order clause'
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1 order by a
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a order by a1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a order by a1 ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02
+order by second.a, first.a;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ?
+ order by second.a, first.a';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+drop table if exists t2 ;
+create table t2 as select * from t1 ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
+the join statement is:
+SELECT * FROM t2 right join t1 using(a) order by t2.a
+prepare stmt1 from @query9 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural right join t1 order by t2.a
+prepare stmt1 from @query8 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query7 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 using(a) order by t2.a
+prepare stmt1 from @query6 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural left join t1 order by t2.a
+prepare stmt1 from @query5 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query4 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 join t1 using(a) order by t2.a
+prepare stmt1 from @query3 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural join t1 order by t2.a
+prepare stmt1 from @query2 ;
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+the join statement is:
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
+prepare stmt1 from @query1 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+drop table t2 ;
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) order by a ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t1;
+prepare stmt1 from ' select a in (select a from t2) from t1 ' ;
+execute stmt1 ;
+a in (select a from t2)
+1
+1
+1
+1
+drop table if exists t5, t6, t7 ;
+create table t5 (a int , b int) ;
+create table t6 like t5 ;
+create table t7 like t5 ;
+insert into t5 values (0, 100), (1, 2), (1, 3), (2, 2), (2, 7),
+(2, -1), (3, 10) ;
+insert into t6 values (0, 0), (1, 1), (2, 1), (3, 1), (4, 1) ;
+insert into t7 values (3, 3), (2, 2), (1, 1) ;
+prepare stmt1 from ' select a, (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1) from t7 ' ;
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+drop table t5, t6, t7 ;
+drop table if exists t2 ;
+create table t2 as select * from t9;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t9.c2 - 0e-3) = t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t9.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t9.c2-?)=t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t9.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+drop table t2 ;
+select 1 < (select a from t1) ;
+ERROR 21000: Subquery returns more than 1 row
+prepare stmt1 from ' select 1 < (select a from t1) ' ;
+execute stmt1 ;
+ERROR 21000: Subquery returns more than 1 row
+select 1 as my_col ;
+my_col
+1
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+prepare stmt1 from ' SELECT 1, 2 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT 1, 2 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT * from t1 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT * from t1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' explain select * from t9 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 6 N 1 31 33
+def table 253 64 2 N 1 31 33
+def type 253 10 3 N 1 31 33
+def possible_keys 253 4096 0 Y 0 31 33
+def key 253 64 0 Y 0 31 33
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 33
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 0 N 1 31 33
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t9 ALL NULL NULL NULL NULL 2
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+select a,b from t1 order by a;
+a b
+0 two
+1 one
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 order by a;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+create table t2
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'InnoDB' ;
+insert into t2(a,b) select a, b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @NULL= null ;
+set @arg00= 'abc' ;
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg00 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg00 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 abc
+10002 abc
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @NULL ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @NULL ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 NULL
+10002 NULL
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 10 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 9 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 8 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 7 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 6 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 5 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 4 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 3 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg01 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 10001
+10002 10002
+10003 10003
+10004 10004
+10005 10005
+10006 10006
+10007 10007
+10008 10008
+10009 10009
+10010 10010
+delete from t1 where a > 10000 ;
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1 order by a;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+8 eight
+9 nine
+81 8-1
+82 8-2
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+drop table if exists t2 ;
+create table t2 (id int auto_increment primary key)
+ENGINE= 'InnoDB' ;
+prepare stmt1 from ' select last_insert_id() ' ;
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+1
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+2
+drop table t2 ;
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+execute stmt1;
+execute stmt1;
+execute stmt1;
+test_sequence
+------ multi table tests ------
+delete from t1 ;
+delete from t9 ;
+insert into t1(a,b) values (1, 'one'), (2, 'two'), (3, 'three') ;
+insert into t9 (c1,c21)
+values (1, 'one'), (2, 'two'), (3, 'three') ;
+prepare stmt_delete from " delete t1, t9
+ from t1, t9 where t1.a=t9.c1 and t1.b='updated' ";
+prepare stmt_update from " update t1, t9
+ set t1.b='updated', t9.c21='updated'
+ where t1.a=t9.c1 and t1.a=? ";
+prepare stmt_select1 from " select a, b from t1 order by a" ;
+prepare stmt_select2 from " select c1, c21 from t9 order by c1" ;
+set @arg00= 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+2 two
+3 three
+execute stmt_select2 ;
+c1 c21
+2 two
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+3 three
+execute stmt_select2 ;
+c1 c21
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+execute stmt_select2 ;
+c1 c21
+set @arg00= @arg00 + 1 ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t1 values(0,NULL) ;
+set @duplicate='duplicate ' ;
+set @1000=1000 ;
+set @5=5 ;
+select a,b from t1 where a < 5 order by a ;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+insert into t1 select a + @1000, concat(@duplicate,b) from t1
+where a < @5 ;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' insert into t1 select a + ?, concat(?,b) from t1
+where a < ? ' ;
+execute stmt1 using @1000, @duplicate, @5;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+set @float=1.00;
+set @five='five' ;
+drop table if exists t2;
+create table t2 like t1 ;
+insert into t2 (b,a)
+select @duplicate, sum(first.a) from t1 first, t1 second
+where first.a <> @5 and second.b = first.b
+and second.b <> @five
+group by second.b
+having sum(second.a) > @2
+union
+select b, a + @100 from t1
+where (a,b) in ( select sqrt(a+@1)+CAST(@float AS signed),b
+from t1);
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 0
+select a,b from t2 order by a ;
+a b
+3 duplicate
+4 duplicate
+103 three
+delete from t2 ;
+prepare stmt1 from ' insert into t2 (b,a)
+select ?, sum(first.a)
+ from t1 first, t1 second
+ where first.a <> ? and second.b = first.b and second.b <> ?
+ group by second.b
+ having sum(second.a) > ?
+union
+select b, a + ? from t1
+ where (a,b) in ( select sqrt(a+?)+CAST(? AS signed),b
+ from t1 ) ' ;
+execute stmt1 using @duplicate, @5, @five, @2, @100, @1, @float ;
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 0
+select a,b from t2 order by a ;
+a b
+3 duplicate
+4 duplicate
+103 three
+drop table t2;
+drop table if exists t5 ;
+set @arg01= 8;
+set @arg02= 8.0;
+set @arg03= 80.00000000000e-1;
+set @arg04= 'abc' ;
+set @arg05= CAST('abc' as binary) ;
+set @arg06= '1991-08-05' ;
+set @arg07= CAST('1991-08-05' as date);
+set @arg08= '1991-08-05 01:01:01' ;
+set @arg09= CAST('1991-08-05 01:01:01' as datetime) ;
+set @arg10= unix_timestamp('1991-01-01 01:01:01');
+set @arg11= YEAR('1991-01-01 01:01:01');
+set @arg12= 8 ;
+set @arg12= NULL ;
+set @arg13= 8.0 ;
+set @arg13= NULL ;
+set @arg14= 'abc';
+set @arg14= NULL ;
+set @arg15= CAST('abc' as binary) ;
+set @arg15= NULL ;
+create table t5 as select
+8 as const01, @arg01 as param01,
+8.0 as const02, @arg02 as param02,
+80.00000000000e-1 as const03, @arg03 as param03,
+'abc' as const04, @arg04 as param04,
+CAST('abc' as binary) as const05, @arg05 as param05,
+'1991-08-05' as const06, @arg06 as param06,
+CAST('1991-08-05' as date) as const07, @arg07 as param07,
+'1991-08-05 01:01:01' as const08, @arg08 as param08,
+CAST('1991-08-05 01:01:01' as datetime) as const09, @arg09 as param09,
+unix_timestamp('1991-01-01 01:01:01') as const10, @arg10 as param10,
+YEAR('1991-01-01 01:01:01') as const11, @arg11 as param11,
+NULL as const12, @arg12 as param12,
+@arg13 as param13,
+@arg14 as param14,
+@arg15 as param15;
+show create table t5 ;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `const01` bigint(1) NOT NULL default '0',
+ `param01` bigint(20) default NULL,
+ `const02` double(3,1) NOT NULL default '0.0',
+ `param02` double default NULL,
+ `const03` double NOT NULL default '0',
+ `param03` double default NULL,
+ `const04` char(3) NOT NULL default '',
+ `param04` longtext,
+ `const05` binary(3) NOT NULL default '',
+ `param05` longblob,
+ `const06` varchar(10) NOT NULL default '',
+ `param06` longtext,
+ `const07` date default NULL,
+ `param07` longblob,
+ `const08` varchar(19) NOT NULL default '',
+ `param08` longtext,
+ `const09` datetime default NULL,
+ `param09` longblob,
+ `const10` int(10) NOT NULL default '0',
+ `param10` bigint(20) default NULL,
+ `const11` int(4) default NULL,
+ `param11` bigint(20) default NULL,
+ `const12` binary(0) default NULL,
+ `param12` bigint(20) default NULL,
+ `param13` double default NULL,
+ `param14` longtext,
+ `param15` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t5 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t5 t5 const01 const01 8 1 1 N 32769 0 63
+def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
+def test t5 t5 const02 const02 5 3 3 N 32769 1 63
+def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
+def test t5 t5 const03 const03 5 23 1 N 32769 31 63
+def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
+def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
+def test t5 t5 const06 const06 253 10 10 N 1 0 8
+def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
+def test t5 t5 const07 const07 10 10 10 Y 128 0 63
+def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
+def test t5 t5 const08 const08 253 19 19 N 1 0 8
+def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
+def test t5 t5 const09 const09 12 19 19 Y 128 0 63
+def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63
+def test t5 t5 const10 const10 3 10 9 N 32769 0 63
+def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
+def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
+def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
+def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
+def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
+def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
+const01 8
+param01 8
+const02 8.0
+param02 8
+const03 8
+param03 8
+const04 abc
+param04 abc
+const05 abc
+param05 abc
+const06 1991-08-05
+param06 1991-08-05
+const07 1991-08-05
+param07 1991-08-05
+const08 1991-08-05 01:01:01
+param08 1991-08-05 01:01:01
+const09 1991-08-05 01:01:01
+param09 1991-08-05 01:01:01
+const10 662680861
+param10 662680861
+const11 1991
+param11 1991
+const12 NULL
+param12 NULL
+param13 NULL
+param14 NULL
+param15 NULL
+drop table t5 ;
+test_sequence
+------ data type conversion tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t9 set c1= 0, c15= '1991-01-01 01:01:01' ;
+select * from t9 order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ select @parameter:= column ------
+prepare full_info from "select @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" ;
+select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 1 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 0 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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
+ @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+ @arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+ @arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+ @arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+ @arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+ @arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+ @arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+ @arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':= c1 from t9 where c1= 1' at line 1
+test_sequence
+------ select column, .. into @parm,.. ------
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 1 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 0 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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,
+ c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+ c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t9 where c1= 1' at line 1
+test_sequence
+-- insert into numeric columns --
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 ) ;
+set @arg00= 21 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22 )" ;
+execute stmt1 ;
+set @arg00= 23;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0,
+30.0, 30.0, 30.0 ) ;
+set @arg00= 31.0 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0,
+ 32.0, 32.0, 32.0 )" ;
+execute stmt1 ;
+set @arg00= 33.0;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( '40', '40', '40', '40', '40', '40', '40', '40',
+'40', '40', '40' ) ;
+set @arg00= '41' ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( '42', '42', '42', '42', '42', '42', '42', '42',
+ '42', '42', '42' )" ;
+execute stmt1 ;
+set @arg00= '43';
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary) ) ;
+set @arg00= CAST('51' as binary) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary) )" ;
+execute stmt1 ;
+set @arg00= CAST('53' as binary) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 2 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 60, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, NULL ) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 61, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 62, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL )" ;
+execute stmt1 ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 63, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 8.0 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 71, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 73, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 'abc' ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 81, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 83, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c1 >= 20
+order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c12
+20 20 20 20 20 20 20 20 20 20 20.0000
+21 21 21 21 21 21 21 21 21 21 21.0000
+22 22 22 22 22 22 22 22 22 22 22.0000
+23 23 23 23 23 23 23 23 23 23 23.0000
+30 30 30 30 30 30 30 30 30 30 30.0000
+31 31 31 31 31 31 31 31 31 31 31.0000
+32 32 32 32 32 32 32 32 32 32 32.0000
+33 33 33 33 33 33 33 33 33 33 33.0000
+40 40 40 40 40 40 40 40 40 40 40.0000
+41 41 41 41 41 41 41 41 41 41 41.0000
+42 42 42 42 42 42 42 42 42 42 42.0000
+43 43 43 43 43 43 43 43 43 43 43.0000
+50 50 50 50 50 50 50 50 50 50 50.0000
+51 51 51 51 51 51 51 51 51 51 51.0000
+52 52 52 52 52 52 52 52 52 52 52.0000
+53 53 53 53 53 53 53 53 53 53 53.0000
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where numeric column = .. --
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+and c8= 20 and c9= 20 and c10= 20 and c12= 20;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+ and c8= 20 and c9= 20 and c10= 20 and c12= 20 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+ and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20';
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20' ";
+execute stmt1 ;
+found
+true
+set @arg00= '20';
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+c12= CAST('20' as binary);
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+ c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+ c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+ c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+ c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+ c12= CAST('20' as binary) ";
+execute stmt1 ;
+found
+true
+set @arg00= CAST('20' as binary) ;
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- some numeric overflow experiments --
+prepare my_insert from "insert into t9
+ ( c21, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 'O', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+prepare my_select from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c21 = 'O' ";
+prepare my_delete from "delete from t9 where c21 = 'O' ";
+set @arg00= 9223372036854775807 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= '9223372036854775807' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= -9223372036854775808 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-9223372036854775808' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= 1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= '1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 1
+c2 1
+c3 1
+c4 1
+c5 1
+c6 1
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= -1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -1
+c2 -1
+c3 -1
+c4 -1
+c5 -1
+c6 -1
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+test_sequence
+-- insert into string columns --
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+select c1, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30
+from t9 where c1 >= 20
+order by c1 ;
+c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
+20 2 20 20 20 20 20 20 20 20 20 20
+21 2 21 21 21 21 21 21 21 21 21 21
+22 2 22 22 22 22 22 22 22 22 22 22
+23 2 23 23 23 23 23 23 23 23 23 23
+30 3 30 30 30 30 30 30 30 30 30 30
+31 3 31 31 31 31 31 31 31 31 31 31
+32 3 32 32 32 32 32 32 32 32 32 32
+33 3 33 33 33 33 33 33 33 33 33 33
+40 4 40 40 40 40 40 40 40 40 40 40
+41 4 41 41 41 41 41 41 41 41 41 41
+42 4 42 42 42 42 42 42 42 42 42 42
+43 4 43 43 43 43 43 43 43 43 43 43
+50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
+51 5 51 51 51 51 51 51 51 51 51 51
+52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
+53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
+55 5 55 55 55 55 55 55 55 55 55 55
+56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
+57 6 57 57 57.00 57.00 57.00 57.00 57.00 57.00 57.00 57.00
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where string column = .. --
+set @arg00= '20';
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+c27= '20' and c28= '20' and c29= '20' and c30= '20' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+ c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+ c27= '20' and c28= '20' and c29= '20' and c30= '20'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('20' as binary);
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+= CAST('20' as binary) and c21= CAST('20' as binary)
+and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+c30= CAST('20' as binary) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20))) = @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and
+c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+ = CAST('20' as binary) and c21= CAST('20' as binary)
+ and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+ c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+ c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+ c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+ c30= CAST('20' as binary)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20))) = ? and c21= ? and
+ c22= ? and c23= ? and c25= ? and c26= ? and c27= ? and c28= ? and
+ c29= ? and c30= ?";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+c27= 20 and c28= 20 and c29= 20 and c30= 20 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+ c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+ c27= 20 and c28= 20 and c29= 20 and c30= 20" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+ c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+ c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- insert into date/time columns --
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
+c1 c13 c14 c15 c16 c17
+20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+21 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+22 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+23 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+30 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+31 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+32 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+33 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+40 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+41 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+42 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+43 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+50 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+51 0010-00-00 0010-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+52 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+53 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+60 NULL NULL 1991-01-01 01:01:01 NULL NULL
+61 NULL NULL 1991-01-01 01:01:01 NULL NULL
+62 NULL NULL 1991-01-01 01:01:01 NULL NULL
+63 NULL NULL 1991-01-01 01:01:01 NULL NULL
+71 NULL NULL 1991-01-01 01:01:01 NULL NULL
+73 NULL NULL 1991-01-01 01:01:01 NULL NULL
+81 NULL NULL 1991-01-01 01:01:01 NULL NULL
+83 NULL NULL 1991-01-01 01:01:01 NULL NULL
+test_sequence
+-- select .. where date/time column = .. --
+set @arg00= '1991-01-01 01:01:01' ;
+select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+c17= '1991-01-01 01:01:01' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+ c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+ c17= '1991-01-01 01:01:01'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('1991-01-01 01:01:01' as datetime) ;
+select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+c14= CAST('1991-01-01 01:01:01' as datetime) and
+c15= CAST('1991-01-01 01:01:01' as datetime) and
+c16= CAST('1991-01-01 01:01:01' as datetime) and
+c17= CAST('1991-01-01 01:01:01' as datetime) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+ c14= CAST('1991-01-01 01:01:01' as datetime) and
+ c15= CAST('1991-01-01 01:01:01' as datetime) and
+ c16= CAST('1991-01-01 01:01:01' as datetime) and
+ c17= CAST('1991-01-01 01:01:01' as datetime)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 1991 ;
+select 'true' as found from t9
+where c1= 20 and c17= 1991 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= 1991" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= ?" ;
+execute stmt1 using @arg00 ;
+found
+true
+set @arg00= 1.991e+3 ;
+select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and abs(c17 - @arg00) < 0.01 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - ?) < 0.01" ;
+execute stmt1 using @arg00 ;
+found
+true
+drop table t1, t9;
diff --git a/mysql-test/r/ps_4heap.result b/mysql-test/r/ps_4heap.result
index 9cbe87b004a..d6e835adbc6 100644
--- a/mysql-test/r/ps_4heap.result
+++ b/mysql-test/r/ps_4heap.result
@@ -13,9 +13,9 @@ c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
c13 date, c14 datetime, c15 timestamp(14), c16 time,
c17 year, c18 bit, c19 bool, c20 char,
-c21 char(10), c22 varchar(30), c23 char(100), c24 char(100),
-c25 char(100), c26 char(100), c27 char(100), c28 char(100),
-c29 char(100), c30 char(100), c31 enum('one', 'two', 'three'),
+c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100),
+c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100),
+c29 varchar(100), c30 varchar(100), c31 enum('one', 'two', 'three'),
c32 set('monday', 'tuesday', 'wednesday'),
primary key(c1)
) engine = 'HEAP' ;
@@ -70,7 +70,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 253 100 8 Y 0 0 8
def test t9 t9 c24 c24 253 100 8 Y 0 0 8
@@ -1564,7 +1564,9 @@ a b
1200 x1000_1updatedupdated
delete from t1 where a >= 1000 ;
prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
-ERROR HY000: This command is not supported in the prepared statement protocol yet
+execute stmt1;
+execute stmt1;
+execute stmt1;
test_sequence
------ multi table tests ------
delete from t1 ;
@@ -1687,8 +1689,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@@ -1706,8 +1708,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
drop table t2;
drop table if exists t5 ;
@@ -1755,7 +1757,7 @@ t5 CREATE TABLE `t5` (
`param02` double default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
@@ -1771,10 +1773,10 @@ t5 CREATE TABLE `t5` (
`param10` bigint(20) default NULL,
`const11` int(4) default NULL,
`param11` bigint(20) default NULL,
- `const12` char(0) default NULL,
+ `const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
`param13` double default NULL,
- `param14` longblob,
+ `param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t5 ;
@@ -1785,9 +1787,9 @@ def test t5 t5 const02 const02 5 3 3 N 32769 1 63
def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
def test t5 t5 const03 const03 5 23 1 N 32769 31 63
def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
@@ -1801,10 +1803,10 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63
def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
-def test t5 t5 const12 const12 254 0 0 Y 0 0 8
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
-def test t5 t5 param14 param14 252 16777215 0 Y 144 0 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
param01 8
@@ -1891,38 +1893,38 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 0 31 8
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 0 31 8
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 0 31 8
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 0 31 8
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -1938,38 +1940,38 @@ from t9 where c1= 0 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 0 31 8
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 0 31 8
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 0 31 8
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 0 31 8
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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
@@ -1988,38 +1990,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 0 31 8
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 0 31 8
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 0 31 8
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 0 31 8
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
@@ -2028,38 +2030,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 0 31 8
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 0 31 8
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 0 31 8
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 0 31 8
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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" ;
@@ -2076,38 +2078,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 0 31 8
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 0 31 8
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 0 31 8
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 0 31 8
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -2120,38 +2122,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 0 31 8
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 0 31 8
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 0 31 8
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 0 31 8
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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,
@@ -2166,76 +2168,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 0 31 8
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 0 31 8
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 0 31 8
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 0 31 8
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 0 31 8
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 0 31 8
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 0 31 8
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 0 31 8
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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.es b/mysql-test/r/ps_4heap.result.es
new file mode 100644
index 00000000000..fcd9c52b4f9
--- /dev/null
+++ b/mysql-test/r/ps_4heap.result.es
@@ -0,0 +1,3114 @@
+use test;
+drop table if exists t1, t9 ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'HEAP' ;
+drop table if exists t9;
+create table t9
+(
+c1 tinyint, c2 smallint, c3 mediumint, c4 int,
+c5 integer, c6 bigint, c7 float, c8 double,
+c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
+c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c17 year, c18 bit, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 char(100), c24 char(100),
+c25 char(100), c26 char(100), c27 char(100), c28 char(100),
+c29 char(100), c30 char(100), c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'HEAP' ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+test_sequence
+------ simple select tests ------
+prepare stmt1 from ' select * from t9 order by c1 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t9 t9 c1 c1 1 4 1 N 49155 0 63
+def test t9 t9 c2 c2 2 6 1 Y 32768 0 63
+def test t9 t9 c3 c3 9 9 1 Y 32768 0 63
+def test t9 t9 c4 c4 3 11 1 Y 32768 0 63
+def test t9 t9 c5 c5 3 11 1 Y 32768 0 63
+def test t9 t9 c6 c6 8 20 1 Y 32768 0 63
+def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
+def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
+def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
+def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
+def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c13 c13 10 10 10 Y 128 0 63
+def test t9 t9 c14 c14 12 19 19 Y 128 0 63
+def test t9 t9 c15 c15 7 19 19 N 1249 0 63
+def test t9 t9 c16 c16 11 8 8 Y 128 0 63
+def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
+def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
+def test t9 t9 c20 c20 254 1 1 Y 0 0 8
+def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c22 c22 253 30 30 Y 0 0 8
+def test t9 t9 c23 c23 253 100 8 Y 0 0 8
+def test t9 t9 c24 c24 253 100 8 Y 0 0 8
+def test t9 t9 c25 c25 253 100 4 Y 0 0 8
+def test t9 t9 c26 c26 253 100 4 Y 0 0 8
+def test t9 t9 c27 c27 253 100 10 Y 0 0 8
+def test t9 t9 c28 c28 253 100 10 Y 0 0 8
+def test t9 t9 c29 c29 253 100 8 Y 0 0 8
+def test t9 t9 c30 c30 253 100 8 Y 0 0 8
+def test t9 t9 c31 c31 254 5 3 Y 256 0 8
+def test t9 t9 c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00=null ;
+select @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select @arg00 + 1 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? + 1 as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select 1 + @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select 1 + ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 order by a;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 order by a ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b order by a) from t1
+group by 'a' ;
+group_concat(@arg00,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00 order by a) from t1
+group by 'a' ;
+group_concat(b,@arg00 order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,? order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists t5 ;
+create table t5 (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+1 ii
+2 hh
+drop table t5 ;
+drop table if exists t5 ;
+create table t5(session_id char(9) not null) ;
+insert into t5 values ('abc') ;
+prepare stmt1 from ' select * from t5
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table t5 ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01) order by a;
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+set @arg00= 'one' ;
+set @arg01= 'two' ;
+set @arg02= 'five' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
+execute stmt1 using @arg00, @arg01, @arg02 ;
+b
+one
+two
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00=null ;
+insert into t9 set c1= 0, c5 = NULL ;
+select c5 from t9 where c5 > NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 > ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 < NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 < ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 = NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 = ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 <=> NULL ;
+c5
+NULL
+prepare stmt1 from ' select c5 from t9 where c5 <=> ? ';
+execute stmt1 using @arg00 ;
+c5
+NULL
+delete from t9 where c1= 0 ;
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 order by a ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? order by a ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1 ;
+execute stmt1 using @arg00;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=0 ;
+execute stmt1 using @arg00;
+ERROR 42S22: Unknown column '?' in 'order clause'
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1 order by a
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a order by a1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a order by a1 ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02
+order by second.a, first.a;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ?
+ order by second.a, first.a';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+drop table if exists t2 ;
+create table t2 as select * from t1 ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
+the join statement is:
+SELECT * FROM t2 right join t1 using(a) order by t2.a
+prepare stmt1 from @query9 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural right join t1 order by t2.a
+prepare stmt1 from @query8 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query7 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 using(a) order by t2.a
+prepare stmt1 from @query6 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural left join t1 order by t2.a
+prepare stmt1 from @query5 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query4 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 join t1 using(a) order by t2.a
+prepare stmt1 from @query3 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural join t1 order by t2.a
+prepare stmt1 from @query2 ;
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+the join statement is:
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
+prepare stmt1 from @query1 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+drop table t2 ;
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) order by a ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t1;
+prepare stmt1 from ' select a in (select a from t2) from t1 ' ;
+execute stmt1 ;
+a in (select a from t2)
+1
+1
+1
+1
+drop table if exists t5, t6, t7 ;
+create table t5 (a int , b int) ;
+create table t6 like t5 ;
+create table t7 like t5 ;
+insert into t5 values (0, 100), (1, 2), (1, 3), (2, 2), (2, 7),
+(2, -1), (3, 10) ;
+insert into t6 values (0, 0), (1, 1), (2, 1), (3, 1), (4, 1) ;
+insert into t7 values (3, 3), (2, 2), (1, 1) ;
+prepare stmt1 from ' select a, (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1) from t7 ' ;
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+drop table t5, t6, t7 ;
+drop table if exists t2 ;
+create table t2 as select * from t9;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t9.c2 - 0e-3) = t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t9.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t9.c2-?)=t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t9.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+drop table t2 ;
+select 1 < (select a from t1) ;
+ERROR 21000: Subquery returns more than 1 row
+prepare stmt1 from ' select 1 < (select a from t1) ' ;
+execute stmt1 ;
+ERROR 21000: Subquery returns more than 1 row
+select 1 as my_col ;
+my_col
+1
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+prepare stmt1 from ' SELECT 1, 2 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT 1, 2 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT * from t1 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT * from t1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' explain select * from t9 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 6 N 1 31 33
+def table 253 64 2 N 1 31 33
+def type 253 10 3 N 1 31 33
+def possible_keys 253 4096 0 Y 0 31 33
+def key 253 64 0 Y 0 31 33
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 33
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 0 N 1 31 33
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t9 ALL NULL NULL NULL NULL 2
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+select a,b from t1 order by a;
+a b
+0 two
+1 one
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 order by a;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+create table t2
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'HEAP' ;
+insert into t2(a,b) select a, b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @NULL= null ;
+set @arg00= 'abc' ;
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg00 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg00 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 abc
+10002 abc
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @NULL ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @NULL ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 NULL
+10002 NULL
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 10 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 9 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 8 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 7 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 6 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 5 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 4 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 3 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg01 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 10001
+10002 10002
+10003 10003
+10004 10004
+10005 10005
+10006 10006
+10007 10007
+10008 10008
+10009 10009
+10010 10010
+delete from t1 where a > 10000 ;
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1 order by a;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+8 eight
+9 nine
+81 8-1
+82 8-2
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+drop table if exists t2 ;
+create table t2 (id int auto_increment primary key)
+ENGINE= 'HEAP' ;
+prepare stmt1 from ' select last_insert_id() ' ;
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+1
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+2
+drop table t2 ;
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+execute stmt1;
+execute stmt1;
+execute stmt1;
+test_sequence
+------ multi table tests ------
+delete from t1 ;
+delete from t9 ;
+insert into t1(a,b) values (1, 'one'), (2, 'two'), (3, 'three') ;
+insert into t9 (c1,c21)
+values (1, 'one'), (2, 'two'), (3, 'three') ;
+prepare stmt_delete from " delete t1, t9
+ from t1, t9 where t1.a=t9.c1 and t1.b='updated' ";
+prepare stmt_update from " update t1, t9
+ set t1.b='updated', t9.c21='updated'
+ where t1.a=t9.c1 and t1.a=? ";
+prepare stmt_select1 from " select a, b from t1 order by a" ;
+prepare stmt_select2 from " select c1, c21 from t9 order by c1" ;
+set @arg00= 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+2 two
+3 three
+execute stmt_select2 ;
+c1 c21
+2 two
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+3 three
+execute stmt_select2 ;
+c1 c21
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+execute stmt_select2 ;
+c1 c21
+set @arg00= @arg00 + 1 ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t1 values(0,NULL) ;
+set @duplicate='duplicate ' ;
+set @1000=1000 ;
+set @5=5 ;
+select a,b from t1 where a < 5 order by a ;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+insert into t1 select a + @1000, concat(@duplicate,b) from t1
+where a < @5 ;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' insert into t1 select a + ?, concat(?,b) from t1
+where a < ? ' ;
+execute stmt1 using @1000, @duplicate, @5;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+set @float=1.00;
+set @five='five' ;
+drop table if exists t2;
+create table t2 like t1 ;
+insert into t2 (b,a)
+select @duplicate, sum(first.a) from t1 first, t1 second
+where first.a <> @5 and second.b = first.b
+and second.b <> @five
+group by second.b
+having sum(second.a) > @2
+union
+select b, a + @100 from t1
+where (a,b) in ( select sqrt(a+@1)+CAST(@float AS signed),b
+from t1);
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 0
+select a,b from t2 order by a ;
+a b
+3 duplicate
+4 duplicate
+103 three
+delete from t2 ;
+prepare stmt1 from ' insert into t2 (b,a)
+select ?, sum(first.a)
+ from t1 first, t1 second
+ where first.a <> ? and second.b = first.b and second.b <> ?
+ group by second.b
+ having sum(second.a) > ?
+union
+select b, a + ? from t1
+ where (a,b) in ( select sqrt(a+?)+CAST(? AS signed),b
+ from t1 ) ' ;
+execute stmt1 using @duplicate, @5, @five, @2, @100, @1, @float ;
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 0
+select a,b from t2 order by a ;
+a b
+3 duplicate
+4 duplicate
+103 three
+drop table t2;
+drop table if exists t5 ;
+set @arg01= 8;
+set @arg02= 8.0;
+set @arg03= 80.00000000000e-1;
+set @arg04= 'abc' ;
+set @arg05= CAST('abc' as binary) ;
+set @arg06= '1991-08-05' ;
+set @arg07= CAST('1991-08-05' as date);
+set @arg08= '1991-08-05 01:01:01' ;
+set @arg09= CAST('1991-08-05 01:01:01' as datetime) ;
+set @arg10= unix_timestamp('1991-01-01 01:01:01');
+set @arg11= YEAR('1991-01-01 01:01:01');
+set @arg12= 8 ;
+set @arg12= NULL ;
+set @arg13= 8.0 ;
+set @arg13= NULL ;
+set @arg14= 'abc';
+set @arg14= NULL ;
+set @arg15= CAST('abc' as binary) ;
+set @arg15= NULL ;
+create table t5 as select
+8 as const01, @arg01 as param01,
+8.0 as const02, @arg02 as param02,
+80.00000000000e-1 as const03, @arg03 as param03,
+'abc' as const04, @arg04 as param04,
+CAST('abc' as binary) as const05, @arg05 as param05,
+'1991-08-05' as const06, @arg06 as param06,
+CAST('1991-08-05' as date) as const07, @arg07 as param07,
+'1991-08-05 01:01:01' as const08, @arg08 as param08,
+CAST('1991-08-05 01:01:01' as datetime) as const09, @arg09 as param09,
+unix_timestamp('1991-01-01 01:01:01') as const10, @arg10 as param10,
+YEAR('1991-01-01 01:01:01') as const11, @arg11 as param11,
+NULL as const12, @arg12 as param12,
+@arg13 as param13,
+@arg14 as param14,
+@arg15 as param15;
+show create table t5 ;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `const01` bigint(1) NOT NULL default '0',
+ `param01` bigint(20) default NULL,
+ `const02` double(3,1) NOT NULL default '0.0',
+ `param02` double default NULL,
+ `const03` double NOT NULL default '0',
+ `param03` double default NULL,
+ `const04` char(3) NOT NULL default '',
+ `param04` longtext,
+ `const05` binary(3) NOT NULL default '',
+ `param05` longblob,
+ `const06` varchar(10) NOT NULL default '',
+ `param06` longtext,
+ `const07` date default NULL,
+ `param07` longblob,
+ `const08` varchar(19) NOT NULL default '',
+ `param08` longtext,
+ `const09` datetime default NULL,
+ `param09` longblob,
+ `const10` int(10) NOT NULL default '0',
+ `param10` bigint(20) default NULL,
+ `const11` int(4) default NULL,
+ `param11` bigint(20) default NULL,
+ `const12` binary(0) default NULL,
+ `param12` bigint(20) default NULL,
+ `param13` double default NULL,
+ `param14` longtext,
+ `param15` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t5 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t5 t5 const01 const01 8 1 1 N 32769 0 63
+def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
+def test t5 t5 const02 const02 5 3 3 N 32769 1 63
+def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
+def test t5 t5 const03 const03 5 23 1 N 32769 31 63
+def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
+def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
+def test t5 t5 const06 const06 253 10 10 N 1 0 8
+def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
+def test t5 t5 const07 const07 10 10 10 Y 128 0 63
+def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
+def test t5 t5 const08 const08 253 19 19 N 1 0 8
+def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
+def test t5 t5 const09 const09 12 19 19 Y 128 0 63
+def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63
+def test t5 t5 const10 const10 3 10 9 N 32769 0 63
+def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
+def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
+def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
+def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
+def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
+def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
+const01 8
+param01 8
+const02 8.0
+param02 8
+const03 8
+param03 8
+const04 abc
+param04 abc
+const05 abc
+param05 abc
+const06 1991-08-05
+param06 1991-08-05
+const07 1991-08-05
+param07 1991-08-05
+const08 1991-08-05 01:01:01
+param08 1991-08-05 01:01:01
+const09 1991-08-05 01:01:01
+param09 1991-08-05 01:01:01
+const10 662680861
+param10 662680861
+const11 1991
+param11 1991
+const12 NULL
+param12 NULL
+param13 NULL
+param14 NULL
+param15 NULL
+drop table t5 ;
+test_sequence
+------ data type conversion tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t9 set c1= 0, c15= '1991-01-01 01:01:01' ;
+select * from t9 order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ select @parameter:= column ------
+prepare full_info from "select @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" ;
+select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 1 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 0 31 8
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 0 31 8
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 0 31 8
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 0 31 8
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 0 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 0 31 8
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 0 31 8
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 0 31 8
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 0 31 8
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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
+ @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+ @arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+ @arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+ @arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+ @arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+ @arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+ @arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+ @arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 0 31 8
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 0 31 8
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 0 31 8
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 0 31 8
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 0 31 8
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 0 31 8
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 0 31 8
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 0 31 8
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':= c1 from t9 where c1= 1' at line 1
+test_sequence
+------ select column, .. into @parm,.. ------
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 1 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 0 31 8
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 0 31 8
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 0 31 8
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 0 31 8
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 0 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 0 31 8
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 0 31 8
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 0 31 8
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 0 31 8
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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,
+ c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+ c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 0 31 8
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 0 31 8
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 0 31 8
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 0 31 8
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 0 31 8
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 0 31 8
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 0 31 8
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 0 31 8
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t9 where c1= 1' at line 1
+test_sequence
+-- insert into numeric columns --
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 ) ;
+set @arg00= 21 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22 )" ;
+execute stmt1 ;
+set @arg00= 23;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0,
+30.0, 30.0, 30.0 ) ;
+set @arg00= 31.0 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0,
+ 32.0, 32.0, 32.0 )" ;
+execute stmt1 ;
+set @arg00= 33.0;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( '40', '40', '40', '40', '40', '40', '40', '40',
+'40', '40', '40' ) ;
+set @arg00= '41' ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( '42', '42', '42', '42', '42', '42', '42', '42',
+ '42', '42', '42' )" ;
+execute stmt1 ;
+set @arg00= '43';
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary) ) ;
+set @arg00= CAST('51' as binary) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary) )" ;
+execute stmt1 ;
+set @arg00= CAST('53' as binary) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 2 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 60, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, NULL ) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 61, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 62, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL )" ;
+execute stmt1 ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 63, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 8.0 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 71, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 73, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 'abc' ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 81, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 83, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c1 >= 20
+order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c12
+20 20 20 20 20 20 20 20 20 20 20.0000
+21 21 21 21 21 21 21 21 21 21 21.0000
+22 22 22 22 22 22 22 22 22 22 22.0000
+23 23 23 23 23 23 23 23 23 23 23.0000
+30 30 30 30 30 30 30 30 30 30 30.0000
+31 31 31 31 31 31 31 31 31 31 31.0000
+32 32 32 32 32 32 32 32 32 32 32.0000
+33 33 33 33 33 33 33 33 33 33 33.0000
+40 40 40 40 40 40 40 40 40 40 40.0000
+41 41 41 41 41 41 41 41 41 41 41.0000
+42 42 42 42 42 42 42 42 42 42 42.0000
+43 43 43 43 43 43 43 43 43 43 43.0000
+50 50 50 50 50 50 50 50 50 50 50.0000
+51 51 51 51 51 51 51 51 51 51 51.0000
+52 52 52 52 52 52 52 52 52 52 52.0000
+53 53 53 53 53 53 53 53 53 53 53.0000
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where numeric column = .. --
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+and c8= 20 and c9= 20 and c10= 20 and c12= 20;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+ and c8= 20 and c9= 20 and c10= 20 and c12= 20 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+ and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20';
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20' ";
+execute stmt1 ;
+found
+true
+set @arg00= '20';
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+c12= CAST('20' as binary);
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+ c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+ c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+ c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+ c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+ c12= CAST('20' as binary) ";
+execute stmt1 ;
+found
+true
+set @arg00= CAST('20' as binary) ;
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- some numeric overflow experiments --
+prepare my_insert from "insert into t9
+ ( c21, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 'O', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+prepare my_select from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c21 = 'O' ";
+prepare my_delete from "delete from t9 where c21 = 'O' ";
+set @arg00= 9223372036854775807 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= '9223372036854775807' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= -9223372036854775808 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-9223372036854775808' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= 1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= '1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 1
+c2 1
+c3 1
+c4 1
+c5 1
+c6 1
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= -1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -1
+c2 -1
+c3 -1
+c4 -1
+c5 -1
+c6 -1
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+test_sequence
+-- insert into string columns --
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+select c1, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30
+from t9 where c1 >= 20
+order by c1 ;
+c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
+20 2 20 20 20 20 20 20 20 20 20 20
+21 2 21 21 21 21 21 21 21 21 21 21
+22 2 22 22 22 22 22 22 22 22 22 22
+23 2 23 23 23 23 23 23 23 23 23 23
+30 3 30 30 30 30 30 30 30 30 30 30
+31 3 31 31 31 31 31 31 31 31 31 31
+32 3 32 32 32 32 32 32 32 32 32 32
+33 3 33 33 33 33 33 33 33 33 33 33
+40 4 40 40 40 40 40 40 40 40 40 40
+41 4 41 41 41 41 41 41 41 41 41 41
+42 4 42 42 42 42 42 42 42 42 42 42
+43 4 43 43 43 43 43 43 43 43 43 43
+50 5 50 50 50 50 50 50 50 50 50 50
+51 5 51 51 51 51 51 51 51 51 51 51
+52 5 52 52 52 52 52 52 52 52 52 52
+53 5 53 53 53 53 53 53 53 53 53 53
+54 5 54 54 54 54 54 54 54 54 54 54
+55 5 55 55 55 55 55 55 55 55 55 55
+56 6 56 56 56 56 56 56 56 56 56 56
+57 6 57 57 57 57 57 57 57 57 57 57
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where string column = .. --
+set @arg00= '20';
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+c27= '20' and c28= '20' and c29= '20' and c30= '20' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+ c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+ c27= '20' and c28= '20' and c29= '20' and c30= '20'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('20' as binary);
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+= CAST('20' as binary) and c21= CAST('20' as binary)
+and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+c30= CAST('20' as binary) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20))) = @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and
+c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+ = CAST('20' as binary) and c21= CAST('20' as binary)
+ and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+ c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+ c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+ c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+ c30= CAST('20' as binary)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20))) = ? and c21= ? and
+ c22= ? and c23= ? and c25= ? and c26= ? and c27= ? and c28= ? and
+ c29= ? and c30= ?";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+c27= 20 and c28= 20 and c29= 20 and c30= 20 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+ c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+ c27= 20 and c28= 20 and c29= 20 and c30= 20" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+ c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+ c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- insert into date/time columns --
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
+c1 c13 c14 c15 c16 c17
+20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+21 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+22 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+23 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+30 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+31 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+32 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+33 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+40 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+41 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+42 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+43 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+50 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+51 0010-00-00 0010-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+52 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+53 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+60 NULL NULL 1991-01-01 01:01:01 NULL NULL
+61 NULL NULL 1991-01-01 01:01:01 NULL NULL
+62 NULL NULL 1991-01-01 01:01:01 NULL NULL
+63 NULL NULL 1991-01-01 01:01:01 NULL NULL
+71 NULL NULL 1991-01-01 01:01:01 NULL NULL
+73 NULL NULL 1991-01-01 01:01:01 NULL NULL
+81 NULL NULL 1991-01-01 01:01:01 NULL NULL
+83 NULL NULL 1991-01-01 01:01:01 NULL NULL
+test_sequence
+-- select .. where date/time column = .. --
+set @arg00= '1991-01-01 01:01:01' ;
+select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+c17= '1991-01-01 01:01:01' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+ c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+ c17= '1991-01-01 01:01:01'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('1991-01-01 01:01:01' as datetime) ;
+select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+c14= CAST('1991-01-01 01:01:01' as datetime) and
+c15= CAST('1991-01-01 01:01:01' as datetime) and
+c16= CAST('1991-01-01 01:01:01' as datetime) and
+c17= CAST('1991-01-01 01:01:01' as datetime) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+ c14= CAST('1991-01-01 01:01:01' as datetime) and
+ c15= CAST('1991-01-01 01:01:01' as datetime) and
+ c16= CAST('1991-01-01 01:01:01' as datetime) and
+ c17= CAST('1991-01-01 01:01:01' as datetime)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 1991 ;
+select 'true' as found from t9
+where c1= 20 and c17= 1991 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= 1991" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= ?" ;
+execute stmt1 using @arg00 ;
+found
+true
+set @arg00= 1.991e+3 ;
+select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and abs(c17 - @arg00) < 0.01 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - ?) < 0.01" ;
+execute stmt1 using @arg00 ;
+found
+true
+drop table t1, t9;
diff --git a/mysql-test/r/ps_5merge.result b/mysql-test/r/ps_5merge.result
index 4ed0295a92e..9a0b0cb8b75 100644
--- a/mysql-test/r/ps_5merge.result
+++ b/mysql-test/r/ps_5merge.result
@@ -112,7 +112,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -1606,7 +1606,9 @@ a b
1200 x1000_1updatedupdated
delete from t1 where a >= 1000 ;
prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
-ERROR HY000: This command is not supported in the prepared statement protocol yet
+execute stmt1;
+execute stmt1;
+execute stmt1;
test_sequence
------ multi table tests ------
delete from t1 ;
@@ -1694,7 +1696,7 @@ t5 CREATE TABLE `t5` (
`param02` double default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
@@ -1710,10 +1712,10 @@ t5 CREATE TABLE `t5` (
`param10` bigint(20) default NULL,
`const11` int(4) default NULL,
`param11` bigint(20) default NULL,
- `const12` char(0) default NULL,
+ `const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
`param13` double default NULL,
- `param14` longblob,
+ `param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t5 ;
@@ -1724,9 +1726,9 @@ def test t5 t5 const02 const02 5 3 3 N 32769 1 63
def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
def test t5 t5 const03 const03 5 23 1 N 32769 31 63
def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
@@ -1740,10 +1742,10 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63
def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
-def test t5 t5 const12 const12 254 0 0 Y 0 0 8
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
-def test t5 t5 param14 param14 252 16777215 0 Y 144 0 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
param01 8
@@ -1830,38 +1832,38 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -1877,38 +1879,38 @@ from t9 where c1= 0 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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
@@ -1927,38 +1929,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
@@ -1967,38 +1969,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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" ;
@@ -2015,38 +2017,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -2059,38 +2061,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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,
@@ -2105,76 +2107,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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" ;
@@ -3119,7 +3121,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -4613,7 +4615,9 @@ a b
1200 x1000_1updatedupdated
delete from t1 where a >= 1000 ;
prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
-ERROR HY000: This command is not supported in the prepared statement protocol yet
+execute stmt1;
+execute stmt1;
+execute stmt1;
test_sequence
------ multi table tests ------
delete from t1 ;
@@ -4701,9 +4705,9 @@ t5 CREATE TABLE `t5` (
`param02` double default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
- `const05` binary(3) NOT NULL default '',
+ `const05` varchar(3) NOT NULL default '',
`param05` longblob,
`const06` varchar(10) NOT NULL default '',
`param06` longtext,
@@ -4717,10 +4721,10 @@ t5 CREATE TABLE `t5` (
`param10` bigint(20) default NULL,
`const11` int(4) default NULL,
`param11` bigint(20) default NULL,
- `const12` char(0) default NULL,
+ `const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
`param13` double default NULL,
- `param14` longblob,
+ `param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t5 ;
@@ -4731,9 +4735,9 @@ def test t5 t5 const02 const02 5 3 3 N 32769 1 63
def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
def test t5 t5 const03 const03 5 23 1 N 32769 31 63
def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
@@ -4747,10 +4751,10 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63
def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
-def test t5 t5 const12 const12 254 0 0 Y 0 0 8
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
-def test t5 t5 param14 param14 252 16777215 0 Y 144 0 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
param01 8
@@ -4837,38 +4841,38 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -4884,38 +4888,38 @@ from t9 where c1= 0 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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
@@ -4934,38 +4938,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
@@ -4974,38 +4978,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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" ;
@@ -5022,38 +5026,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -5066,38 +5070,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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,
@@ -5112,76 +5116,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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.es b/mysql-test/r/ps_5merge.result.es
new file mode 100644
index 00000000000..4f05be1b4d9
--- /dev/null
+++ b/mysql-test/r/ps_5merge.result.es
@@ -0,0 +1,6064 @@
+use test;
+drop table if exists t1, t1_1, t1_2,
+t9, t9_1, t9_2;
+drop table if exists t1, t9 ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+create table t9
+(
+c1 tinyint, c2 smallint, c3 mediumint, c4 int,
+c5 integer, c6 bigint, c7 float, c8 double,
+c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
+c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c17 year, c18 bit, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
+c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'MYISAM' ;
+rename table t1 to t1_1, t9 to t9_1 ;
+drop table if exists t1, t9 ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+create table t9
+(
+c1 tinyint, c2 smallint, c3 mediumint, c4 int,
+c5 integer, c6 bigint, c7 float, c8 double,
+c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
+c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c17 year, c18 bit, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
+c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'MYISAM' ;
+rename table t1 to t1_2, t9 to t9_2 ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) ENGINE = MERGE UNION=(t1_1,t1_2)
+INSERT_METHOD=FIRST;
+create table t9
+(
+c1 tinyint, c2 smallint, c3 mediumint, c4 int,
+c5 integer, c6 bigint, c7 float, c8 double,
+c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
+c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c17 year, c18 bit, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
+c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) ENGINE = MERGE UNION=(t9_1,t9_2)
+INSERT_METHOD=FIRST;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+test_sequence
+------ simple select tests ------
+prepare stmt1 from ' select * from t9 order by c1 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t9 t9 c1 c1 1 4 1 N 49155 0 63
+def test t9 t9 c2 c2 2 6 1 Y 32768 0 63
+def test t9 t9 c3 c3 9 9 1 Y 32768 0 63
+def test t9 t9 c4 c4 3 11 1 Y 32768 0 63
+def test t9 t9 c5 c5 3 11 1 Y 32768 0 63
+def test t9 t9 c6 c6 8 20 1 Y 32768 0 63
+def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
+def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
+def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
+def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
+def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c13 c13 10 10 10 Y 128 0 63
+def test t9 t9 c14 c14 12 19 19 Y 128 0 63
+def test t9 t9 c15 c15 7 19 19 N 1249 0 63
+def test t9 t9 c16 c16 11 8 8 Y 128 0 63
+def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
+def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
+def test t9 t9 c20 c20 254 1 1 Y 0 0 8
+def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c22 c22 253 30 30 Y 0 0 8
+def test t9 t9 c23 c23 252 255 8 Y 144 0 63
+def test t9 t9 c24 c24 252 255 8 Y 16 0 8
+def test t9 t9 c25 c25 252 65535 4 Y 144 0 63
+def test t9 t9 c26 c26 252 65535 4 Y 16 0 8
+def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63
+def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8
+def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63
+def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8
+def test t9 t9 c31 c31 254 5 3 Y 256 0 8
+def test t9 t9 c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00=null ;
+select @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select @arg00 + 1 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? + 1 as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select 1 + @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select 1 + ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 order by a;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 order by a ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b order by a) from t1
+group by 'a' ;
+group_concat(@arg00,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00 order by a) from t1
+group by 'a' ;
+group_concat(b,@arg00 order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,? order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists t5 ;
+create table t5 (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+1 ii
+2 hh
+drop table t5 ;
+drop table if exists t5 ;
+create table t5(session_id char(9) not null) ;
+insert into t5 values ('abc') ;
+prepare stmt1 from ' select * from t5
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table t5 ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01) order by a;
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+set @arg00= 'one' ;
+set @arg01= 'two' ;
+set @arg02= 'five' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
+execute stmt1 using @arg00, @arg01, @arg02 ;
+b
+one
+two
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00=null ;
+insert into t9 set c1= 0, c5 = NULL ;
+select c5 from t9 where c5 > NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 > ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 < NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 < ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 = NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 = ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 <=> NULL ;
+c5
+NULL
+prepare stmt1 from ' select c5 from t9 where c5 <=> ? ';
+execute stmt1 using @arg00 ;
+c5
+NULL
+delete from t9 where c1= 0 ;
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 order by a ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? order by a ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1 ;
+execute stmt1 using @arg00;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=0 ;
+execute stmt1 using @arg00;
+ERROR 42S22: Unknown column '?' in 'order clause'
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1 order by a
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a order by a1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a order by a1 ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02
+order by second.a, first.a;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ?
+ order by second.a, first.a';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+drop table if exists t2 ;
+create table t2 as select * from t1 ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
+the join statement is:
+SELECT * FROM t2 right join t1 using(a) order by t2.a
+prepare stmt1 from @query9 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural right join t1 order by t2.a
+prepare stmt1 from @query8 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query7 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 using(a) order by t2.a
+prepare stmt1 from @query6 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural left join t1 order by t2.a
+prepare stmt1 from @query5 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query4 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 join t1 using(a) order by t2.a
+prepare stmt1 from @query3 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural join t1 order by t2.a
+prepare stmt1 from @query2 ;
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+the join statement is:
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
+prepare stmt1 from @query1 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+drop table t2 ;
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) order by a ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t1;
+prepare stmt1 from ' select a in (select a from t2) from t1 ' ;
+execute stmt1 ;
+a in (select a from t2)
+1
+1
+1
+1
+drop table if exists t5, t6, t7 ;
+create table t5 (a int , b int) ;
+create table t6 like t5 ;
+create table t7 like t5 ;
+insert into t5 values (0, 100), (1, 2), (1, 3), (2, 2), (2, 7),
+(2, -1), (3, 10) ;
+insert into t6 values (0, 0), (1, 1), (2, 1), (3, 1), (4, 1) ;
+insert into t7 values (3, 3), (2, 2), (1, 1) ;
+prepare stmt1 from ' select a, (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1) from t7 ' ;
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+drop table t5, t6, t7 ;
+drop table if exists t2 ;
+create table t2 as select * from t9;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t9.c2 - 0e-3) = t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t9.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t9.c2-?)=t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t9.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+drop table t2 ;
+select 1 < (select a from t1) ;
+ERROR 21000: Subquery returns more than 1 row
+prepare stmt1 from ' select 1 < (select a from t1) ' ;
+execute stmt1 ;
+ERROR 21000: Subquery returns more than 1 row
+select 1 as my_col ;
+my_col
+1
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+prepare stmt1 from ' SELECT 1, 2 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT 1, 2 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT * from t1 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT * from t1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' explain select * from t9 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 6 N 1 31 33
+def table 253 64 2 N 1 31 33
+def type 253 10 3 N 1 31 33
+def possible_keys 253 4096 0 Y 0 31 33
+def key 253 64 0 Y 0 31 33
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 33
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 0 N 1 31 33
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t9 ALL NULL NULL NULL NULL 2
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+select a,b from t1 order by a;
+a b
+0 two
+1 one
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 order by a;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+create table t2
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+insert into t2(a,b) select a, b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @NULL= null ;
+set @arg00= 'abc' ;
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg00 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg00 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 abc
+10002 abc
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @NULL ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @NULL ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 NULL
+10002 NULL
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 10 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 9 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 8 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 7 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 6 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 5 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 4 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 3 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg01 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 10001
+10002 10002
+10003 10003
+10004 10004
+10005 10005
+10006 10006
+10007 10007
+10008 10008
+10009 10009
+10010 10010
+delete from t1 where a > 10000 ;
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1 order by a;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+8 eight
+9 nine
+81 8-1
+82 8-2
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+drop table if exists t2 ;
+create table t2 (id int auto_increment primary key)
+ENGINE= 'MYISAM' ;
+prepare stmt1 from ' select last_insert_id() ' ;
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+1
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+2
+drop table t2 ;
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+execute stmt1;
+execute stmt1;
+execute stmt1;
+test_sequence
+------ multi table tests ------
+delete from t1 ;
+delete from t9 ;
+insert into t1(a,b) values (1, 'one'), (2, 'two'), (3, 'three') ;
+insert into t9 (c1,c21)
+values (1, 'one'), (2, 'two'), (3, 'three') ;
+prepare stmt_delete from " delete t1, t9
+ from t1, t9 where t1.a=t9.c1 and t1.b='updated' ";
+prepare stmt_update from " update t1, t9
+ set t1.b='updated', t9.c21='updated'
+ where t1.a=t9.c1 and t1.a=? ";
+prepare stmt_select1 from " select a, b from t1 order by a" ;
+prepare stmt_select2 from " select c1, c21 from t9 order by c1" ;
+set @arg00= 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+2 two
+3 three
+execute stmt_select2 ;
+c1 c21
+2 two
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+3 three
+execute stmt_select2 ;
+c1 c21
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+execute stmt_select2 ;
+c1 c21
+set @arg00= @arg00 + 1 ;
+drop table if exists t5 ;
+set @arg01= 8;
+set @arg02= 8.0;
+set @arg03= 80.00000000000e-1;
+set @arg04= 'abc' ;
+set @arg05= CAST('abc' as binary) ;
+set @arg06= '1991-08-05' ;
+set @arg07= CAST('1991-08-05' as date);
+set @arg08= '1991-08-05 01:01:01' ;
+set @arg09= CAST('1991-08-05 01:01:01' as datetime) ;
+set @arg10= unix_timestamp('1991-01-01 01:01:01');
+set @arg11= YEAR('1991-01-01 01:01:01');
+set @arg12= 8 ;
+set @arg12= NULL ;
+set @arg13= 8.0 ;
+set @arg13= NULL ;
+set @arg14= 'abc';
+set @arg14= NULL ;
+set @arg15= CAST('abc' as binary) ;
+set @arg15= NULL ;
+create table t5 as select
+8 as const01, @arg01 as param01,
+8.0 as const02, @arg02 as param02,
+80.00000000000e-1 as const03, @arg03 as param03,
+'abc' as const04, @arg04 as param04,
+CAST('abc' as binary) as const05, @arg05 as param05,
+'1991-08-05' as const06, @arg06 as param06,
+CAST('1991-08-05' as date) as const07, @arg07 as param07,
+'1991-08-05 01:01:01' as const08, @arg08 as param08,
+CAST('1991-08-05 01:01:01' as datetime) as const09, @arg09 as param09,
+unix_timestamp('1991-01-01 01:01:01') as const10, @arg10 as param10,
+YEAR('1991-01-01 01:01:01') as const11, @arg11 as param11,
+NULL as const12, @arg12 as param12,
+@arg13 as param13,
+@arg14 as param14,
+@arg15 as param15;
+show create table t5 ;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `const01` bigint(1) NOT NULL default '0',
+ `param01` bigint(20) default NULL,
+ `const02` double(3,1) NOT NULL default '0.0',
+ `param02` double default NULL,
+ `const03` double NOT NULL default '0',
+ `param03` double default NULL,
+ `const04` char(3) NOT NULL default '',
+ `param04` longtext,
+ `const05` binary(3) NOT NULL default '',
+ `param05` longblob,
+ `const06` varchar(10) NOT NULL default '',
+ `param06` longtext,
+ `const07` date default NULL,
+ `param07` longblob,
+ `const08` varchar(19) NOT NULL default '',
+ `param08` longtext,
+ `const09` datetime default NULL,
+ `param09` longblob,
+ `const10` int(10) NOT NULL default '0',
+ `param10` bigint(20) default NULL,
+ `const11` int(4) default NULL,
+ `param11` bigint(20) default NULL,
+ `const12` binary(0) default NULL,
+ `param12` bigint(20) default NULL,
+ `param13` double default NULL,
+ `param14` longtext,
+ `param15` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t5 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t5 t5 const01 const01 8 1 1 N 32769 0 63
+def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
+def test t5 t5 const02 const02 5 3 3 N 32769 1 63
+def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
+def test t5 t5 const03 const03 5 23 1 N 32769 31 63
+def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
+def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
+def test t5 t5 const06 const06 253 10 10 N 1 0 8
+def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
+def test t5 t5 const07 const07 10 10 10 Y 128 0 63
+def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
+def test t5 t5 const08 const08 253 19 19 N 1 0 8
+def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
+def test t5 t5 const09 const09 12 19 19 Y 128 0 63
+def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63
+def test t5 t5 const10 const10 3 10 9 N 32769 0 63
+def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
+def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
+def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
+def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
+def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
+def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
+const01 8
+param01 8
+const02 8.0
+param02 8
+const03 8
+param03 8
+const04 abc
+param04 abc
+const05 abc
+param05 abc
+const06 1991-08-05
+param06 1991-08-05
+const07 1991-08-05
+param07 1991-08-05
+const08 1991-08-05 01:01:01
+param08 1991-08-05 01:01:01
+const09 1991-08-05 01:01:01
+param09 1991-08-05 01:01:01
+const10 662680861
+param10 662680861
+const11 1991
+param11 1991
+const12 NULL
+param12 NULL
+param13 NULL
+param14 NULL
+param15 NULL
+drop table t5 ;
+test_sequence
+------ data type conversion tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t9 set c1= 0, c15= '1991-01-01 01:01:01' ;
+select * from t9 order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ select @parameter:= column ------
+prepare full_info from "select @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" ;
+select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 1 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 0 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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
+ @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+ @arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+ @arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+ @arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+ @arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+ @arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+ @arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+ @arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':= c1 from t9 where c1= 1' at line 1
+test_sequence
+------ select column, .. into @parm,.. ------
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 1 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 0 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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,
+ c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+ c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t9 where c1= 1' at line 1
+test_sequence
+-- insert into numeric columns --
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 ) ;
+set @arg00= 21 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22 )" ;
+execute stmt1 ;
+set @arg00= 23;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0,
+30.0, 30.0, 30.0 ) ;
+set @arg00= 31.0 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0,
+ 32.0, 32.0, 32.0 )" ;
+execute stmt1 ;
+set @arg00= 33.0;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( '40', '40', '40', '40', '40', '40', '40', '40',
+'40', '40', '40' ) ;
+set @arg00= '41' ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( '42', '42', '42', '42', '42', '42', '42', '42',
+ '42', '42', '42' )" ;
+execute stmt1 ;
+set @arg00= '43';
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary) ) ;
+set @arg00= CAST('51' as binary) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary) )" ;
+execute stmt1 ;
+set @arg00= CAST('53' as binary) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 2 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 60, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, NULL ) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 61, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 62, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL )" ;
+execute stmt1 ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 63, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 8.0 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 71, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 73, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 'abc' ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 81, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 83, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c1 >= 20
+order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c12
+20 20 20 20 20 20 20 20 20 20 20.0000
+21 21 21 21 21 21 21 21 21 21 21.0000
+22 22 22 22 22 22 22 22 22 22 22.0000
+23 23 23 23 23 23 23 23 23 23 23.0000
+30 30 30 30 30 30 30 30 30 30 30.0000
+31 31 31 31 31 31 31 31 31 31 31.0000
+32 32 32 32 32 32 32 32 32 32 32.0000
+33 33 33 33 33 33 33 33 33 33 33.0000
+40 40 40 40 40 40 40 40 40 40 40.0000
+41 41 41 41 41 41 41 41 41 41 41.0000
+42 42 42 42 42 42 42 42 42 42 42.0000
+43 43 43 43 43 43 43 43 43 43 43.0000
+50 50 50 50 50 50 50 50 50 50 50.0000
+51 51 51 51 51 51 51 51 51 51 51.0000
+52 52 52 52 52 52 52 52 52 52 52.0000
+53 53 53 53 53 53 53 53 53 53 53.0000
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where numeric column = .. --
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+and c8= 20 and c9= 20 and c10= 20 and c12= 20;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+ and c8= 20 and c9= 20 and c10= 20 and c12= 20 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+ and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20';
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20' ";
+execute stmt1 ;
+found
+true
+set @arg00= '20';
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+c12= CAST('20' as binary);
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+ c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+ c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+ c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+ c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+ c12= CAST('20' as binary) ";
+execute stmt1 ;
+found
+true
+set @arg00= CAST('20' as binary) ;
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- some numeric overflow experiments --
+prepare my_insert from "insert into t9
+ ( c21, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 'O', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+prepare my_select from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c21 = 'O' ";
+prepare my_delete from "delete from t9 where c21 = 'O' ";
+set @arg00= 9223372036854775807 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= '9223372036854775807' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= -9223372036854775808 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-9223372036854775808' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= 1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= '1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 1
+c2 1
+c3 1
+c4 1
+c5 1
+c6 1
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= -1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -1
+c2 -1
+c3 -1
+c4 -1
+c5 -1
+c6 -1
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+test_sequence
+-- insert into string columns --
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+select c1, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30
+from t9 where c1 >= 20
+order by c1 ;
+c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
+20 2 20 20 20 20 20 20 20 20 20 20
+21 2 21 21 21 21 21 21 21 21 21 21
+22 2 22 22 22 22 22 22 22 22 22 22
+23 2 23 23 23 23 23 23 23 23 23 23
+30 3 30 30 30 30 30 30 30 30 30 30
+31 3 31 31 31 31 31 31 31 31 31 31
+32 3 32 32 32 32 32 32 32 32 32 32
+33 3 33 33 33 33 33 33 33 33 33 33
+40 4 40 40 40 40 40 40 40 40 40 40
+41 4 41 41 41 41 41 41 41 41 41 41
+42 4 42 42 42 42 42 42 42 42 42 42
+43 4 43 43 43 43 43 43 43 43 43 43
+50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
+51 5 51 51 51 51 51 51 51 51 51 51
+52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
+53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
+55 5 55 55 55 55 55 55 55 55 55 55
+56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
+57 6 57 57 57.00 57.00 57.00 57.00 57.00 57.00 57.00 57.00
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where string column = .. --
+set @arg00= '20';
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+c27= '20' and c28= '20' and c29= '20' and c30= '20' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+ c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+ c27= '20' and c28= '20' and c29= '20' and c30= '20'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('20' as binary);
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+= CAST('20' as binary) and c21= CAST('20' as binary)
+and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+c30= CAST('20' as binary) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20))) = @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and
+c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+ = CAST('20' as binary) and c21= CAST('20' as binary)
+ and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+ c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+ c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+ c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+ c30= CAST('20' as binary)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20))) = ? and c21= ? and
+ c22= ? and c23= ? and c25= ? and c26= ? and c27= ? and c28= ? and
+ c29= ? and c30= ?";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+c27= 20 and c28= 20 and c29= 20 and c30= 20 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+ c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+ c27= 20 and c28= 20 and c29= 20 and c30= 20" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+ c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+ c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- insert into date/time columns --
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
+c1 c13 c14 c15 c16 c17
+20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+21 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+22 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+23 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+30 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+31 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+32 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+33 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+40 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+41 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+42 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+43 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+50 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+51 0010-00-00 0010-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+52 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+53 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+60 NULL NULL 1991-01-01 01:01:01 NULL NULL
+61 NULL NULL 1991-01-01 01:01:01 NULL NULL
+62 NULL NULL 1991-01-01 01:01:01 NULL NULL
+63 NULL NULL 1991-01-01 01:01:01 NULL NULL
+71 NULL NULL 1991-01-01 01:01:01 NULL NULL
+73 NULL NULL 1991-01-01 01:01:01 NULL NULL
+81 NULL NULL 1991-01-01 01:01:01 NULL NULL
+83 NULL NULL 1991-01-01 01:01:01 NULL NULL
+test_sequence
+-- select .. where date/time column = .. --
+set @arg00= '1991-01-01 01:01:01' ;
+select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+c17= '1991-01-01 01:01:01' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+ c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+ c17= '1991-01-01 01:01:01'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('1991-01-01 01:01:01' as datetime) ;
+select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+c14= CAST('1991-01-01 01:01:01' as datetime) and
+c15= CAST('1991-01-01 01:01:01' as datetime) and
+c16= CAST('1991-01-01 01:01:01' as datetime) and
+c17= CAST('1991-01-01 01:01:01' as datetime) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+ c14= CAST('1991-01-01 01:01:01' as datetime) and
+ c15= CAST('1991-01-01 01:01:01' as datetime) and
+ c16= CAST('1991-01-01 01:01:01' as datetime) and
+ c17= CAST('1991-01-01 01:01:01' as datetime)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 1991 ;
+select 'true' as found from t9
+where c1= 20 and c17= 1991 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= 1991" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= ?" ;
+execute stmt1 using @arg00 ;
+found
+true
+set @arg00= 1.991e+3 ;
+select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and abs(c17 - @arg00) < 0.01 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - ?) < 0.01" ;
+execute stmt1 using @arg00 ;
+found
+true
+drop table t1, t9 ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) ENGINE = MERGE UNION=(t1_1,t1_2)
+INSERT_METHOD=LAST;
+create table t9
+(
+c1 tinyint, c2 smallint, c3 mediumint, c4 int,
+c5 integer, c6 bigint, c7 float, c8 double,
+c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
+c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c17 year, c18 bit, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
+c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) ENGINE = MERGE UNION=(t9_1,t9_2)
+INSERT_METHOD=LAST;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+test_sequence
+------ simple select tests ------
+prepare stmt1 from ' select * from t9 order by c1 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t9 t9 c1 c1 1 4 1 N 49155 0 63
+def test t9 t9 c2 c2 2 6 1 Y 32768 0 63
+def test t9 t9 c3 c3 9 9 1 Y 32768 0 63
+def test t9 t9 c4 c4 3 11 1 Y 32768 0 63
+def test t9 t9 c5 c5 3 11 1 Y 32768 0 63
+def test t9 t9 c6 c6 8 20 1 Y 32768 0 63
+def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
+def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
+def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
+def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
+def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c13 c13 10 10 10 Y 128 0 63
+def test t9 t9 c14 c14 12 19 19 Y 128 0 63
+def test t9 t9 c15 c15 7 19 19 N 1249 0 63
+def test t9 t9 c16 c16 11 8 8 Y 128 0 63
+def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
+def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
+def test t9 t9 c20 c20 254 1 1 Y 0 0 8
+def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c22 c22 253 30 30 Y 0 0 8
+def test t9 t9 c23 c23 252 255 8 Y 144 0 63
+def test t9 t9 c24 c24 252 255 8 Y 16 0 8
+def test t9 t9 c25 c25 252 65535 4 Y 144 0 63
+def test t9 t9 c26 c26 252 65535 4 Y 16 0 8
+def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63
+def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8
+def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63
+def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8
+def test t9 t9 c31 c31 254 5 3 Y 256 0 8
+def test t9 t9 c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00=null ;
+select @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select @arg00 + 1 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? + 1 as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select 1 + @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select 1 + ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 order by a;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 order by a ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b order by a) from t1
+group by 'a' ;
+group_concat(@arg00,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00 order by a) from t1
+group by 'a' ;
+group_concat(b,@arg00 order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,? order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists t5 ;
+create table t5 (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+1 ii
+2 hh
+drop table t5 ;
+drop table if exists t5 ;
+create table t5(session_id char(9) not null) ;
+insert into t5 values ('abc') ;
+prepare stmt1 from ' select * from t5
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table t5 ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01) order by a;
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+set @arg00= 'one' ;
+set @arg01= 'two' ;
+set @arg02= 'five' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
+execute stmt1 using @arg00, @arg01, @arg02 ;
+b
+one
+two
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00=null ;
+insert into t9 set c1= 0, c5 = NULL ;
+select c5 from t9 where c5 > NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 > ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 < NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 < ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 = NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 = ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 <=> NULL ;
+c5
+NULL
+prepare stmt1 from ' select c5 from t9 where c5 <=> ? ';
+execute stmt1 using @arg00 ;
+c5
+NULL
+delete from t9 where c1= 0 ;
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 order by a ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? order by a ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1 ;
+execute stmt1 using @arg00;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=0 ;
+execute stmt1 using @arg00;
+ERROR 42S22: Unknown column '?' in 'order clause'
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1 order by a
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a order by a1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a order by a1 ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02
+order by second.a, first.a;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ?
+ order by second.a, first.a';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+drop table if exists t2 ;
+create table t2 as select * from t1 ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
+the join statement is:
+SELECT * FROM t2 right join t1 using(a) order by t2.a
+prepare stmt1 from @query9 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural right join t1 order by t2.a
+prepare stmt1 from @query8 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query7 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 using(a) order by t2.a
+prepare stmt1 from @query6 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural left join t1 order by t2.a
+prepare stmt1 from @query5 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query4 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 join t1 using(a) order by t2.a
+prepare stmt1 from @query3 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural join t1 order by t2.a
+prepare stmt1 from @query2 ;
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+the join statement is:
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
+prepare stmt1 from @query1 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+drop table t2 ;
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) order by a ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t1;
+prepare stmt1 from ' select a in (select a from t2) from t1 ' ;
+execute stmt1 ;
+a in (select a from t2)
+1
+1
+1
+1
+drop table if exists t5, t6, t7 ;
+create table t5 (a int , b int) ;
+create table t6 like t5 ;
+create table t7 like t5 ;
+insert into t5 values (0, 100), (1, 2), (1, 3), (2, 2), (2, 7),
+(2, -1), (3, 10) ;
+insert into t6 values (0, 0), (1, 1), (2, 1), (3, 1), (4, 1) ;
+insert into t7 values (3, 3), (2, 2), (1, 1) ;
+prepare stmt1 from ' select a, (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1) from t7 ' ;
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+drop table t5, t6, t7 ;
+drop table if exists t2 ;
+create table t2 as select * from t9;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t9.c2 - 0e-3) = t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t9.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t9.c2-?)=t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t9.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+drop table t2 ;
+select 1 < (select a from t1) ;
+ERROR 21000: Subquery returns more than 1 row
+prepare stmt1 from ' select 1 < (select a from t1) ' ;
+execute stmt1 ;
+ERROR 21000: Subquery returns more than 1 row
+select 1 as my_col ;
+my_col
+1
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+prepare stmt1 from ' SELECT 1, 2 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT 1, 2 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT * from t1 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT * from t1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' explain select * from t9 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 6 N 1 31 33
+def table 253 64 2 N 1 31 33
+def type 253 10 3 N 1 31 33
+def possible_keys 253 4096 0 Y 0 31 33
+def key 253 64 0 Y 0 31 33
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 33
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 0 N 1 31 33
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t9 ALL NULL NULL NULL NULL 2
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+select a,b from t1 order by a;
+a b
+0 two
+1 one
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 order by a;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+create table t2
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'MYISAM' ;
+insert into t2(a,b) select a, b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @NULL= null ;
+set @arg00= 'abc' ;
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg00 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg00 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 abc
+10002 abc
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @NULL ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @NULL ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 NULL
+10002 NULL
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 10 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 9 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 8 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 7 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 6 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 5 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 4 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 3 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg01 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 10001
+10002 10002
+10003 10003
+10004 10004
+10005 10005
+10006 10006
+10007 10007
+10008 10008
+10009 10009
+10010 10010
+delete from t1 where a > 10000 ;
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1 order by a;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+8 eight
+9 nine
+81 8-1
+82 8-2
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+drop table if exists t2 ;
+create table t2 (id int auto_increment primary key)
+ENGINE= 'MYISAM' ;
+prepare stmt1 from ' select last_insert_id() ' ;
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+1
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+2
+drop table t2 ;
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+execute stmt1;
+execute stmt1;
+execute stmt1;
+test_sequence
+------ multi table tests ------
+delete from t1 ;
+delete from t9 ;
+insert into t1(a,b) values (1, 'one'), (2, 'two'), (3, 'three') ;
+insert into t9 (c1,c21)
+values (1, 'one'), (2, 'two'), (3, 'three') ;
+prepare stmt_delete from " delete t1, t9
+ from t1, t9 where t1.a=t9.c1 and t1.b='updated' ";
+prepare stmt_update from " update t1, t9
+ set t1.b='updated', t9.c21='updated'
+ where t1.a=t9.c1 and t1.a=? ";
+prepare stmt_select1 from " select a, b from t1 order by a" ;
+prepare stmt_select2 from " select c1, c21 from t9 order by c1" ;
+set @arg00= 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+2 two
+3 three
+execute stmt_select2 ;
+c1 c21
+2 two
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+3 three
+execute stmt_select2 ;
+c1 c21
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+execute stmt_select2 ;
+c1 c21
+set @arg00= @arg00 + 1 ;
+drop table if exists t5 ;
+set @arg01= 8;
+set @arg02= 8.0;
+set @arg03= 80.00000000000e-1;
+set @arg04= 'abc' ;
+set @arg05= CAST('abc' as binary) ;
+set @arg06= '1991-08-05' ;
+set @arg07= CAST('1991-08-05' as date);
+set @arg08= '1991-08-05 01:01:01' ;
+set @arg09= CAST('1991-08-05 01:01:01' as datetime) ;
+set @arg10= unix_timestamp('1991-01-01 01:01:01');
+set @arg11= YEAR('1991-01-01 01:01:01');
+set @arg12= 8 ;
+set @arg12= NULL ;
+set @arg13= 8.0 ;
+set @arg13= NULL ;
+set @arg14= 'abc';
+set @arg14= NULL ;
+set @arg15= CAST('abc' as binary) ;
+set @arg15= NULL ;
+create table t5 as select
+8 as const01, @arg01 as param01,
+8.0 as const02, @arg02 as param02,
+80.00000000000e-1 as const03, @arg03 as param03,
+'abc' as const04, @arg04 as param04,
+CAST('abc' as binary) as const05, @arg05 as param05,
+'1991-08-05' as const06, @arg06 as param06,
+CAST('1991-08-05' as date) as const07, @arg07 as param07,
+'1991-08-05 01:01:01' as const08, @arg08 as param08,
+CAST('1991-08-05 01:01:01' as datetime) as const09, @arg09 as param09,
+unix_timestamp('1991-01-01 01:01:01') as const10, @arg10 as param10,
+YEAR('1991-01-01 01:01:01') as const11, @arg11 as param11,
+NULL as const12, @arg12 as param12,
+@arg13 as param13,
+@arg14 as param14,
+@arg15 as param15;
+show create table t5 ;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `const01` bigint(1) NOT NULL default '0',
+ `param01` bigint(20) default NULL,
+ `const02` double(3,1) NOT NULL default '0.0',
+ `param02` double default NULL,
+ `const03` double NOT NULL default '0',
+ `param03` double default NULL,
+ `const04` char(3) NOT NULL default '',
+ `param04` longtext,
+ `const05` binary(3) NOT NULL default '',
+ `param05` longblob,
+ `const06` varchar(10) NOT NULL default '',
+ `param06` longtext,
+ `const07` date default NULL,
+ `param07` longblob,
+ `const08` varchar(19) NOT NULL default '',
+ `param08` longtext,
+ `const09` datetime default NULL,
+ `param09` longblob,
+ `const10` int(10) NOT NULL default '0',
+ `param10` bigint(20) default NULL,
+ `const11` int(4) default NULL,
+ `param11` bigint(20) default NULL,
+ `const12` binary(0) default NULL,
+ `param12` bigint(20) default NULL,
+ `param13` double default NULL,
+ `param14` longtext,
+ `param15` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t5 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t5 t5 const01 const01 8 1 1 N 32769 0 63
+def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
+def test t5 t5 const02 const02 5 3 3 N 32769 1 63
+def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
+def test t5 t5 const03 const03 5 23 1 N 32769 31 63
+def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
+def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
+def test t5 t5 const06 const06 253 10 10 N 1 0 8
+def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
+def test t5 t5 const07 const07 10 10 10 Y 128 0 63
+def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
+def test t5 t5 const08 const08 253 19 19 N 1 0 8
+def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
+def test t5 t5 const09 const09 12 19 19 Y 128 0 63
+def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63
+def test t5 t5 const10 const10 3 10 9 N 32769 0 63
+def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
+def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
+def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
+def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
+def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
+def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
+const01 8
+param01 8
+const02 8.0
+param02 8
+const03 8
+param03 8
+const04 abc
+param04 abc
+const05 abc
+param05 abc
+const06 1991-08-05
+param06 1991-08-05
+const07 1991-08-05
+param07 1991-08-05
+const08 1991-08-05 01:01:01
+param08 1991-08-05 01:01:01
+const09 1991-08-05 01:01:01
+param09 1991-08-05 01:01:01
+const10 662680861
+param10 662680861
+const11 1991
+param11 1991
+const12 NULL
+param12 NULL
+param13 NULL
+param14 NULL
+param15 NULL
+drop table t5 ;
+test_sequence
+------ data type conversion tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t9 set c1= 0, c15= '1991-01-01 01:01:01' ;
+select * from t9 order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ select @parameter:= column ------
+prepare full_info from "select @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" ;
+select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 1 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 0 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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
+ @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+ @arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+ @arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+ @arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+ @arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+ @arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+ @arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+ @arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':= c1 from t9 where c1= 1' at line 1
+test_sequence
+------ select column, .. into @parm,.. ------
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 1 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 0 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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,
+ c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+ c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t9 where c1= 1' at line 1
+test_sequence
+-- insert into numeric columns --
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 ) ;
+set @arg00= 21 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22 )" ;
+execute stmt1 ;
+set @arg00= 23;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0,
+30.0, 30.0, 30.0 ) ;
+set @arg00= 31.0 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0,
+ 32.0, 32.0, 32.0 )" ;
+execute stmt1 ;
+set @arg00= 33.0;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( '40', '40', '40', '40', '40', '40', '40', '40',
+'40', '40', '40' ) ;
+set @arg00= '41' ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( '42', '42', '42', '42', '42', '42', '42', '42',
+ '42', '42', '42' )" ;
+execute stmt1 ;
+set @arg00= '43';
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary) ) ;
+set @arg00= CAST('51' as binary) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary) )" ;
+execute stmt1 ;
+set @arg00= CAST('53' as binary) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 2 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 60, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, NULL ) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 61, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 62, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL )" ;
+execute stmt1 ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 63, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 8.0 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 71, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 73, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 'abc' ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 81, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 83, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c1 >= 20
+order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c12
+20 20 20 20 20 20 20 20 20 20 20.0000
+21 21 21 21 21 21 21 21 21 21 21.0000
+22 22 22 22 22 22 22 22 22 22 22.0000
+23 23 23 23 23 23 23 23 23 23 23.0000
+30 30 30 30 30 30 30 30 30 30 30.0000
+31 31 31 31 31 31 31 31 31 31 31.0000
+32 32 32 32 32 32 32 32 32 32 32.0000
+33 33 33 33 33 33 33 33 33 33 33.0000
+40 40 40 40 40 40 40 40 40 40 40.0000
+41 41 41 41 41 41 41 41 41 41 41.0000
+42 42 42 42 42 42 42 42 42 42 42.0000
+43 43 43 43 43 43 43 43 43 43 43.0000
+50 50 50 50 50 50 50 50 50 50 50.0000
+51 51 51 51 51 51 51 51 51 51 51.0000
+52 52 52 52 52 52 52 52 52 52 52.0000
+53 53 53 53 53 53 53 53 53 53 53.0000
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where numeric column = .. --
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+and c8= 20 and c9= 20 and c10= 20 and c12= 20;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+ and c8= 20 and c9= 20 and c10= 20 and c12= 20 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+ and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20';
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20' ";
+execute stmt1 ;
+found
+true
+set @arg00= '20';
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+c12= CAST('20' as binary);
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+ c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+ c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+ c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+ c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+ c12= CAST('20' as binary) ";
+execute stmt1 ;
+found
+true
+set @arg00= CAST('20' as binary) ;
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- some numeric overflow experiments --
+prepare my_insert from "insert into t9
+ ( c21, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 'O', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+prepare my_select from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c21 = 'O' ";
+prepare my_delete from "delete from t9 where c21 = 'O' ";
+set @arg00= 9223372036854775807 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= '9223372036854775807' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= -9223372036854775808 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-9223372036854775808' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= 1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= '1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 1
+c2 1
+c3 1
+c4 1
+c5 1
+c6 1
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= -1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -1
+c2 -1
+c3 -1
+c4 -1
+c5 -1
+c6 -1
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+test_sequence
+-- insert into string columns --
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+select c1, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30
+from t9 where c1 >= 20
+order by c1 ;
+c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
+20 2 20 20 20 20 20 20 20 20 20 20
+21 2 21 21 21 21 21 21 21 21 21 21
+22 2 22 22 22 22 22 22 22 22 22 22
+23 2 23 23 23 23 23 23 23 23 23 23
+30 3 30 30 30 30 30 30 30 30 30 30
+31 3 31 31 31 31 31 31 31 31 31 31
+32 3 32 32 32 32 32 32 32 32 32 32
+33 3 33 33 33 33 33 33 33 33 33 33
+40 4 40 40 40 40 40 40 40 40 40 40
+41 4 41 41 41 41 41 41 41 41 41 41
+42 4 42 42 42 42 42 42 42 42 42 42
+43 4 43 43 43 43 43 43 43 43 43 43
+50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
+51 5 51 51 51 51 51 51 51 51 51 51
+52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
+53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
+55 5 55 55 55 55 55 55 55 55 55 55
+56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
+57 6 57 57 57.00 57.00 57.00 57.00 57.00 57.00 57.00 57.00
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where string column = .. --
+set @arg00= '20';
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+c27= '20' and c28= '20' and c29= '20' and c30= '20' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+ c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+ c27= '20' and c28= '20' and c29= '20' and c30= '20'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('20' as binary);
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+= CAST('20' as binary) and c21= CAST('20' as binary)
+and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+c30= CAST('20' as binary) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20))) = @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and
+c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+ = CAST('20' as binary) and c21= CAST('20' as binary)
+ and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+ c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+ c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+ c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+ c30= CAST('20' as binary)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20))) = ? and c21= ? and
+ c22= ? and c23= ? and c25= ? and c26= ? and c27= ? and c28= ? and
+ c29= ? and c30= ?";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+c27= 20 and c28= 20 and c29= 20 and c30= 20 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+ c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+ c27= 20 and c28= 20 and c29= 20 and c30= 20" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+ c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+ c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- insert into date/time columns --
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
+c1 c13 c14 c15 c16 c17
+20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+21 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+22 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+23 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+30 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+31 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+32 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+33 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+40 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+41 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+42 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+43 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+50 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+51 0010-00-00 0010-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+52 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+53 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+60 NULL NULL 1991-01-01 01:01:01 NULL NULL
+61 NULL NULL 1991-01-01 01:01:01 NULL NULL
+62 NULL NULL 1991-01-01 01:01:01 NULL NULL
+63 NULL NULL 1991-01-01 01:01:01 NULL NULL
+71 NULL NULL 1991-01-01 01:01:01 NULL NULL
+73 NULL NULL 1991-01-01 01:01:01 NULL NULL
+81 NULL NULL 1991-01-01 01:01:01 NULL NULL
+83 NULL NULL 1991-01-01 01:01:01 NULL NULL
+test_sequence
+-- select .. where date/time column = .. --
+set @arg00= '1991-01-01 01:01:01' ;
+select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+c17= '1991-01-01 01:01:01' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+ c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+ c17= '1991-01-01 01:01:01'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('1991-01-01 01:01:01' as datetime) ;
+select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+c14= CAST('1991-01-01 01:01:01' as datetime) and
+c15= CAST('1991-01-01 01:01:01' as datetime) and
+c16= CAST('1991-01-01 01:01:01' as datetime) and
+c17= CAST('1991-01-01 01:01:01' as datetime) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+ c14= CAST('1991-01-01 01:01:01' as datetime) and
+ c15= CAST('1991-01-01 01:01:01' as datetime) and
+ c16= CAST('1991-01-01 01:01:01' as datetime) and
+ c17= CAST('1991-01-01 01:01:01' as datetime)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 1991 ;
+select 'true' as found from t9
+where c1= 20 and c17= 1991 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= 1991" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= ?" ;
+execute stmt1 using @arg00 ;
+found
+true
+set @arg00= 1.991e+3 ;
+select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and abs(c17 - @arg00) < 0.01 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - ?) < 0.01" ;
+execute stmt1 using @arg00 ;
+found
+true
+drop table t1, t1_1, t1_2,
+t9_1, t9_2, t9;
diff --git a/mysql-test/r/ps_6bdb.result b/mysql-test/r/ps_6bdb.result
index 7ec7e303b42..3f9f3c61575 100644
--- a/mysql-test/r/ps_6bdb.result
+++ b/mysql-test/r/ps_6bdb.result
@@ -69,7 +69,7 @@ def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
-def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c21 c21 254 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
def test t9 t9 c23 c23 252 255 8 Y 144 0 63
def test t9 t9 c24 c24 252 255 8 Y 16 0 8
@@ -1563,7 +1563,9 @@ a b
1200 x1000_1updatedupdated
delete from t1 where a >= 1000 ;
prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
-ERROR HY000: This command is not supported in the prepared statement protocol yet
+execute stmt1;
+execute stmt1;
+execute stmt1;
test_sequence
------ multi table tests ------
delete from t1 ;
@@ -1686,8 +1688,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
delete from t2 ;
prepare stmt1 from ' insert into t2 (b,a)
@@ -1705,8 +1707,8 @@ affected rows: 3
info: Records: 3 Duplicates: 0 Warnings: 0
select a,b from t2 order by a ;
a b
-3 duplicate
-4 duplicate
+3 duplicate
+4 duplicate
103 three
drop table t2;
drop table if exists t5 ;
@@ -1754,7 +1756,7 @@ t5 CREATE TABLE `t5` (
`param02` double default NULL,
`const03` double NOT NULL default '0',
`param03` double default NULL,
- `const04` char(3) NOT NULL default '',
+ `const04` varchar(3) NOT NULL default '',
`param04` longtext,
`const05` binary(3) NOT NULL default '',
`param05` longblob,
@@ -1770,10 +1772,10 @@ t5 CREATE TABLE `t5` (
`param10` bigint(20) default NULL,
`const11` int(4) default NULL,
`param11` bigint(20) default NULL,
- `const12` char(0) default NULL,
+ `const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
`param13` double default NULL,
- `param14` longblob,
+ `param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t5 ;
@@ -1784,9 +1786,9 @@ def test t5 t5 const02 const02 5 3 3 N 32769 1 63
def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
def test t5 t5 const03 const03 5 23 1 N 32769 31 63
def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
-def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 const04 const04 253 3 3 N 1 0 8
def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
-def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 const05 const05 253 3 3 N 129 0 63
def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
def test t5 t5 const06 const06 253 10 10 N 1 0 8
def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
@@ -1800,10 +1802,10 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63
def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
-def test t5 t5 const12 const12 254 0 0 Y 0 0 8
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
-def test t5 t5 param14 param14 252 16777215 0 Y 144 0 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
param01 8
@@ -1890,38 +1892,38 @@ from t9 where c1= 1 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -1937,38 +1939,38 @@ from t9 where c1= 0 ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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
@@ -1987,38 +1989,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
@@ -2027,38 +2029,38 @@ execute stmt1 using @my_key ;
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
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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" ;
@@ -2075,38 +2077,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 1 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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,
@@ -2119,38 +2121,38 @@ into @arg01, @arg02, @arg03, @arg04, @arg05, @arg06, @arg07, @arg08,
from t9 where c1= 0 ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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,
@@ -2165,76 +2167,76 @@ set @my_key= 1 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 1 Y 128 31 63
-def @arg03 254 20 1 Y 128 31 63
-def @arg04 254 20 1 Y 128 31 63
-def @arg05 254 20 1 Y 128 31 63
-def @arg06 254 20 1 Y 128 31 63
-def @arg07 254 20 1 Y 128 31 63
-def @arg08 254 20 1 Y 128 31 63
-def @arg09 254 20 1 Y 128 31 63
-def @arg10 254 20 1 Y 128 31 63
-def @arg11 254 20 1 Y 128 31 63
-def @arg12 254 20 1 Y 128 31 63
-def @arg13 254 8192 10 Y 128 31 63
-def @arg14 254 8192 19 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 8 Y 128 31 63
-def @arg17 254 20 4 Y 128 31 63
-def @arg18 254 20 1 Y 128 31 63
-def @arg19 254 20 1 Y 128 31 63
-def @arg20 254 8192 1 Y 0 31 8
-def @arg21 254 8192 10 Y 0 31 8
-def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 128 31 63
-def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 128 31 63
-def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 128 31 63
-def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 128 31 63
-def @arg30 254 8192 8 Y 0 31 8
-def @arg31 254 8192 3 Y 0 31 8
-def @arg32 254 8192 6 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 1 Y 128 31 63
+def @arg03 253 20 1 Y 128 31 63
+def @arg04 253 20 1 Y 128 31 63
+def @arg05 253 20 1 Y 128 31 63
+def @arg06 253 20 1 Y 128 31 63
+def @arg07 253 20 1 Y 128 31 63
+def @arg08 253 20 1 Y 128 31 63
+def @arg09 253 20 1 Y 128 31 63
+def @arg10 253 20 1 Y 128 31 63
+def @arg11 253 20 1 Y 128 31 63
+def @arg12 253 20 1 Y 128 31 63
+def @arg13 253 8192 10 Y 128 31 63
+def @arg14 253 8192 19 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 8 Y 128 31 63
+def @arg17 253 20 4 Y 128 31 63
+def @arg18 253 20 1 Y 128 31 63
+def @arg19 253 20 1 Y 128 31 63
+def @arg20 253 8192 1 Y 0 31 8
+def @arg21 253 8192 10 Y 0 31 8
+def @arg22 253 8192 30 Y 0 31 8
+def @arg23 253 8192 8 Y 128 31 63
+def @arg24 253 8192 8 Y 0 31 8
+def @arg25 253 8192 4 Y 128 31 63
+def @arg26 253 8192 4 Y 0 31 8
+def @arg27 253 8192 10 Y 128 31 63
+def @arg28 253 8192 10 Y 0 31 8
+def @arg29 253 8192 8 Y 128 31 63
+def @arg30 253 8192 8 Y 0 31 8
+def @arg31 253 8192 3 Y 0 31 8
+def @arg32 253 8192 6 Y 128 31 63
@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 1 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 ;
execute stmt1 using @my_key ;
execute full_info ;
Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
-def @arg01 254 20 1 Y 128 31 63
-def @arg02 254 20 0 Y 128 31 63
-def @arg03 254 20 0 Y 128 31 63
-def @arg04 254 20 0 Y 128 31 63
-def @arg05 254 20 0 Y 128 31 63
-def @arg06 254 20 0 Y 128 31 63
-def @arg07 254 20 0 Y 128 31 63
-def @arg08 254 20 0 Y 128 31 63
-def @arg09 254 20 0 Y 128 31 63
-def @arg10 254 20 0 Y 128 31 63
-def @arg11 254 20 0 Y 128 31 63
-def @arg12 254 20 0 Y 128 31 63
-def @arg13 254 8192 0 Y 128 31 63
-def @arg14 254 8192 0 Y 128 31 63
-def @arg15 254 8192 19 Y 128 31 63
-def @arg16 254 8192 0 Y 128 31 63
-def @arg17 254 20 0 Y 128 31 63
-def @arg18 254 20 0 Y 128 31 63
-def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
-def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
-def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
-def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
-def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg01 253 20 1 Y 128 31 63
+def @arg02 253 20 0 Y 128 31 63
+def @arg03 253 20 0 Y 128 31 63
+def @arg04 253 20 0 Y 128 31 63
+def @arg05 253 20 0 Y 128 31 63
+def @arg06 253 20 0 Y 128 31 63
+def @arg07 253 20 0 Y 128 31 63
+def @arg08 253 20 0 Y 128 31 63
+def @arg09 253 20 0 Y 128 31 63
+def @arg10 253 20 0 Y 128 31 63
+def @arg11 253 20 0 Y 128 31 63
+def @arg12 253 20 0 Y 128 31 63
+def @arg13 253 8192 0 Y 128 31 63
+def @arg14 253 8192 0 Y 128 31 63
+def @arg15 253 8192 19 Y 128 31 63
+def @arg16 253 8192 0 Y 128 31 63
+def @arg17 253 20 0 Y 128 31 63
+def @arg18 253 20 0 Y 128 31 63
+def @arg19 253 20 0 Y 128 31 63
+def @arg20 253 8192 0 Y 0 31 8
+def @arg21 253 8192 0 Y 0 31 8
+def @arg22 253 8192 0 Y 0 31 8
+def @arg23 253 8192 0 Y 128 31 63
+def @arg24 253 8192 0 Y 0 31 8
+def @arg25 253 8192 0 Y 128 31 63
+def @arg26 253 8192 0 Y 0 31 8
+def @arg27 253 8192 0 Y 128 31 63
+def @arg28 253 8192 0 Y 0 31 8
+def @arg29 253 8192 0 Y 128 31 63
+def @arg30 253 8192 0 Y 0 31 8
+def @arg31 253 8192 0 Y 0 31 8
+def @arg32 253 8192 0 Y 0 31 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_6bdb.result.es b/mysql-test/r/ps_6bdb.result.es
new file mode 100644
index 00000000000..7b7f7e23bbf
--- /dev/null
+++ b/mysql-test/r/ps_6bdb.result.es
@@ -0,0 +1,3113 @@
+use test;
+drop table if exists t1, t9 ;
+create table t1
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'BDB' ;
+create table t9
+(
+c1 tinyint, c2 smallint, c3 mediumint, c4 int,
+c5 integer, c6 bigint, c7 float, c8 double,
+c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
+c13 date, c14 datetime, c15 timestamp(14), c16 time,
+c17 year, c18 bit, c19 bool, c20 char,
+c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
+c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
+c32 set('monday', 'tuesday', 'wednesday'),
+primary key(c1)
+) engine = 'BDB' ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+test_sequence
+------ simple select tests ------
+prepare stmt1 from ' select * from t9 order by c1 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t9 t9 c1 c1 1 4 1 N 49155 0 63
+def test t9 t9 c2 c2 2 6 1 Y 32768 0 63
+def test t9 t9 c3 c3 9 9 1 Y 32768 0 63
+def test t9 t9 c4 c4 3 11 1 Y 32768 0 63
+def test t9 t9 c5 c5 3 11 1 Y 32768 0 63
+def test t9 t9 c6 c6 8 20 1 Y 32768 0 63
+def test t9 t9 c7 c7 4 12 1 Y 32768 31 63
+def test t9 t9 c8 c8 5 22 1 Y 32768 31 63
+def test t9 t9 c9 c9 5 22 1 Y 32768 31 63
+def test t9 t9 c10 c10 5 22 1 Y 32768 31 63
+def test t9 t9 c11 c11 0 9 6 Y 32768 4 63
+def test t9 t9 c12 c12 0 10 6 Y 32768 4 63
+def test t9 t9 c13 c13 10 10 10 Y 128 0 63
+def test t9 t9 c14 c14 12 19 19 Y 128 0 63
+def test t9 t9 c15 c15 7 19 19 N 1249 0 63
+def test t9 t9 c16 c16 11 8 8 Y 128 0 63
+def test t9 t9 c17 c17 13 4 4 Y 32864 0 63
+def test t9 t9 c18 c18 1 1 1 Y 32768 0 63
+def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
+def test t9 t9 c20 c20 254 1 1 Y 0 0 8
+def test t9 t9 c21 c21 253 10 10 Y 0 0 8
+def test t9 t9 c22 c22 253 30 30 Y 0 0 8
+def test t9 t9 c23 c23 252 255 8 Y 144 0 63
+def test t9 t9 c24 c24 252 255 8 Y 16 0 8
+def test t9 t9 c25 c25 252 65535 4 Y 144 0 63
+def test t9 t9 c26 c26 252 65535 4 Y 16 0 8
+def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63
+def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8
+def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63
+def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8
+def test t9 t9 c31 c31 254 5 3 Y 256 0 8
+def test t9 t9 c32 c32 254 24 7 Y 2048 0 8
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+set @arg00='SELECT' ;
+prepare stmt1 from ' ? a from t1 where a=1 ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a from t1 where a=1' at line 1
+set @arg00=1 ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+1 one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+1 one
+set @arg00='lion' ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+lion one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+lion one
+set @arg00=NULL ;
+select @arg00, b from t1 where a=1 ;
+@arg00 b
+NULL one
+prepare stmt1 from ' select ?, b from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+? b
+NULL one
+set @arg00=1 ;
+select b, a - @arg00 from t1 where a=1 ;
+b a - @arg00
+one 0
+prepare stmt1 from ' select b, a - ? from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+b a - ?
+one 0
+set @arg00=null ;
+select @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select @arg00 + 1 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select ? + 1 as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+select 1 + @arg00 as my_col ;
+my_col
+NULL
+prepare stmt1 from ' select 1 + ? as my_col';
+execute stmt1 using @arg00 ;
+my_col
+NULL
+set @arg00='MySQL' ;
+select substr(@arg00,1,2) from t1 where a=1 ;
+substr(@arg00,1,2)
+My
+prepare stmt1 from ' select substr(?,1,2) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr(?,1,2)
+My
+set @arg00=3 ;
+select substr('MySQL',@arg00,5) from t1 where a=1 ;
+substr('MySQL',@arg00,5)
+SQL
+prepare stmt1 from ' select substr(''MySQL'',?,5) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',?,5)
+SQL
+select substr('MySQL',1,@arg00) from t1 where a=1 ;
+substr('MySQL',1,@arg00)
+MyS
+prepare stmt1 from ' select substr(''MySQL'',1,?) from t1 where a=1 ' ;
+execute stmt1 using @arg00 ;
+substr('MySQL',1,?)
+MyS
+set @arg00='MySQL' ;
+select a , concat(@arg00,b) from t1 order by a;
+a concat(@arg00,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+prepare stmt1 from ' select a , concat(?,b) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(?,b)
+1 MySQLone
+2 MySQLtwo
+3 MySQLthree
+4 MySQLfour
+select a , concat(b,@arg00) from t1 order by a ;
+a concat(b,@arg00)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+prepare stmt1 from ' select a , concat(b,?) from t1 order by a ' ;
+execute stmt1 using @arg00;
+a concat(b,?)
+1 oneMySQL
+2 twoMySQL
+3 threeMySQL
+4 fourMySQL
+set @arg00='MySQL' ;
+select group_concat(@arg00,b order by a) from t1
+group by 'a' ;
+group_concat(@arg00,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+prepare stmt1 from ' select group_concat(?,b order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(?,b order by a)
+MySQLone,MySQLtwo,MySQLthree,MySQLfour
+select group_concat(b,@arg00 order by a) from t1
+group by 'a' ;
+group_concat(b,@arg00 order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+prepare stmt1 from ' select group_concat(b,? order by a) from t1
+group by ''a'' ' ;
+execute stmt1 using @arg00;
+group_concat(b,? order by a)
+oneMySQL,twoMySQL,threeMySQL,fourMySQL
+set @arg00='first' ;
+set @arg01='second' ;
+set @arg02=NULL;
+select @arg00, @arg01 from t1 where a=1 ;
+@arg00 @arg01
+first second
+prepare stmt1 from ' select ?, ? from t1 where a=1 ' ;
+execute stmt1 using @arg00, @arg01 ;
+? ?
+first second
+execute stmt1 using @arg02, @arg01 ;
+? ?
+NULL second
+execute stmt1 using @arg00, @arg02 ;
+? ?
+first NULL
+execute stmt1 using @arg02, @arg02 ;
+? ?
+NULL NULL
+drop table if exists t5 ;
+create table t5 (id1 int(11) not null default '0',
+value2 varchar(100), value1 varchar(100)) ;
+insert into t5 values (1,'hh','hh'),(2,'hh','hh'),
+(1,'ii','ii'),(2,'ii','ii') ;
+prepare stmt1 from ' select id1,value1 from t5 where id1=? or value1=? order by id1,value1 ' ;
+set @arg00=1 ;
+set @arg01='hh' ;
+execute stmt1 using @arg00, @arg01 ;
+id1 value1
+1 hh
+1 ii
+2 hh
+drop table t5 ;
+drop table if exists t5 ;
+create table t5(session_id char(9) not null) ;
+insert into t5 values ('abc') ;
+prepare stmt1 from ' select * from t5
+where ?=''1111'' and session_id = ''abc'' ' ;
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+set @arg00='1111' ;
+execute stmt1 using @arg00 ;
+session_id
+abc
+set @arg00='abc' ;
+execute stmt1 using @arg00 ;
+session_id
+drop table t5 ;
+set @arg00='FROM' ;
+select a @arg00 t1 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 t1 where a=1' at line 1
+prepare stmt1 from ' select a ? t1 where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? t1 where a=1' at line 1
+set @arg00='t1' ;
+select a from @arg00 where a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 where a=1' at line 1
+prepare stmt1 from ' select a from ? where a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? where a=1' at line 1
+set @arg00='WHERE' ;
+select a from t1 @arg00 a=1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 a=1' at line 1
+prepare stmt1 from ' select a from t1 ? a=1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? a=1' at line 1
+set @arg00=1 ;
+select a FROM t1 where a=@arg00 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+1
+set @arg00=1000 ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=NULL ;
+select a FROM t1 where a=@arg00 ;
+a
+prepare stmt1 from ' select a FROM t1 where a=? ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=4 ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+2
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+2
+set @arg00=NULL ;
+select a FROM t1 where a=sqrt(@arg00) ;
+a
+prepare stmt1 from ' select a FROM t1 where a=sqrt(?) ' ;
+execute stmt1 using @arg00 ;
+a
+set @arg00=2 ;
+set @arg01=3 ;
+select a FROM t1 where a in (@arg00,@arg01) order by a;
+a
+2
+3
+prepare stmt1 from ' select a FROM t1 where a in (?,?) order by a ';
+execute stmt1 using @arg00, @arg01;
+a
+2
+3
+set @arg00= 'one' ;
+set @arg01= 'two' ;
+set @arg02= 'five' ;
+prepare stmt1 from ' select b FROM t1 where b in (?,?,?) order by b ' ;
+execute stmt1 using @arg00, @arg01, @arg02 ;
+b
+one
+two
+prepare stmt1 from ' select b FROM t1 where b like ? ';
+set @arg00='two' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='tw%' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00='%wo' ;
+execute stmt1 using @arg00 ;
+b
+two
+set @arg00=null ;
+insert into t9 set c1= 0, c5 = NULL ;
+select c5 from t9 where c5 > NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 > ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 < NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 < ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 = NULL ;
+c5
+prepare stmt1 from ' select c5 from t9 where c5 = ? ';
+execute stmt1 using @arg00 ;
+c5
+select c5 from t9 where c5 <=> NULL ;
+c5
+NULL
+prepare stmt1 from ' select c5 from t9 where c5 <=> ? ';
+execute stmt1 using @arg00 ;
+c5
+NULL
+delete from t9 where c1= 0 ;
+set @arg00='>' ;
+select a FROM t1 where a @arg00 1 ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '@arg00 1' at line 1
+prepare stmt1 from ' select a FROM t1 where a ? 1 ' ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? 1' at line 1
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL group by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00='two' ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> @arg00 order by a ;
+a b
+1 one
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL having b <> ? order by a ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+3 three
+4 four
+set @arg00=1 ;
+select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' select a,b FROM t1 where a is not NULL
+AND b is not NULL order by a - ? ' ;
+execute stmt1 using @arg00 ;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=2 ;
+select a,b from t1 order by 2 ;
+a b
+4 four
+1 one
+3 three
+2 two
+prepare stmt1 from ' select a,b from t1
+order by ? ';
+execute stmt1 using @arg00;
+a b
+4 four
+1 one
+3 three
+2 two
+set @arg00=1 ;
+execute stmt1 using @arg00;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=0 ;
+execute stmt1 using @arg00;
+ERROR 42S22: Unknown column '?' in 'order clause'
+set @arg00=1;
+prepare stmt1 from ' select a,b from t1 order by a
+limit 1 ';
+execute stmt1 ;
+a b
+1 one
+prepare stmt1 from ' select a,b from t1
+limit ? ';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 2
+set @arg00='b' ;
+set @arg01=0 ;
+set @arg02=2 ;
+set @arg03=2 ;
+select sum(a), @arg00 from t1 where a > @arg01
+and b is not null group by substr(b,@arg02)
+having sum(a) <> @arg03 ;
+sum(a) @arg00
+3 b
+1 b
+4 b
+prepare stmt1 from ' select sum(a), ? from t1 where a > ?
+and b is not null group by substr(b,?)
+having sum(a) <> ? ';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+sum(a) ?
+3 b
+1 b
+4 b
+test_sequence
+------ join tests ------
+select first.a as a1, second.a as a2
+from t1 first, t1 second
+where first.a = second.a order by a1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+prepare stmt1 from ' select first.a as a1, second.a as a2
+ from t1 first, t1 second
+ where first.a = second.a order by a1 ';
+execute stmt1 ;
+a1 a2
+1 1
+2 2
+3 3
+4 4
+set @arg00='ABC';
+set @arg01='two';
+set @arg02='one';
+select first.a, @arg00, second.a FROM t1 first, t1 second
+where @arg01 = first.b or first.a = second.a or second.b = @arg02
+order by second.a, first.a;
+a @arg00 a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+prepare stmt1 from ' select first.a, ?, second.a FROM t1 first, t1 second
+ where ? = first.b or first.a = second.a or second.b = ?
+ order by second.a, first.a';
+execute stmt1 using @arg00, @arg01, @arg02;
+a ? a
+1 ABC 1
+2 ABC 1
+3 ABC 1
+4 ABC 1
+2 ABC 2
+2 ABC 3
+3 ABC 3
+2 ABC 4
+4 ABC 4
+drop table if exists t2 ;
+create table t2 as select * from t1 ;
+set @query1= 'SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a ' ;
+set @query2= 'SELECT * FROM t2 natural join t1 order by t2.a ' ;
+set @query3= 'SELECT * FROM t2 join t1 using(a) order by t2.a ' ;
+set @query4= 'SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query5= 'SELECT * FROM t2 natural left join t1 order by t2.a ' ;
+set @query6= 'SELECT * FROM t2 left join t1 using(a) order by t2.a ' ;
+set @query7= 'SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a ' ;
+set @query8= 'SELECT * FROM t2 natural right join t1 order by t2.a ' ;
+set @query9= 'SELECT * FROM t2 right join t1 using(a) order by t2.a ' ;
+the join statement is:
+SELECT * FROM t2 right join t1 using(a) order by t2.a
+prepare stmt1 from @query9 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural right join t1 order by t2.a
+prepare stmt1 from @query8 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 right join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query7 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 using(a) order by t2.a
+prepare stmt1 from @query6 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural left join t1 order by t2.a
+prepare stmt1 from @query5 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 left join t1 on(t1.a=t2.a) order by t2.a
+prepare stmt1 from @query4 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 join t1 using(a) order by t2.a
+prepare stmt1 from @query3 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+the join statement is:
+SELECT * FROM t2 natural join t1 order by t2.a
+prepare stmt1 from @query2 ;
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+the join statement is:
+SELECT * FROM t2 join t1 on (t1.a=t2.a) order by t2.a
+prepare stmt1 from @query1 ;
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+execute stmt1 ;
+a b a b
+1 one 1 one
+2 two 2 two
+3 three 3 three
+4 four 4 four
+drop table t2 ;
+test_sequence
+------ subquery tests ------
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') ';
+execute stmt1 ;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = 'two' ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ''two'') and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = @arg00 ) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = ? ) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=3 ;
+set @arg01='three' ;
+select a,b FROM t1 where (a,b) in (select 3, 'three');
+a b
+3 three
+select a FROM t1 where (a,b) in (select @arg00,@arg01);
+a
+3
+prepare stmt1 from ' select a FROM t1 where (a,b) in (select ?, ?) ';
+execute stmt1 using @arg00, @arg01;
+a
+3
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where b = @arg03 ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where b = ? ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b ) order by a ';
+execute stmt1 ;
+a b
+1 one
+2 two
+3 three
+4 four
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+prepare stmt1 from ' SELECT a as ccc from t1 where a+1=
+ (SELECT 1+ccc from t1 where ccc+1=a+1 and a=1) ';
+execute stmt1 ;
+ccc
+1
+deallocate prepare stmt1 ;
+set @arg00='two' ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where b = outer_table.b ) and b=@arg00 ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where b = outer_table.b) and b=? ';
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where a = @arg00 and b = outer_table.b) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where a = ? and b = outer_table.b) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=2 ;
+select a, b FROM t1 outer_table where
+a = (select a from t1 where outer_table.a = @arg00 and a=2) and b='two' ;
+a b
+2 two
+prepare stmt1 from ' select a, b FROM t1 outer_table where
+ a = (select a from t1 where outer_table.a = ? and a=2) and b=''two'' ' ;
+execute stmt1 using @arg00;
+a b
+2 two
+set @arg00=1 ;
+set @arg01='two' ;
+set @arg02=2 ;
+set @arg03='two' ;
+select a, @arg00, b FROM t1 outer_table where
+b=@arg01 and a = (select @arg02 from t1 where outer_table.b = @arg03
+and outer_table.a=a ) ;
+a @arg00 b
+2 1 two
+prepare stmt1 from ' select a, ?, b FROM t1 outer_table where
+ b=? and a = (select ? from t1 where outer_table.b = ?
+ and outer_table.a=a ) ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+a ? b
+2 1 two
+set @arg00=1 ;
+set @arg01=0 ;
+select a, @arg00
+from ( select a - @arg00 as a from t1 where a=@arg00 ) as t2
+where a=@arg01;
+a @arg00
+0 1
+prepare stmt1 from ' select a, ?
+ from ( select a - ? as a from t1 where a=? ) as t2
+ where a=? ';
+execute stmt1 using @arg00, @arg00, @arg00, @arg01 ;
+a ?
+0 1
+drop table if exists t2 ;
+create table t2 as select * from t1;
+prepare stmt1 from ' select a in (select a from t2) from t1 ' ;
+execute stmt1 ;
+a in (select a from t2)
+1
+1
+1
+1
+drop table if exists t5, t6, t7 ;
+create table t5 (a int , b int) ;
+create table t6 like t5 ;
+create table t7 like t5 ;
+insert into t5 values (0, 100), (1, 2), (1, 3), (2, 2), (2, 7),
+(2, -1), (3, 10) ;
+insert into t6 values (0, 0), (1, 1), (2, 1), (3, 1), (4, 1) ;
+insert into t7 values (3, 3), (2, 2), (1, 1) ;
+prepare stmt1 from ' select a, (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1) from t7 ' ;
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+execute stmt1 ;
+a (select count(distinct t5.b) as sum from t5, t6
+ where t5.a=t6.a and t6.b > 0 and t5.a <= t7.b
+ group by t5.a order by sum limit 1)
+3 1
+2 2
+1 2
+drop table t5, t6, t7 ;
+drop table if exists t2 ;
+create table t2 as select * from t9;
+set @stmt= ' SELECT
+ (SELECT SUM(c1 + c12 + 0.0) FROM t2
+ where (t9.c2 - 0e-3) = t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select 1.0e+0 from t2
+ where t2.c3 * 9.0000000000 = t9.c4) as exists_s,
+ c5 * 4 in (select c6 + 0.3e+1 from t2) as in_s,
+ (c7 - 4, c8 - 4) in (select c9 + 4.0, c10 + 40e-1 from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x = c25 ' ;
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 ;
+execute stmt1 ;
+set @stmt= ' SELECT
+ (SELECT SUM(c1+c12+?) FROM t2 where (t9.c2-?)=t2.c2
+ GROUP BY t9.c15 LIMIT 1) as scalar_s,
+ exists (select ? from t2
+ where t2.c3*?=t9.c4) as exists_s,
+ c5*? in (select c6+? from t2) as in_s,
+ (c7-?, c8-?) in (select c9+?, c10+? from t2) as in_row_s
+FROM t9,
+(select c25 x, c32 y from t2) tt WHERE x =c25 ' ;
+set @arg00= 0.0 ;
+set @arg01= 0e-3 ;
+set @arg02= 1.0e+0 ;
+set @arg03= 9.0000000000 ;
+set @arg04= 4 ;
+set @arg05= 0.3e+1 ;
+set @arg06= 4 ;
+set @arg07= 4 ;
+set @arg08= 4.0 ;
+set @arg09= 40e-1 ;
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+set @stmt= concat('explain ',@stmt);
+prepare stmt1 from @stmt ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04, @arg05, @arg06,
+@arg07, @arg08, @arg09 ;
+drop table t2 ;
+select 1 < (select a from t1) ;
+ERROR 21000: Subquery returns more than 1 row
+prepare stmt1 from ' select 1 < (select a from t1) ' ;
+execute stmt1 ;
+ERROR 21000: Subquery returns more than 1 row
+select 1 as my_col ;
+my_col
+1
+test_sequence
+------ union tests ------
+prepare stmt1 from ' select a FROM t1 where a=1
+ union distinct
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+execute stmt1 ;
+a
+1
+prepare stmt1 from ' select a FROM t1 where a=1
+ union all
+ select a FROM t1 where a=1 ';
+execute stmt1 ;
+a
+1
+1
+prepare stmt1 from ' SELECT 1, 2 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT 1, 2 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT * from t1 union SELECT 1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+prepare stmt1 from ' SELECT 1 union SELECT * from t1 ' ;
+ERROR 21000: The used SELECT statements have a different number of columns
+set @arg00=1 ;
+select @arg00 FROM t1 where a=1
+union distinct
+select 1 FROM t1 where a=1;
+@arg00
+1
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select 1 FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+?
+1
+set @arg00=1 ;
+select 1 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+1
+1
+prepare stmt1 from ' select 1 FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ' ;
+execute stmt1 using @arg00;
+1
+1
+set @arg00='a' ;
+select @arg00 FROM t1 where a=1
+union distinct
+select @arg00 FROM t1 where a=1;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=1
+ union distinct
+ select ? FROM t1 where a=1 ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+prepare stmt1 from ' select ?
+ union distinct
+ select ? ';
+execute stmt1 using @arg00, @arg00;
+?
+a
+set @arg00='a' ;
+set @arg01=1 ;
+set @arg02='a' ;
+set @arg03=2 ;
+select @arg00 FROM t1 where a=@arg01
+union distinct
+select @arg02 FROM t1 where a=@arg03;
+@arg00
+a
+prepare stmt1 from ' select ? FROM t1 where a=?
+ union distinct
+ select ? FROM t1 where a=? ' ;
+execute stmt1 using @arg00, @arg01, @arg02, @arg03;
+?
+a
+set @arg00=1 ;
+prepare stmt1 from ' select sum(a) + 200, ? from t1
+union distinct
+select sum(a) + 200, 1 from t1
+group by b ' ;
+execute stmt1 using @arg00;
+sum(a) + 200 ?
+210 1
+204 1
+201 1
+203 1
+202 1
+set @Oporto='Oporto' ;
+set @Lisboa='Lisboa' ;
+set @0=0 ;
+set @1=1 ;
+set @2=2 ;
+set @3=3 ;
+set @4=4 ;
+select @Oporto,@Lisboa,@0,@1,@2,@3,@4 ;
+@Oporto @Lisboa @0 @1 @2 @3 @4
+Oporto Lisboa 0 1 2 3 4
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+group by b ;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ group by b ' ;
+execute stmt1 using @Oporto, @Lisboa;
+the_sum the_town
+204 Oporto
+201 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+201 Lisboa
+203 Lisboa
+202 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b ;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b ' ;
+execute stmt1 using @Oporto, @1, @Lisboa, @2;
+the_sum the_town
+204 Oporto
+203 Oporto
+202 Oporto
+204 Lisboa
+203 Lisboa
+select sum(a) + 200 as the_sum, @Oporto as the_town from t1
+where a > @1
+group by b
+having avg(a) > @2
+union distinct
+select sum(a) + 200, @Lisboa from t1
+where a > @2
+group by b
+having avg(a) > @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+prepare stmt1 from ' select sum(a) + 200 as the_sum, ? as the_town from t1
+ where a > ?
+ group by b
+ having avg(a) > ?
+ union distinct
+ select sum(a) + 200, ? from t1
+ where a > ?
+ group by b
+ having avg(a) > ? ';
+execute stmt1 using @Oporto, @1, @2, @Lisboa, @2, @3;
+the_sum the_town
+204 Oporto
+203 Oporto
+204 Lisboa
+test_sequence
+------ explain select tests ------
+prepare stmt1 from ' explain select * from t9 ' ;
+execute stmt1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def id 8 3 1 N 32801 0 8
+def select_type 253 19 6 N 1 31 33
+def table 253 64 2 N 1 31 33
+def type 253 10 3 N 1 31 33
+def possible_keys 253 4096 0 Y 0 31 33
+def key 253 64 0 Y 0 31 33
+def key_len 8 3 0 Y 32800 0 8
+def ref 253 1024 0 Y 0 31 33
+def rows 8 10 1 N 32801 0 8
+def Extra 253 255 0 N 1 31 33
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t9 ALL NULL NULL NULL NULL 3
+test_sequence
+------ delete tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'delete from t1 where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+execute stmt1;
+insert into t1 values(0,NULL);
+set @arg00=NULL;
+prepare stmt1 from 'delete from t1 where b=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL ;
+a b
+0 NULL
+set @arg00='one';
+execute stmt1 using @arg00;
+select a,b from t1 where b=@arg00;
+a b
+prepare stmt1 from 'truncate table t1' ;
+ERROR HY000: This command is not supported in the prepared statement protocol yet
+test_sequence
+------ update tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+execute stmt1;
+select a,b from t1 where a=2;
+a b
+2 a=two
+set @arg00=NULL;
+prepare stmt1 from 'update t1 set b=? where a=2' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 NULL
+set @arg00='two';
+execute stmt1 using @arg00;
+select a,b from t1 where a=2;
+a b
+2 two
+set @arg00=2;
+prepare stmt1 from 'update t1 set b=NULL where a=?' ;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 NULL
+update t1 set b='two' where a=@arg00;
+set @arg00=2000;
+execute stmt1 using @arg00;
+select a,b from t1 where a=@arg00;
+a b
+set @arg00=2;
+set @arg01=22;
+prepare stmt1 from 'update t1 set a=? where a=?' ;
+execute stmt1 using @arg00, @arg00;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 where a=@arg01;
+a b
+22 two
+execute stmt1 using @arg00, @arg01;
+select a,b from t1 where a=@arg00;
+a b
+2 two
+set @arg00=NULL;
+set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1263 Data truncated; NULL supplied to NOT NULL column 'a' at row 1
+select a,b from t1 order by a;
+a b
+0 two
+1 one
+3 three
+4 four
+set @arg00=0;
+execute stmt1 using @arg01, @arg00;
+select a,b from t1 order by a;
+a b
+1 one
+2 two
+3 three
+4 four
+set @arg00=23;
+set @arg01='two';
+set @arg02=2;
+set @arg03='two';
+set @arg04=2;
+drop table if exists t2;
+create table t2 as select a,b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+create table t2
+(
+a int, b varchar(30),
+primary key(a)
+) engine = 'BDB' ;
+insert into t2(a,b) select a, b from t1 ;
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 where a = @arg00 ;
+a b
+23 two
+prepare stmt1 from 'update t1 set a=? where b=?
+ and a not in (select ? from t2
+ where b = ? or a = ?)';
+execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
+a b
+1 one
+2 two
+3 three
+4 four
+drop table t2 ;
+set @arg00=1;
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit 1';
+execute stmt1 ;
+select a,b from t1 where b = 'bla' ;
+a b
+2 bla
+prepare stmt1 from 'update t1 set b=''bla''
+where a=2
+limit ?';
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '?' at line 3
+test_sequence
+------ insert tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+prepare stmt1 from 'insert into t1 values(5, ''five'' )';
+execute stmt1;
+select a,b from t1 where a = 5;
+a b
+5 five
+set @arg00='six' ;
+prepare stmt1 from 'insert into t1 values(6, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b = @arg00;
+a b
+6 six
+execute stmt1 using @arg00;
+ERROR 23000: Duplicate entry '6' for key 1
+set @arg00=NULL ;
+prepare stmt1 from 'insert into t1 values(0, ? )';
+execute stmt1 using @arg00;
+select a,b from t1 where b is NULL;
+a b
+0 NULL
+set @arg00=8 ;
+set @arg01='eight' ;
+prepare stmt1 from 'insert into t1 values(?, ? )';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where b = @arg01;
+a b
+8 eight
+set @NULL= null ;
+set @arg00= 'abc' ;
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @NULL ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+execute stmt1 using @NULL, @arg00 ;
+ERROR 23000: Column 'a' cannot be null
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg00 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg00 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 abc
+10002 abc
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @NULL ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @NULL ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 NULL
+10002 NULL
+delete from t1 where a > 10000 ;
+set @arg01= 10000 + 10 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 9 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 8 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 7 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 6 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 5 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 4 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 3 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 2 ;
+execute stmt1 using @arg01, @arg01 ;
+set @arg01= 10000 + 1 ;
+execute stmt1 using @arg01, @arg01 ;
+select * from t1 where a > 10000 order by a ;
+a b
+10001 10001
+10002 10002
+10003 10003
+10004 10004
+10005 10005
+10006 10006
+10007 10007
+10008 10008
+10009 10009
+10010 10010
+delete from t1 where a > 10000 ;
+set @arg00=81 ;
+set @arg01='8-1' ;
+set @arg02=82 ;
+set @arg03='8-2' ;
+prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
+select a,b from t1 where a in (@arg00,@arg02) ;
+a b
+81 8-1
+82 8-2
+set @arg00=9 ;
+set @arg01='nine' ;
+prepare stmt1 from 'insert into t1 set a=?, b=? ';
+execute stmt1 using @arg00, @arg01 ;
+select a,b from t1 where a = @arg00 ;
+a b
+9 nine
+set @arg00=6 ;
+set @arg01=1 ;
+prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
+ on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
+select * from t1 order by a;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+5 five
+7 sixmodified
+8 eight
+9 nine
+81 8-1
+82 8-2
+set @arg00=81 ;
+set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
+drop table if exists t2 ;
+create table t2 (id int auto_increment primary key)
+ENGINE= 'BDB' ;
+prepare stmt1 from ' select last_insert_id() ' ;
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+1
+insert into t2 values (NULL) ;
+execute stmt1 ;
+last_insert_id()
+2
+drop table t2 ;
+set @1000=1000 ;
+set @x1000_2="x1000_2" ;
+set @x1000_3="x1000_3" ;
+set @x1000="x1000" ;
+set @1100=1100 ;
+set @x1100="x1100" ;
+set @100=100 ;
+set @updated="updated" ;
+insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+prepare stmt1 from ' insert into t1 values(?,?),(?,?)
+ on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 x1000_3
+1100 x1000_1updated
+delete from t1 where a >= 1000 ;
+insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1200 x1000_1updatedupdated
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
+execute stmt1;
+execute stmt1;
+execute stmt1;
+test_sequence
+------ multi table tests ------
+delete from t1 ;
+delete from t9 ;
+insert into t1(a,b) values (1, 'one'), (2, 'two'), (3, 'three') ;
+insert into t9 (c1,c21)
+values (1, 'one'), (2, 'two'), (3, 'three') ;
+prepare stmt_delete from " delete t1, t9
+ from t1, t9 where t1.a=t9.c1 and t1.b='updated' ";
+prepare stmt_update from " update t1, t9
+ set t1.b='updated', t9.c21='updated'
+ where t1.a=t9.c1 and t1.a=? ";
+prepare stmt_select1 from " select a, b from t1 order by a" ;
+prepare stmt_select2 from " select c1, c21 from t9 order by c1" ;
+set @arg00= 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+2 two
+3 three
+execute stmt_select2 ;
+c1 c21
+2 two
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+3 three
+execute stmt_select2 ;
+c1 c21
+3 three
+set @arg00= @arg00 + 1 ;
+execute stmt_update using @arg00 ;
+execute stmt_delete ;
+execute stmt_select1 ;
+a b
+execute stmt_select2 ;
+c1 c21
+set @arg00= @arg00 + 1 ;
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t1 values(0,NULL) ;
+set @duplicate='duplicate ' ;
+set @1000=1000 ;
+set @5=5 ;
+select a,b from t1 where a < 5 order by a ;
+a b
+0 NULL
+1 one
+2 two
+3 three
+4 four
+insert into t1 select a + @1000, concat(@duplicate,b) from t1
+where a < @5 ;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+prepare stmt1 from ' insert into t1 select a + ?, concat(?,b) from t1
+where a < ? ' ;
+execute stmt1 using @1000, @duplicate, @5;
+affected rows: 5
+info: Records: 5 Duplicates: 0 Warnings: 0
+select a,b from t1 where a >= 1000 order by a ;
+a b
+1000 NULL
+1001 duplicate one
+1002 duplicate two
+1003 duplicate three
+1004 duplicate four
+delete from t1 where a >= 1000 ;
+set @float=1.00;
+set @five='five' ;
+drop table if exists t2;
+create table t2 like t1 ;
+insert into t2 (b,a)
+select @duplicate, sum(first.a) from t1 first, t1 second
+where first.a <> @5 and second.b = first.b
+and second.b <> @five
+group by second.b
+having sum(second.a) > @2
+union
+select b, a + @100 from t1
+where (a,b) in ( select sqrt(a+@1)+CAST(@float AS signed),b
+from t1);
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 0
+select a,b from t2 order by a ;
+a b
+3 duplicate
+4 duplicate
+103 three
+delete from t2 ;
+prepare stmt1 from ' insert into t2 (b,a)
+select ?, sum(first.a)
+ from t1 first, t1 second
+ where first.a <> ? and second.b = first.b and second.b <> ?
+ group by second.b
+ having sum(second.a) > ?
+union
+select b, a + ? from t1
+ where (a,b) in ( select sqrt(a+?)+CAST(? AS signed),b
+ from t1 ) ' ;
+execute stmt1 using @duplicate, @5, @five, @2, @100, @1, @float ;
+affected rows: 3
+info: Records: 3 Duplicates: 0 Warnings: 0
+select a,b from t2 order by a ;
+a b
+3 duplicate
+4 duplicate
+103 three
+drop table t2;
+drop table if exists t5 ;
+set @arg01= 8;
+set @arg02= 8.0;
+set @arg03= 80.00000000000e-1;
+set @arg04= 'abc' ;
+set @arg05= CAST('abc' as binary) ;
+set @arg06= '1991-08-05' ;
+set @arg07= CAST('1991-08-05' as date);
+set @arg08= '1991-08-05 01:01:01' ;
+set @arg09= CAST('1991-08-05 01:01:01' as datetime) ;
+set @arg10= unix_timestamp('1991-01-01 01:01:01');
+set @arg11= YEAR('1991-01-01 01:01:01');
+set @arg12= 8 ;
+set @arg12= NULL ;
+set @arg13= 8.0 ;
+set @arg13= NULL ;
+set @arg14= 'abc';
+set @arg14= NULL ;
+set @arg15= CAST('abc' as binary) ;
+set @arg15= NULL ;
+create table t5 as select
+8 as const01, @arg01 as param01,
+8.0 as const02, @arg02 as param02,
+80.00000000000e-1 as const03, @arg03 as param03,
+'abc' as const04, @arg04 as param04,
+CAST('abc' as binary) as const05, @arg05 as param05,
+'1991-08-05' as const06, @arg06 as param06,
+CAST('1991-08-05' as date) as const07, @arg07 as param07,
+'1991-08-05 01:01:01' as const08, @arg08 as param08,
+CAST('1991-08-05 01:01:01' as datetime) as const09, @arg09 as param09,
+unix_timestamp('1991-01-01 01:01:01') as const10, @arg10 as param10,
+YEAR('1991-01-01 01:01:01') as const11, @arg11 as param11,
+NULL as const12, @arg12 as param12,
+@arg13 as param13,
+@arg14 as param14,
+@arg15 as param15;
+show create table t5 ;
+Table Create Table
+t5 CREATE TABLE `t5` (
+ `const01` bigint(1) NOT NULL default '0',
+ `param01` bigint(20) default NULL,
+ `const02` double(3,1) NOT NULL default '0.0',
+ `param02` double default NULL,
+ `const03` double NOT NULL default '0',
+ `param03` double default NULL,
+ `const04` char(3) NOT NULL default '',
+ `param04` longtext,
+ `const05` binary(3) NOT NULL default '',
+ `param05` longblob,
+ `const06` varchar(10) NOT NULL default '',
+ `param06` longtext,
+ `const07` date default NULL,
+ `param07` longblob,
+ `const08` varchar(19) NOT NULL default '',
+ `param08` longtext,
+ `const09` datetime default NULL,
+ `param09` longblob,
+ `const10` int(10) NOT NULL default '0',
+ `param10` bigint(20) default NULL,
+ `const11` int(4) default NULL,
+ `param11` bigint(20) default NULL,
+ `const12` binary(0) default NULL,
+ `param12` bigint(20) default NULL,
+ `param13` double default NULL,
+ `param14` longtext,
+ `param15` longblob
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select * from t5 ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t5 t5 const01 const01 8 1 1 N 32769 0 63
+def test t5 t5 param01 param01 8 20 1 Y 32768 0 63
+def test t5 t5 const02 const02 5 3 3 N 32769 1 63
+def test t5 t5 param02 param02 5 20 1 Y 32768 31 63
+def test t5 t5 const03 const03 5 23 1 N 32769 31 63
+def test t5 t5 param03 param03 5 20 1 Y 32768 31 63
+def test t5 t5 const04 const04 254 3 3 N 1 0 8
+def test t5 t5 param04 param04 252 16777215 3 Y 16 0 8
+def test t5 t5 const05 const05 254 3 3 N 129 0 63
+def test t5 t5 param05 param05 252 16777215 3 Y 144 0 63
+def test t5 t5 const06 const06 253 10 10 N 1 0 8
+def test t5 t5 param06 param06 252 16777215 10 Y 16 0 8
+def test t5 t5 const07 const07 10 10 10 Y 128 0 63
+def test t5 t5 param07 param07 252 16777215 10 Y 144 0 63
+def test t5 t5 const08 const08 253 19 19 N 1 0 8
+def test t5 t5 param08 param08 252 16777215 19 Y 16 0 8
+def test t5 t5 const09 const09 12 19 19 Y 128 0 63
+def test t5 t5 param09 param09 252 16777215 19 Y 144 0 63
+def test t5 t5 const10 const10 3 10 9 N 32769 0 63
+def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
+def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
+def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
+def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
+def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
+def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
+const01 8
+param01 8
+const02 8.0
+param02 8
+const03 8
+param03 8
+const04 abc
+param04 abc
+const05 abc
+param05 abc
+const06 1991-08-05
+param06 1991-08-05
+const07 1991-08-05
+param07 1991-08-05
+const08 1991-08-05 01:01:01
+param08 1991-08-05 01:01:01
+const09 1991-08-05 01:01:01
+param09 1991-08-05 01:01:01
+const10 662680861
+param10 662680861
+const11 1991
+param11 1991
+const12 NULL
+param12 NULL
+param13 NULL
+param14 NULL
+param15 NULL
+drop table t5 ;
+test_sequence
+------ data type conversion tests ------
+delete from t1 ;
+insert into t1 values (1,'one');
+insert into t1 values (2,'two');
+insert into t1 values (3,'three');
+insert into t1 values (4,'four');
+commit ;
+delete from t9 ;
+insert into t9
+set c1= 1, c2= 1, c3= 1, c4= 1, c5= 1, c6= 1, c7= 1, c8= 1, c9= 1,
+c10= 1, c11= 1, c12 = 1,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=true, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='one', c32= 'monday';
+insert into t9
+set c1= 9, c2= 9, c3= 9, c4= 9, c5= 9, c6= 9, c7= 9, c8= 9, c9= 9,
+c10= 9, c11= 9, c12 = 9,
+c13= '2004-02-29', c14= '2004-02-29 11:11:11', c15= '2004-02-29 11:11:11',
+c16= '11:11:11', c17= '2004',
+c18= 1, c19=false, c20= 'a', c21= '123456789a',
+c22= '123456789a123456789b123456789c', c23= 'tinyblob', c24= 'tinytext',
+c25= 'blob', c26= 'text', c27= 'mediumblob', c28= 'mediumtext',
+c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
+commit ;
+insert into t9 set c1= 0, c15= '1991-01-01 01:01:01' ;
+select * from t9 order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
+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
+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
+9 9 9 9 9 9 9 9 9 9 9.0000 9.0000 2004-02-29 2004-02-29 11:11:11 2004-02-29 11:11:11 11:11:11 2004 1 0 a 123456789a 123456789a123456789b123456789c tinyblob tinytext blob text mediumblob mediumtext longblob longtext two tuesday
+test_sequence
+------ select @parameter:= column ------
+prepare full_info from "select @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" ;
+select @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 1 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+@arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+@arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+@arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+@arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+@arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+@arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+@arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= 0 ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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
+ @arg01:= c1, @arg02:= c2, @arg03:= c3, @arg04:= c4,
+ @arg05:= c5, @arg06:= c6, @arg07:= c7, @arg08:= c8,
+ @arg09:= c9, @arg10:= c10, @arg11:= c11, @arg12:= c12,
+ @arg13:= c13, @arg14:= c14, @arg15:= c15, @arg16:= c16,
+ @arg17:= c17, @arg18:= c18, @arg19:= c19, @arg20:= c20,
+ @arg21:= c21, @arg22:= c22, @arg23:= c23, @arg24:= c24,
+ @arg25:= c25, @arg26:= c26, @arg27:= c27, @arg28:= c28,
+ @arg29:= c29, @arg30:= c30, @arg31:= c31, @arg32:= c32
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+@arg01:= c1 @arg02:= c2 @arg03:= c3 @arg04:= c4 @arg05:= c5 @arg06:= c6 @arg07:= c7 @arg08:= c8 @arg09:= c9 @arg10:= c10 @arg11:= c11 @arg12:= c12 @arg13:= c13 @arg14:= c14 @arg15:= c15 @arg16:= c16 @arg17:= c17 @arg18:= c18 @arg19:= c19 @arg20:= c20 @arg21:= c21 @arg22:= c22 @arg23:= c23 @arg24:= c24 @arg25:= c25 @arg26:= c26 @arg27:= c27 @arg28:= c28 @arg29:= c29 @arg30:= c30 @arg31:= c31 @arg32:= c32
+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
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near ':= c1 from t9 where c1= 1' at line 1
+test_sequence
+------ select column, .. into @parm,.. ------
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c11, c12,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 1 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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,
+c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= 0 ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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,
+ c13, c14, c15, c16, c17, c18, c19, c20, c21, c22, c23, c24,
+ c25, c26, c27, c28, c29, c30, c31, c32
+into @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
+from t9 where c1= ?" ;
+set @my_key= 1 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 1 Y 128 31 63
+def @arg03 254 20 1 Y 128 31 63
+def @arg04 254 20 1 Y 128 31 63
+def @arg05 254 20 1 Y 128 31 63
+def @arg06 254 20 1 Y 128 31 63
+def @arg07 254 20 1 Y 128 31 63
+def @arg08 254 20 1 Y 128 31 63
+def @arg09 254 20 1 Y 128 31 63
+def @arg10 254 20 1 Y 128 31 63
+def @arg11 254 20 1 Y 128 31 63
+def @arg12 254 20 1 Y 128 31 63
+def @arg13 254 8192 10 Y 128 31 63
+def @arg14 254 8192 19 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 8 Y 128 31 63
+def @arg17 254 20 4 Y 128 31 63
+def @arg18 254 20 1 Y 128 31 63
+def @arg19 254 20 1 Y 128 31 63
+def @arg20 254 8192 1 Y 0 31 8
+def @arg21 254 8192 10 Y 0 31 8
+def @arg22 254 8192 30 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
+def @arg24 254 8192 8 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
+def @arg26 254 8192 4 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
+def @arg28 254 8192 10 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
+def @arg30 254 8192 8 Y 0 31 8
+def @arg31 254 8192 3 Y 0 31 8
+def @arg32 254 8192 6 Y 128 31 63
+@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 1 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 ;
+execute stmt1 using @my_key ;
+execute full_info ;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def @arg01 254 20 1 Y 128 31 63
+def @arg02 254 20 0 Y 128 31 63
+def @arg03 254 20 0 Y 128 31 63
+def @arg04 254 20 0 Y 128 31 63
+def @arg05 254 20 0 Y 128 31 63
+def @arg06 254 20 0 Y 128 31 63
+def @arg07 254 20 0 Y 128 31 63
+def @arg08 254 20 0 Y 128 31 63
+def @arg09 254 20 0 Y 128 31 63
+def @arg10 254 20 0 Y 128 31 63
+def @arg11 254 20 0 Y 128 31 63
+def @arg12 254 20 0 Y 128 31 63
+def @arg13 254 8192 0 Y 128 31 63
+def @arg14 254 8192 0 Y 128 31 63
+def @arg15 254 8192 19 Y 128 31 63
+def @arg16 254 8192 0 Y 128 31 63
+def @arg17 254 20 0 Y 128 31 63
+def @arg18 254 20 0 Y 128 31 63
+def @arg19 254 20 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
+def @arg23 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
+def @arg25 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
+def @arg27 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
+def @arg29 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '? from t9 where c1= 1' at line 1
+test_sequence
+-- insert into numeric columns --
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 20, 20, 20, 20, 20, 20, 20, 20, 20, 20, 20 ) ;
+set @arg00= 21 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 22, 22, 22, 22, 22, 22, 22, 22, 22, 22, 22 )" ;
+execute stmt1 ;
+set @arg00= 23;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0, 30.0,
+30.0, 30.0, 30.0 ) ;
+set @arg00= 31.0 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0, 32.0,
+ 32.0, 32.0, 32.0 )" ;
+execute stmt1 ;
+set @arg00= 33.0;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( '40', '40', '40', '40', '40', '40', '40', '40',
+'40', '40', '40' ) ;
+set @arg00= '41' ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( '42', '42', '42', '42', '42', '42', '42', '42',
+ '42', '42', '42' )" ;
+execute stmt1 ;
+set @arg00= '43';
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary),
+CAST('50' as binary), CAST('50' as binary), CAST('50' as binary) ) ;
+set @arg00= CAST('51' as binary) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary),
+ CAST('52' as binary), CAST('52' as binary), CAST('52' as binary) )" ;
+execute stmt1 ;
+set @arg00= CAST('53' as binary) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 2 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 60, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+NULL, NULL, NULL ) ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 61, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt1 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 62, NULL, NULL, NULL, NULL, NULL, NULL, NULL,
+ NULL, NULL, NULL )" ;
+execute stmt1 ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 63, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 8.0 ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 71, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 73, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+set @arg00= 'abc' ;
+set @arg00= NULL ;
+insert into t9
+( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+( 81, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ) ;
+prepare stmt2 from "insert into t9
+ ( c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 83, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+execute stmt2 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c1 >= 20
+order by c1 ;
+c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c12
+20 20 20 20 20 20 20 20 20 20 20.0000
+21 21 21 21 21 21 21 21 21 21 21.0000
+22 22 22 22 22 22 22 22 22 22 22.0000
+23 23 23 23 23 23 23 23 23 23 23.0000
+30 30 30 30 30 30 30 30 30 30 30.0000
+31 31 31 31 31 31 31 31 31 31 31.0000
+32 32 32 32 32 32 32 32 32 32 32.0000
+33 33 33 33 33 33 33 33 33 33 33.0000
+40 40 40 40 40 40 40 40 40 40 40.0000
+41 41 41 41 41 41 41 41 41 41 41.0000
+42 42 42 42 42 42 42 42 42 42 42.0000
+43 43 43 43 43 43 43 43 43 43 43.0000
+50 50 50 50 50 50 50 50 50 50 50.0000
+51 51 51 51 51 51 51 51 51 51 51.0000
+52 52 52 52 52 52 52 52 52 52 52.0000
+53 53 53 53 53 53 53 53 53 53 53.0000
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where numeric column = .. --
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+and c8= 20 and c9= 20 and c10= 20 and c12= 20;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c2= 20 and c3= 20 and c4= 20 and c5= 20 and c6= 20 and c7= 20
+ and c8= 20 and c9= 20 and c10= 20 and c12= 20 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0;
+found
+true
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20.0 and c2= 20.0 and c3= 20.0 and c4= 20.0 and c5= 20.0 and c6= 20.0
+ and c7= 20.0 and c8= 20.0 and c9= 20.0 and c10= 20.0 and c12= 20.0 ";
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20';
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= '20' and c2= '20' and c3= '20' and c4= '20' and c5= '20' and c6= '20'
+ and c7= '20' and c8= '20' and c9= '20' and c10= '20' and c12= '20' ";
+execute stmt1 ;
+found
+true
+set @arg00= '20';
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+c12= CAST('20' as binary);
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= CAST('20' as binary) and c2= CAST('20' as binary) and
+ c3= CAST('20' as binary) and c4= CAST('20' as binary) and
+ c5= CAST('20' as binary) and c6= CAST('20' as binary) and
+ c7= CAST('20' as binary) and c8= CAST('20' as binary) and
+ c9= CAST('20' as binary) and c10= CAST('20' as binary) and
+ c12= CAST('20' as binary) ";
+execute stmt1 ;
+found
+true
+set @arg00= CAST('20' as binary) ;
+select 'true' as found from t9
+where c1= @arg00 and c2= @arg00 and c3= @arg00 and c4= @arg00 and c5= @arg00
+and c6= @arg00 and c7= @arg00 and c8= @arg00 and c9= @arg00 and c10= @arg00
+and c12= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= ? and c2= ? and c3= ? and c4= ? and c5= ?
+ and c6= ? and c7= ? and c8= ? and c9= ? and c10= ?
+ and c12= ? ";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- some numeric overflow experiments --
+prepare my_insert from "insert into t9
+ ( c21, c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12 )
+values
+ ( 'O', ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ? )" ;
+prepare my_select from "select c1, c2, c3, c4, c5, c6, c7, c8, c9, c10, c12
+from t9 where c21 = 'O' ";
+prepare my_delete from "delete from t9 where c21 = 'O' ";
+set @arg00= 9223372036854775807 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= '9223372036854775807' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 9.22337e+18
+c8 9.22337203685478e+18
+c9 9.22337203685478e+18
+c10 9.22337203685478e+18
+c12 99999.9999
+execute my_delete ;
+set @arg00= -9223372036854775808 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-9223372036854775808' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -9.22337e+18
+c8 -9.22337203685478e+18
+c9 -9.22337203685478e+18
+c10 -9.22337203685478e+18
+c12 -9999.9999
+execute my_delete ;
+set @arg00= 1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 127
+c2 32767
+c3 8388607
+c4 2147483647
+c5 2147483647
+c6 9223372036854775807
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= '1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 1
+c2 1
+c3 1
+c4 1
+c5 1
+c6 1
+c7 3.40282e+38
+c8 1.11111111111111e+50
+c9 1.11111111111111e+50
+c10 1.11111111111111e+50
+c12 99999.9999
+execute my_delete ;
+set @arg00= -1.11111111111111111111e+50 ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c1' at row 1
+Warning 1264 Data truncated; out of range for column 'c2' at row 1
+Warning 1264 Data truncated; out of range for column 'c3' at row 1
+Warning 1264 Data truncated; out of range for column 'c4' at row 1
+Warning 1264 Data truncated; out of range for column 'c5' at row 1
+Warning 1264 Data truncated; out of range for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -128
+c2 -32768
+c3 -8388608
+c4 -2147483648
+c5 -2147483648
+c6 -9223372036854775808
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+set @arg00= '-1.11111111111111111111e+50' ;
+execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+Warnings:
+Warning 1265 Data truncated for column 'c1' at row 1
+Warning 1265 Data truncated for column 'c2' at row 1
+Warning 1265 Data truncated for column 'c3' at row 1
+Warning 1265 Data truncated for column 'c4' at row 1
+Warning 1265 Data truncated for column 'c5' at row 1
+Warning 1265 Data truncated for column 'c6' at row 1
+Warning 1264 Data truncated; out of range for column 'c7' at row 1
+Warning 1264 Data truncated; out of range for column 'c12' at row 1
+execute my_select ;
+c1 -1
+c2 -1
+c3 -1
+c4 -1
+c5 -1
+c6 -1
+c7 -3.40282e+38
+c8 -1.11111111111111e+50
+c9 -1.11111111111111e+50
+c10 -1.11111111111111e+50
+c12 -9999.9999
+execute my_delete ;
+test_sequence
+-- insert into string columns --
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
+select c1, c20, c21, c22, c23, c24, c25, c26, c27, c28, c29, c30
+from t9 where c1 >= 20
+order by c1 ;
+c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
+20 2 20 20 20 20 20 20 20 20 20 20
+21 2 21 21 21 21 21 21 21 21 21 21
+22 2 22 22 22 22 22 22 22 22 22 22
+23 2 23 23 23 23 23 23 23 23 23 23
+30 3 30 30 30 30 30 30 30 30 30 30
+31 3 31 31 31 31 31 31 31 31 31 31
+32 3 32 32 32 32 32 32 32 32 32 32
+33 3 33 33 33 33 33 33 33 33 33 33
+40 4 40 40 40 40 40 40 40 40 40 40
+41 4 41 41 41 41 41 41 41 41 41 41
+42 4 42 42 42 42 42 42 42 42 42 42
+43 4 43 43 43 43 43 43 43 43 43 43
+50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
+51 5 51 51 51 51 51 51 51 51 51 51
+52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
+53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
+55 5 55 55 55 55 55 55 55 55 55 55
+56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
+57 6 57 57 57.00 57.00 57.00 57.00 57.00 57.00 57.00 57.00
+60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+63 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+71 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+73 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+81 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+83 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
+test_sequence
+-- select .. where string column = .. --
+set @arg00= '20';
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+c27= '20' and c28= '20' and c29= '20' and c30= '20' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr('20',1+length(c20)))= '20' and c21= '20' and
+ c22= '20' and c23= '20' and c24= '20' and c25= '20' and c26= '20' and
+ c27= '20' and c28= '20' and c29= '20' and c30= '20'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('20' as binary);
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+= CAST('20' as binary) and c21= CAST('20' as binary)
+and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+c30= CAST('20' as binary) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20))) = @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and
+c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(CAST('20' as binary),1+length(c20)))
+ = CAST('20' as binary) and c21= CAST('20' as binary)
+ and c22= CAST('20' as binary) and c23= CAST('20' as binary) and
+ c24= CAST('20' as binary) and c25= CAST('20' as binary) and
+ c26= CAST('20' as binary) and c27= CAST('20' as binary) and
+ c28= CAST('20' as binary) and c29= CAST('20' as binary) and
+ c30= CAST('20' as binary)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20))) = ? and c21= ? and
+ c22= ? and c23= ? and c25= ? and c26= ? and c27= ? and c28= ? and
+ c29= ? and c30= ?";
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+c27= 20 and c28= 20 and c29= 20 and c30= 20 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20,1+length(c20)))= 20 and c21= 20 and
+ c22= 20 and c23= 20 and c24= 20 and c25= 20 and c26= 20 and
+ c27= 20 and c28= 20 and c29= 20 and c30= 20" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 20.0;
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and concat(c20,substr(@arg00,1+length(c20)))= @arg00 and
+c21= @arg00 and c22= @arg00 and c23= @arg00 and c25= @arg00 and
+c26= @arg00 and c27= @arg00 and c28= @arg00 and c29= @arg00 and c30= @arg00;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(20.0,1+length(c20)))= 20.0 and c21= 20.0 and
+ c22= 20.0 and c23= 20.0 and c24= 20.0 and c25= 20.0 and c26= 20.0 and
+ c27= 20.0 and c28= 20.0 and c29= 20.0 and c30= 20.0" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and concat(c20,substr(?,1+length(c20)))= ? and
+ c21= ? and c22= ? and c23= ? and c25= ? and
+ c26= ? and c27= ? and c28= ? and c29= ? and c30= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
+@arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+delete from t9 ;
+test_sequence
+-- insert into date/time columns --
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1265 Data truncated for column 'c14' at row 1
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warnings:
+Warning 1265 Data truncated for column 'c15' at row 1
+Warning 1264 Data truncated; out of range for column 'c16' at row 1
+Warning 1264 Data truncated; out of range for column 'c17' at row 1
+select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
+c1 c13 c14 c15 c16 c17
+20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+21 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+22 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+23 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+30 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+31 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+32 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+33 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
+40 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+41 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+42 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+43 0000-00-00 0000-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+50 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+51 0010-00-00 0010-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+52 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+53 2001-00-00 2001-00-00 00:00:00 0000-00-00 00:00:00 838:59:59 0000
+60 NULL NULL 1991-01-01 01:01:01 NULL NULL
+61 NULL NULL 1991-01-01 01:01:01 NULL NULL
+62 NULL NULL 1991-01-01 01:01:01 NULL NULL
+63 NULL NULL 1991-01-01 01:01:01 NULL NULL
+71 NULL NULL 1991-01-01 01:01:01 NULL NULL
+73 NULL NULL 1991-01-01 01:01:01 NULL NULL
+81 NULL NULL 1991-01-01 01:01:01 NULL NULL
+83 NULL NULL 1991-01-01 01:01:01 NULL NULL
+test_sequence
+-- select .. where date/time column = .. --
+set @arg00= '1991-01-01 01:01:01' ;
+select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+c17= '1991-01-01 01:01:01' ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= '1991-01-01 01:01:01' and c14= '1991-01-01 01:01:01' and
+ c15= '1991-01-01 01:01:01' and c16= '1991-01-01 01:01:01' and
+ c17= '1991-01-01 01:01:01'" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= CAST('1991-01-01 01:01:01' as datetime) ;
+select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+c14= CAST('1991-01-01 01:01:01' as datetime) and
+c15= CAST('1991-01-01 01:01:01' as datetime) and
+c16= CAST('1991-01-01 01:01:01' as datetime) and
+c17= CAST('1991-01-01 01:01:01' as datetime) ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c13= @arg00 and c14= @arg00 and c15= @arg00 and c16= @arg00
+and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= CAST('1991-01-01 01:01:01' as datetime) and
+ c14= CAST('1991-01-01 01:01:01' as datetime) and
+ c15= CAST('1991-01-01 01:01:01' as datetime) and
+ c16= CAST('1991-01-01 01:01:01' as datetime) and
+ c17= CAST('1991-01-01 01:01:01' as datetime)" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c13= ? and c14= ? and c15= ? and c16= ? and c17= ?" ;
+execute stmt1 using @arg00, @arg00, @arg00, @arg00, @arg00 ;
+found
+true
+set @arg00= 1991 ;
+select 'true' as found from t9
+where c1= 20 and c17= 1991 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and c17= @arg00 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= 1991" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and c17= ?" ;
+execute stmt1 using @arg00 ;
+found
+true
+set @arg00= 1.991e+3 ;
+select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01 ;
+found
+true
+select 'true' as found from t9
+where c1= 20 and abs(c17 - @arg00) < 0.01 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - 1.991e+3) < 0.01" ;
+execute stmt1 ;
+found
+true
+prepare stmt1 from "select 'true' as found from t9
+where c1= 20 and abs(c17 - ?) < 0.01" ;
+execute stmt1 using @arg00 ;
+found
+true
+drop table t1, t9;
diff --git a/mysql-test/r/ps_7ndb.result b/mysql-test/r/ps_7ndb.result
index cf567750b85..a0da0b5c7bb 100644
--- a/mysql-test/r/ps_7ndb.result
+++ b/mysql-test/r/ps_7ndb.result
@@ -2,20 +2,19 @@ use test;
drop table if exists t1, t9 ;
create table t1
(
-a int not null, b varchar(30),
+a int, b varchar(30),
primary key(a)
) engine = 'NDB' ;
-drop table if exists t9;
create table t9
(
-c1 tinyint not null, c2 smallint, c3 mediumint, c4 int,
+c1 tinyint, c2 smallint, c3 mediumint, c4 int,
c5 integer, c6 bigint, c7 float, c8 double,
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
c13 date, c14 datetime, c15 timestamp(14), c16 time,
c17 year, c18 bit, c19 bool, c20 char,
-c21 char(10), c22 varchar(30), c23 char(100), c24 char(100),
-c25 char(100), c26 char(100), c27 char(100), c28 char(100),
-c29 char(100), c30 char(100), c31 enum('one', 'two', 'three'),
+c21 char(10), c22 varchar(30), c23 tinyblob, c24 tinytext,
+c25 blob, c26 text, c27 mediumblob, c28 mediumtext,
+c29 longblob, c30 longtext, c31 enum('one', 'two', 'three'),
c32 set('monday', 'tuesday', 'wednesday'),
primary key(c1)
) engine = 'NDB' ;
@@ -72,14 +71,14 @@ def test t9 t9 c19 c19 1 1 1 Y 32768 0 63
def test t9 t9 c20 c20 254 1 1 Y 0 0 8
def test t9 t9 c21 c21 253 10 10 Y 0 0 8
def test t9 t9 c22 c22 253 30 30 Y 0 0 8
-def test t9 t9 c23 c23 253 100 8 Y 0 0 8
-def test t9 t9 c24 c24 253 100 8 Y 0 0 8
-def test t9 t9 c25 c25 253 100 4 Y 0 0 8
-def test t9 t9 c26 c26 253 100 4 Y 0 0 8
-def test t9 t9 c27 c27 253 100 10 Y 0 0 8
-def test t9 t9 c28 c28 253 100 10 Y 0 0 8
-def test t9 t9 c29 c29 253 100 8 Y 0 0 8
-def test t9 t9 c30 c30 253 100 8 Y 0 0 8
+def test t9 t9 c23 c23 252 255 8 Y 144 0 63
+def test t9 t9 c24 c24 252 255 8 Y 16 0 8
+def test t9 t9 c25 c25 252 65535 4 Y 144 0 63
+def test t9 t9 c26 c26 252 65535 4 Y 16 0 8
+def test t9 t9 c27 c27 252 16777215 10 Y 144 0 63
+def test t9 t9 c28 c28 252 16777215 10 Y 16 0 8
+def test t9 t9 c29 c29 252 16777215 8 Y 144 0 63
+def test t9 t9 c30 c30 252 16777215 8 Y 16 0 8
def test t9 t9 c31 c31 254 5 3 Y 256 0 8
def test t9 t9 c32 c32 254 24 7 Y 2048 0 8
c1 c2 c3 c4 c5 c6 c7 c8 c9 c10 c11 c12 c13 c14 c15 c16 c17 c18 c19 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30 c31 c32
@@ -1152,7 +1151,7 @@ def table 253 64 2 N 1 31 8
def type 253 10 3 N 1 31 8
def possible_keys 253 4096 0 Y 0 31 8
def key 253 64 0 Y 0 31 8
-def key_len 8 3 0 Y 32800 0 8
+def key_len 253 4096 0 Y 128 31 63
def ref 253 1024 0 Y 0 31 8
def rows 8 10 1 N 32801 0 8
def Extra 253 255 0 N 1 31 8
@@ -1188,7 +1187,7 @@ c29= 'longblob', c30= 'longtext', c31='two', c32= 'tuesday';
commit ;
prepare stmt1 from 'delete from t1 where a=2' ;
execute stmt1;
-select a,b from t1 where a=2 order by b;
+select a,b from t1 where a=2;
a b
execute stmt1;
insert into t1 values(0,NULL);
@@ -1203,7 +1202,6 @@ execute stmt1 using @arg00;
select a,b from t1 where b=@arg00;
a b
prepare stmt1 from 'truncate table t1' ;
-ERROR HY000: This command is not supported in the prepared statement protocol yet
test_sequence
------ update tests ------
delete from t1 ;
@@ -1270,18 +1268,23 @@ execute stmt1 using @arg00, @arg00;
select a,b from t1 where a=@arg00;
a b
2 two
+execute stmt1 using @arg01, @arg00;
select a,b from t1 where a=@arg01;
a b
+22 two
execute stmt1 using @arg00, @arg01;
select a,b from t1 where a=@arg00;
a b
2 two
set @arg00=NULL;
set @arg01=2;
+execute stmt1 using @arg00, @arg01;
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 1
select a,b from t1 order by a;
a b
+0 two
1 one
-2 two
3 three
4 four
set @arg00=0;
@@ -1302,15 +1305,19 @@ create table t2 as select a,b from t1 ;
prepare stmt1 from 'update t1 set a=? where b=?
and a in (select ? from t2
where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
select a,b from t1 where a = @arg00 ;
a b
+23 two
prepare stmt1 from 'update t1 set a=? where b=?
and a not in (select ? from t2
where b = ? or a = ?)';
execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
-affected rows: 0
-info: Rows matched: 0 Changed: 0 Warnings: 0
-select a,b from t1 order by a;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
+select a,b from t1 order by a ;
a b
1 one
2 two
@@ -1319,21 +1326,25 @@ a b
drop table t2 ;
create table t2
(
-a int not null, b varchar(30),
+a int, b varchar(30),
primary key(a)
) engine = 'NDB' ;
insert into t2(a,b) select a, b from t1 ;
prepare stmt1 from 'update t1 set a=? where b=?
and a in (select ? from t2
where b = ? or a = ?)';
+execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
select a,b from t1 where a = @arg00 ;
a b
+23 two
prepare stmt1 from 'update t1 set a=? where b=?
and a not in (select ? from t2
where b = ? or a = ?)';
execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
-affected rows: 0
-info: Rows matched: 0 Changed: 0 Warnings: 0
+affected rows: 1
+info: Rows matched: 1 Changed: 1 Warnings: 0
select a,b from t1 order by a ;
a b
1 one
@@ -1474,7 +1485,7 @@ set @arg02=82 ;
set @arg03='8-2' ;
prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
-select a,b from t1 where a in (@arg00,@arg02) order by a ;
+select a,b from t1 where a in (@arg00,@arg02) ;
a b
81 8-1
82 8-2
@@ -1489,6 +1500,7 @@ set @arg00=6 ;
set @arg01=1 ;
prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
on duplicate key update a=a + ?, b=concat(b,''modified'') ';
+execute stmt1 using @arg00, @arg01;
select * from t1 order by a;
a b
0 NULL
@@ -1497,13 +1509,15 @@ a b
3 three
4 four
5 five
-6 six
+7 sixmodified
8 eight
9 nine
81 8-1
82 8-2
set @arg00=81 ;
set @arg01=1 ;
+execute stmt1 using @arg00, @arg01;
+ERROR 23000: Duplicate entry '82' for key 1
drop table if exists t2 ;
create table t2 (id int auto_increment primary key)
ENGINE= 'NDB' ;
@@ -1526,24 +1540,32 @@ set @x1100="x1100" ;
set @100=100 ;
set @updated="updated" ;
insert into t1 values(1000,'x1000_1') ;
+insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
+on duplicate key update a = a + @100, b = concat(b,@updated) ;
select a,b from t1 where a >= 1000 order by a ;
a b
-1000 x1000_1
+1000 x1000_3
+1100 x1000_1updated
delete from t1 where a >= 1000 ;
insert into t1 values(1000,'x1000_1') ;
prepare stmt1 from ' insert into t1 values(?,?),(?,?)
on duplicate key update a = a + ?, b = concat(b,?) ';
+execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
select a,b from t1 where a >= 1000 order by a ;
a b
-1000 x1000_1
+1000 x1000_3
+1100 x1000_1updated
delete from t1 where a >= 1000 ;
insert into t1 values(1000,'x1000_1') ;
+execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
select a,b from t1 where a >= 1000 order by a ;
a b
-1000 x1000_1
+1200 x1000_1updatedupdated
delete from t1 where a >= 1000 ;
prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
-ERROR HY000: This command is not supported in the prepared statement protocol yet
+execute stmt1;
+execute stmt1;
+execute stmt1;
test_sequence
------ multi table tests ------
delete from t1 ;
@@ -1750,10 +1772,10 @@ t5 CREATE TABLE `t5` (
`param10` bigint(20) default NULL,
`const11` int(4) default NULL,
`param11` bigint(20) default NULL,
- `const12` char(0) default NULL,
+ `const12` binary(0) default NULL,
`param12` bigint(20) default NULL,
`param13` double default NULL,
- `param14` longblob,
+ `param14` longtext,
`param15` longblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select * from t5 ;
@@ -1780,10 +1802,10 @@ def test t5 t5 const10 const10 3 10 9 N 32769 0 63
def test t5 t5 param10 param10 8 20 9 Y 32768 0 63
def test t5 t5 const11 const11 3 4 4 Y 32768 0 63
def test t5 t5 param11 param11 8 20 4 Y 32768 0 63
-def test t5 t5 const12 const12 254 0 0 Y 0 0 8
+def test t5 t5 const12 const12 254 0 0 Y 128 0 63
def test t5 t5 param12 param12 8 20 0 Y 32768 0 63
def test t5 t5 param13 param13 5 20 0 Y 32768 31 63
-def test t5 t5 param14 param14 252 16777215 0 Y 144 0 63
+def test t5 t5 param14 param14 252 16777215 0 Y 16 0 8
def test t5 t5 param15 param15 252 16777215 0 Y 144 0 63
const01 8
param01 8
@@ -1892,13 +1914,13 @@ def @arg19 254 20 1 Y 128 31 63
def @arg20 254 8192 1 Y 0 31 8
def @arg21 254 8192 10 Y 0 31 8
def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
def @arg30 254 8192 8 Y 0 31 8
def @arg31 254 8192 3 Y 0 31 8
def @arg32 254 8192 6 Y 128 31 63
@@ -1936,19 +1958,19 @@ def @arg16 254 8192 0 Y 128 31 63
def @arg17 254 20 0 Y 128 31 63
def @arg18 254 20 0 Y 128 31 63
def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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
@@ -1989,13 +2011,13 @@ def @arg19 254 20 1 Y 128 31 63
def @arg20 254 8192 1 Y 0 31 8
def @arg21 254 8192 10 Y 0 31 8
def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
def @arg30 254 8192 8 Y 0 31 8
def @arg31 254 8192 3 Y 0 31 8
def @arg32 254 8192 6 Y 128 31 63
@@ -2026,19 +2048,19 @@ def @arg16 254 8192 0 Y 128 31 63
def @arg17 254 20 0 Y 128 31 63
def @arg18 254 20 0 Y 128 31 63
def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
@@ -2077,13 +2099,13 @@ def @arg19 254 20 1 Y 128 31 63
def @arg20 254 8192 1 Y 0 31 8
def @arg21 254 8192 10 Y 0 31 8
def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
def @arg30 254 8192 8 Y 0 31 8
def @arg31 254 8192 3 Y 0 31 8
def @arg32 254 8192 6 Y 128 31 63
@@ -2118,19 +2140,19 @@ def @arg16 254 8192 0 Y 128 31 63
def @arg17 254 20 0 Y 128 31 63
def @arg18 254 20 0 Y 128 31 63
def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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,
@@ -2167,13 +2189,13 @@ def @arg19 254 20 1 Y 128 31 63
def @arg20 254 8192 1 Y 0 31 8
def @arg21 254 8192 10 Y 0 31 8
def @arg22 254 8192 30 Y 0 31 8
-def @arg23 254 8192 8 Y 0 31 8
+def @arg23 254 8192 8 Y 128 31 63
def @arg24 254 8192 8 Y 0 31 8
-def @arg25 254 8192 4 Y 0 31 8
+def @arg25 254 8192 4 Y 128 31 63
def @arg26 254 8192 4 Y 0 31 8
-def @arg27 254 8192 10 Y 0 31 8
+def @arg27 254 8192 10 Y 128 31 63
def @arg28 254 8192 10 Y 0 31 8
-def @arg29 254 8192 8 Y 0 31 8
+def @arg29 254 8192 8 Y 128 31 63
def @arg30 254 8192 8 Y 0 31 8
def @arg31 254 8192 3 Y 0 31 8
def @arg32 254 8192 6 Y 128 31 63
@@ -2202,19 +2224,19 @@ def @arg16 254 8192 0 Y 128 31 63
def @arg17 254 20 0 Y 128 31 63
def @arg18 254 20 0 Y 128 31 63
def @arg19 254 20 0 Y 128 31 63
-def @arg20 254 8192 0 Y 128 31 63
-def @arg21 254 8192 0 Y 128 31 63
-def @arg22 254 8192 0 Y 128 31 63
+def @arg20 254 8192 0 Y 0 31 8
+def @arg21 254 8192 0 Y 0 31 8
+def @arg22 254 8192 0 Y 0 31 8
def @arg23 254 8192 0 Y 128 31 63
-def @arg24 254 8192 0 Y 128 31 63
+def @arg24 254 8192 0 Y 0 31 8
def @arg25 254 8192 0 Y 128 31 63
-def @arg26 254 8192 0 Y 128 31 63
+def @arg26 254 8192 0 Y 0 31 8
def @arg27 254 8192 0 Y 128 31 63
-def @arg28 254 8192 0 Y 128 31 63
+def @arg28 254 8192 0 Y 0 31 8
def @arg29 254 8192 0 Y 128 31 63
-def @arg30 254 8192 0 Y 128 31 63
-def @arg31 254 8192 0 Y 128 31 63
-def @arg32 254 8192 0 Y 128 31 63
+def @arg30 254 8192 0 Y 0 31 8
+def @arg31 254 8192 0 Y 0 31 8
+def @arg32 254 8192 0 Y 0 31 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" ;
@@ -2525,12 +2547,12 @@ set @arg00= 9223372036854775807 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2548,12 +2570,12 @@ set @arg00= '9223372036854775807' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2571,12 +2593,12 @@ set @arg00= -9223372036854775808 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2594,12 +2616,12 @@ set @arg00= '-9223372036854775808' ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1265 Data truncated for column 'c4' at row 1
-Warning 1265 Data truncated for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2617,14 +2639,14 @@ set @arg00= 1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 127
c2 32767
@@ -2648,8 +2670,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 1
c2 1
@@ -2667,14 +2689,14 @@ set @arg00= -1.11111111111111111111e+50 ;
execute my_insert using @arg00, @arg00, @arg00, @arg00, @arg00, @arg00,
@arg00, @arg00, @arg00, @arg00, @arg00 ;
Warnings:
-Warning 1264 Data truncated; out of range for column 'c1' at row 1
-Warning 1264 Data truncated; out of range for column 'c2' at row 1
-Warning 1264 Data truncated; out of range for column 'c3' at row 1
-Warning 1264 Data truncated; out of range for column 'c4' at row 1
-Warning 1264 Data truncated; out of range for column 'c5' at row 1
-Warning 1264 Data truncated; out of range for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c1' at row 1
+Warning 1264 Out of range value adjusted for column 'c2' at row 1
+Warning 1264 Out of range value adjusted for column 'c3' at row 1
+Warning 1264 Out of range value adjusted for column 'c4' at row 1
+Warning 1264 Out of range value adjusted for column 'c5' at row 1
+Warning 1264 Out of range value adjusted for column 'c6' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -128
c2 -32768
@@ -2698,8 +2720,8 @@ Warning 1265 Data truncated for column 'c3' at row 1
Warning 1265 Data truncated for column 'c4' at row 1
Warning 1265 Data truncated for column 'c5' at row 1
Warning 1265 Data truncated for column 'c6' at row 1
-Warning 1264 Data truncated; out of range for column 'c7' at row 1
-Warning 1264 Data truncated; out of range for column 'c12' at row 1
+Warning 1264 Out of range value adjusted for column 'c7' at row 1
+Warning 1264 Out of range value adjusted for column 'c12' at row 1
execute my_select ;
c1 -1
c2 -1
@@ -2771,14 +2793,14 @@ c1 c20 c21 c22 c23 c24 c25 c26 c27 c28 c29 c30
41 4 41 41 41 41 41 41 41 41 41 41
42 4 42 42 42 42 42 42 42 42 42 42
43 4 43 43 43 43 43 43 43 43 43 43
-50 5 50 50 50 50 50 50 50 50 50 50
+50 5 50 50 50.00 50.00 50.00 50.00 50.00 50.00 50.00 50.00
51 5 51 51 51 51 51 51 51 51 51 51
-52 5 52 52 52 52 52 52 52 52 52 52
-53 5 53 53 53 53 53 53 53 53 53 53
-54 5 54 54 54 54 54 54 54 54 54 54
+52 5 52 52 52.00 52.00 52.00 52.00 52.00 52.00 52.00 52.00
+53 5 53 53 53.00 53.00 53.00 53.00 53.00 53.00 53.00 53.00
+54 5 54 54 54.00 54.00 54.00 54.00 54.00 54.00 54.00 54.00
55 5 55 55 55 55 55 55 55 55 55 55
-56 6 56 56 56 56 56 56 56 56 56 56
-57 6 57 57 57 57 57 57 57 57 57 57
+56 6 56 56 56.00 56.00 56.00 56.00 56.00 56.00 56.00 56.00
+57 6 57 57 57.00 57.00 57.00 57.00 57.00 57.00 57.00 57.00
60 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
61 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
62 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL
@@ -2930,45 +2952,45 @@ Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
Warning 1265 Data truncated for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
Warning 1265 Data truncated for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
Warning 1265 Data truncated for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
-Warning 1264 Data truncated; out of range for column 'c13' at row 1
+Warning 1264 Out of range value adjusted for column 'c13' at row 1
Warning 1265 Data truncated for column 'c14' at row 1
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
Warnings:
Warning 1265 Data truncated for column 'c15' at row 1
-Warning 1264 Data truncated; out of range for column 'c16' at row 1
-Warning 1264 Data truncated; out of range for column 'c17' at row 1
+Warning 1264 Out of range value adjusted for column 'c16' at row 1
+Warning 1264 Out of range value adjusted for column 'c17' at row 1
select c1, c13, c14, c15, c16, c17 from t9 order by c1 ;
c1 c13 c14 c15 c16 c17
20 1991-01-01 1991-01-01 01:01:01 1991-01-01 01:01:01 01:01:01 1991
diff --git a/mysql-test/r/query_cache.result.es b/mysql-test/r/query_cache.result.es
index 218e4e1ae2a..1e16354d87d 100644
--- a/mysql-test/r/query_cache.result.es
+++ b/mysql-test/r/query_cache.result.es
@@ -791,6 +791,19 @@ Qcache_queries_in_cache 1
unlock table;
drop table t1,t2;
set query_cache_wlock_invalidate=default;
+CREATE TABLE t1 (id INT PRIMARY KEY);
+insert into t1 values (1),(2),(3);
+select * from t1;
+id
+1
+2
+3
+create temporary table t1 (a int not null auto_increment
+primary key);
+select * from t1;
+a
+drop table t1;
+drop table t1;
SET NAMES koi8r;
CREATE TABLE t1 (a char(1) character set koi8r);
INSERT INTO t1 VALUES (_koi8r'á'),(_koi8r'Á');
@@ -901,6 +914,8 @@ set group_concat_max_len=10;
select group_concat(a) FROM t1 group by b;
group_concat(a)
1234567890
+Warnings:
+Warning 1260 1 line(s) were cut by GROUP_CONCAT()
set group_concat_max_len=1024;
select group_concat(a) FROM t1 group by b;
group_concat(a)
diff --git a/mysql-test/r/range.result b/mysql-test/r/range.result
index e7375b428c2..8a1d80e9f79 100644
--- a/mysql-test/r/range.result
+++ b/mysql-test/r/range.result
@@ -218,12 +218,14 @@ drop table t1;
create table t1 (x int, y int, index(x), index(y));
insert into t1 (x) values (1),(2),(3),(4),(5),(6),(7),(8),(9);
update t1 set y=x;
-explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 7 and t1.y+0;
+explain select * from t1, t1 t2 where t1.y = 8 and t2.x between 7 and t1.y+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, t1 t2 where t1.y = 2 and t2.x >= 7 and t2.x <= t1.y+0;
+1 SIMPLE t1 ref y y 5 const 1 Using where
+1 SIMPLE t2 range x x 5 NULL 2 Using where
+explain select * from t1, t1 t2 where t1.y = 8 and t2.x >= 7 and t2.x <= t1.y+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
+1 SIMPLE t1 ref y y 5 const 1 Using where
+1 SIMPLE t2 range x x 5 NULL 2 Using where
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 ref y y 5 const 1 Using where
@@ -547,3 +549,20 @@ select count(*) from t2 where x = 18446744073709551601;
count(*)
0
drop table t1,t2;
+set names latin1;
+create table t1 (a char(10), b text, key (a)) character set latin1;
+INSERT INTO t1 (a) VALUES
+('111'),('222'),('222'),('222'),('222'),('444'),('aaa'),('AAA'),('bbb');
+explain select * from t1 where a='aaa';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ref a a 11 const 2 Using where
+explain select * from t1 where a=binary 'aaa';
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 11 NULL 2 Using where
+explain select * from t1 where a='aaa' collate latin1_bin;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 range a a 11 NULL 2 Using where
+explain select * from t1 where a='aaa' collate latin1_german1_ci;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL a NULL NULL NULL 9 Using where
+drop table t1;
diff --git a/mysql-test/r/rpl_auto_increment.result b/mysql-test/r/rpl_auto_increment.result
index ec3bf4019e0..9eca51ad2d9 100644
--- a/mysql-test/r/rpl_auto_increment.result
+++ b/mysql-test/r/rpl_auto_increment.result
@@ -37,11 +37,10 @@ a b
32 6
drop table t1;
set @@session.auto_increment_increment=100, @@session.auto_increment_offset=10;
-show variables like "%auto%";
+show variables like "%auto_inc%";
Variable_name Value
auto_increment_increment 100
auto_increment_offset 10
-innodb_autoextend_increment 8
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
insert into t1 values (NULL),(5),(NULL);
insert into t1 values (250),(NULL);
diff --git a/mysql-test/r/rpl_charset.result b/mysql-test/r/rpl_charset.result
index 2ffdb2c720a..0224bd6dba2 100644
--- a/mysql-test/r/rpl_charset.result
+++ b/mysql-test/r/rpl_charset.result
@@ -105,15 +105,15 @@ drop database mysqltest2;
drop database mysqltest3;
show binlog events from 95;
Log_name Pos Event_type Server_id End_log_pos Info
-master-bin.000001 # Query 1 # use `test`; drop database if exists mysqltest2
-master-bin.000001 # Query 1 # use `test`; drop database if exists mysqltest3
-master-bin.000001 # Query 1 # use `test`; create database mysqltest2 character set latin2
+master-bin.000001 # Query 1 # drop database if exists mysqltest2
+master-bin.000001 # Query 1 # drop database if exists mysqltest3
+master-bin.000001 # Query 1 # create database mysqltest2 character set latin2
master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=30
-master-bin.000001 # Query 1 # use `test`; create database mysqltest3
+master-bin.000001 # Query 1 # create database mysqltest3
master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=64
-master-bin.000001 # Query 1 # use `test`; drop database mysqltest3
+master-bin.000001 # Query 1 # drop database mysqltest3
master-bin.000001 # Query 1 # use `test`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=8,COLLATION_SERVER=64
-master-bin.000001 # Query 1 # use `test`; create database mysqltest3
+master-bin.000001 # Query 1 # create database mysqltest3
master-bin.000001 # Query 1 # use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=8,COLLATION_DATABASE=9,COLLATION_SERVER=64
master-bin.000001 # Query 1 # use `mysqltest2`; create table t1 (a int auto_increment primary key, b varchar(100))
master-bin.000001 # Query 1 # use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=4,COLLATION_CONNECTION=27,COLLATION_DATABASE=9,COLLATION_SERVER=64
@@ -158,13 +158,13 @@ master-bin.000001 # Intvar 1 # INSERT_ID=1
master-bin.000001 # User var 1 # @`a`=_cp850 0x4DFC6C6C6572 COLLATE cp850_general_ci
master-bin.000001 # Query 1 # use `mysqltest2`; insert into t1 (b) values(collation(@a))
master-bin.000001 # Query 1 # use `mysqltest2`; SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
-master-bin.000001 # Query 1 # use `mysqltest2`; drop database mysqltest2
+master-bin.000001 # Query 1 # drop database mysqltest2
master-bin.000001 # Query 1 # SET ONE_SHOT CHARACTER_SET_CLIENT=8,COLLATION_CONNECTION=31,COLLATION_DATABASE=9,COLLATION_SERVER=64
master-bin.000001 # Query 1 # drop database mysqltest3
set global character_set_server=latin2;
-ERROR HY000: Binary logging and replication forbid changing the global server character set or collation
+ERROR HY000: Binary logging and replication forbid changing the global server character set, collation
set global character_set_server=latin2;
-ERROR HY000: Binary logging and replication forbid changing the global server character set or collation
+ERROR HY000: Binary logging and replication forbid changing the global server character set, collation
set one_shot @@character_set_server=latin5;
set @@max_join_size=1000;
select @@character_set_server;
@@ -181,7 +181,7 @@ select @@character_set_server;
@@character_set_server
latin5
set one_shot max_join_size=10;
-ERROR HY000: The SET ONE_SHOT syntax is reserved for purposes internal to the MySQL server
+ERROR HY000: The 'SET ONE_SHOT' syntax is reserved for purposes internal to the MySQL server
set character_set_client=9999999;
ERROR 42000: Unknown character set: '9999999'
set collation_server=9999998;
@@ -200,8 +200,8 @@ hex(c1) hex(c2)
CDF32C20E7E020F0FBE1E0EBEAF3 CDF32C20E7E020F0FBE1E0EBEAF3
stop slave;
delete from t1;
-change master to master_log_pos=6763;
-start slave until master_log_file='master-bin.000001', master_log_pos=6921;
+change master to master_log_pos=6809;
+start slave until master_log_file='master-bin.000001', master_log_pos=6967;
start slave;
select hex(c1), hex(c2) from t1;
hex(c1) hex(c2)
diff --git a/mysql-test/r/rpl_create_database.result b/mysql-test/r/rpl_create_database.result
new file mode 100644
index 00000000000..86282ce3cc5
--- /dev/null
+++ b/mysql-test/r/rpl_create_database.result
@@ -0,0 +1,83 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+DROP DATABASE IF EXISTS mysqltest_prometheus;
+DROP DATABASE IF EXISTS mysqltest_sisyfos;
+DROP DATABASE IF EXISTS mysqltest_bob;
+DROP DATABASE IF EXISTS mysqltest_bob;
+CREATE DATABASE mysqltest_prometheus;
+CREATE DATABASE mysqltest_sisyfos;
+CREATE DATABASE mysqltest_bob;
+USE mysqltest_sisyfos;
+CREATE TABLE t1 (b int);
+INSERT INTO t1 VALUES(1);
+USE mysqltest_bob;
+CREATE TABLE t2 (b int);
+INSERT INTO t2 VALUES(2);
+ALTER DATABASE mysqltest_sisyfos CHARACTER SET latin1;
+USE mysqltest_sisyfos;
+ALTER DATABASE mysqltest_bob CHARACTER SET latin1;
+SHOW DATABASES;
+Database
+mysql
+mysqltest_bob
+mysqltest_prometheus
+mysqltest_sisyfos
+test
+SHOW DATABASES;
+Database
+mysql
+mysqltest_prometheus
+mysqltest_sisyfos
+test
+DROP DATABASE IF EXISTS mysqltest_sisyfos;
+USE mysqltest_prometheus;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+CREATE DATABASE mysqltest_sisyfos;
+USE mysqltest_sisyfos;
+CREATE TABLE t2 (a INT);
+SHOW BINLOG EVENTS;
+Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 # Format_desc 1 # Server ver: VERSION, Binlog ver: 4
+master-bin.000001 # Query 1 # DROP DATABASE IF EXISTS mysqltest_prometheus
+master-bin.000001 # Query 1 # DROP DATABASE IF EXISTS mysqltest_sisyfos
+master-bin.000001 # Query 1 # CREATE DATABASE mysqltest_prometheus
+master-bin.000001 # Query 1 # CREATE DATABASE mysqltest_sisyfos
+master-bin.000001 # Query 1 # use `mysqltest_sisyfos`; CREATE TABLE t1 (b int)
+master-bin.000001 # Query 1 # use `mysqltest_sisyfos`; INSERT INTO t1 VALUES(1)
+master-bin.000001 # Query 1 # ALTER DATABASE mysqltest_sisyfos CHARACTER SET latin1
+master-bin.000001 # Query 1 # DROP DATABASE IF EXISTS mysqltest_sisyfos
+master-bin.000001 # Query 1 # use `mysqltest_prometheus`; CREATE TABLE t1 (a INT)
+master-bin.000001 # Query 1 # use `mysqltest_prometheus`; INSERT INTO t1 VALUES (1)
+master-bin.000001 # Query 1 # CREATE DATABASE mysqltest_sisyfos
+master-bin.000001 # Query 1 # use `mysqltest_sisyfos`; CREATE TABLE t2 (a INT)
+SHOW DATABASES;
+Database
+mysql
+mysqltest_bob
+mysqltest_prometheus
+mysqltest_sisyfos
+test
+SHOW DATABASES;
+Database
+mysql
+mysqltest_prometheus
+mysqltest_sisyfos
+test
+SHOW CREATE TABLE mysqltest_prometheus.t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+SHOW CREATE TABLE mysqltest_sisyfos.t2;
+Table Create Table
+t2 CREATE TABLE `t2` (
+ `a` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+DROP DATABASE IF EXISTS mysqltest_prometheus;
+DROP DATABASE IF EXISTS mysqltest_sisyfos;
+DROP DATABASE IF EXISTS mysqltest_bob;
diff --git a/mysql-test/r/rpl_failed_optimize.result b/mysql-test/r/rpl_failed_optimize.result
new file mode 100644
index 00000000000..1576ec60500
--- /dev/null
+++ b/mysql-test/r/rpl_failed_optimize.result
@@ -0,0 +1,15 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+CREATE TABLE t1 ( a int ) ENGINE=InnoDB;
+BEGIN;
+INSERT INTO t1 VALUES (1);
+OPTIMIZE TABLE t1;
+Table Op Msg_type Msg_text
+test.t1 optimize status Operation failed
+OPTIMIZE TABLE non_existing;
+Table Op Msg_type Msg_text
+test.non_existing optimize error Table 'test.non_existing' doesn't exist
diff --git a/mysql-test/r/rpl_loaddata_rule_m.result b/mysql-test/r/rpl_loaddata_rule_m.result
index 1b7ea5661fb..b241fc9ce0b 100644
--- a/mysql-test/r/rpl_loaddata_rule_m.result
+++ b/mysql-test/r/rpl_loaddata_rule_m.result
@@ -12,4 +12,6 @@ use mysqltest;
load data infile '../../std_data/rpl_loaddata.dat' into table test.t1;
show binlog events from 95;
Log_name Pos Event_type Server_id End_log_pos Info
+master-bin.000001 95 Query 1 190 drop database if exists mysqltest
+master-bin.000001 190 Query 1 277 create database mysqltest
drop database mysqltest;
diff --git a/mysql-test/r/rpl_rewrite_db.result b/mysql-test/r/rpl_rewrite_db.result
new file mode 100644
index 00000000000..b22eb98067b
--- /dev/null
+++ b/mysql-test/r/rpl_rewrite_db.result
@@ -0,0 +1,92 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+drop database if exists mysqltest1;
+create database mysqltest1;
+use mysqltest1;
+create table t1 (a int);
+insert into t1 values(9);
+select * from mysqltest1.t1;
+a
+9
+show databases like 'mysqltest1';
+Database (mysqltest1)
+mysqltest1
+select * from test.t1;
+a
+9
+drop table t1;
+drop database mysqltest1;
+drop database if exists rewrite;
+create database rewrite;
+use test;
+create table t1 (a date, b date, c date not null, d date);
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',';
+Warnings:
+Warning 1265 Data truncated for column 'a' at row 1
+Warning 1265 Data truncated for column 'c' at row 1
+Warning 1265 Data truncated for column 'd' at row 1
+Warning 1265 Data truncated for column 'a' at row 2
+Warning 1265 Data truncated for column 'b' at row 2
+Warning 1265 Data truncated for column 'd' at row 2
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
+select * from rewrite.t1;
+a b c d
+0000-00-00 NULL 0000-00-00 0000-00-00
+0000-00-00 0000-00-00 0000-00-00 0000-00-00
+2003-03-03 2003-03-03 2003-03-03 NULL
+2003-03-03 2003-03-03 2003-03-03 NULL
+truncate table t1;
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
+Warnings:
+Warning 1265 Data truncated for column 'c' at row 1
+Warning 1265 Data truncated for column 'd' at row 1
+Warning 1265 Data truncated for column 'b' at row 2
+Warning 1265 Data truncated for column 'd' at row 2
+select * from rewrite.t1;
+a b c d
+NULL NULL 0000-00-00 0000-00-00
+NULL 0000-00-00 0000-00-00 0000-00-00
+NULL 2003-03-03 2003-03-03 NULL
+drop table t1;
+create table t1 (a text, b text);
+load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
+Warnings:
+Warning 1261 Row 3 doesn't contain data for all columns
+select concat('|',a,'|'), concat('|',b,'|') from rewrite.t1;
+concat('|',a,'|') concat('|',b,'|')
+|Field A| |Field B|
+|Field 1| |Field 2'
+Field 3,'Field 4|
+|Field 5' ,'Field 6| NULL
+|Field 6| | 'Field 7'|
+drop table t1;
+create table t1 (a int, b char(10));
+load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 3
+Warning 1262 Row 3 was truncated; it contained more data than there were input columns
+Warning 1264 Out of range value adjusted for column 'a' at row 5
+Warning 1262 Row 5 was truncated; it contained more data than there were input columns
+select * from rewrite.t1;
+a b
+1 row 1
+2 row 2
+0 1234567890
+3 row 3
+0 1234567890
+truncate table t1;
+load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines;
+Warnings:
+Warning 1264 Out of range value adjusted for column 'a' at row 4
+Warning 1261 Row 4 doesn't contain data for all columns
+select * from rewrite.t1;
+a b
+1 row 1
+2 row 2
+3 row 3
+0
+drop table t1;
diff --git a/mysql-test/r/rpl_rotate_logs.result b/mysql-test/r/rpl_rotate_logs.result
index 85071e13555..cfd296fd44b 100644
--- a/mysql-test/r/rpl_rotate_logs.result
+++ b/mysql-test/r/rpl_rotate_logs.result
@@ -1,7 +1,7 @@
drop table if exists t1, t2, t3, t4;
drop table if exists t1, t2, t3, t4;
start slave;
-ERROR HY000: Could not initialize master info structure; more error messages can be found in the MySQL error log
+ERROR HY000: File 'TESTDIR/var/slave-data/master.info' not found (Errcode: 13)
start slave;
ERROR HY000: Could not initialize master info structure; more error messages can be found in the MySQL error log
change master to master_host='127.0.0.1',master_port=MASTER_PORT, master_user='root';
diff --git a/mysql-test/r/rpl_start_stop_slave.result b/mysql-test/r/rpl_start_stop_slave.result
new file mode 100644
index 00000000000..1fcb586d1fb
--- /dev/null
+++ b/mysql-test/r/rpl_start_stop_slave.result
@@ -0,0 +1,12 @@
+stop slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+reset master;
+reset slave;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+start slave;
+stop slave;
+create table t1(n int);
+start slave;
+stop slave io_thread;
+start slave io_thread;
+drop table t1;
diff --git a/mysql-test/r/rpl_timezone.result b/mysql-test/r/rpl_timezone.result
index 6dc8f87393c..495fccd35a3 100644
--- a/mysql-test/r/rpl_timezone.result
+++ b/mysql-test/r/rpl_timezone.result
@@ -73,5 +73,5 @@ t
2001-09-09 03:46:40
1000000000
set global time_zone='MET';
-ERROR HY000: Binary logging and replication forbid changing of the global server time zone
+ERROR HY000: Binary logging and replication forbid changing the global server time zone
drop table t1, t2;
diff --git a/mysql-test/r/select.result b/mysql-test/r/select.result
index e0e839abdce..e4232a759b1 100644
--- a/mysql-test/r/select.result
+++ b/mysql-test/r/select.result
@@ -2058,6 +2058,10 @@ t2 1 fld3 1 fld3 A NULL NULL NULL BTREE
drop table t4, t3, t2, t1;
DO 1;
DO benchmark(100,1+1),1,1;
+do default;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+do foobar;
+ERROR 42S22: Unknown column 'foobar' in 'field list'
CREATE TABLE t1 (
id mediumint(8) unsigned NOT NULL auto_increment,
pseudo varchar(35) NOT NULL default '',
@@ -2309,7 +2313,7 @@ select * from t2 where s = 'one';
s
select * from t3 where s = 'one';
s
-one
+one
select * from t1,t2 where t1.s = t2.s;
s s
two two
@@ -2317,6 +2321,27 @@ select * from t2,t3 where t2.s = t3.s;
s s
two two
drop table t1, t2, t3;
+create table t1 (a integer, b integer, index(a), index(b));
+create table t2 (c integer, d integer, index(c), index(d));
+insert into t1 values (1,2), (2,2), (3,2), (4,2);
+insert into t2 values (1,3), (2,3), (3,4), (4,4);
+explain select * from t1 left join t2 on a=c where d in (4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
+1 SIMPLE t1 ALL a NULL NULL NULL 3 Using where
+select * from t1 left join t2 on a=c where d in (4);
+a b c d
+3 2 3 4
+4 2 4 4
+explain select * from t1 left join t2 on a=c where d = 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
+1 SIMPLE t1 ALL a NULL NULL NULL 3 Using where
+select * from t1 left join t2 on a=c where d = 4;
+a b c d
+3 2 3 4
+4 2 4 4
+drop table t1, t2;
CREATE TABLE t1 (
i int(11) NOT NULL default '0',
c char(10) NOT NULL default '',
@@ -2329,7 +2354,37 @@ INSERT INTO t1 VALUES (3,'c');
EXPLAIN SELECT i FROM t1 WHERE i=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
-EXPLAIN SELECT i FROM t1 WHERE i=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
+DROP TABLE t1;
+CREATE TABLE t1 (
+K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '',
+K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000',
+F2I4 int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+INSERT INTO t1 VALUES
+('W%RT', '0100', 1),
+('W-RT', '0100', 1),
+('WART', '0100', 1),
+('WART', '0200', 1),
+('WERT', '0100', 2),
+('WORT','0200', 2),
+('WT', '0100', 2),
+('W_RT', '0100', 2),
+('WaRT', '0100', 3),
+('WART', '0300', 3),
+('WRT' , '0400', 3),
+('WURM', '0500', 3),
+('W%T', '0600', 4),
+('WA%T', '0700', 4),
+('WA_T', '0800', 4);
+SELECT K2C4, K4N4, F2I4 FROM t1
+WHERE K2C4 = 'WART' AND
+(F2I4 = 2 AND K2C4 = 'WART' OR (F2I4 = 2 OR K4N4 = '0200'));
+K2C4 K4N4 F2I4
+WART 0200 1
+SELECT K2C4, K4N4, F2I4 FROM t1
+WHERE K2C4 = 'WART' AND (K2C4 = 'WART' OR K4N4 = '0200');
+K2C4 K4N4 F2I4
+WART 0100 1
+WART 0200 1
+WART 0300 3
DROP TABLE t1;
diff --git a/mysql-test/r/select.result.es b/mysql-test/r/select.result.es
index 2ff58372d6d..86809c1aebb 100644
--- a/mysql-test/r/select.result.es
+++ b/mysql-test/r/select.result.es
@@ -1,4 +1,7 @@
drop table if exists t1,t2,t3,t4;
+drop table if exists t1_1,t1_2,t9_1,t9_2;
+drop table if exists t1_1,t1_2,t9_1,t9_2;
+drop view if exists v1;
CREATE TABLE t1 (
Period smallint(4) unsigned zerofill DEFAULT '0000' NOT NULL,
Varor_period smallint(4) unsigned DEFAULT '0' NOT NULL
@@ -2056,6 +2059,10 @@ t2 1 fld3 1 fld3 A NULL NULL NULL BTREE
drop table t4, t3, t2, t1;
DO 1;
DO benchmark(100,1+1),1,1;
+do default;
+ERROR 42000: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near '' at line 1
+do foobar;
+ERROR 42S22: Unknown column 'foobar' in 'field list'
CREATE TABLE t1 (
id mediumint(8) unsigned NOT NULL auto_increment,
pseudo varchar(35) NOT NULL default '',
@@ -2074,10 +2081,8 @@ INSERT INTO t2 VALUES (1,3,10,'2002-06-01 08:00:00',35),(1,3,1010,'2002-06-01 12
SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= 'wrong-date-value' AND b.sampletime < 'wrong-date-value' AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
gvid the_success the_fail the_size the_time
Warnings:
-Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
-Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
-Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
-Warning 1292 Truncated incorrect datetime value: 'wrong-date-value'
+Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
+Warning 1292 Incorrect datetime value: 'wrong-date-value' for column 'sampletime' at row 1
SELECT a.gvid, (SUM(CASE b.sampletid WHEN 140 THEN b.samplevalue ELSE 0 END)) as the_success,(SUM(CASE b.sampletid WHEN 141 THEN b.samplevalue ELSE 0 END)) as the_fail,(SUM(CASE b.sampletid WHEN 142 THEN b.samplevalue ELSE 0 END)) as the_size,(SUM(CASE b.sampletid WHEN 143 THEN b.samplevalue ELSE 0 END)) as the_time FROM t1 a, t2 b WHERE a.hmid = b.hmid AND a.volid = b.volid AND b.sampletime >= NULL AND b.sampletime < NULL AND b.sampletid IN (140, 141, 142, 143) GROUP BY a.gvid;
gvid the_success the_fail the_size the_time
DROP TABLE t1,t2;
@@ -2340,7 +2345,7 @@ select * from t2 where s = 'one';
s
select * from t3 where s = 'one';
s
-one
+one
select * from t1,t2 where t1.s = t2.s;
s s
two two
@@ -2348,6 +2353,27 @@ select * from t2,t3 where t2.s = t3.s;
s s
two two
drop table t1, t2, t3;
+create table t1 (a integer, b integer, index(a), index(b));
+create table t2 (c integer, d integer, index(c), index(d));
+insert into t1 values (1,2), (2,2), (3,2), (4,2);
+insert into t2 values (1,3), (2,3), (3,4), (4,4);
+explain select * from t1 left join t2 on a=c where d in (4);
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
+1 SIMPLE t1 ALL a NULL NULL NULL 3 Using where
+select * from t1 left join t2 on a=c where d in (4);
+a b c d
+3 2 3 4
+4 2 4 4
+explain select * from t1 left join t2 on a=c where d = 4;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t2 ref c,d d 5 const 2 Using where
+1 SIMPLE t1 ALL a NULL NULL NULL 3 Using where
+select * from t1 left join t2 on a=c where d = 4;
+a b c d
+3 2 3 4
+4 2 4 4
+drop table t1, t2;
CREATE TABLE t1 (
i int(11) NOT NULL default '0',
c char(10) NOT NULL default '',
@@ -2360,7 +2386,4 @@ INSERT INTO t1 VALUES (3,'c');
EXPLAIN SELECT i FROM t1 WHERE i=1;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
-EXPLAIN SELECT i FROM t1 WHERE i=1;
-id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 const PRIMARY PRIMARY 4 const 1 Using index
DROP TABLE t1;
diff --git a/mysql-test/r/select_found.result b/mysql-test/r/select_found.result
index 00dbcb54d93..5a2f26a7105 100644
--- a/mysql-test/r/select_found.result
+++ b/mysql-test/r/select_found.result
@@ -84,7 +84,7 @@ UNIQUE KEY e_n (email,name)
EXPLAIN SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
id select_type table type possible_keys key key_len ref rows Extra
1 SIMPLE t1 system PRIMARY,kid NULL NULL NULL 0 const row not found
-1 SIMPLE t2 index NULL e_n 100 NULL 200
+1 SIMPLE t2 index NULL e_n 104 NULL 200
SELECT SQL_CALC_FOUND_ROWS DISTINCT email FROM t2 LEFT JOIN t1 ON kid = t2.id WHERE t1.id IS NULL LIMIT 10;
email
email1
diff --git a/mysql-test/r/show_check.result b/mysql-test/r/show_check.result
index be4b9622983..931fb8b20b9 100644
--- a/mysql-test/r/show_check.result
+++ b/mysql-test/r/show_check.result
@@ -154,7 +154,7 @@ show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
`a` int(11) NOT NULL,
- `b` char(10) default NULL,
+ `b` varchar(10) default NULL,
KEY `b` (`b`)
) ENGINE=MyISAM DEFAULT CHARSET=latin1 MIN_ROWS=10 MAX_ROWS=100 AVG_ROW_LENGTH=10 PACK_KEYS=1 CHECKSUM=1 DELAY_KEY_WRITE=1 ROW_FORMAT=FIXED COMMENT='test'
alter table t1 MAX_ROWS=200 ROW_FORMAT=dynamic PACK_KEYS=0;
diff --git a/mysql-test/r/sp-error.result b/mysql-test/r/sp-error.result
index 9bea0fe0d4c..642f1aedd78 100644
--- a/mysql-test/r/sp-error.result
+++ b/mysql-test/r/sp-error.result
@@ -460,4 +460,17 @@ end|
call bug3294()|
ERROR 42S02: Unknown table 't5'
drop procedure bug3294|
+drop procedure if exists bug6807|
+create procedure bug6807()
+begin
+declare id int;
+set id = connection_id();
+kill query id;
+select 'Not reached';
+end|
+call bug6807()|
+ERROR 70100: Query execution was interrupted
+call bug6807()|
+ERROR 70100: Query execution was interrupted
+drop procedure bug6807|
drop table t1|
diff --git a/mysql-test/r/sp-security.result b/mysql-test/r/sp-security.result
index 23804e62ef5..25582796812 100644
--- a/mysql-test/r/sp-security.result
+++ b/mysql-test/r/sp-security.result
@@ -30,7 +30,7 @@ db1_secret
select * from db1_secret.t1;
ERROR 42000: Access denied for user 'user1'@'localhost' to database 'db1_secret'
create procedure db1_secret.dummy() begin end;
-ERROR 42000: Unknown database 'db1_secret'
+ERROR 42000: Access denied for user 'user1'@'localhost' to database 'db1_secret'
drop procedure db1_secret.dummy;
ERROR 42000: PROCEDURE db1_secret.dummy does not exist
call db1_secret.stamp(3);
@@ -40,7 +40,7 @@ db1_secret
select * from db1_secret.t1;
ERROR 42000: Access denied for user ''@'localhost' to database 'db1_secret'
create procedure db1_secret.dummy() begin end;
-ERROR 42000: Unknown database 'db1_secret'
+ERROR 42000: Access denied for user ''@'localhost' to database 'db1_secret'
drop procedure db1_secret.dummy;
ERROR 42000: PROCEDURE db1_secret.dummy does not exist
select * from t1;
diff --git a/mysql-test/r/sp.result b/mysql-test/r/sp.result
index bcabf693e4c..8745a274851 100644
--- a/mysql-test/r/sp.result
+++ b/mysql-test/r/sp.result
@@ -1746,10 +1746,20 @@ drop table if exists t3|
create procedure bug4904()
begin
declare continue handler for sqlstate 'HY000' begin end;
-create table t2 as select * from t;
+create table t2 as select * from t3;
end|
call bug4904()|
+ERROR 42S02: Table 'test.t3' doesn't exist
drop procedure bug4904|
+create table t3 (s1 char character set latin1, s2 char character set latin2)|
+create procedure bug4904 ()
+begin
+declare continue handler for sqlstate 'HY000' begin end;
+select s1 from t3 union select s2 from t3;
+end|
+call bug4904()|
+drop procedure bug4904|
+drop table t3|
create procedure bug336(out y int)
begin
declare x int;
diff --git a/mysql-test/r/sql_mode.result b/mysql-test/r/sql_mode.result
index a892967ac79..fea99086303 100644
--- a/mysql-test/r/sql_mode.result
+++ b/mysql-test/r/sql_mode.result
@@ -61,7 +61,7 @@ t1 CREATE TABLE `t1` (
set @@sql_mode="no_field_options,mysql323,mysql40";
show variables like 'sql_mode';
Variable_name Value
-sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40
+sql_mode NO_FIELD_OPTIONS,MYSQL323,MYSQL40,HIGH_NOT_PRECEDENCE
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
@@ -85,6 +85,36 @@ t1 CREATE TABLE "t1" (
UNIQUE KEY "email" ("email")
)
drop table t1;
+CREATE TABLE t1 (
+a char(10),
+b char(10) collate latin1_bin,
+c binary(10)
+) character set latin1;
+set @@sql_mode="";
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) default NULL,
+ `b` char(10) character set latin1 collate latin1_bin default NULL,
+ `c` binary(10) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+set @@sql_mode="mysql323";
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) default NULL,
+ `b` char(10) binary default NULL,
+ `c` binary(10) default NULL
+) TYPE=MyISAM
+set @@sql_mode="mysql40";
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` char(10) default NULL,
+ `b` char(10) binary default NULL,
+ `c` binary(10) default NULL
+) TYPE=MyISAM
+drop table t1;
set session sql_mode = '';
create table t1 ( min_num dec(6,6) default .000001);
show create table t1;
diff --git a/mysql-test/r/strict.result b/mysql-test/r/strict.result
index 19c4def9b32..4da0f1e48f1 100644
--- a/mysql-test/r/strict.result
+++ b/mysql-test/r/strict.result
@@ -531,6 +531,7 @@ Warning 1264 Out of range value adjusted for column 'col1' at row 1
Warning 1264 Out of range value adjusted for column 'col2' at row 1
Warning 1264 Out of range value adjusted for column 'col1' at row 2
Warning 1264 Out of range value adjusted for column 'col2' at row 2
+Warning 1264 Out of range value adjusted for column 'col2' at row 2
UPDATE IGNORE t1 SET col2=1/NULL where col1=0;
SELECT * FROM t1;
col1 col2
@@ -616,7 +617,7 @@ col1 col2
-9223372036854775808 0
9223372036854775807 18446744073709551615
-9223372036854773760 0
--9223372036854775808 1844674407370953984
+9223372036854775807 1844674407370953984
-9223372036854775808 NULL
-9223372036854775808 NULL
NULL 18446744073709551615
@@ -713,8 +714,8 @@ NULL
-99.99
DROP TABLE t1;
CREATE TABLE t1 (col1 FLOAT, col2 FLOAT UNSIGNED);
-INSERT INTO t1 VALUES (-1.1E-38,0),(+3.4E+38,+3.4E+38);
-INSERT INTO t1 VALUES ('-1.1E-38',0),('+3.4E+38','+3.4E+38');
+INSERT INTO t1 VALUES (-1.1E-37,0),(+3.4E+38,+3.4E+38);
+INSERT INTO t1 VALUES ('-1.1E-37',0),('+3.4E+38','+3.4E+38');
INSERT INTO t1 (col1) VALUES (3E-46);
INSERT INTO t1 (col1) VALUES (+3.4E+39);
ERROR 22003: Out of range value adjusted for column 'col1' at row 1
@@ -752,9 +753,9 @@ Warning 1264 Out of range value adjusted for column 'col1' at row 1
Warning 1264 Out of range value adjusted for column 'col2' at row 1
SELECT * FROM t1;
col1 col2
--1.1e-38 0
+-1.1e-37 0
3.4e+38 3.4e+38
--1.1e-38 0
+-1.1e-37 0
3.4e+38 3.4e+38
0 NULL
2 NULL
@@ -763,8 +764,8 @@ NULL NULL
3.40282e+38 0
DROP TABLE t1;
CREATE TABLE t1 (col1 DOUBLE PRECISION, col2 DOUBLE PRECISION UNSIGNED);
-INSERT INTO t1 VALUES (-2.2E-308,0),(+1.7E+308,+1.7E+308);
-INSERT INTO t1 VALUES ('-2.2E-308',0),('+1.7E+308','+1.7E+308');
+INSERT INTO t1 VALUES (-2.2E-307,0),(+1.7E+308,+1.7E+308);
+INSERT INTO t1 VALUES ('-2.2E-307',0),('+1.7E+308','+1.7E+308');
INSERT INTO t1 (col1) VALUES (-2.2E-330);
INSERT INTO t1 (col1) VALUES (+1.7E+309);
ERROR 22007: Illegal double '1.7E+309' value found during parsing
@@ -801,21 +802,23 @@ Warning 1264 Out of range value adjusted for column 'col2' at row 1
Warning 1264 Out of range value adjusted for column 'col2' at row 1
SELECT * FROM t1;
col1 col2
--2.2e-308 0
+-2.2e-307 0
1.7e+308 1.7e+308
--2.2e-308 0
+-2.2e-307 0
1.7e+308 1.7e+308
0 NULL
2 NULL
NULL NULL
1.79769313486232e+308 0
DROP TABLE t1;
-CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(5));
-INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
+CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
+INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
INSERT INTO t1 (col1) VALUES ('hellobob');
ERROR 01000: Data truncated for column 'col1' at row 1
INSERT INTO t1 (col2) VALUES ('hellobob');
ERROR 01000: Data truncated for column 'col2' at row 1
+INSERT INTO t1 (col2) VALUES ('hello ');
+ERROR 01000: Data truncated for column 'col2' at row 1
UPDATE t1 SET col1 ='hellobob' WHERE col1 ='he';
ERROR 01000: Data truncated for column 'col1' at row 2
UPDATE t1 SET col2 ='hellobob' WHERE col2 ='he';
@@ -830,9 +833,9 @@ Warning 1265 Data truncated for column 'col2' at row 2
SELECT * FROM t1;
col1 col2
hello hello
-he hello
-hello hello
-hello hello
+he hellot
+hello hello
+hello hellob
DROP TABLE t1;
CREATE TABLE t1 (col1 enum('red','blue','green'));
INSERT INTO t1 VALUES ('red'),('blue'),('green');
diff --git a/mysql-test/r/subselect.result b/mysql-test/r/subselect.result
index ceb8919b26a..931f3c3d71b 100644
--- a/mysql-test/r/subselect.result
+++ b/mysql-test/r/subselect.result
@@ -361,10 +361,10 @@ INSERT INTO t8 (pseudo,email) VALUES ('joce1','test1');
INSERT INTO t8 (pseudo,email) VALUES ('2joce1','2test1');
EXPLAIN EXTENDED SELECT pseudo,(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce')) FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce');
id select_type table type possible_keys key key_len ref rows Extra
-1 PRIMARY t8 const PRIMARY PRIMARY 35 const 1 Using index
-4 SUBQUERY t8 const PRIMARY PRIMARY 35 1 Using index
-2 SUBQUERY t8 const PRIMARY PRIMARY 35 const 1
-3 SUBQUERY t8 const PRIMARY PRIMARY 35 1 Using index
+1 PRIMARY t8 ref PRIMARY PRIMARY 37 const 1 Using where; Using index
+4 SUBQUERY t8 ref PRIMARY PRIMARY 37 1 Using where; Using index
+2 SUBQUERY t8 ref PRIMARY PRIMARY 37 const 1 Using where
+3 SUBQUERY t8 ref PRIMARY PRIMARY 37 1 Using where; Using index
Warnings:
Note 1003 select `test`.`t8`.`pseudo` AS `pseudo`,(select `test`.`t8`.`email` AS `email` from `test`.`t8` where (`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo` from `test`.`t8` where (`test`.`t8`.`pseudo` = _latin1'joce')))) AS `(SELECT email FROM t8 WHERE pseudo=(SELECT pseudo FROM t8 WHERE pseudo='joce'))` from `test`.`t8` where (`test`.`t8`.`pseudo` = (select `test`.`t8`.`pseudo` AS `pseudo` from `test`.`t8` where (`test`.`t8`.`pseudo` = _latin1'joce')))
SELECT pseudo FROM t8 WHERE pseudo=(SELECT pseudo,email FROM
@@ -390,13 +390,13 @@ INSERT INTO t1 (topic,date,pseudo) VALUES
('43506','2002-10-02','joce'),('40143','2002-08-03','joce');
EXPLAIN EXTENDED SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
id select_type table type possible_keys key key_len ref rows Extra
-1 SIMPLE t1 index NULL PRIMARY 41 NULL 2 Using where; Using index
+1 SIMPLE t1 index NULL PRIMARY 43 NULL 2 Using where; Using index
Warnings:
Note 1003 select distinct `test`.`t1`.`date` AS `date` from `test`.`t1` where (`test`.`t1`.`date` = 20020803)
EXPLAIN EXTENDED SELECT (SELECT DISTINCT date FROM t1 WHERE date='2002-08-03');
id select_type table type possible_keys key key_len ref rows Extra
1 PRIMARY NULL NULL NULL NULL NULL NULL NULL No tables used
-2 SUBQUERY t1 index NULL PRIMARY 41 NULL 2 Using where; Using index
+2 SUBQUERY t1 index NULL PRIMARY 43 NULL 2 Using where; Using index
Warnings:
Note 1003 select (select distinct `test`.`t1`.`date` AS `date` from `test`.`t1` where (`test`.`t1`.`date` = 20020803)) AS `(SELECT DISTINCT date FROM t1 WHERE date='2002-08-03')`
SELECT DISTINCT date FROM t1 WHERE date='2002-08-03';
@@ -1998,3 +1998,44 @@ ac
700
NULL
drop tables t1,t2;
+create table t1 (a int not null, b int not null, c int, primary key (a,b));
+insert into t1 values (1,1,1), (2,2,2), (3,3,3);
+set @b:= 0;
+explain select sum(a) from t1 where b > @b;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 index NULL PRIMARY 8 NULL 3 Using where; Using index
+set @a:= (select sum(a) from t1 where b > @b);
+explain select a from t1 where c=2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+do @a:= (select sum(a) from t1 where b > @b);
+explain select a from t1 where c=2;
+id select_type table type possible_keys key key_len ref rows Extra
+1 SIMPLE t1 ALL NULL NULL NULL NULL 3 Using where
+drop table t1;
+set @got_val= (SELECT 1 FROM (SELECT 'A' as my_col) as T1 ) ;
+create table t1 (a int, b int);
+create table t2 (a int, b int);
+insert into t1 values (1,1),(1,2),(1,3),(2,4),(2,5);
+insert into t2 values (1,3),(2,1);
+select distinct a,b, (select max(b) from t2 where t1.b=t2.a) from t1 order by t1.b;
+a b (select max(b) from t2 where t1.b=t2.a)
+1 1 3
+1 2 1
+1 3 NULL
+2 4 NULL
+2 5 NULL
+drop table t1, t2;
+create table t1 (id int);
+create table t2 (id int, body text, fulltext (body));
+insert into t1 values(1),(2),(3);
+insert into t2 values (1,'test'), (2,'mysql'), (3,'test'), (4,'test');
+select count(distinct id) from t1 where id in (select id from t2 where match(body) against ('mysql' in boolean mode));
+count(distinct id)
+1
+drop table t2,t1;
+create table t1 (s1 int,s2 int);
+insert into t1 values (20,15);
+select * from t1 where (('a',null) <=> (select 'a',s2 from t1 where s1 = 0));
+s1 s2
+drop table t1;
diff --git a/mysql-test/r/subselect_innodb.result b/mysql-test/r/subselect_innodb.result
index e8f6426f51b..0b813a07a1d 100644
--- a/mysql-test/r/subselect_innodb.result
+++ b/mysql-test/r/subselect_innodb.result
@@ -114,3 +114,29 @@ SELECT R.unit, R.ingredient FROM t1 R WHERE R.ingredient IN (SELECT N.ingredient
unit ingredient
xx yy
drop table t1, t2;
+CREATE TABLE t1 (
+id INT NOT NULL auto_increment,
+date1 DATE, coworkerid INT,
+description VARCHAR(255),
+sum_used DOUBLE,
+sum_remaining DOUBLE,
+comments VARCHAR(255),
+PRIMARY KEY(id)
+) engine=innodb;
+insert into t1 values (NULL, '1999-01-01', 1,'test', 22, 33, 'comment'), (NULL, '1999-01-01', 1,'test', 22, 33, 'comment'), (NULL, '1999-01-01', 1,'test', 22, 33, 'comment'), (NULL, '1998-01-01', 1,'test', 22, 33, 'comment'), (NULL, '1998-01-01', 1,'test', 22, 33, 'comment'), (NULL, '2004-01-01', 1,'test', 22, 33, 'comment'), (NULL, '2004-01-01', 1,'test', 22, 33, 'comment');
+SELECT DISTINCT
+(SELECT sum(sum_used) FROM t1 WHERE sum_used > 0 AND year(date1) <= '2004') as somallontvangsten,
+(SELECT sum(sum_used) FROM t1 WHERE sum_used < 0 AND year(date1) <= '2004') as somalluitgaven
+FROM t1;
+somallontvangsten somalluitgaven
+154 NULL
+select * from t1;
+id date1 coworkerid description sum_used sum_remaining comments
+1 1999-01-01 1 test 22 33 comment
+2 1999-01-01 1 test 22 33 comment
+3 1999-01-01 1 test 22 33 comment
+4 1998-01-01 1 test 22 33 comment
+5 1998-01-01 1 test 22 33 comment
+6 2004-01-01 1 test 22 33 comment
+7 2004-01-01 1 test 22 33 comment
+drop table t1;
diff --git a/mysql-test/r/system_mysql_db.result b/mysql-test/r/system_mysql_db.result
index 35d7a78ab56..400b508ff50 100644
--- a/mysql-test/r/system_mysql_db.result
+++ b/mysql-test/r/system_mysql_db.result
@@ -63,9 +63,9 @@ host CREATE TABLE `host` (
show create table user;
Table Create Table
user CREATE TABLE `user` (
- `Host` varchar(60) collate utf8_bin NOT NULL default '',
- `User` varchar(16) collate utf8_bin NOT NULL default '',
- `Password` varchar(41) collate utf8_bin NOT NULL default '',
+ `Host` char(60) collate utf8_bin NOT NULL default '',
+ `User` char(16) collate utf8_bin NOT NULL default '',
+ `Password` char(41) collate utf8_bin NOT NULL default '',
`Select_priv` enum('N','Y') collate utf8_bin NOT NULL default 'N',
`Insert_priv` enum('N','Y') collate utf8_bin NOT NULL default 'N',
`Update_priv` enum('N','Y') collate utf8_bin NOT NULL default 'N',
diff --git a/mysql-test/r/timezone3.result b/mysql-test/r/timezone3.result
new file mode 100644
index 00000000000..ec0b6045f93
--- /dev/null
+++ b/mysql-test/r/timezone3.result
@@ -0,0 +1,41 @@
+drop table if exists t1;
+create table t1 (i int, c varchar(20));
+insert into t1 values
+(unix_timestamp("2004-01-01 00:00:00"), "2004-01-01 00:00:00");
+insert into t1 values
+(unix_timestamp("2004-03-28 01:59:59"), "2004-03-28 01:59:59"),
+(unix_timestamp("2004-03-28 02:30:00"), "2004-03-28 02:30:00"),
+(unix_timestamp("2004-03-28 03:00:00"), "2004-03-28 03:00:00");
+insert into t1 values
+(unix_timestamp('2004-05-01 00:00:00'),'2004-05-01 00:00:00');
+insert into t1 values
+(unix_timestamp('2004-10-31 01:00:00'),'2004-10-31 01:00:00'),
+(unix_timestamp('2004-10-31 02:00:00'),'2004-10-31 02:00:00'),
+(unix_timestamp('2004-10-31 02:59:59'),'2004-10-31 02:59:59'),
+(unix_timestamp('2004-10-31 04:00:00'),'2004-10-31 04:00:00'),
+(unix_timestamp('2004-10-31 02:59:59'),'2004-10-31 02:59:59');
+insert into t1 values
+(unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'),
+(unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00');
+select i, from_unixtime(i), c from t1;
+i from_unixtime(i) c
+1072904422 2004-01-01 00:00:00 2004-01-01 00:00:00
+1080428421 2004-03-28 01:59:59 2004-03-28 01:59:59
+1080428422 2004-03-28 03:00:00 2004-03-28 02:30:00
+1080428422 2004-03-28 03:00:00 2004-03-28 03:00:00
+1083355222 2004-05-01 00:00:00 2004-05-01 00:00:00
+1099170022 2004-10-31 01:00:00 2004-10-31 01:00:00
+1099177222 2004-10-31 02:00:00 2004-10-31 02:00:00
+1099180821 2004-10-31 02:59:59 2004-10-31 02:59:59
+1099184422 2004-10-31 04:00:00 2004-10-31 04:00:00
+1099180821 2004-10-31 02:59:59 2004-10-31 02:59:59
+362793608 1981-07-01 03:59:59 1981-07-01 03:59:59
+362793610 1981-07-01 04:00:00 1981-07-01 04:00:00
+drop table t1;
+create table t1 (ts timestamp);
+insert into t1 values (19730101235900), (20040101235900);
+select * from t1;
+ts
+1973-01-01 23:59:00
+2004-01-01 23:59:00
+drop table t1;
diff --git a/mysql-test/r/trigger.result b/mysql-test/r/trigger.result
index 2a2e10dbbd5..4a85097cfce 100644
--- a/mysql-test/r/trigger.result
+++ b/mysql-test/r/trigger.result
@@ -150,6 +150,10 @@ create trigger trg before delete on t1 for each row set new.i:=1;
ERROR HY000: There is no NEW row in on DELETE trigger
create trigger trg after update on t1 for each row set new.i:=1;
ERROR HY000: Updating of NEW row is not allowed in after trigger
+create trigger trg before update on t1 for each row set new.j:=1;
+ERROR 42S22: Unknown column 'j' in 'NEW'
+create trigger trg before update on t1 for each row set @a:=old.j;
+ERROR 42S22: Unknown column 'j' in 'OLD'
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;
@@ -174,3 +178,15 @@ create trigger tx1 before insert on t1 for each row set new.x1col = 'x';
insert into t1 values ('y');
drop trigger t1.tx1;
drop table t1;
+create table t1 (i int) engine=myisam;
+insert into t1 values (1), (2);
+create trigger trg1 before delete on t1 for each row set @del_before:= @del_before + old.i;
+create trigger trg2 after delete on t1 for each row set @del_after:= @del_after + old.i;
+set @del_before:=0, @del_after:= 0;
+delete from t1;
+select @del_before, @del_after;
+@del_before @del_after
+3 3
+drop trigger t1.trg1;
+drop trigger t1.trg2;
+drop table t1;
diff --git a/mysql-test/r/type_blob.result b/mysql-test/r/type_blob.result
index 2f564112e40..7b9a94ba998 100644
--- a/mysql-test/r/type_blob.result
+++ b/mysql-test/r/type_blob.result
@@ -4,17 +4,19 @@ show columns from t1;
Field Type Null Key Default Extra
a blob YES NULL
b text YES NULL
-c blob YES NULL
+c tinyblob YES NULL
d mediumtext YES NULL
e longtext YES NULL
-CREATE TABLE t2 (a char(257), b varbinary(70000), c varchar(70000000));
+CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000));
Warnings:
-Note 1246 Converting column 'a' from CHAR to TEXT
-Note 1246 Converting column 'b' from CHAR to BLOB
-Note 1246 Converting column 'c' from CHAR to TEXT
+Note 1246 Converting column 'b' from VARCHAR to BLOB
+Note 1246 Converting column 'c' from VARCHAR to TEXT
+CREATE TABLE t4 (c varchar(65530) character set utf8 not null);
+Warnings:
+Note 1246 Converting column 'c' from VARCHAR to TEXT
show columns from t2;
Field Type Null Key Default Extra
-a text YES NULL
+a char(255) YES NULL
b mediumblob YES NULL
c longtext YES NULL
create table t3 (a long, b long byte);
@@ -24,10 +26,18 @@ t3 CREATE TABLE `t3` (
`a` mediumtext,
`b` mediumblob
) ENGINE=MyISAM DEFAULT CHARSET=latin1
-drop table t1,t2,t3
-#;
+show create TABLE t4;
+Table Create Table
+t4 CREATE TABLE `t4` (
+ `c` mediumtext character set utf8 NOT NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1,t2,t3,t4;
CREATE TABLE t1 (a char(257) default "hello");
ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB instead
+CREATE TABLE t2 (a char(256));
+ERROR 42000: Column length too big for column 'a' (max = 255); use BLOB instead
+CREATE TABLE t1 (a varchar(70000) default "hello");
+ERROR 42000: Column length too big for column 'a' (max = 65535); use BLOB instead
CREATE TABLE t2 (a blob default "hello");
ERROR 42000: BLOB/TEXT column 'a' can't have a default value
drop table if exists t1,t2;
@@ -71,16 +81,16 @@ lock tables t1 READ;
show full fields from t1;
Field Type Collation Null Key Default Extra Privileges Comment
t text latin1_swedish_ci YES NULL select,insert,update,references
-c varchar(10) latin1_swedish_ci YES NULL select,insert,update,references
+c char(10) latin1_swedish_ci YES NULL select,insert,update,references
b blob NULL YES NULL select,insert,update,references
-d varbinary(10) NULL YES NULL select,insert,update,references
+d binary(10) NULL YES NULL select,insert,update,references
lock tables t1 WRITE;
show full fields from t1;
Field Type Collation Null Key Default Extra Privileges Comment
t text latin1_swedish_ci YES NULL select,insert,update,references
-c varchar(10) latin1_swedish_ci YES NULL select,insert,update,references
+c char(10) latin1_swedish_ci YES NULL select,insert,update,references
b blob NULL YES NULL select,insert,update,references
-d varbinary(10) NULL YES NULL select,insert,update,references
+d binary(10) NULL YES NULL select,insert,update,references
unlock tables;
select t from t1 where t like "hello";
t
@@ -520,6 +530,11 @@ load_file('../../std_data/words.dat') longblob NULL YES NULL select,insert,upd
drop table t1;
create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy ');
+ERROR 23000: Duplicate entry 'Chevy ' for key 2
+insert into t1 (txt) values ('Chevy'), ('CHEVY');
+ERROR 23000: Duplicate entry 'Chevy' for key 2
+alter table t1 drop index txt_index, add index txt_index (txt(20));
+insert into t1 (txt) values ('Chevy ');
select * from t1 where txt='Chevy';
id txt
1 Chevy
@@ -589,7 +604,7 @@ id txt
2 Chevy
3 Ford
drop table t1;
-create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20)));
+create table t1 (id integer primary key auto_increment, txt text, index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL;
id txt
@@ -682,8 +697,8 @@ id txt
3 NULL
1 Chevy
drop table t1;
-CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, PRIMARY KEY (i), KEY (c(1),c(1)));
-INSERT t1 VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
+CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, d varchar(1) NOT NULL DEFAULT ' ', PRIMARY KEY (i), KEY (c(1),d));
+INSERT t1 (i, c) VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
select max(i) from t1 where c = '';
max(i)
4
diff --git a/mysql-test/r/type_blob.result.es b/mysql-test/r/type_blob.result.es
index 84d02b4a4b4..a510eee8f38 100644
--- a/mysql-test/r/type_blob.result.es
+++ b/mysql-test/r/type_blob.result.es
@@ -684,8 +684,8 @@ id txt
3 NULL
1 Chevy
drop table t1;
-CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, PRIMARY KEY (i), KEY (c(1),c(1)));
-INSERT t1 VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
+CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, d varchar(1) NOT NULL DEFAULT ' ', PRIMARY KEY (i), KEY (c(1),d));
+INSERT t1 (i, c) VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
select max(i) from t1 where c = '';
max(i)
4
diff --git a/mysql-test/r/type_datetime.result b/mysql-test/r/type_datetime.result
index bbfd3da9d11..586f74bee20 100644
--- a/mysql-test/r/type_datetime.result
+++ b/mysql-test/r/type_datetime.result
@@ -97,13 +97,15 @@ select * from t1 where a is null or b is null;
a b
drop table t1;
create table t1 (t datetime);
-insert into t1 values (20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460);
+insert into t1 values (20030102030460),(20030102036301),(20030102240401),
+(20030132030401),(20031302030401),(100001202030401);
Warnings:
Warning 1265 Data truncated for column 't' at row 1
Warning 1265 Data truncated for column 't' at row 2
Warning 1265 Data truncated for column 't' at row 3
Warning 1265 Data truncated for column 't' at row 4
Warning 1265 Data truncated for column 't' at row 5
+Warning 1265 Data truncated for column 't' at row 6
select * from t1;
t
0000-00-00 00:00:00
@@ -111,14 +113,18 @@ t
0000-00-00 00:00:00
0000-00-00 00:00:00
0000-00-00 00:00:00
+0000-00-00 00:00:00
delete from t1;
-insert into t1 values ("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460");
+insert into t1 values
+("2003-01-02 03:04:60"),("2003-01-02 03:63:01"),("2003-01-02 24:04:01"),
+("2003-01-32 03:04:01"),("2003-13-02 03:04:01"), ("10000-12-02 03:04:00");
Warnings:
Warning 1264 Out of range value adjusted for column 't' at row 1
Warning 1264 Out of range value adjusted for column 't' at row 2
Warning 1264 Out of range value adjusted for column 't' at row 3
Warning 1264 Out of range value adjusted for column 't' at row 4
Warning 1264 Out of range value adjusted for column 't' at row 5
+Warning 1264 Out of range value adjusted for column 't' at row 6
select * from t1;
t
0000-00-00 00:00:00
@@ -126,6 +132,7 @@ t
0000-00-00 00:00:00
0000-00-00 00:00:00
0000-00-00 00:00:00
+0000-00-00 00:00:00
delete from t1;
insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer");
Warnings:
diff --git a/mysql-test/r/type_enum.result b/mysql-test/r/type_enum.result
index da85ffe6495..2ccf32367fb 100644
--- a/mysql-test/r/type_enum.result
+++ b/mysql-test/r/type_enum.result
@@ -1693,3 +1693,47 @@ oe
ue
ss
DROP TABLE t1;
+CREATE TABLE t1 (
+a ENUM('ä','ö','ü') character set utf8 default 'ü'
+);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` enum('ä','ö','ü') character set utf8 default 'ü'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('ä'), ('ö'), ('ü');
+select a from t1 order by a;
+a
+drop table t1;
+set names utf8;
+CREATE TABLE t1 (
+a ENUM('ä','ö','ü') character set latin1 default 'ü'
+);
+insert into t1 values ('ä'),('ö'),('ü');
+set names latin1;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` enum('ä','ö','ü') default 'ü'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select a from t1 order by a;
+a
+drop table t1;
+create table t1 (a enum ('Y','N') CHARACTER SET utf8 COLLATE utf8_bin);
+insert into t1 values ('Y');
+alter table t1 add b set ('Y','N') CHARACTER SET utf8 COLLATE utf8_bin;
+alter table t1 add c enum ('Y','N') CHARACTER SET utf8 COLLATE utf8_bin;
+select * from t1;
+Catalog Database Table Table_alias Column Column_alias Name Type Length Max length Is_null Flags Decimals Charsetnr
+def test t1 t1 a a 254 3 1 Y 384 0 8
+def test t1 t1 b b 254 9 0 Y 2176 0 8
+def test t1 t1 c c 254 3 0 Y 384 0 8
+a b c
+Y NULL NULL
+drop table t1;
diff --git a/mysql-test/r/type_float.result b/mysql-test/r/type_float.result
index 159a6c466de..151ec404455 100644
--- a/mysql-test/r/type_float.result
+++ b/mysql-test/r/type_float.result
@@ -22,14 +22,14 @@ select * from t1;
f1 f2
10 10
100000 100000
-1.23457e+09 1234567890
+1.23457e+9 1234567890
1e+10 10000000000
1e+15 1e+15
1e+20 1e+20
3.40282e+38 1e+50
3.40282e+38 1e+150
-10 -10
-1e-05 1e-05
+1e-5 1e-5
1e-10 1e-10
1e-15 1e-15
1e-20 1e-20
diff --git a/mysql-test/r/type_float.result.es b/mysql-test/r/type_float.result.es
index 411817bbfef..4bfe644d7fb 100644
--- a/mysql-test/r/type_float.result.es
+++ b/mysql-test/r/type_float.result.es
@@ -22,14 +22,14 @@ select * from t1;
f1 f2
10 10
100000 100000
-1.23457e+09 1234567890
+1.23457e+9 1234567890
1e+10 10000000000
1e+15 1e+15
1e+20 1e+20
3.40282e+38 1e+50
3.40282e+38 1e+150
-10 -10
-1e-05 1e-05
+1e-5 1e-5
1e-10 1e-10
1e-15 1e-15
1e-20 1e-20
@@ -137,6 +137,8 @@ t1 CREATE TABLE `t1` (
drop table t1;
create table t1 (c20 char);
insert into t1 values (5000.0);
+Warnings:
+Warning 1265 Data truncated for column 'c20' at row 1
drop table t1;
create table t1 (f float(54));
ERROR 42000: Incorrect column specifier for column 'f'
diff --git a/mysql-test/r/type_ranges.result b/mysql-test/r/type_ranges.result
index f08a160be3b..4f2d2d7b54c 100644
--- a/mysql-test/r/type_ranges.result
+++ b/mysql-test/r/type_ranges.result
@@ -41,7 +41,7 @@ KEY (options,flags)
show full fields from t1;
Field Type Collation Null Key Default Extra Privileges Comment
auto int(5) unsigned NULL PRI NULL auto_increment select,insert,update,references
-string varchar(10) latin1_swedish_ci YES hello select,insert,update,references
+string char(10) latin1_swedish_ci YES hello select,insert,update,references
tiny tinyint(4) NULL MUL 0 select,insert,update,references
short smallint(6) NULL MUL 1 select,insert,update,references
medium mediumint(8) NULL MUL 0 select,insert,update,references
@@ -209,7 +209,7 @@ update t2 set string="changed" where auto=16;
show full columns from t1;
Field Type Collation Null Key Default Extra Privileges Comment
auto int(5) unsigned NULL MUL NULL auto_increment select,insert,update,references
-string varchar(10) latin1_swedish_ci YES new defaul select,insert,update,references
+string char(10) latin1_swedish_ci YES new defaul select,insert,update,references
tiny tinyint(4) NULL MUL 0 select,insert,update,references
short smallint(6) NULL MUL 0 select,insert,update,references
medium mediumint(8) NULL MUL 0 select,insert,update,references
@@ -223,7 +223,7 @@ umedium mediumint(8) unsigned NULL MUL 0 select,insert,update,references
ulong int(11) unsigned NULL MUL 0 select,insert,update,references
ulonglong bigint(13) unsigned NULL MUL 0 select,insert,update,references
time_stamp timestamp NULL YES CURRENT_TIMESTAMP select,insert,update,references
-date_field varchar(10) latin1_swedish_ci YES NULL select,insert,update,references
+date_field char(10) latin1_swedish_ci YES NULL select,insert,update,references
time_field time NULL YES NULL select,insert,update,references
date_time datetime NULL YES NULL select,insert,update,references
new_blob_col varchar(20) latin1_swedish_ci YES NULL select,insert,update,references
@@ -231,11 +231,11 @@ tinyblob_col tinyblob NULL YES NULL select,insert,update,references
mediumblob_col mediumblob NULL select,insert,update,references
options enum('one','two','tree') latin1_swedish_ci MUL one select,insert,update,references
flags set('one','two','tree') latin1_swedish_ci select,insert,update,references
-new_field varchar(10) latin1_swedish_ci new select,insert,update,references
+new_field char(10) latin1_swedish_ci new select,insert,update,references
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
auto int(5) unsigned NULL 0 select,insert,update,references
-string varchar(10) latin1_swedish_ci YES new defaul select,insert,update,references
+string char(10) latin1_swedish_ci YES new defaul select,insert,update,references
tiny tinyint(4) NULL 0 select,insert,update,references
short smallint(6) NULL 0 select,insert,update,references
medium mediumint(8) NULL 0 select,insert,update,references
@@ -249,7 +249,7 @@ umedium mediumint(8) unsigned NULL 0 select,insert,update,references
ulong int(11) unsigned NULL 0 select,insert,update,references
ulonglong bigint(13) unsigned NULL 0 select,insert,update,references
time_stamp timestamp NULL YES 0000-00-00 00:00:00 select,insert,update,references
-date_field varchar(10) latin1_swedish_ci YES NULL select,insert,update,references
+date_field char(10) latin1_swedish_ci YES NULL select,insert,update,references
time_field time NULL YES NULL select,insert,update,references
date_time datetime NULL YES NULL select,insert,update,references
new_blob_col varchar(20) latin1_swedish_ci YES NULL select,insert,update,references
@@ -257,7 +257,7 @@ tinyblob_col tinyblob NULL YES NULL select,insert,update,references
mediumblob_col mediumblob NULL select,insert,update,references
options enum('one','two','tree') latin1_swedish_ci one select,insert,update,references
flags set('one','two','tree') latin1_swedish_ci select,insert,update,references
-new_field varchar(10) latin1_swedish_ci new select,insert,update,references
+new_field char(10) latin1_swedish_ci new select,insert,update,references
select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and ((t1.string<>t2.string and (t1.string is not null or t2.string is not null)) or (t1.tiny<>t2.tiny and (t1.tiny is not null or t2.tiny is not null)) or (t1.short<>t2.short and (t1.short is not null or t2.short is not null)) or (t1.medium<>t2.medium and (t1.medium is not null or t2.medium is not null)) or (t1.long_int<>t2.long_int and (t1.long_int is not null or t2.long_int is not null)) or (t1.longlong<>t2.longlong and (t1.longlong is not null or t2.longlong is not null)) or (t1.real_float<>t2.real_float and (t1.real_float is not null or t2.real_float is not null)) or (t1.real_double<>t2.real_double and (t1.real_double is not null or t2.real_double is not null)) or (t1.utiny<>t2.utiny and (t1.utiny is not null or t2.utiny is not null)) or (t1.ushort<>t2.ushort and (t1.ushort is not null or t2.ushort is not null)) or (t1.umedium<>t2.umedium and (t1.umedium is not null or t2.umedium is not null)) or (t1.ulong<>t2.ulong and (t1.ulong is not null or t2.ulong is not null)) or (t1.ulonglong<>t2.ulonglong and (t1.ulonglong is not null or t2.ulonglong is not null)) or (t1.time_stamp<>t2.time_stamp and (t1.time_stamp is not null or t2.time_stamp is not null)) or (t1.date_field<>t2.date_field and (t1.date_field is not null or t2.date_field is not null)) or (t1.time_field<>t2.time_field and (t1.time_field is not null or t2.time_field is not null)) or (t1.date_time<>t2.date_time and (t1.date_time is not null or t2.date_time is not null)) or (t1.new_blob_col<>t2.new_blob_col and (t1.new_blob_col is not null or t2.new_blob_col is not null)) or (t1.tinyblob_col<>t2.tinyblob_col and (t1.tinyblob_col is not null or t2.tinyblob_col is not null)) or (t1.mediumblob_col<>t2.mediumblob_col and (t1.mediumblob_col is not null or t2.mediumblob_col is not null)) or (t1.options<>t2.options and (t1.options is not null or t2.options is not null)) or (t1.flags<>t2.flags and (t1.flags is not null or t2.flags is not null)) or (t1.new_field<>t2.new_field and (t1.new_field is not null or t2.new_field is not null)));
auto auto
16 16
@@ -265,23 +265,27 @@ select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and not (t1.string<=>t2.
auto auto
16 16
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 from t1;
+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 bigint(17) unsigned NULL PRI 0 select,insert,update,references
t1 bigint(1) NULL 0 select,insert,update,references
-t2 char(1) latin1_swedish_ci select,insert,update,references
-t3 longtext latin1_swedish_ci select,insert,update,references
-t4 longblob NULL select,insert,update,references
-select * from t2;
-auto t1 t2 t3 t4
-11 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-12 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-13 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-14 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-15 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-16 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
-17 1 a aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa bbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbbb
+t2 varchar(1) latin1_swedish_ci select,insert,update,references
+t3 varchar(256) latin1_swedish_ci select,insert,update,references
+t4 varchar(256) NULL select,insert,update,references
+t5 longtext latin1_swedish_ci select,insert,update,references
+t6 longblob NULL select,insert,update,references
+t7 char(0) latin1_swedish_ci select,insert,update,references
+t8 binary(0) NULL select,insert,update,references
+select t1,t2,length(t3),length(t4),length(t5),length(t6),t7,t8 from t2;
+t1 t2 length(t3) length(t4) length(t5) length(t6) t7 t8
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
+1 a 256 256 4096 4096
drop table t1,t2;
create table t1 (c int);
insert into t1 values(1),(2);
diff --git a/mysql-test/r/type_ranges.result.es b/mysql-test/r/type_ranges.result.es
index 548b00750ea..c1f6d2453e9 100644
--- a/mysql-test/r/type_ranges.result.es
+++ b/mysql-test/r/type_ranges.result.es
@@ -223,7 +223,7 @@ umedium mediumint(8) unsigned NULL MUL 0
ulong int(11) unsigned NULL MUL 0
ulonglong bigint(13) unsigned NULL MUL 0
time_stamp timestamp NULL YES CURRENT_TIMESTAMP
-date_field varchar(10) latin1_swedish_ci YES NULL
+date_field char(10) latin1_swedish_ci YES NULL
time_field time NULL YES NULL
date_time datetime NULL YES NULL
new_blob_col varchar(20) latin1_swedish_ci YES NULL
@@ -231,7 +231,7 @@ tinyblob_col tinyblob NULL YES NULL
mediumblob_col mediumblob NULL
options enum('one','two','tree') latin1_swedish_ci MUL one
flags set('one','two','tree') latin1_swedish_ci
-new_field varchar(10) latin1_swedish_ci new
+new_field char(10) latin1_swedish_ci new
show full columns from t2;
Field Type Collation Null Key Default Extra Privileges Comment
auto int(5) unsigned NULL 0
@@ -249,7 +249,7 @@ umedium mediumint(8) unsigned NULL 0
ulong int(11) unsigned NULL 0
ulonglong bigint(13) unsigned NULL 0
time_stamp timestamp NULL YES 0000-00-00 00:00:00
-date_field varchar(10) latin1_swedish_ci YES NULL
+date_field char(10) latin1_swedish_ci YES NULL
time_field time NULL YES NULL
date_time datetime NULL YES NULL
new_blob_col varchar(20) latin1_swedish_ci YES NULL
@@ -257,7 +257,7 @@ tinyblob_col tinyblob NULL YES NULL
mediumblob_col mediumblob NULL
options enum('one','two','tree') latin1_swedish_ci one
flags set('one','two','tree') latin1_swedish_ci
-new_field varchar(10) latin1_swedish_ci new
+new_field char(10) latin1_swedish_ci new
select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and ((t1.string<>t2.string and (t1.string is not null or t2.string is not null)) or (t1.tiny<>t2.tiny and (t1.tiny is not null or t2.tiny is not null)) or (t1.short<>t2.short and (t1.short is not null or t2.short is not null)) or (t1.medium<>t2.medium and (t1.medium is not null or t2.medium is not null)) or (t1.long_int<>t2.long_int and (t1.long_int is not null or t2.long_int is not null)) or (t1.longlong<>t2.longlong and (t1.longlong is not null or t2.longlong is not null)) or (t1.real_float<>t2.real_float and (t1.real_float is not null or t2.real_float is not null)) or (t1.real_double<>t2.real_double and (t1.real_double is not null or t2.real_double is not null)) or (t1.utiny<>t2.utiny and (t1.utiny is not null or t2.utiny is not null)) or (t1.ushort<>t2.ushort and (t1.ushort is not null or t2.ushort is not null)) or (t1.umedium<>t2.umedium and (t1.umedium is not null or t2.umedium is not null)) or (t1.ulong<>t2.ulong and (t1.ulong is not null or t2.ulong is not null)) or (t1.ulonglong<>t2.ulonglong and (t1.ulonglong is not null or t2.ulonglong is not null)) or (t1.time_stamp<>t2.time_stamp and (t1.time_stamp is not null or t2.time_stamp is not null)) or (t1.date_field<>t2.date_field and (t1.date_field is not null or t2.date_field is not null)) or (t1.time_field<>t2.time_field and (t1.time_field is not null or t2.time_field is not null)) or (t1.date_time<>t2.date_time and (t1.date_time is not null or t2.date_time is not null)) or (t1.new_blob_col<>t2.new_blob_col and (t1.new_blob_col is not null or t2.new_blob_col is not null)) or (t1.tinyblob_col<>t2.tinyblob_col and (t1.tinyblob_col is not null or t2.tinyblob_col is not null)) or (t1.mediumblob_col<>t2.mediumblob_col and (t1.mediumblob_col is not null or t2.mediumblob_col is not null)) or (t1.options<>t2.options and (t1.options is not null or t2.options is not null)) or (t1.flags<>t2.flags and (t1.flags is not null or t2.flags is not null)) or (t1.new_field<>t2.new_field and (t1.new_field is not null or t2.new_field is not null)));
auto auto
16 16
diff --git a/mysql-test/r/type_varchar.result b/mysql-test/r/type_varchar.result
new file mode 100644
index 00000000000..70b5bcc9a6d
--- /dev/null
+++ b/mysql-test/r/type_varchar.result
@@ -0,0 +1,51 @@
+drop table if exists t1;
+create table t1 (v varchar(30), c char(3), e enum('abc','def','ghi'), t text);
+truncate table vchar;
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `v` varchar(30) default NULL,
+ `c` char(3) default NULL,
+ `e` enum('abc','def','ghi') default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+show create table vchar;
+Table Create Table
+vchar CREATE TABLE `vchar` (
+ `v` varchar(30) default NULL,
+ `c` char(3) default NULL,
+ `e` enum('abc','def','ghi') default NULL,
+ `t` text
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+insert into t1 values ('abc', 'de', 'ghi', 'jkl');
+insert into t1 values ('abc ', 'de ', 'ghi', 'jkl ');
+insert into t1 values ('abc ', 'd ', 'ghi', 'jkl ');
+insert into vchar values ('abc', 'de', 'ghi', 'jkl');
+insert into vchar values ('abc ', 'de ', 'ghi', 'jkl ');
+insert into vchar values ('abc ', 'd ', 'ghi', 'jkl ');
+select length(v),length(c),length(e),length(t) from t1;
+length(v) length(c) length(e) length(t)
+3 2 3 3
+4 2 3 4
+7 1 3 7
+select length(v),length(c),length(e),length(t) from vchar;
+length(v) length(c) length(e) length(t)
+3 2 3 3
+3 2 3 4
+3 1 3 7
+alter table vchar add i int;
+show create table vchar;
+Table Create Table
+vchar CREATE TABLE `vchar` (
+ `v` varchar(30) default NULL,
+ `c` char(3) default NULL,
+ `e` enum('abc','def','ghi') default NULL,
+ `t` text,
+ `i` int(11) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+select length(v),length(c),length(e),length(t) from vchar;
+length(v) length(c) length(e) length(t)
+3 2 3 3
+3 2 3 4
+3 1 3 7
+drop table t1, vchar;
diff --git a/mysql-test/r/union.result b/mysql-test/r/union.result
index acfd5a97dce..d4ce1e45bf0 100644
--- a/mysql-test/r/union.result
+++ b/mysql-test/r/union.result
@@ -543,7 +543,7 @@ aa
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` char(2) NOT NULL default ''
+ `a` varchar(2) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT 12 as a UNION select "aa" as a;
@@ -554,7 +554,7 @@ aa
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` char(20) NOT NULL default ''
+ `a` varchar(20) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 SELECT 12 as a UNION select 12.2 as a;
@@ -812,7 +812,7 @@ create table t1 select _latin2"test" union select _latin2"testt" ;
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `test` char(5) character set latin2 NOT NULL default ''
+ `test` varchar(5) character set latin2 NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 (s char(200));
@@ -1040,7 +1040,7 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `test` char(4) NOT NULL default ''
+ `test` varchar(4) NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
@@ -1053,7 +1053,7 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `_latin1'test' collate latin1_bin` char(4) character set latin1 collate latin1_bin NOT NULL default ''
+ `_latin1'test' collate latin1_bin` varchar(4) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
@@ -1066,7 +1066,7 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `test` char(4) character set latin1 collate latin1_bin NOT NULL default ''
+ `test` varchar(4) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
@@ -1079,7 +1079,7 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `test` char(4) character set latin1 collate latin1_bin NOT NULL default ''
+ `test` varchar(4) character set latin1 collate latin1_bin NOT NULL default ''
) ENGINE=MyISAM DEFAULT CHARSET=latin1
select count(*) from t1;
count(*)
@@ -1098,7 +1098,7 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a collate latin1_german1_ci` char(1) character set latin1 collate latin1_german1_ci default NULL
+ `a collate latin1_german1_ci` varchar(1) character set latin1 collate latin1_german1_ci default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
create table t1 as
@@ -1107,7 +1107,17 @@ create table t1 as
show create table t1;
Table Create Table
t1 CREATE TABLE `t1` (
- `a` char(1) character set latin1 collate latin1_german1_ci default NULL
+ `a` varchar(1) character set latin1 collate latin1_german1_ci default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=latin1
+drop table t1;
+create table t1 as
+(select a from t2) union
+(select b from t2) union
+(select 'c' collate latin1_german1_ci from t2);
+show create table t1;
+Table Create Table
+t1 CREATE TABLE `t1` (
+ `a` varchar(1) character set latin1 collate latin1_german1_ci default NULL
) ENGINE=MyISAM DEFAULT CHARSET=latin1
drop table t1;
drop table t2;
diff --git a/mysql-test/r/user_var.result b/mysql-test/r/user_var.result
index 80d8af095cb..d7d527dd720 100644
--- a/mysql-test/r/user_var.result
+++ b/mysql-test/r/user_var.result
@@ -173,18 +173,12 @@ SET @`a b`='hello';
INSERT INTO t1 VALUES(@`a b`);
set @var1= "';aaa";
insert into t1 values (@var1);
-create table t2 (c char(30)) charset=ucs2;
-set @v=convert('abc' using ucs2);
-insert into t2 values (@v);
show binlog events from 95;
Log_name Pos Event_type Server_id End_log_pos Info
master-bin.000001 95 User var 1 136 @`a b`=_latin1 0x68656C6C6F COLLATE latin1_swedish_ci
master-bin.000001 136 Query 1 222 use `test`; INSERT INTO t1 VALUES(@`a b`)
master-bin.000001 222 User var 1 264 @`var1`=_latin1 0x273B616161 COLLATE latin1_swedish_ci
master-bin.000001 264 Query 1 350 use `test`; insert into t1 values (@var1)
-master-bin.000001 350 Query 1 448 use `test`; create table t2 (c char(30)) charset=ucs2
-master-bin.000001 448 User var 1 488 @`v`=_ucs2 0x006100620063 COLLATE ucs2_general_ci
-master-bin.000001 488 Query 1 571 use `test`; insert into t2 values (@v)
/*!40019 SET @@session.max_insert_delayed_threads=0*/;
SET @`a b`:=_latin1 0x68656C6C6F COLLATE latin1_swedish_ci;
use test;
@@ -195,9 +189,8 @@ INSERT INTO t1 VALUES(@`a b`);
SET @`var1`:=_latin1 0x273B616161 COLLATE latin1_swedish_ci;
SET TIMESTAMP=10000;
insert into t1 values (@var1);
-SET TIMESTAMP=10000;
-create table t2 (c char(30)) charset=ucs2;
-SET @`v`:=_ucs2 0x006100620063 COLLATE ucs2_general_ci;
-SET TIMESTAMP=10000;
-insert into t2 values (@v);
-drop table t1, t2;
+drop table t1;
+set @var= NULL ;
+select FIELD( @var,'1it','Hit') as my_column;
+my_column
+0
diff --git a/mysql-test/r/view.result b/mysql-test/r/view.result
index 9e9ad7a6da6..41de883a4d6 100644
--- a/mysql-test/r/view.result
+++ b/mysql-test/r/view.result
@@ -887,7 +887,7 @@ insert into t1 values (1), (2), (3), (200);
create view v1 (x) as select a from t1 where a > 1;
create view v2 (y) as select x from v1 where x < 100;
select * from v2;
-x
+y
2
3
drop table t1;
@@ -1221,11 +1221,7 @@ ERROR 42000: FUNCTION test.x1 does not exist
show table status;
Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
t1 MyISAM 9 Fixed 0 0 0 21474836479 1024 0 NULL # # NULL latin1_swedish_ci NULL
-v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view
-show table status;
-Name Engine Version Row_format Rows Avg_row_length Data_length Max_data_length Index_length Data_free Auto_increment Create_time Update_time Check_time Collation Checksum Create_options Comment
-t1 MyISAM 9 Fixed 0 0 0 21474836479 1024 0 NULL # # NULL latin1_swedish_ci NULL
-v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL view
+v1 NULL NULL NULL NULL NULL NULL NULL NULL NULL NULL # # NULL NULL NULL NULL FUNCTION test.x1 does not exist
drop view v1;
drop table t1;
create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1;
@@ -1339,16 +1335,14 @@ c
prepare stmt1 from "update v1,t1 set v1.s1=? where t1.s1=v1.s1";
set @arg='d';
execute stmt1 using @arg;
-ERROR HY000: Table 't1' is read only
select * from v1;
s1
-c
+d
set @arg='e';
execute stmt1 using @arg;
-ERROR HY000: Table 't1' is read only
select * from v1;
s1
-c
+e
deallocate prepare stmt1;
drop view v1;
drop table t1;
@@ -1628,3 +1622,206 @@ Field 3,'Field 4|
|Field 6| | 'Field 7'|
drop view v1;
drop table t1;
+create database mysqltest;
+create table mysqltest.t1 (a int);
+grant all privileges on mysqltest.* to mysqltest_1@localhost;
+use mysqltest;
+create view v1 as select * from t1;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+drop database mysqltest;
+create table t1 (s1 smallint);
+create view v1 as select * from t1 where 20 < (select (s1) from t1);
+insert into v1 values (30);
+ERROR HY000: The target table v1 of the INSERT is not updatable
+create view v2 as select * from t1;
+create view v3 as select * from t1 where 20 < (select (s1) from v2);
+insert into v3 values (30);
+ERROR HY000: The target table v3 of the INSERT is not updatable
+create view v4 as select * from v2 where 20 < (select (s1) from t1);
+insert into v4 values (30);
+ERROR HY000: You can't specify target table 'v4' for update in FROM clause
+drop view v4, v3, v2, v1;
+drop table t1;
+create table t1 (a int);
+create view v1 as select * from t1;
+check table t1,v1;
+Table Op Msg_type Msg_text
+test.t1 check status OK
+test.v1 check status OK
+check table v1,t1;
+Table Op Msg_type Msg_text
+test.v1 check status OK
+test.t1 check status OK
+drop table t1;
+check table v1;
+Table Op Msg_type Msg_text
+test.v1 check error View 'test.v1' references invalid table(s) or column(s)
+drop view v1;
+create table t1 (a int);
+create table t2 (a int);
+create table t3 (a int);
+insert into t1 values (1), (2), (3);
+insert into t2 values (1), (3);
+insert into t3 values (1), (2), (4);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1 left join t2 on (t1.a=t2.a);
+select * from t3 left join v3 on (t3.a = v3.a);
+a a b
+1 1 1
+2 2 NULL
+4 NULL NULL
+explain extended select * from t3 left join v3 on (t3.a = v3.a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 3
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2
+Warnings:
+Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`t1` left join `test`.`t2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
+create view v1 (a) as select a from t1;
+create view v2 (a) as select a from t2;
+create view v4 (a,b) as select v1.a as a, v2.a as b from v1 left join v2 on (v1.a=v2.a);
+select * from t3 left join v4 on (t3.a = v4.a);
+a a b
+1 1 1
+2 2 NULL
+4 NULL NULL
+explain extended select * from t3 left join v4 on (t3.a = v4.a);
+id select_type table type possible_keys key key_len ref rows Extra
+1 PRIMARY t3 ALL NULL NULL NULL NULL 3
+1 PRIMARY t1 ALL NULL NULL NULL NULL 3
+1 PRIMARY t2 ALL NULL NULL NULL NULL 2
+Warnings:
+Note 1003 select `test`.`t3`.`a` AS `a`,`test`.`t1`.`a` AS `a`,`test`.`t2`.`a` AS `b` from `test`.`t3` left join (`test`.`v1` left join `test`.`v2` on((`test`.`t1`.`a` = `test`.`t2`.`a`))) on((`test`.`t3`.`a` = `test`.`t1`.`a`)) where 1
+prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);";
+execute stmt1;
+a a b
+1 1 1
+2 2 NULL
+4 NULL NULL
+execute stmt1;
+a a b
+1 1 1
+2 2 NULL
+4 NULL NULL
+deallocate prepare stmt1;
+drop view v4,v3,v2,v1;
+drop tables t1,t2,t3;
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a));
+insert into t1 values (1,100), (2,200);
+insert into t2 values (1), (3);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+update v3 set a= 10 where a=1;
+select * from t1;
+a b
+10 100
+2 200
+select * from t2;
+a
+1
+3
+create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
+set updatable_views_with_limit=NO;
+update v2 set a= 10 where a=200 limit 1;
+ERROR HY000: The target table t1 of the UPDATE is not updatable
+set updatable_views_with_limit=DEFAULT;
+select * from v3;
+a b
+2 1
+10 1
+2 3
+10 3
+select * from v2;
+a b
+100 1
+200 1
+100 3
+200 3
+set @a= 10;
+set @b= 100;
+prepare stmt1 from "update v3 set a= ? where a=?";
+execute stmt1 using @a,@b;
+select * from v3;
+a b
+2 1
+10 1
+2 3
+10 3
+set @a= 300;
+set @b= 10;
+execute stmt1 using @a,@b;
+select * from v3;
+a b
+2 1
+300 1
+2 3
+300 3
+deallocate prepare stmt1;
+drop view v3,v2;
+drop tables t1,t2;
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a), b int);
+insert into t2 values (1000, 2000);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+insert into v3 values (1,2);
+ERROR HY000: Can not insert into join view 'test.v3' without fields list
+insert into v3 select * from t2;
+ERROR HY000: Can not insert into join view 'test.v3' without fields list
+insert into v3(a,b) values (1,2);
+ERROR HY000: Can not modify more than one base table through a join view 'test.v3'
+insert into v3(a,b) select * from t2;
+ERROR HY000: Can not modify more than one base table through a join view 'test.v3'
+insert into v3(a) values (1);
+insert into v3(b) values (10);
+insert into v3(a) select a from t2;
+insert into v3(b) select b from t2;
+Warnings:
+Warning 1263 Column set to default value; NULL supplied to NOT NULL column 'a' at row 2
+insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a);
+select * from t1;
+a b
+10002 NULL
+10 NULL
+1000 NULL
+select * from t2;
+a b
+1000 2000
+10 NULL
+2000 NULL
+0 NULL
+delete from v3;
+ERROR HY000: Can not delete from join view 'test.v3'
+delete v3,t1 from v3,t1;
+ERROR HY000: Can not delete from join view 'test.v3'
+delete from t1;
+prepare stmt1 from "insert into v3(a) values (?);";
+set @a= 100;
+execute stmt1 using @a;
+set @a= 300;
+execute stmt1 using @a;
+deallocate prepare stmt1;
+prepare stmt1 from "insert into v3(a) select ?;";
+set @a= 101;
+execute stmt1 using @a;
+set @a= 301;
+execute stmt1 using @a;
+deallocate prepare stmt1;
+select * from v3;
+a b
+100 1000
+101 1000
+300 1000
+301 1000
+100 10
+101 10
+300 10
+301 10
+100 2000
+101 2000
+300 2000
+301 2000
+100 0
+101 0
+300 0
+301 0
+drop view v3;
+drop tables t1,t2;
diff --git a/mysql-test/std_data/Moscow_leap b/mysql-test/std_data/Moscow_leap
new file mode 100644
index 00000000000..4994c005595
--- /dev/null
+++ b/mysql-test/std_data/Moscow_leap
Binary files differ
diff --git a/mysql-test/std_data/vchar.frm b/mysql-test/std_data/vchar.frm
new file mode 100644
index 00000000000..5f037261d5f
--- /dev/null
+++ b/mysql-test/std_data/vchar.frm
Binary files differ
diff --git a/mysql-test/t/alter_table.test b/mysql-test/t/alter_table.test
index e46027ae8d9..66a4adc90fe 100644
--- a/mysql-test/t/alter_table.test
+++ b/mysql-test/t/alter_table.test
@@ -324,3 +324,15 @@ alter table t1 rename to `t1\\`;
rename table t1 to `t1\\`;
drop table t1;
+#
+# Bug #6479 ALTER TABLE ... changing charset fails for TEXT columns
+#
+# The column's character set was changed but the actual data was not
+# modified. In other words, the values were reinterpreted
+# as UTF8 instead of being converted.
+create table t1 (a text) character set koi8r;
+insert into t1 values (_koi8r'ÔÅÓÔ');
+select hex(a) from t1;
+alter table t1 convert to character set cp1251;
+select hex(a) from t1;
+drop table t1;
diff --git a/mysql-test/t/archive.test b/mysql-test/t/archive.test
index f55aea6e104..e710de7b35e 100644
--- a/mysql-test/t/archive.test
+++ b/mysql-test/t/archive.test
@@ -1299,4 +1299,15 @@ INSERT INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
SELECT * FROM t2;
OPTIMIZE TABLE t2;
SELECT * FROM t2;
+
+#
+# Test bulk inserts
+INSERT INTO t2 VALUES (1,000001,00,'Omaha','teethe','neat','') , (2,011401,37,'breaking','dreaded','Steinberg','W') , (3,011402,37,'Romans','scholastics','jarring','') , (4,011403,37,'intercepted','audiology','tinily','');
+SELECT * FROM t2;
+
+# Just test syntax, we will never know if the out put is right or wrong
+INSERT DELAYED INTO t2 VALUES (4,011403,37,'intercepted','audiology','tinily','');
+#
+# Cleanup, test is over
+#
drop table t1, t2;
diff --git a/mysql-test/t/bdb-deadlock.tminus b/mysql-test/t/bdb-deadlock.tminus
new file mode 100644
index 00000000000..d86403fcffc
--- /dev/null
+++ b/mysql-test/t/bdb-deadlock.tminus
@@ -0,0 +1,57 @@
+# This test doesn't work with the embedded version as this code
+# assumes that one query is running while we are doing queries on
+# a second connection.
+# This would work if mysqltest run would be threaded and handle each
+# connection in a separate thread.
+#
+
+#-- source include/not_embedded.inc
+-- source include/have_bdb.inc
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+--disable_warnings
+drop table if exists t1,t2;
+--enable_warnings
+connection con1;
+create table t1 (id integer, x integer) engine=BDB;
+create table t2 (id integer, x integer) engine=BDB;
+insert into t1 values(0, 0);
+insert into t2 values(0, 0);
+set autocommit=0;
+update t1 set x = 1 where id = 0;
+
+connection con2;
+set autocommit=0;
+update t2 set x = 1 where id = 0;
+
+# The following query should hang because con1 is locking the page
+--send
+select x from t1 where id = 0;
+
+connection con1;
+# This should generate a deadlock as we are trying to access a locked row
+--send
+select x from t2 where id = 0;
+
+connection con2;
+--error 1213
+reap;
+commit;
+
+connection con1;
+reap;
+commit;
+
+connection con2;
+select * from t1;
+select * from t2;
+commit;
+
+connection con1;
+select * from t1;
+select * from t2;
+commit;
+
+drop table t1,t2;
diff --git a/mysql-test/t/bdb.test b/mysql-test/t/bdb.test
index 069ec758ba2..01d82c0ba16 100644
--- a/mysql-test/t/bdb.test
+++ b/mysql-test/t/bdb.test
@@ -929,3 +929,22 @@ SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterb");
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "lettera");
SELECT id FROM t1 WHERE (list_id = 1) AND (term = "letterd");
DROP TABLE t1;
+
+#
+# alter temp table
+#
+create temporary table t1 (a int, primary key(a)) engine=bdb;
+select * from t1;
+alter table t1 add b int;
+select * from t1;
+drop table t1;
+
+
+#
+# Test varchar
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=bdb;
+source include/varchar.inc;
+eval set storage_engine=$default;
diff --git a/mysql-test/t/binary.test b/mysql-test/t/binary.test
index 3e702fd5257..54ad8e92237 100644
--- a/mysql-test/t/binary.test
+++ b/mysql-test/t/binary.test
@@ -80,3 +80,10 @@ select * from t1 where firstname='john' and firstname = binary 'john';
select * from t1 where firstname='John' and firstname like binary 'john';
select * from t1 where firstname='john' and firstname like binary 'John';
drop table t1;
+
+#
+# Bug #6552 CHAR column w/o length is legal, BINARY w/o length is not
+#
+create table t1 (a binary);
+show create table t1;
+drop table t1;
diff --git a/mysql-test/t/bool.test b/mysql-test/t/bool.test
index b263ecfded2..53230dd5fa3 100644
--- a/mysql-test/t/bool.test
+++ b/mysql-test/t/bool.test
@@ -20,6 +20,16 @@ SELECT * FROM t1 where (1 AND a)=0;
SELECT * FROM t1 where (1 AND a)=1;
SELECT * FROM t1 where (1 AND a) IS NULL;
+# WL#638 - Behaviour of NOT does not follow SQL specification
+set sql_mode='high_not_precedence';
+select * from t1 where not a between 2 and 3;
+set sql_mode=default;
+select * from t1 where not a between 2 and 3;
+
+# SQL boolean tests
+select a, a is false, a is true, a is unknown from t1;
+select a, a is not false, a is not true, a is not unknown from t1;
+
# Verify that NULL optimisation works in AND clause:
SET @a=0, @b=0;
SELECT * FROM t1 WHERE NULL AND (@a:=@a+1);
diff --git a/mysql-test/t/client_test.test b/mysql-test/t/client_test.test
index b56e8038d9b..66f5e69eb36 100644
--- a/mysql-test/t/client_test.test
+++ b/mysql-test/t/client_test.test
@@ -1,2 +1,2 @@
--disable_result_log
---exec $TESTS_BINDIR/client_test --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT
+--exec $TESTS_BINDIR/client_test --no-defaults --testcase --user=root --socket=$MASTER_MYSOCK --port=$MYSQL_TCP_PORT --silent
diff --git a/mysql-test/t/comments.test b/mysql-test/t/comments.test
index 2fc6237907c..087df60f3f5 100644
--- a/mysql-test/t/comments.test
+++ b/mysql-test/t/comments.test
@@ -5,7 +5,8 @@
select 1+2/*hello*/+3;
select 1 /* long
multi line comment */;
-!$1065 ;
+--error 1065
+ ;
select 1 /*!32301 +1 */;
select 1 /*!52301 +1 */;
select 1--1;
diff --git a/mysql-test/t/connect.test b/mysql-test/t/connect.test
index 4598ca5ea15..8e1a92a586e 100644
--- a/mysql-test/t/connect.test
+++ b/mysql-test/t/connect.test
@@ -49,7 +49,7 @@ flush privileges;
#show tables;
connect (con1,localhost,test,gambling2,mysql);
set password="";
---error 1105
+--error 1372
set password='gambling3';
set password=old_password('gambling3');
show tables;
diff --git a/mysql-test/t/consistent_snapshot.test b/mysql-test/t/consistent_snapshot.test
new file mode 100644
index 00000000000..7afdae36325
--- /dev/null
+++ b/mysql-test/t/consistent_snapshot.test
@@ -0,0 +1,41 @@
+-- source include/have_innodb.inc
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+
+### Test 1:
+### - While a consistent snapshot transaction is executed,
+### no external inserts should be visible to the transaction.
+
+connection con1;
+create table t1 (a int) engine=innodb;
+start transaction with consistent snapshot;
+
+connection con2;
+insert into t1 values(1);
+
+connection con1;
+select * from t1; # if consistent snapshot was set as expected, we
+# should see nothing.
+commit;
+
+### Test 2:
+### - For any non-consistent snapshot transaction, external
+### committed inserts should be visible to the transaction.
+
+delete from t1;
+start transaction; # Now we omit WITH CONSISTENT SNAPSHOT
+
+connection con2;
+insert into t1 values(1);
+
+connection con1;
+select * from t1; # if consistent snapshot was not set, as expected, we
+# should see 1.
+commit;
+
+drop table t1;
diff --git a/mysql-test/t/count_distinct.test b/mysql-test/t/count_distinct.test
index 1f0404876cb..73c6951e78f 100644
--- a/mysql-test/t/count_distinct.test
+++ b/mysql-test/t/count_distinct.test
@@ -55,3 +55,11 @@ create table t1 (f int);
select count(distinct f) from t1;
drop table t1;
+#
+# Bug #6515
+#
+
+create table t1 (a char(3), b char(20), primary key (a, b));
+insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English');
+select count(distinct a) from t1 group by b;
+drop table t1;
diff --git a/mysql-test/t/ctype_big5.test b/mysql-test/t/ctype_big5.test
index 9bf1808636e..b1d71a6af15 100644
--- a/mysql-test/t/ctype_big5.test
+++ b/mysql-test/t/ctype_big5.test
@@ -7,12 +7,6 @@
drop table if exists t1;
--enable_warnings
-SET NAMES big5;
-
-#
-# Bug 1883: LIKE did not work in some cases with a key.
-#
-CREATE TABLE t1 (c CHAR(10) CHARACTER SET big5, KEY(c));
-INSERT INTO t1 VALUES ('aaa'),('aaaa'),('aaaaa');
-SELECT * FROM t1 WHERE c LIKE 'aaa%';
-DROP TABLE t1;
+SET @test_character_set= 'big5';
+SET @test_collation= 'big5_chinese_ci';
+-- source include/ctype_common.inc
diff --git a/mysql-test/t/ctype_latin1.test b/mysql-test/t/ctype_latin1.test
index 14062437428..677acd9faa9 100644
--- a/mysql-test/t/ctype_latin1.test
+++ b/mysql-test/t/ctype_latin1.test
@@ -53,3 +53,10 @@ SELECT
hex(@l:=convert(@u using latin1)),
a=@l FROM t1;
DROP TABLE t1;
+
+#
+# Bug #6737: REGEXP gives wrong result with case sensitive collation
+#
+select 'a' regexp 'A' collate latin1_general_ci;
+select 'a' regexp 'A' collate latin1_general_cs;
+select 'a' regexp 'A' collate latin1_bin;
diff --git a/mysql-test/t/ctype_recoding.test b/mysql-test/t/ctype_recoding.test
index 5f417352d95..0e5e954c720 100644
--- a/mysql-test/t/ctype_recoding.test
+++ b/mysql-test/t/ctype_recoding.test
@@ -131,3 +131,51 @@ create table t1 (a char(10) character set koi8r, b text character set koi8r);
insert into t1 values ('test','test');
insert into t1 values ('ÊÃÕË','ÊÃÕË');
drop table t1;
+
+#
+# Try to apply an automatic conversion in some cases:
+# E.g. when mixing a column to a string, the string
+# is converted into the column character set.
+# If conversion loses data, then error. Otherwise,
+# the string is replaced by its converted representation
+#
+set names koi8r;
+create table t1 (a char(10) character set cp1251);
+insert into t1 values (_koi8r'×ÁÓÑ');
+# this is possible:
+select * from t1 where a=_koi8r'×ÁÓÑ';
+# this is not possible, because we have a function, not just a constant:
+--error 1267
+select * from t1 where a=concat(_koi8r'×ÁÓÑ');
+# this is not posible, cannot convert _latin1'×ÁÓÑ' into cp1251:
+--error 1267
+select * from t1 where a=_latin1'×ÁÓÑ';
+drop table t1;
+set names latin1;
+
+#
+# Check more automatic conversion
+#
+set names koi8r;
+create table t1 (c1 char(10) character set cp1251);
+insert into t1 values ('ß');
+select c1 from t1 where c1 between 'ß' and 'ß';
+select ifnull(c1,'ß'), ifnull(null,c1) from t1;
+select if(1,c1,'ö'), if(0,c1,'ö') from t1;
+select coalesce('ö',c1), coalesce(null,c1) from t1;
+select least(c1,'ö'), greatest(c1,'ö') from t1;
+select locate(c1,'ß'), locate('ß',c1) from t1;
+select field(c1,'ß'),field('ß',c1) from t1;
+select concat(c1,'ö'), concat('ö',c1) from t1;
+select concat_ws(c1,'ö','ß'), concat_ws('ö',c1,'ß') from t1;
+select replace(c1,'ß','ö'), replace('ß',c1,'ö') from t1;
+select substring_index(c1,'öößß',2) from t1;
+select elt(1,c1,'ö'),elt(1,'ö',c1) from t1;
+select make_set(3,c1,'ö'), make_set(3,'ö',c1) from t1;
+select insert(c1,1,2,'ö'),insert('ö',1,2,c1) from t1;
+select trim(c1 from 'ß'),trim('ß' from c1) from t1;
+select lpad(c1,3,'ö'), lpad('ö',3,c1) from t1;
+select rpad(c1,3,'ö'), rpad('ö',3,c1) from t1;
+# TODO
+#select case c1 when 'ß' then 'ß' when 'ö' then 'ö' else 'c' end from t1;
+#select export_set(5,c1,'ö'), export_set(5,'ö',c1) from t1;
diff --git a/mysql-test/t/ctype_sjis.test b/mysql-test/t/ctype_sjis.test
index c910812ef8a..a3a44789975 100644
--- a/mysql-test/t/ctype_sjis.test
+++ b/mysql-test/t/ctype_sjis.test
@@ -51,3 +51,14 @@ insert into t1 values (0x9353);
insert into t1 values (0x9373);
select hex(c) from t1;
drop table t1;
+
+#
+# Bug #6223 Japanese half-width kana characters get truncated
+#
+SET NAMES sjis;
+CREATE TABLE t1 (
+ c char(16) default NULL
+) ENGINE=MyISAM DEFAULT CHARSET=sjis;
+insert into t1 values(0xb1),(0xb2),(0xb3);
+select hex(c) from t1;
+drop table t1;
diff --git a/mysql-test/t/ctype_tis620.test b/mysql-test/t/ctype_tis620.test
index 92a9eada05f..21ec314dca7 100644
--- a/mysql-test/t/ctype_tis620.test
+++ b/mysql-test/t/ctype_tis620.test
@@ -116,3 +116,38 @@ CREATE TABLE t1 (a char(10) not null) CHARACTER SET tis620;
INSERT INTO t1 VALUES ('a'),('a\0'),('a\t'),('a ');
SELECT hex(a),STRCMP(a,'a'), STRCMP(a,'a ') FROM t1;
DROP TABLE t1;
+
+#
+# Bug#6608
+#
+CREATE TABLE t1 (
+ `id` int(11) NOT NULL auto_increment,
+ `url` varchar(200) NOT NULL default '',
+ `name` varchar(250) NOT NULL default '',
+ `type` int(11) NOT NULL default '0',
+ `website` varchar(250) NOT NULL default '',
+ `adddate` date NOT NULL default '0000-00-00',
+ `size` varchar(20) NOT NULL default '',
+ `movieid` int(11) NOT NULL default '0',
+ `musicid` int(11) NOT NULL default '0',
+ `star` varchar(20) NOT NULL default '',
+ `download` int(11) NOT NULL default '0',
+ `lastweek` int(11) NOT NULL default '0',
+ `thisweek` int(11) NOT NULL default '0',
+ `page` varchar(250) NOT NULL default '',
+ PRIMARY KEY (`id`),
+ UNIQUE KEY `url` (`url`)
+) CHARACTER SET tis620;
+
+INSERT INTO t1 VALUES
+(1,'http://www.siamzone.com/download/download/000001-frodo_1024.jpg','The Lord
+of the Rings
+Wallpapers',1,'http://www.lordoftherings.net','2002-01-22','',448,0,'',3805,0,0,
+'');
+INSERT INTO t1 VALUES (2,'http://www.othemovie.com/OScreenSaver1.EXE','O
+Screensaver',2,'','2002-01-22','',491,0,'',519,0,0,'');
+INSERT INTO t1 VALUES
+(3,'http://www.siamzone.com/download/download/000003-jasonx2(800x600).jpg','Jaso
+n X Wallpapers',1,'','2002-05-31','',579,0,'',1091,0,0,'');
+select * from t1 order by id;
+DROP TABLE t1;
diff --git a/mysql-test/t/ctype_uca.test b/mysql-test/t/ctype_uca.test
index 708a31d637e..11833ba9bc7 100644
--- a/mysql-test/t/ctype_uca.test
+++ b/mysql-test/t/ctype_uca.test
@@ -25,6 +25,11 @@ select 'a ' = 'a\t', 'a ' < 'a\t', 'a ' > 'a\t';
select 'a a' > 'a', 'a \t' < 'a';
#
+# Bug #6787 LIKE not working properly with _ and utf8 data
+#
+select 'c' like '\_' as want0;
+
+#
# Bug #5679 utf8_unicode_ci LIKE--trailing % doesn't equal zero characters
#
CREATE TABLE t (
@@ -435,3 +440,7 @@ INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06280648062F0646062F USING utf8));
INSERT INTO t1 VALUES (CONVERT(_ucs2 0x06450647064506270646 USING utf8));
SELECT HEX(CONVERT(col1 USING ucs2)) FROM t1 ORDER BY col1 COLLATE utf8_persian_ci, col1 COLLATE utf8_bin;
DROP TABLE t1;
+
+SET @test_character_set= 'utf8';
+SET @test_collation= 'utf8_swedish_ci';
+-- source include/ctype_common.inc
diff --git a/mysql-test/t/ctype_ucs.test b/mysql-test/t/ctype_ucs.test
index d9ef91496e9..597b364dbb1 100644
--- a/mysql-test/t/ctype_ucs.test
+++ b/mysql-test/t/ctype_ucs.test
@@ -4,6 +4,10 @@
DROP TABLE IF EXISTS t1;
--enable_warnings
+SET NAMES latin1;
+SET character_set_connection=ucs2;
+-- source include/endspace.inc
+
SET CHARACTER SET koi8r;
#
@@ -16,17 +20,19 @@ SET CHARACTER SET koi8r;
# which contains 0x20 in the high byte.
#
-CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2);
-INSERT INTO t1 VALUES (_koi8r'ò'), (X'2004');
+CREATE TABLE t1 (word VARCHAR(64) CHARACTER SET ucs2, word2 CHAR(64) CHARACTER SET ucs2);
+INSERT INTO t1 VALUES (_koi8r'ò',_koi8r'ò'), (X'2004',X'2004');
SELECT hex(word) FROM t1 ORDER BY word;
+SELECT hex(word2) FROM t1 ORDER BY word2;
DELETE FROM t1;
#
# Check that real spaces are correctly trimmed.
#
-INSERT INTO t1 VALUES (X'042000200020'), (X'200400200020');
+INSERT INTO t1 VALUES (X'042000200020',X'042000200020'), (X'200400200020', X'200400200020');
SELECT hex(word) FROM t1 ORDER BY word;
+SELECT hex(word2) FROM t1 ORDER BY word2;
DROP TABLE t1;
#
@@ -48,7 +54,6 @@ RPAD(_ucs2 X'0420',10,_ucs2 X'0421') r;
SHOW CREATE TABLE t1;
DROP TABLE t1;
-
#
# BUG3946
#
@@ -57,6 +62,7 @@ create table t2(f1 Char(30));
insert into t2 values ("103000"), ("22720000"), ("3401200"), ("78000");
select lpad(f1, 12, "-o-/") from t2;
drop table t2;
+
######################################################
#
# Test of like
@@ -315,3 +321,27 @@ alter table t1 modify a char(5);
select a, hex(a) from t1;
drop table t1;
+#
+# Check prepare statement from an UCS2 string
+#
+set @ivar= 1234;
+set @str1 = 'select ?';
+set @str2 = convert(@str1 using ucs2);
+prepare stmt1 from @str2;
+execute stmt1 using @ivar;
+
+#
+# Check correct binlogging of UCS2 user variables (BUG#3875)
+#
+SET TIMESTAMP=10000;
+create table t2 (c char(30)) charset=ucs2;
+set @v=convert('abc' using ucs2);
+reset master;
+insert into t2 values (@v);
+show binlog events from 95;
+# more important than SHOW BINLOG EVENTS, mysqlbinlog (where we
+# absolutely need variables names to be quoted and strings to be
+# escaped).
+--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
+--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001
+drop table t2;
diff --git a/mysql-test/t/ctype_ujis.test b/mysql-test/t/ctype_ujis.test
index e5405d9f1bd..9cfb6b14d7e 100644
--- a/mysql-test/t/ctype_ujis.test
+++ b/mysql-test/t/ctype_ujis.test
@@ -83,3 +83,39 @@ CREATE TABLE t1 (
SHOW CREATE TABLE t1;
SHOW COLUMNS FROM t1;
DROP TABLE t1;
+
+#
+# Bug #6345 Unexpected behaviour with partial indices
+#
+--disable_warnings
+CREATE TABLE t1
+(
+ a INTEGER NOT NULL,
+ b VARCHAR(50) NOT NULL DEFAULT '',
+ PRIMARY KEY (a),
+ KEY b (b(10))
+) TYPE=InnoDB CHARACTER SET 'ujis' COLLATE 'ujis_japanese_ci';
+--enable_warnings
+INSERT INTO t1 (a, b) VALUES (0, 'aaabbbcccddd');
+INSERT INTO t1 (a, b) VALUES (1, 'eeefffggghhh');
+INSERT INTO t1 (a, b) VALUES (2, 'iiijjjkkkl');
+SELECT t1.* FROM t1 WHERE b='aaabbbcccddd' ORDER BY a;
+SELECT t1.* FROM t1 WHERE b='eeefffggghhh' ORDER BY a;
+SELECT t1.* FROM t1 WHERE b='iiijjjkkkl' ORDER BY a;
+DROP TABLE t1;
+--disable_warnings
+CREATE TABLE t1
+(
+ a INTEGER NOT NULL,
+ b VARCHAR(50) NOT NULL DEFAULT '',
+ PRIMARY KEY (a),
+ KEY b (b(10))
+) TYPE=MyISAM CHARACTER SET 'ujis' COLLATE 'ujis_japanese_ci';
+--enable_warnings
+INSERT INTO t1 (a, b) VALUES (0, 'aaabbbcccddd');
+INSERT INTO t1 (a, b) VALUES (1, 'eeefffggghhh');
+INSERT INTO t1 (a, b) VALUES (2, 'iiijjjkkkl');
+SELECT t1.* FROM t1 WHERE b='aaabbbcccddd' ORDER BY a;
+SELECT t1.* FROM t1 WHERE b='eeefffggghhh' ORDER BY a;
+SELECT t1.* FROM t1 WHERE b='iiijjjkkkl' ORDER BY a;
+DROP TABLE t1;
diff --git a/mysql-test/t/ctype_utf8.test b/mysql-test/t/ctype_utf8.test
index 0c8bdd6a94d..42031be8f3c 100644
--- a/mysql-test/t/ctype_utf8.test
+++ b/mysql-test/t/ctype_utf8.test
@@ -645,6 +645,7 @@ insert into t1 values(1,'foo'),(2,'foobar');
select * from t1 where b like 'foob%';
--disable_warnings
alter table t1 engine=bdb;
+--enable_warnings
select * from t1 where b like 'foob%';
drop table t1;
@@ -659,3 +660,9 @@ create table t2 select concat(a,_utf8'') as a, concat(b,_utf8'')as b from t1;
show create table t2;
drop table t2;
drop table t1;
+
+#
+# Bug #6787 LIKE not working properly with _ and utf8 data
+#
+select 'c' like '\_' as want0;
+
diff --git a/mysql-test/t/delete.test b/mysql-test/t/delete.test
index 5f60445d765..0bf7187865d 100644
--- a/mysql-test/t/delete.test
+++ b/mysql-test/t/delete.test
@@ -29,12 +29,34 @@ drop table t1;
# (This assumes a block size of 1024)
#
-create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
-insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23);
+create table t1 (
+ a bigint not null,
+ b bigint not null default 0,
+ c bigint not null default 0,
+ d bigint not null default 0,
+ e bigint not null default 0,
+ f bigint not null default 0,
+ g bigint not null default 0,
+ h bigint not null default 0,
+ i bigint not null default 0,
+ j bigint not null default 0,
+ primary key (a,b,c,d,e,f,g,h,i,j));
+insert into t1 (a) values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23);
delete from t1 where a=26;
drop table t1;
-create table t1 (a bigint not null, primary key (a,a,a,a,a,a,a,a,a,a));
-insert into t1 values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27);
+create table t1 (
+ a bigint not null,
+ b bigint not null default 0,
+ c bigint not null default 0,
+ d bigint not null default 0,
+ e bigint not null default 0,
+ f bigint not null default 0,
+ g bigint not null default 0,
+ h bigint not null default 0,
+ i bigint not null default 0,
+ j bigint not null default 0,
+ primary key (a,b,c,d,e,f,g,h,i,j));
+insert into t1 (a) values (2),(4),(6),(8),(10),(12),(14),(16),(18),(20),(22),(24),(26),(23),(27);
delete from t1 where a=27;
drop table t1;
diff --git a/mysql-test/t/endspace.test b/mysql-test/t/endspace.test
index 9ee5e32967a..3d27c44c3b9 100644
--- a/mysql-test/t/endspace.test
+++ b/mysql-test/t/endspace.test
@@ -7,13 +7,7 @@
drop table if exists t1;
--enable_warnings
-select 'a' = 'a', 'a' = 'a ', 'a ' = 'a';
-select 'a\0' = 'a', 'a\0' < 'a', 'a\0' > 'a';
-select 'a' = 'a\0', 'a' < 'a\0', 'a' > 'a\0';
-select 'a\0' = 'a ', 'a\0' < 'a ', 'a\0' > 'a ';
-select 'a ' = 'a\0', 'a ' < 'a\0', 'a ' > 'a\0';
-select 'a a' > 'a', 'a \0' < 'a';
-select binary 'a a' > 'a', binary 'a \0' > 'a', binary 'a\0' > 'a';
+-- source include/endspace.inc
#
# Test MyISAM tables.
@@ -47,16 +41,16 @@ alter table t1 modify text1 text not null, pack_keys=1;
select concat('|', text1, '|') from t1 where text1='teststring';
select concat('|', text1, '|') from t1 where text1='teststring ';
explain select concat('|', text1, '|') from t1 where text1='teststring ';
-select * from t1 where text1 like 'teststring_%';
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
+select concat('|', text1, '|') from t1 where text1 like 'teststring_%';
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
select concat('|', text1, '|') from t1 where text1='teststring' or text1 > 'teststring\t';
select concat('|', text1, '|') from t1 order by text1;
drop table t1;
create table t1 (text1 varchar(32) not NULL, KEY key1 (text1)) pack_keys=0;
insert into t1 values ('teststring'), ('nothing'), ('teststring\t');
-select * from t1 where text1='teststring' or text1 like 'teststring_%';
-select * from t1 where text1='teststring' or text1 >= 'teststring\t';
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 like 'teststring_%';
+select concat('|', text1, '|') from t1 where text1='teststring' or text1 >= 'teststring\t';
drop table t1;
# Test HEAP tables (with BTREE keys)
diff --git a/mysql-test/t/flush_block_commit.test b/mysql-test/t/flush_block_commit.test
index 3d13086f517..ac14b7b98bc 100644
--- a/mysql-test/t/flush_block_commit.test
+++ b/mysql-test/t/flush_block_commit.test
@@ -48,5 +48,19 @@ reap;
connection con3;
reap;
unlock tables;
+
+# BUG#6732 FLUSH TABLES WITH READ LOCK + COMMIT hangs later FLUSH TABLES
+# WITH READ LOCK
+
+connection con2;
+commit; # unlock InnoDB row locks to allow insertions
connection con1;
+begin;
+insert into t1 values(10);
+flush tables with read lock;
+commit;
+unlock tables;
+connection con2;
+flush tables with read lock; # bug caused hang here
+unlock tables;
drop table t1;
diff --git a/mysql-test/t/flush_read_lock_kill-master.opt b/mysql-test/t/flush_read_lock_kill-master.opt
new file mode 100644
index 00000000000..e7fe203239c
--- /dev/null
+++ b/mysql-test/t/flush_read_lock_kill-master.opt
@@ -0,0 +1 @@
+--debug=d,make_global_read_lock_block_commit_loop
diff --git a/mysql-test/t/flush_read_lock_kill.test b/mysql-test/t/flush_read_lock_kill.test
new file mode 100644
index 00000000000..b711bc63e0e
--- /dev/null
+++ b/mysql-test/t/flush_read_lock_kill.test
@@ -0,0 +1,46 @@
+# Let's see if FLUSH TABLES WITH READ LOCK can be killed when waiting
+# for running commits to finish (in the past it could not)
+# This will not be a meaningful test on non-debug servers so will be
+# skipped.
+# If running mysql-test-run --debug, the --debug added by
+# mysql-test-run to the mysqld command line will override the one of
+# -master.opt. But this test is designed to still pass then (though it
+# won't test anything interesting).
+
+-- source include/have_debug.inc
+
+connect (con1,localhost,root,,);
+connect (con2,localhost,root,,);
+connection con1;
+
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+create table t1 (kill_id int);
+insert into t1 values(connection_id());
+
+# Thanks to the parameter we passed to --debug, this FLUSH will
+# block on a debug build running with our --debug=make_global... It
+# will block until killed. In other cases (non-debug build or other
+# --debug) it will succeed immediately
+
+connection con1;
+send flush tables with read lock;
+
+# kill con1
+connection con2;
+select ((@id := kill_id) - kill_id) from t1;
+
+--sleep 2; # leave time for FLUSH to block
+kill connection @id;
+
+connection con1;
+# On debug builds it will be error 1053 (killed); on non-debug, or
+# debug build running without our --debug=make_global..., will be
+# error 0 (no error). The only important thing to test is that on
+# debug builds with our --debug=make_global... we don't hang forever.
+--error 0,1053
+reap;
+
+connection con2;
+drop table t1;
diff --git a/mysql-test/t/fulltext.test b/mysql-test/t/fulltext.test
index 66df5b1cb92..008e965297f 100644
--- a/mysql-test/t/fulltext.test
+++ b/mysql-test/t/fulltext.test
@@ -98,6 +98,8 @@ select * from t1 where match a against ("+aaa* +bbb*" in boolean mode);
select * from t1 where match a against ("+aaa* +bbb1*" in boolean mode);
select * from t1 where match a against ("+aaa* +ccc*" in boolean mode);
select * from t1 where match a against ("+aaa10 +(bbb*)" in boolean mode);
+select * from t1 where match a against ("+(+aaa* +bbb1*)" in boolean mode);
+select * from t1 where match a against ("(+aaa* +bbb1*)" in boolean mode);
drop table t1;
#
@@ -253,10 +255,17 @@ select * from t1 join t2 using(`t1_id`) where match (t1.name, t2.name) against('
# bug with many short (< ft_min_word_len) words in boolean search
#
select * from t2 where match name against ('a* b* c* d* e* f*' in boolean mode);
-
drop table t1,t2;
#
+# bug with repair-by-sort and incorrect records estimation
+#
+
+create table t1 (a text, fulltext key (a));
+insert into t1 select "xxxx yyyy zzzz";
+drop table t1;
+
+#
# UTF8
#
SET NAMES latin1;
@@ -272,7 +281,7 @@ SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück');
SET NAMES latin1;
SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück');
SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrueck');
-SELECT t, collation(t),MATCH t AGAINST ('Osnabruck') FROM t1 WHERE MATCH t AGAINST ('Osnabruck');
+SELECT t, collation(t),FORMAT(MATCH t AGAINST ('Osnabruck'),6) FROM t1 WHERE MATCH t AGAINST ('Osnabruck');
#alter table t1 modify t text character set latin1 collate latin1_german2_ci not null;
alter table t1 modify t varchar(200) collate latin1_german2_ci not null;
SELECT t, collation(t) FROM t1 WHERE MATCH t AGAINST ('Osnabrück');
@@ -288,3 +297,27 @@ insert into t1 (s) values ('pära para para'),('para para para');
select * from t1 where match(s) against('para' in boolean mode);
select * from t1 where match(s) against('par*' in boolean mode);
DROP TABLE t1;
+
+#
+# icc -ip bug (ip = interprocedural optimization)
+# bug#5528
+#
+CREATE TABLE t1 (h text, FULLTEXT (h));
+INSERT INTO t1 VALUES ('Jesses Hasse Ling and his syncopators of Swing');
+REPAIR TABLE t1;
+select count(*) from t1;
+drop table t1;
+
+#
+# bug#6784
+# mi_flush_bulk_insert (on dup key error in mi_write)
+# was mangling info->dupp_key_pos
+#
+
+create table t1 (a int primary key, b text, fulltext(b));
+create table t2 (a int, b text);
+insert t1 values (1, "aaaa"), (2, "bbbb");
+insert t2 values (10, "aaaa"), (2, "cccc");
+replace t1 select * from t2;
+drop table t1, t2;
+
diff --git a/mysql-test/t/fulltext_order_by.test b/mysql-test/t/fulltext_order_by.test
index f8afe49d95d..5856f68ec9e 100644
--- a/mysql-test/t/fulltext_order_by.test
+++ b/mysql-test/t/fulltext_order_by.test
@@ -10,25 +10,25 @@ CREATE TABLE t1 (
INSERT INTO t1 (message) VALUES ("Testing"),("table"),("testbug"),
("steve"),("is"),("cool"),("steve is cool");
# basic MATCH
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve');
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve');
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve');
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE);
# MATCH + ORDER BY (with ft-ranges)
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a;
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE MATCH (message) AGAINST ('steve') ORDER BY a;
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a;
# MATCH + ORDER BY (with normal ranges) + UNIQUE
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC;
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve') ORDER BY a DESC;
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a in (2,7,4) and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY a DESC;
# MATCH + ORDER BY + UNIQUE (const_table)
-SELECT a, MATCH (message) AGAINST ('steve') FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1;
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve') ORDER BY 1;
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) FROM t1 WHERE a=7 and MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) ORDER BY 1;
# ORDER BY MATCH
-SELECT a, MATCH (message) AGAINST ('steve') as rel FROM t1 ORDER BY rel;
+SELECT a, FORMAT(MATCH (message) AGAINST ('steve'),6) as rel FROM t1 ORDER BY rel;
SELECT a, MATCH (message) AGAINST ('steve' IN BOOLEAN MODE) as rel FROM t1 ORDER BY rel;
drop table t1;
diff --git a/mysql-test/t/func_compress.test b/mysql-test/t/func_compress.test
index 7b70289d2c0..f46589e9e0e 100644
--- a/mysql-test/t/func_compress.test
+++ b/mysql-test/t/func_compress.test
@@ -38,7 +38,10 @@ drop table t1;
#
# Bug #5497: a problem with large strings
+# note that when LOW_MEMORY is set the "test" below is meaningless
#
set @@max_allowed_packet=1048576*100;
-select compress(repeat('aaaaaaaaaa', 10000000)) is null;
+--replace_result "''" XXX "'1'" XXX
+eval select compress(repeat('aaaaaaaaaa', IF('$LOW_MEMORY', 10, 10000000))) is null;
+
diff --git a/mysql-test/t/func_gconcat.test b/mysql-test/t/func_gconcat.test
index e0737a42221..c5147dc381e 100644
--- a/mysql-test/t/func_gconcat.test
+++ b/mysql-test/t/func_gconcat.test
@@ -277,3 +277,12 @@ select group_concat(b order by b) from t1 group by a;
select group_concat(distinct b order by b) from t1 group by a;
drop table t1;
+
+#
+# Bug #6475
+#
+
+create table t1 (a char(3), b char(20), primary key (a, b));
+insert into t1 values ('ABW', 'Dutch'), ('ABW', 'English');
+select group_concat(a) from t1 group by b;
+drop table t1;
diff --git a/mysql-test/t/func_group.test b/mysql-test/t/func_group.test
index e67d4fa3757..5e3881d74ed 100644
--- a/mysql-test/t/func_group.test
+++ b/mysql-test/t/func_group.test
@@ -385,6 +385,17 @@ select coercibility(max(a)) from t1;
drop table t1;
#
+# Bug #6658 MAX(column) returns incorrect coercibility
+#
+create table t1 (a char character set latin2);
+insert into t1 values ('a'),('b');
+select charset(max(a)), coercibility(max(a)),
+ charset(min(a)), coercibility(min(a)) from t1;
+create table t2 select max(a),min(a) from t1;
+show create table t2;
+drop table t2,t1;
+
+#
# aggregate functions on static tables
#
create table t1 (a int);
diff --git a/mysql-test/t/func_in.test b/mysql-test/t/func_in.test
index 22079377ad2..3cd8c064817 100644
--- a/mysql-test/t/func_in.test
+++ b/mysql-test/t/func_in.test
@@ -89,3 +89,10 @@ select 1 in ('1.0',2.0);
select 1 in (1.0,'2.0');
select 1 in ('1.1',2);
select 1 in ('1.1',2.0);
+
+# Test case for bug #6365
+
+create table t1 (a char(20) character set binary);
+insert into t1 values ('aa'), ('bb');
+select * from t1 where a in (NULL, 'aa');
+drop table t1;
diff --git a/mysql-test/t/func_str.test b/mysql-test/t/func_str.test
index 3eab694ee05..d5a3e80c417 100644
--- a/mysql-test/t/func_str.test
+++ b/mysql-test/t/func_str.test
@@ -83,6 +83,12 @@ select hex(unhex("1")), hex(unhex("12")), hex(unhex("123")), hex(unhex("1234")),
select length(unhex(md5("abrakadabra")));
#
+# Bug #6564: QUOTE(NULL
+#
+
+select concat('a', quote(NULL));
+
+#
# Wrong usage of functions
#
diff --git a/mysql-test/t/func_time.test b/mysql-test/t/func_time.test
index 0ca3d86818e..b6240054e0a 100644
--- a/mysql-test/t/func_time.test
+++ b/mysql-test/t/func_time.test
@@ -230,6 +230,13 @@ select unix_timestamp(@a);
select unix_timestamp('1969-12-01 19:00:01');
#
+# Test for bug #6439 "unix_timestamp() function returns wrong datetime
+# values for too big argument". It should return error instead.
+#
+select from_unixtime(0);
+select from_unixtime(2145916800);
+
+#
# Test types from + INTERVAL
#
diff --git a/mysql-test/t/gis.test b/mysql-test/t/gis.test
index 739fced1f29..86c34eacbc5 100644
--- a/mysql-test/t/gis.test
+++ b/mysql-test/t/gis.test
@@ -284,3 +284,78 @@ drop table t1;
create table t1 select POINT(1,3);
show create table t1;
drop table t1;
+
+CREATE TABLE `t1` (`object_id` bigint(20) unsigned NOT NULL default '0', `geo`
+geometry NOT NULL default '') ENGINE=MyISAM ;
+
+insert into t1 values ('85984',GeomFromText('MULTIPOLYGON(((-115.006363
+36.305435,-114.992394 36.305202,-114.991219 36.305975,-114.991163
+36.306845,-114.989432 36.309452,-114.978275 36.312642,-114.977363
+36.311978,-114.975327 36.312344,-114.96502 36.31597,-114.963364
+36.313629,-114.961723 36.313721,-114.956398 36.316057,-114.951882
+36.320979,-114.947073 36.323475,-114.945207 36.326451,-114.945207
+36.326451,-114.944132 36.326061,-114.94003 36.326588,-114.924017
+36.334484,-114.923281 36.334146,-114.92564 36.331504,-114.94072
+36.319282,-114.945348 36.314812,-114.948091 36.314762,-114.951755
+36.316211,-114.952446 36.313883,-114.952644 36.309488,-114.944725
+36.313083,-114.93706 36.32043,-114.932478 36.323497,-114.924556
+36.327708,-114.922608 36.329715,-114.92009 36.328695,-114.912105
+36.323566,-114.901647 36.317952,-114.897436 36.313968,-114.895344
+36.309573,-114.891699 36.304398,-114.890569 36.303551,-114.886356
+36.302702,-114.885141 36.301351,-114.885709 36.297391,-114.892499
+36.290893,-114.902142 36.288974,-114.904941 36.288838,-114.905308
+36.289845,-114.906325 36.290395,-114.909916 36.289549,-114.914527
+36.287535,-114.918797 36.284423,-114.922982 36.279731,-114.924113
+36.277282,-114.924057 36.275817,-114.927733 36.27053,-114.929354
+36.269029,-114.929354 36.269029,-114.950856 36.268715,-114.950768
+36.264324,-114.960206 36.264293,-114.960301 36.268943,-115.006662
+36.268929,-115.008583 36.265619,-115.00665 36.264247,-115.006659
+36.246873,-115.006659 36.246873,-115.006838 36.247697,-115.010764
+36.247774,-115.015609 36.25113,-115.015765 36.254505,-115.029517
+36.254619,-115.038573 36.249317,-115.038573 36.249317,-115.023403
+36.25841,-115.023873 36.258994,-115.031845 36.259829,-115.03183
+36.261053,-115.025561 36.261095,-115.036417 36.274632,-115.033729
+36.276041,-115.032217 36.274851,-115.029845 36.273959,-115.029934
+36.274966,-115.025763 36.274896,-115.025406 36.281044,-115.028731
+36.284471,-115.036497 36.290377,-115.042071 36.291039,-115.026759
+36.298478,-115.008995 36.301966,-115.006363 36.305435),(-115.079835
+36.244369,-115.079735 36.260186,-115.076435 36.262369,-115.069758
+36.265,-115.070235 36.268757,-115.064542 36.268655,-115.061843
+36.269857,-115.062676 36.270693,-115.06305 36.272344,-115.059051
+36.281023,-115.05918 36.283008,-115.060591 36.285246,-115.061913
+36.290022,-115.062499 36.306353,-115.062499 36.306353,-115.060918
+36.30642,-115.06112 36.289779,-115.05713 36.2825,-115.057314
+36.279446,-115.060779 36.274659,-115.061366 36.27209,-115.057858
+36.26557,-115.055805 36.262883,-115.054688 36.262874,-115.047335
+36.25037,-115.044234 36.24637,-115.052434 36.24047,-115.061734
+36.23507,-115.061934 36.22677,-115.061934 36.22677,-115.061491
+36.225267,-115.062024 36.218194,-115.060134 36.218278,-115.060133
+36.210771,-115.057833 36.210771,-115.057433 36.196271,-115.062233
+36.196271,-115.062233 36.190371,-115.062233 36.190371,-115.065533
+36.190371,-115.071333 36.188571,-115.098331 36.188275,-115.098331
+36.188275,-115.098435 36.237569,-115.097535 36.240369,-115.097535
+36.240369,-115.093235 36.240369,-115.089135 36.240469,-115.083135
+36.240569,-115.083135 36.240569,-115.079835
+36.244369)))')),('85998',GeomFromText('MULTIPOLYGON(((-115.333107
+36.264587,-115.333168 36.280638,-115.333168 36.280638,-115.32226
+36.280643,-115.322538 36.274311,-115.327222 36.274258,-115.32733
+36.263026,-115.330675 36.262984,-115.332132 36.264673,-115.333107
+36.264587),(-115.247239 36.247066,-115.247438 36.218267,-115.247438
+36.218267,-115.278525 36.219263,-115.278525 36.219263,-115.301545
+36.219559,-115.332748 36.219197,-115.332757 36.220041,-115.332757
+36.220041,-115.332895 36.233514,-115.349023 36.233479,-115.351489
+36.234475,-115.353681 36.237021,-115.357106 36.239789,-115.36519
+36.243331,-115.368156 36.243487,-115.367389 36.244902,-115.364553
+36.246014,-115.359219 36.24616,-115.356186 36.248025,-115.353347
+36.248004,-115.350813 36.249507,-115.339673 36.25387,-115.333069
+36.255018,-115.333069 36.255018,-115.333042 36.247767,-115.279039
+36.248666,-115.263639 36.247466,-115.263839 36.252766,-115.261439
+36.252666,-115.261439 36.247366,-115.247239 36.247066)))'));
+
+select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
+t1 where object_id=85998;
+
+select object_id, geometrytype(geo), ISSIMPLE(GEO), ASTEXT(centroid(geo)) from
+t1 where object_id=85984;
+
+drop table t1;
diff --git a/mysql-test/t/grant.test b/mysql-test/t/grant.test
index 4b1601c245f..cc3d0b35ab3 100644
--- a/mysql-test/t/grant.test
+++ b/mysql-test/t/grant.test
@@ -98,6 +98,30 @@ GRANT FILE on mysqltest.* to mysqltest_1@localhost;
select 1; -- To test that the previous command didn't cause problems
#
+# Bug #4898: User privileges depending on ORDER BY Settings of table db
+#
+insert into mysql.user (host, user) values ('localhost', 'test11');
+insert into mysql.db (host, db, user, select_priv) values
+('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
+alter table mysql.db order by db asc;
+flush privileges;
+show grants for test11@localhost;
+alter table mysql.db order by db desc;
+flush privileges;
+show grants for test11@localhost;
+delete from mysql.user where user='test11';
+delete from mysql.db where user='test11';
+
+#
+# Bug#6123: GRANT USAGE inserts useless Db row
+#
+create database mysqltest1;
+grant usage on mysqltest1.* to test6123 identified by 'magic123';
+select host,db,user,select_priv,insert_priv from mysql.db where db="mysqltest1";
+delete from mysql.user where user='test6123';
+drop database mysqltest1;
+
+#
# Test for 'drop user', 'revoke privileges, grant'
#
@@ -138,16 +162,18 @@ grant select(a) on test.t1 to drop_user1@localhost;
grant select on test.t1 to drop_user2@localhost;
grant select on test.* to drop_user3@localhost;
grant select on *.* to drop_user4@localhost;
---error 1268
+# Drop user now implicitly revokes all privileges.
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
+--error 1269
revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
drop_user3@localhost, drop_user4@localhost;
+--error 1396
drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
drop_user4@localhost;
drop table t1;
grant usage on *.* to mysqltest_1@localhost identified by "password";
-grant select, update, insert on test.* to mysqltest@localhost;
+grant select, update, insert on test.* to mysqltest_1@localhost;
show grants for mysqltest_1@localhost;
drop user mysqltest_1@localhost;
@@ -171,25 +197,13 @@ GRANT SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ TO ÀÚÅÒ@localhost;
SHOW GRANTS FOR ÀÚÅÒ@localhost;
REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost;
+# Revoke does not drop user. Leave a clean user table for the next tests.
+DROP USER ÀÚÅÒ@localhost;
+
DROP DATABASE ÂÄ;
SET NAMES latin1;
#
-# Bug #4898: User privileges depending on ORDER BY Settings of table db
-#
-insert into mysql.user (host, user) values ('localhost', 'test11');
-insert into mysql.db (host, db, user, select_priv) values
-('localhost', 'a%', 'test11', 'Y'), ('localhost', 'ab%', 'test11', 'Y');
-alter table mysql.db order by db asc;
-flush privileges;
-show grants for test11@localhost;
-alter table mysql.db order by db desc;
-flush privileges;
-show grants for test11@localhost;
-delete from mysql.user where user='test11';
-delete from mysql.db where user='test11';
-
-#
# Bug #5831: REVOKE ALL PRIVILEGES, GRANT OPTION does not revoke everything
#
USE test;
@@ -258,6 +272,19 @@ DROP DATABASE testdb8;
DROP DATABASE testdb9;
DROP DATABASE testdb10;
+#
+# Bug #6932: a problem with 'revoke ALL PRIVILEGES'
+#
+
+create table t1(a int, b int, c int, d int);
+grant insert(b), insert(c), insert(d), insert(a) on t1 to grant_user@localhost;
+show grants for grant_user@localhost;
+select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv;
+revoke ALL PRIVILEGES on t1 from grant_user@localhost;
+show grants for grant_user@localhost;
+select Host,Db,User,Table_name,Column_name,Column_priv from mysql.columns_priv;
+drop user grant_user@localhost;
+drop table t1;
#
# just SHOW PRIVILEGES test
diff --git a/mysql-test/t/grant2.test b/mysql-test/t/grant2.test
index fe4a5b55b82..69c42ce2252 100644
--- a/mysql-test/t/grant2.test
+++ b/mysql-test/t/grant2.test
@@ -78,3 +78,152 @@ use test;
delete from mysql.user where user like 'mysqltest\_%';
delete from mysql.db where user like 'mysqltest\_%';
flush privileges;
+
+#
+# Create and drop user
+#
+set sql_mode='maxdb';
+--disable_warnings
+drop table if exists t1, t2;
+--enable_warnings
+create table t1(c1 int);
+create table t2(c1 int, c2 int);
+#
+# Three forms of CREATE USER
+create user 'mysqltest_1';
+--error 1396
+create user 'mysqltest_1';
+create user 'mysqltest_2' identified by 'Mysqltest-2';
+create user 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff';
+grant select on *.* to 'mysqltest_2';
+grant insert on test.* to 'mysqltest_2';
+grant update on test.t1 to 'mysqltest_2';
+grant update (c2) on test.t2 to 'mysqltest_2';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+show grants for 'mysqltest_1';
+show grants for 'mysqltest_2';
+#
+# Drop
+drop user 'mysqltest_1';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+--error 1141
+show grants for 'mysqltest_1';
+#
+# Rename
+rename user 'mysqltest_2' to 'mysqltest_1';
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+select host,db,user from mysql.db where user like 'mysqltest_%' order by host,db,user;
+select host,db,user,table_name from mysql.tables_priv where user like 'mysqltest_%' order by host,db,user,table_name;
+select host,db,user,table_name,column_name from mysql.columns_priv where user like 'mysqltest_%' order by host,db,user,table_name,column_name;
+show grants for 'mysqltest_1';
+drop user 'mysqltest_1', 'mysqltest_3';
+#
+# Grant must not create user
+--error 1211
+grant all on test.t1 to 'mysqltest_1';
+--error 1396
+drop user 'mysqltest_1';
+#
+# Cleanup
+drop table t1, t2;
+#
+# Add a stray record
+insert into mysql.db set user='mysqltest_1', db='%', host='%';
+flush privileges;
+--error 1141
+show grants for 'mysqltest_1';
+--error 1269
+revoke all privileges, grant option from 'mysqltest_1';
+drop user 'mysqltest_1';
+select host,db,user from mysql.db where user = 'mysqltest_1' order by host,db,user;
+#
+# Add a stray record
+insert into mysql.tables_priv set host='%', db='test', user='mysqltest_1', table_name='t1';
+flush privileges;
+--error 1141
+show grants for 'mysqltest_1';
+drop user 'mysqltest_1';
+select host,db,user,table_name from mysql.tables_priv where user = 'mysqltest_1' order by host,db,user,table_name;
+#
+# Add a stray record
+insert into mysql.columns_priv set host='%', db='test', user='mysqltest_1', table_name='t1', column_name='c1';
+flush privileges;
+--error 1141
+show grants for 'mysqltest_1';
+drop user 'mysqltest_1';
+select host,db,user,table_name,column_name from mysql.columns_priv where user = 'mysqltest_1' order by host,db,user,table_name,column_name;
+#
+# Handle multi user lists
+create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+create user 'mysqltest_1', 'mysqltest_2' identified by 'Mysqltest-2', 'mysqltest_3' identified by password 'fffffffffffffffffffffffffffffffffffffffff';
+rename user 'mysqltest_1' to 'mysqltest_1a', 'mysqltest_2' TO 'mysqltest_2a', 'mysqltest_3' TO 'mysqltest_3a';
+--error 1396
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+drop user 'mysqltest_1a', 'mysqltest_2a', 'mysqltest_3a';
+#
+# Let one of multiple users fail
+create user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+--error 1396
+create user 'mysqltest_1a', 'mysqltest_2', 'mysqltest_3a';
+--error 1396
+rename user 'mysqltest_1a' to 'mysqltest_1b', 'mysqltest_2a' TO 'mysqltest_2b', 'mysqltest_3a' TO 'mysqltest_3b';
+drop user 'mysqltest_1', 'mysqltest_2', 'mysqltest_3';
+--error 1396
+drop user 'mysqltest_1b', 'mysqltest_2b', 'mysqltest_3b';
+#
+# Obsolete syntax has been dropped
+create user 'mysqltest_2' identified by 'Mysqltest-2';
+--error 1064
+drop user 'mysqltest_2' identified by 'Mysqltest-2';
+#
+# Strange user names
+create user '%@b'@'b';
+show grants for '%@b'@'b';
+grant select on mysql.* to '%@b'@'b';
+show grants for '%@b'@'b';
+rename user '%@b'@'b' to '%@a'@'a';
+--error 1141
+show grants for '%@b'@'b';
+show grants for '%@a'@'a';
+drop user '%@a'@'a';
+#
+# USAGE WITH GRANT OPTION is sufficient.
+create user mysqltest_2@localhost;
+grant usage on *.* to mysqltest_2@localhost with grant option;
+connect (user2,localhost,mysqltest_2,,);
+connection user2;
+--error 1044
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+create user mysqltest_A@'%';
+rename user mysqltest_A@'%' to mysqltest_B@'%';
+drop user mysqltest_B@'%';
+disconnect user2;
+connection default;
+drop user mysqltest_2@localhost;
+#
+# ALL PRIVILEGES without GRANT OPTION is not sufficient.
+create user mysqltest_3@localhost;
+grant all privileges on mysql.* to mysqltest_3@localhost;
+connect (user3,localhost,mysqltest_3,,);
+connection user3;
+select host,user,password from mysql.user where user like 'mysqltest_%' order by host,user,password;
+insert into mysql.user set host='%', user='mysqltest_B';
+--error 1044
+create user mysqltest_A@'%';
+--error 1044
+rename user mysqltest_B@'%' to mysqltest_C@'%';
+--error 1044
+drop user mysqltest_B@'%';
+disconnect user3;
+connection default;
+drop user mysqltest_B@'%';
+drop user mysqltest_3@localhost;
+#
+
diff --git a/mysql-test/t/group_min_max.test b/mysql-test/t/group_min_max.test
index 0eb6fc49990..17a6cc88597 100644
--- a/mysql-test/t/group_min_max.test
+++ b/mysql-test/t/group_min_max.test
@@ -598,8 +598,10 @@ drop table t3;
# Bug #6142: a problem with the empty innodb table
#
+--disable_warnings
create table t1 (
a varchar(30), b varchar(30), primary key(a), key(b)
) engine=innodb;
+--enable_warnings
select distinct a from t1;
drop table t1;
diff --git a/mysql-test/t/having.test b/mysql-test/t/having.test
index 12a44fd75dc..b0fc600030b 100644
--- a/mysql-test/t/having.test
+++ b/mysql-test/t/having.test
@@ -2,7 +2,7 @@
#
--disable_warnings
-drop table if exists t1,t2;
+drop table if exists t1,t2,t3;
--enable_warnings
create table t1 (a int);
@@ -122,3 +122,196 @@ from t1 a left join t3 b on a.id=b.order_id
group by a.id, a.description
having (a.description is not null) and (c=0);
drop table t1,t2,t3;
+
+
+#
+# Tests for WL#1972 CORRECT EVALUATION OF COLUMN REFERENCES IN THE HAVING CLAUSE
+# Per the SAP VERI tests and WL#1972, MySQL must ensure that HAVING can
+# correctly evaluate column references from the GROUP BY clause, even if the
+# same references are not also found in the select list.
+#
+
+# set global sql_mode='ansi';
+# set session sql_mode='ansi';
+
+create table t1 (col1 int, col2 varchar(5), col_t1 int);
+create table t2 (col1 int, col2 varchar(5), col_t2 int);
+create table t3 (col1 int, col2 varchar(5), col_t3 int);
+
+insert into t1 values(10,'hello',10);
+insert into t1 values(20,'hello',20);
+insert into t1 values(30,'hello',30);
+insert into t1 values(10,'bye',10);
+insert into t1 values(10,'sam',10);
+insert into t1 values(10,'bob',10);
+
+insert into t2 select * from t1;
+insert into t3 select * from t1;
+
+select count(*) from t1 group by col1 having col1 = 10;
+select count(*) as count_col1 from t1 group by col1 having col1 = 10;
+select count(*) as count_col1 from t1 as tmp1 group by col1 having col1 = 10;
+select count(*) from t1 group by col2 having col2 = 'hello';
+--error 1054
+select count(*) from t1 group by col2 having col1 = 10;
+select col1 as count_col1 from t1 as tmp1 group by col1 having col1 = 10;
+select col1 as count_col1 from t1 as tmp1 group by col1 having count_col1 = 10;
+select col1 as count_col1 from t1 as tmp1 group by count_col1 having col1 = 10;
+# ANSI: should return SQLSTATE 42000 Syntax error or access violation
+# MySQL: returns 10 - because of GROUP BY name resolution
+select col1 as count_col1 from t1 as tmp1 group by count_col1 having count_col1 = 10;
+# ANSI: should return SQLSTATE 42000 Syntax error or access violation
+# MySQL: returns 10 - because of GROUP BY name resolution
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col1 = 10;
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having count_col1 = 10;
+select col1 as count_col1,col2 from t1 as tmp1 group by col1,col2 having col2 = 'hello';
+select col1 as count_col1,col2 as group_col2 from t1 as tmp1 group by col1,col2 having group_col2 = 'hello';
+--error 1064
+select sum(col1) as co12 from t1 group by col2 having col2 10;
+select sum(col1) as co2, count(col2) as cc from t1 group by col1 having col1 =10;
+--error 1054
+select t2.col2 from t2 group by t2.col1, t2.col2 having t1.col1 <= 10;
+
+
+#
+# queries with nested sub-queries
+#
+
+# the having column is resolved in the same query
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having t2.col1 <= 10);
+
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2
+ having t2.col1 <=
+ (select min(t3.col1) from t3));
+
+# the having column is resolved in the SELECT clause of the outer query -
+# works in ANSI
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having t1.col1 <= 10);
+
+# the having column is resolved in the SELECT clause of the outer query -
+# error in ANSI, works with MySQL extension
+select t1.col1 as tmp_col from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having tmp_col <= 10);
+
+# the having column is resolved in the FROM clause of the outer query -
+# works in ANSI
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having col_t1 <= 10);
+
+# Item_field must be resolved in the same way as Item_ref
+select sum(col1) from t1
+group by col_t1
+having (select col_t1 from t2 where col_t1 = col_t2 order by col_t2 limit 1);
+
+# nested queries with HAVING, inner having column resolved in outer FROM clause
+# the outer having column is not referenced in GROUP BY which results in an error
+--error 1054
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having col_t1 <= 10)
+having col_t1 <= 20;
+
+# both having columns are resolved in the GROUP clause of the outer query
+select t1.col1 from t1
+where t1.col2 in
+ (select t2.col2 from t2
+ group by t2.col1, t2.col2 having col_t1 <= 10)
+group by col_t1
+having col_t1 <= 20;
+
+
+#
+# nested HAVING clauses
+#
+
+# non-correlated subqueries
+select col_t1, sum(col1) from t1
+group by col_t1
+having col_t1 > 10 and
+ exists (select sum(t2.col1) from t2
+ group by t2.col2 having t2.col2 > 'b');
+
+# correlated subqueries - inner having column 't1.col2' resolves to
+# the outer FROM clause, which cannot be used because the outer query
+# is grouped
+--error 1054
+select sum(col1) from t1
+group by col_t1
+having col_t1 in (select sum(t2.col1) from t2
+ group by t2.col2, t2.col1 having t2.col1 = t1.col1);
+
+# correlated subqueries - inner having column 'col_t1' resolves to
+# the outer GROUP clause
+select sum(col1) from t1
+group by col_t1
+having col_t1 in (select sum(t2.col1) from t2
+ group by t2.col2, t2.col1 having t2.col1 = col_t1);
+
+#
+# queries with joins and ambiguous column names
+#
+--error 1052
+select t1.col1, t2.col1 from t1, t2 where t1.col1 = t2.col1
+group by t1.col1, t2.col1 having col1 = 2;
+
+--error 1052
+select t1.col1*10+t2.col1 from t1,t2 where t1.col1=t2.col1
+group by t1.col1, t2.col1 having col1 = 2;
+
+drop table t1, t2, t3;
+
+# More queries to test ANSI compatibility
+create table t1 (s1 int);
+insert into t1 values (1),(2),(3);
+
+select count(*) from t1 group by s1 having s1 is null;
+
+select s1*0 as s1 from t1 group by s1 having s1 <> 0;
+# ANSI requires: 3 rows
+# MySQL returns: 0 rows - because of GROUP BY name resolution
+
+select s1*0 from t1 group by s1 having s1 = 0;
+
+select s1 from t1 group by 1 having 1 = 0;
+
+select count(s1) from t1 group by s1 having count(1+1)=2;
+# ANSI requires: 3 rows
+# MySQL returns: 0 rows - because of GROUP BY name resolution
+
+select count(s1) from t1 group by s1 having s1*0=0;
+
+-- error 1052
+select * from t1 a, t1 b group by a.s1 having s1 is null;
+# ANSI requires: 0 rows
+# MySQL returns:
+# "ERROR 1052 (23000): Column 's1' in having clause is ambiguous"
+# I think the column is ambiguous in ANSI too.
+# It is the same as:
+# select a.s1, b.s1 from t1 a, t1 b group by a.s1 having s1 is null;
+# currently we first check SELECT, thus s1 is ambiguous.
+
+drop table t1;
+
+create table t1 (s1 char character set latin1 collate latin1_german1_ci);
+insert into t1 values ('ü'),('y');
+
+select s1,count(s1) from t1
+group by s1 collate latin1_swedish_ci having s1 = 'y';
+# ANSI requires: 1 row, with count(s1) = 2
+# MySQL returns: 1 row, with count(s1) = 1
+
+drop table t1;
diff --git a/mysql-test/t/heap.test b/mysql-test/t/heap.test
index e1776245d9e..31b7f997519 100644
--- a/mysql-test/t/heap.test
+++ b/mysql-test/t/heap.test
@@ -3,7 +3,7 @@
#
--disable_warnings
-drop table if exists t1;
+drop table if exists t1,t2,t3;
--enable_warnings
create table t1 (a int not null,b int not null, primary key (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
@@ -174,3 +174,233 @@ CREATE TABLE t1 (a INT NOT NULL, B INT, KEY(B)) ENGINE=HEAP;
INSERT INTO t1 VALUES(1,1), (1,NULL);
SELECT * FROM t1 WHERE B is not null;
DROP TABLE t1;
+
+#
+# Bug #6748
+# heap_rfirst() doesn't work (and never did!)
+#
+CREATE TABLE t1 (pseudo char(35) PRIMARY KEY, date int(10) unsigned NOT NULL) ENGINE=HEAP;
+INSERT INTO t1 VALUES ('massecot',1101106491),('altec',1101106492),('stitch+',1101106304),('Seb Corgan',1101106305),('beerfilou',1101106263),('flaker',1101106529),('joce8',5),('M4vrick',1101106418),('gabay008',1101106525),('Vamp irX',1101106291),('ZoomZip',1101106546),('rip666',1101106502),('CBP ',1101106397),('guezpard',1101106496);
+DELETE FROM t1 WHERE date<1101106546;
+SELECT * FROM t1;
+DROP TABLE t1;
+
+#
+# Bug #6878: a problem with small length records
+#
+
+create table t1(a char(2)) engine=memory;
+insert into t1 values (NULL), (NULL);
+delete from t1 where a is null;
+insert into t1 values ('2'), ('3');
+select * from t1;
+drop table t1;
+
+#
+# Test varchar
+# We can't use varchar.inc becasue heap doesn't support blob's
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=HEAP;
+
+#
+# Simple basic test that endspace is saved
+#
+
+create table t1 (v varchar(10), c char(10), t varchar(50));
+insert into t1 values('+ ', '+ ', '+ ');
+set @a=repeat(' ',20);
+insert into t1 values (concat('+',@a),concat('+',@a),concat('+',@a));
+select concat('*',v,'*',c,'*',t,'*') from t1;
+
+# Check how columns are copied
+show create table t1;
+create table t2 like t1;
+show create table t2;
+create table t3 select * from t1;
+show create table t3;
+alter table t1 modify c varchar(10);
+show create table t1;
+alter table t1 modify v char(10);
+show create table t1;
+alter table t1 modify t varchar(10);
+show create table t1;
+select concat('*',v,'*',c,'*',t,'*') from t1;
+drop table t1,t2,t3;
+
+#
+# Testing of keys
+#
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v), key(c), key(t(10)));
+show create table t1;
+disable_query_log;
+let $1=10;
+while ($1)
+{
+ let $2=27;
+ eval set @space=repeat(' ',10-$1);
+ while ($2)
+ {
+ eval set @char=char(ascii('a')+$2-1);
+ insert into t1 values(concat(@char,@space),concat(@char,@space),concat(@char,@space));
+ dec $2;
+ }
+ dec $1;
+}
+enable_query_log;
+select count(*) from t1;
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+select count(*) from t1 where c='a';
+select count(*) from t1 where t='a';
+select count(*) from t1 where v='a ';
+select count(*) from t1 where c='a ';
+select count(*) from t1 where t='a ';
+select count(*) from t1 where v between 'a' and 'a ';
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+select count(*) from t1 where v like 'a%';
+select count(*) from t1 where c like 'a%';
+select count(*) from t1 where t like 'a%';
+select count(*) from t1 where v like 'a %';
+explain select count(*) from t1 where v='a ';
+explain select count(*) from t1 where c='a ';
+explain select count(*) from t1 where t='a ';
+explain select count(*) from t1 where v like 'a%';
+explain select count(*) from t1 where v between 'a' and 'a ';
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+
+--error 1062
+alter table t1 add unique(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*'));
+explain select * from t1 where v='a';
+
+# GROUP BY
+
+select v,count(*) from t1 group by v limit 10;
+select v,count(t) from t1 group by v limit 10;
+select v,count(c) from t1 group by v limit 10;
+select sql_big_result v,count(t) from t1 group by v limit 10;
+select sql_big_result v,count(c) from t1 group by v limit 10;
+select c,count(*) from t1 group by c limit 10;
+select c,count(t) from t1 group by c limit 10;
+select sql_big_result c,count(t) from t1 group by c limit 10;
+select t,count(*) from t1 group by t limit 10;
+select t,count(t) from t1 group by t limit 10;
+select sql_big_result t,count(t) from t1 group by t limit 10;
+drop table t1;
+
+#
+# Test unique keys
+#
+
+create table t1 (a char(10), unique (a));
+insert into t1 values ('a');
+--error 1062
+insert into t1 values ('a ');
+
+alter table t1 modify a varchar(10);
+--error 1062
+insert into t1 values ('a '),('a '),('a '),('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+update t1 set a='a ' where a like 'a ';
+update t1 set a='a ' where a like 'a ';
+drop table t1;
+
+#
+# Testing of btree keys
+#
+
+create table t1 (v varchar(10), c char(10), t varchar(50), key using btree (v), key using btree (c), key using btree (t(10)));
+show create table t1;
+disable_query_log;
+let $1=10;
+while ($1)
+{
+ let $2=27;
+ eval set @space=repeat(' ',10-$1);
+ while ($2)
+ {
+ eval set @char=char(ascii('a')+$2-1);
+ insert into t1 values(concat(@char,@space),concat(@char,@space),concat(@char,@space));
+ dec $2;
+ }
+ dec $1;
+}
+enable_query_log;
+select count(*) from t1;
+insert into t1 values(concat('a',char(1)),concat('a',char(1)),concat('a',char(1)));
+select count(*) from t1 where v='a';
+select count(*) from t1 where c='a';
+select count(*) from t1 where t='a';
+select count(*) from t1 where v='a ';
+select count(*) from t1 where c='a ';
+select count(*) from t1 where t='a ';
+select count(*) from t1 where v between 'a' and 'a ';
+--replace_column 9 #
+select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+--replace_column 9 #
+explain select count(*) from t1 where v='a ';
+--replace_column 9 #
+explain select count(*) from t1 where c='a ';
+--replace_column 9 #
+explain select count(*) from t1 where t='a ';
+--replace_column 9 #
+explain select count(*) from t1 where v like 'a%';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ';
+--replace_column 9 #
+explain select count(*) from t1 where v between 'a' and 'a ' and v between 'a ' and 'b\n';
+
+--error 1062
+alter table t1 add unique(v);
+select concat('*',v,'*',c,'*',t,'*') as qq from t1 where v='a' order by length(concat('*',v,'*',c,'*',t,'*'));
+explain select * from t1 where v='a';
+
+drop table t1;
+
+#
+# Test unique btree keys
+#
+
+create table t1 (a char(10), unique using btree (a)) engine=heap;
+insert into t1 values ('a');
+--error 1062
+insert into t1 values ('a ');
+
+alter table t1 modify a varchar(10);
+--error 1062
+insert into t1 values ('a '),('a '),('a '),('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+--error 1062
+insert into t1 values ('a ');
+update t1 set a='a ' where a like 'a ';
+update t1 set a='a ' where a like 'a ';
+drop table t1;
+
+#
+# test show create table
+#
+
+create table t1 (v varchar(10), c char(10), t varchar(50), key(v(5)), key(c(5)), key(t(5)));
+show create table t1;
+drop table t1;
+
+create table t1 (v varchar(65530), key(v(10)));
+show create table t1;
+insert into t1 values(repeat('a',65530));
+select length(v) from t1 where v=repeat('a',65530);
+drop table t1;
+
+#
+# Reset varchar test
+#
+eval set storage_engine=$default;
diff --git a/mysql-test/t/heap_hash.test b/mysql-test/t/heap_hash.test
index 412b6f2e705..6d8fdec4b9e 100644
--- a/mysql-test/t/heap_hash.test
+++ b/mysql-test/t/heap_hash.test
@@ -3,7 +3,7 @@
#
--disable_warnings
-drop table if exists t1;
+drop table if exists t1,t2;
--enable_warnings
create table t1 (a int not null,b int not null, primary key using HASH (a)) engine=heap comment="testing heaps" avg_row_length=100 min_rows=1 max_rows=100;
@@ -141,3 +141,113 @@ INSERT into t1 values (1),(2),(3),(4),(5),(6),(7),(8),(9),(10),(11);
DELETE from t1 where a < 100;
SELECT * from t1;
DROP TABLE t1;
+
+
+#
+# Hash index # records estimate test
+#
+create table t1
+(
+ a char(8) not null,
+ b char(20) not null,
+ c int not null,
+ key (a)
+) engine=heap;
+
+insert into t1 values ('aaaa', 'prefill-hash=5',0);
+insert into t1 values ('aaab', 'prefill-hash=0',0);
+insert into t1 values ('aaac', 'prefill-hash=7',0);
+insert into t1 values ('aaad', 'prefill-hash=2',0);
+insert into t1 values ('aaae', 'prefill-hash=1',0);
+insert into t1 values ('aaaf', 'prefill-hash=4',0);
+insert into t1 values ('aaag', 'prefill-hash=3',0);
+insert into t1 values ('aaah', 'prefill-hash=6',0);
+
+explain select * from t1 where a='aaaa';
+explain select * from t1 where a='aaab';
+explain select * from t1 where a='aaac';
+explain select * from t1 where a='aaad';
+insert into t1 select * from t1;
+
+explain select * from t1 where a='aaaa';
+explain select * from t1 where a='aaab';
+explain select * from t1 where a='aaac';
+explain select * from t1 where a='aaad';
+
+# a known effect: table reload causes statistics to be updated:
+flush tables;
+explain select * from t1 where a='aaaa';
+explain select * from t1 where a='aaab';
+explain select * from t1 where a='aaac';
+explain select * from t1 where a='aaad';
+
+# Check if delete_all_rows() updates #hash_buckets
+create table t2 as select * from t1;
+delete from t1;
+insert into t1 select * from t2;
+explain select * from t1 where a='aaaa';
+explain select * from t1 where a='aaab';
+explain select * from t1 where a='aaac';
+explain select * from t1 where a='aaad';
+drop table t1, t2;
+
+
+# Btree and hash index use costs.
+create table t1 (
+ id int unsigned not null primary key auto_increment,
+ name varchar(20) not null,
+ index heap_idx(name),
+ index btree_idx using btree(name)
+) engine=heap;
+
+create table t2 (
+ id int unsigned not null primary key auto_increment,
+ name varchar(20) not null,
+ index btree_idx using btree(name),
+ index heap_idx(name)
+) engine=heap;
+
+insert into t1 (name) values ('Matt'), ('Lilu'), ('Corbin'), ('Carly'),
+ ('Suzy'), ('Hoppy'), ('Burrito'), ('Mimi'), ('Sherry'), ('Ben'), ('Phil'),
+ ('Emily'), ('Mike');
+insert into t2 select * from t1;
+explain select * from t1 where name='matt';
+explain select * from t2 where name='matt';
+
+explain select * from t1 where name='Lilu';
+explain select * from t2 where name='Lilu';
+
+explain select * from t1 where name='Phil';
+explain select * from t2 where name='Phil';
+
+explain select * from t1 where name='Lilu';
+explain select * from t2 where name='Lilu';
+
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+insert into t1 (name) select name from t2;
+flush tables;
+select count(*) from t1 where name='Matt';
+explain select * from t1 ignore index (btree_idx) where name='matt';
+show index from t1;
+
+show index from t1;
+
+create table t3
+(
+ a varchar(20) not null,
+ b varchar(20) not null,
+ key (a,b)
+) engine=heap;
+insert into t3 select name, name from t1;
+show index from t3;
+show index from t3;
+
+# test rec_per_key use for joins.
+explain select * from t1 ignore key(btree_idx), t3 where t1.name='matt' and t3.a = concat('',t1.name) and t3.b=t1.name;
+
+drop table t1, t2, t3;
+
diff --git a/mysql-test/t/index_merge_ror_cpk.test b/mysql-test/t/index_merge_ror_cpk.test
index bf8eb5b77c7..867b0b3a036 100644
--- a/mysql-test/t/index_merge_ror_cpk.test
+++ b/mysql-test/t/index_merge_ror_cpk.test
@@ -72,6 +72,8 @@ explain select * from t1 where pktail2ok=1 and key1=10;
select ' The following is actually a deficiency, it uses sort_union currently:' as 'note:';
explain select * from t1 where (pktail2ok=1 and pk1< 50000) or key1=10;
+# The expected rows differs a bit from platform to platform
+--replace_result 98 ROWS 99 ROWS
explain select * from t1 where pktail3bad=1 and key1=10;
explain select * from t1 where pktail4bad=1 and key1=10;
explain select * from t1 where pktail5bad=1 and key1=10;
diff --git a/mysql-test/t/information_schema.test b/mysql-test/t/information_schema.test
new file mode 100644
index 00000000000..1f44ad49812
--- /dev/null
+++ b/mysql-test/t/information_schema.test
@@ -0,0 +1,276 @@
+
+# Test for information_schema.schemata &
+# show databases
+
+grant all privileges on test.* to mysqltest_1@localhost;
+
+select * from information_schema.SCHEMATA where schema_name > 'm';
+select schema_name from information_schema.schemata;
+show databases *;
+show databases like 't%';
+show databases;
+show databases * where schema_name like 't%';
+show databases * where schema_name = 't%';
+
+# Test for information_schema.tables &
+# show tables
+
+create database testtets;
+create table testtets.t1(a int, b VARCHAR(30), KEY string_data (b));
+create table test.t2(a int);
+create table t3(a int, KEY a_data (a));
+create table testtets.t4(a int);
+create view v1 (c) as select table_name from information_schema.TABLES;
+select * from v1;
+select c,table_name from v1
+left join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+
+select c, v2.table_name from v1
+right join information_schema.TABLES v2 on (v1.c=v2.table_name)
+where v1.c like "t%";
+
+select table_name from information_schema.TABLES
+where table_schema = "testtets" and table_name like "t%";
+
+select * from information_schema.STATISTICS where TABLE_SCHEMA = "testtets";
+show keys * where TABLE_SCHEMA Like "test%";
+show keys where INDEX_NAME = "a_data";
+
+show tables like 't%';
+--replace_column 15 # 16 #
+show tables * from test where table_name like 't%';
+--replace_column 12 # 13 #
+--replace_result "2147483647 " "21474836479 "
+show table status;
+show full columns from t3 like "a%";
+show full columns from mysql.db like "Insert%";
+show full columns from v1;
+select * from information_schema.COLUMNS where table_name="t1"
+and column_name= "a";
+show columns * where table_name = "t1";
+
+drop view v1;
+drop tables testtets.t4, testtets.t1, t2, t3;
+drop database testtets;
+
+# Test for information_schema.CHARACTER_SETS &
+# SHOW CHARACTER SET
+
+select * from information_schema.CHARACTER_SETS
+where CHARACTER_SET_NAME like 'latin1%';
+SHOW CHARACTER SET LIKE 'latin1%';
+SHOW CHARACTER SET * LIKE 'latin1%';
+SHOW CHARACTER SET WHERE CHARACTER_SET_NAME like 'latin1%';
+SHOW CHARACTER SET CHARACTER_SET_NAME WHERE CHARACTER_SET_NAME like 'latin1%';
+SHOW CHARACTER SET * WHERE CHARACTER_SET_NAME like 'latin1%';
+
+# Test for information_schema.COLLATIONS &
+# SHOW COLLATION
+
+select * from information_schema.COLLATIONS
+where COLLATION_NAME like 'latin1%';
+SHOW COLLATION LIKE 'latin1%';
+SHOW COLLATION * LIKE 'latin1%';
+SHOW COLLATION WHERE COLLATION_NAME like 'latin1%';
+SHOW COLLATION COLLATION_NAME WHERE COLLATION_NAME like 'latin1%';
+SHOW COLLATION * WHERE COLLATION_NAME like 'latin1%';
+
+select * from information_schema.COLLATION_CHARACTER_SET_APPLICABILITY
+where COLLATION_NAME like 'latin1%';
+
+# Test for information_schema.ROUTINES &
+#
+
+create function sub1(i int) returns int
+ return i+1;
+delimiter |;
+create procedure sel2()
+begin
+ select * from t1;
+ select * from t2;
+end|
+delimiter ;|
+
+--replace_column 5 # 6 #
+show procedure status;
+--replace_column 5 # 6 #
+show function status;
+select a.ROUTINE_NAME from information_schema.ROUTINES a,
+information_schema.SCHEMATA b where
+a.ROUTINE_SCHEMA = b.SCHEMA_NAME;
+--replace_column 3 #
+explain select a.ROUTINE_NAME from information_schema.ROUTINES a,
+information_schema.SCHEMATA b where
+a.ROUTINE_SCHEMA = b.SCHEMA_NAME;
+
+select a.ROUTINE_NAME, b.name from information_schema.ROUTINES a,
+mysql.proc b where a.ROUTINE_NAME = convert(b.name using utf8);
+select count(*) from information_schema.ROUTINES;
+
+#
+# Test for views
+#
+create view v0 (c) as select schema_name from information_schema.schemata;
+select * from v0;
+--replace_column 3 #
+explain select * from v0;
+create view v1 (c) as select table_name from information_schema.tables
+where table_name="v1";
+select * from v1;
+create view v2 (c) as select column_name from information_schema.columns
+where table_name="v2";
+select * from v2;
+create view v3 (c) as select CHARACTER_SET_NAME from information_schema.character_sets
+where CHARACTER_SET_NAME like "latin1%";
+select * from v3;
+create view v4 (c) as select COLLATION_NAME from information_schema.collations
+where COLLATION_NAME like "latin1%";
+select * from v4;
+show keys from v4;
+select * from information_schema.views where TABLE_NAME like "v%";
+drop view v0, v1, v2, v3, v4;
+
+#
+# Test for privileges tables
+#
+create table t1 (a int);
+grant select,update,insert on t1 to mysqltest_1@localhost;
+grant select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
+grant all on test.* to mysqltest_1@localhost with grant option;
+select * from information_schema.USER_PRIVILEGES where grantee like '%mysqltest_1%';
+select * from information_schema.SCHEMA_PRIVILEGES where grantee like '%mysqltest_1%';
+select * from information_schema.TABLE_PRIVILEGES where grantee like '%mysqltest_1%';
+select * from information_schema.COLUMN_PRIVILEGES where grantee like '%mysqltest_1%';
+delete from mysql.user where user='mysqltest_1';
+delete from mysql.db where user='mysqltest_1';
+delete from mysql.tables_priv where user='mysqltest_1';
+delete from mysql.columns_priv where user='mysqltest_1';
+flush privileges;
+drop table t1;
+
+
+#
+# Test for KEY_COLUMN_USAGE & TABLE_CONSTRAINTS tables
+#
+
+create table t1 (a int null, primary key(a));
+alter table t1 add constraint constraint_1 unique (a);
+alter table t1 add constraint unique key_1(a);
+alter table t1 add constraint constraint_2 unique key_2(a);
+show create table t1;
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_SCHEMA= "test";
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_SCHEMA= "test";
+
+
+connect (user1,localhost,mysqltest_1,,);
+connection user1;
+select table_name from information_schema.TABLES where table_schema like "test%";
+select table_name,column_name from information_schema.COLUMNS where table_schema like "test%";
+select ROUTINE_NAME from information_schema.ROUTINES;
+disconnect user1;
+connection default;
+delete from mysql.user where user='mysqltest_1';
+drop table t1;
+drop procedure sel2;
+drop function sub1;
+
+create table t1(a int);
+create view v1 (c) as select a from t1 with check option;
+create view v2 (c) as select a from t1 WITH LOCAL CHECK OPTION;
+create view v3 (c) as select a from t1 WITH CASCADED CHECK OPTION;
+select * from information_schema.views;
+grant select (a) on test.t1 to joe@localhost with grant option;
+select * from INFORMATION_SCHEMA.COLUMN_PRIVILEGES;
+select * from INFORMATION_SCHEMA.TABLE_PRIVILEGES;
+drop view v1, v2, v3;
+drop table t1;
+delete from mysql.user where user='joe';
+delete from mysql.db where user='joe';
+delete from mysql.tables_priv where user='joe';
+delete from mysql.columns_priv where user='joe';
+flush privileges;
+
+delimiter //;
+create procedure px5 ()
+begin
+declare v int;
+declare c cursor for select version from
+information_schema.tables;
+open c;
+fetch c into v;
+select v;
+close c;
+end;//
+
+call px5()//
+call px5()//
+delimiter ;//
+select sql_mode from information_schema.ROUTINES;
+drop procedure px5;
+
+create table t1 (a int not null auto_increment,b int, primary key (a));
+insert into t1 values (1,1),(NULL,3),(NULL,4);
+select AUTO_INCREMENT from information_schema.tables where table_name = 't1';
+drop table t1;
+
+create table t1 (s1 int);
+insert into t1 values (0),(9),(0);
+select s1 from t1 where s1 in (select version from
+information_schema.tables) union select version from
+information_schema.tables;
+drop table t1;
+
+SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
+set names latin2;
+SHOW CREATE TABLE INFORMATION_SCHEMA.character_sets;
+set names latin1;
+
+create table t1 select * from information_schema.CHARACTER_SETS
+where CHARACTER_SET_NAME like "latin1";
+select * from t1;
+alter table t1 default character set utf8;
+show create table t1;
+drop table t1;
+
+create view v1 as select * from information_schema.TABLES;
+drop view v1;
+create table t1(a NUMERIC(5,3), b NUMERIC(5,1), c float(5,2),
+ d NUMERIC(6,4), e float, f DECIMAL(6,3), g int(11), h DOUBLE(10,3),
+ i DOUBLE);
+select COLUMN_NAME,COLUMN_TYPE, CHARACTER_MAXIMUM_LENGTH,
+ CHARACTER_OCTET_LENGTH, NUMERIC_PRECISION, NUMERIC_SCALE
+from information_schema.columns where table_name= 't1';
+drop table t1;
+
+create table t115 as select table_name, column_name, column_type
+from information_schema.columns where table_name = 'proc';
+select * from t115;
+drop table t115;
+
+create view vk as select count(*) from information_schema.tables a;
+select * from vk;
+drop view vk;
+
+delimiter //;
+create procedure p108 () begin declare c cursor for select data_type
+from information_schema.columns; open c; open c; end;//
+--error 1325
+call p108()//
+delimiter ;//
+drop procedure p108;
+
+create view v1 as select A1.table_name from information_schema.TABLES A1
+where table_name= "user";
+select * from v1;
+drop view v1;
+
+create view vo as select 'a' union select 'a';
+show index from vo;
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_NAME= "vo";
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_NAME= "vo";
+drop view vo;
diff --git a/mysql-test/t/information_schema_inno.test b/mysql-test/t/information_schema_inno.test
new file mode 100644
index 00000000000..15643ebe90c
--- /dev/null
+++ b/mysql-test/t/information_schema_inno.test
@@ -0,0 +1,16 @@
+-- source include/have_innodb.inc
+
+#
+# Test for KEY_COLUMN_USAGE & TABLE_CONSTRAINTS tables
+#
+
+CREATE TABLE t1 (id INT NOT NULL, PRIMARY KEY (id)) ENGINE=INNODB;
+CREATE TABLE t2 (id INT PRIMARY KEY, t1_id INT, INDEX par_ind (t1_id),
+FOREIGN KEY (t1_id) REFERENCES t1(id) ON DELETE CASCADE,
+FOREIGN KEY (t1_id) REFERENCES t1(id) ON UPDATE CASCADE) ENGINE=INNODB;
+select * from information_schema.TABLE_CONSTRAINTS where
+TABLE_SCHEMA= "test";
+select * from information_schema.KEY_COLUMN_USAGE where
+TABLE_SCHEMA= "test";
+
+drop table t2, t1;
diff --git a/mysql-test/t/innodb.test b/mysql-test/t/innodb.test
index f9b1de44b81..e7f08f11a2d 100644
--- a/mysql-test/t/innodb.test
+++ b/mysql-test/t/innodb.test
@@ -1110,6 +1110,7 @@ show create table t2;
drop table t2;
# Test error handling
+--replace_result \\ /
--error 1005
create table t2 (id int(11) not null, id2 int(11) not null, constraint t1_id_fk foreign key (id2,id) references t1 (id)) engine = innodb;
@@ -1179,3 +1180,45 @@ select count(*) from t1 where x = 18446744073709551601;
drop table t1;
+#
+# Bug #6126: Duplicate columns in keys gives misleading error message
+#
+--error 1060
+create table t1 (c char(10), index (c,c)) engine=innodb;
+--error 1060
+create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1)) engine=innodb;
+--error 1060
+create table t1 (c1 char(10), c2 char(10), index (c1,c1,c2)) engine=innodb;
+--error 1060
+create table t1 (c1 char(10), c2 char(10), index (c2,c1,c1)) engine=innodb;
+create table t1 (c1 char(10), c2 char(10)) engine=innodb;
+--error 1060
+alter table t1 add key (c1,c1);
+--error 1060
+alter table t1 add key (c2,c1,c1);
+--error 1060
+alter table t1 add key (c1,c2,c1);
+--error 1060
+alter table t1 add key (c1,c1,c2);
+drop table t1;
+
+# Test for testable InnoDB status variables. This test
+# uses previous ones(pages_created, rows_deleted, ...).
+show status like "Innodb_buffer_pool_pages_total";
+show status like "Innodb_page_size";
+show status like "Innodb_rows_deleted";
+show status like "Innodb_rows_inserted";
+show status like "Innodb_rows_read";
+show status like "Innodb_rows_updated";
+#
+# Test varchar
+#
+
+#let $default=`select @@storage_engine`;
+#set storage_engine=INNODB;
+#source include/varchar.inc;
+#eval set storage_engine=$default;
+
+# InnoDB specific varchar tests
+--error 1074
+create table t1 (v varchar(16384)) engine=innodb;
diff --git a/mysql-test/t/insert.test b/mysql-test/t/insert.test
index c56bc74877e..e977de94871 100644
--- a/mysql-test/t/insert.test
+++ b/mysql-test/t/insert.test
@@ -99,22 +99,27 @@ create table t1(number int auto_increment primary key, original_value varchar(50
set @value= "aa";
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
set @value= "1aa";
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
set @value= "aa1";
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
set @value= "1e+1111111111a";
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
set @value= "-1e+1111111111a";
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
--error 1367
@@ -122,20 +127,25 @@ set @value= 1e+1111111111;
--error 1367
set @value= -1e+1111111111;
+
set @value= 1e+111;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
set @value= -1e+111;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
set @value= 1;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
set @value= -1;
insert into t1 values(null,@value,@value,@value,@value,@value,@value,@value,@value,@value);
+--replace_result e-0 e- e+0 e+
--query_vertical select * from t1 where number =last_insert_id()
drop table t1;
diff --git a/mysql-test/t/insert_select.test b/mysql-test/t/insert_select.test
index db5dc8d91da..e1459310bb9 100644
--- a/mysql-test/t/insert_select.test
+++ b/mysql-test/t/insert_select.test
@@ -89,6 +89,19 @@ show binlog events;
select * from t1;
drop table t1, t2;
+# Verify that a partly-completed CREATE TABLE .. SELECT does not
+# get into the binlog (Bug #6682)
+create table t1(a int);
+insert into t1 values(1),(1);
+reset master;
+--error 1062
+create table t2(unique(a)) select a from t1;
+# The above should produce an error, *and* not appear in the binlog
+let $VERSION=`select version()`;
+--replace_result $VERSION VERSION
+show binlog events;
+drop table t1;
+
#
# Test of insert ... select from same table
#
diff --git a/mysql-test/t/join_outer.test b/mysql-test/t/join_outer.test
index 9b5fdb924e6..665b4fafbca 100644
--- a/mysql-test/t/join_outer.test
+++ b/mysql-test/t/join_outer.test
@@ -34,11 +34,14 @@ explain select t1.*,t2.* from t1 left join t2 on t1.a=t2.a where isnull(t2.a)=1;
select t1.*,t2.*,t3.a from t1 left join t2 on (t1.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
# The next query should rearange the left joins to get this to work
-!$1120 explain select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
-!$1120 select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
+--error 1120
+explain select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
+--error 1120
+select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t1.a=t3.a);
# The next query should give an error in MySQL
-!$1120 select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
+--error 1120
+select t1.*,t2.*,t3.a from t1 left join t2 on (t3.a=t2.a) left join t1 as t3 on (t2.a=t3.a);
# Test of inner join
select t1.*,t2.* from t1 inner join t2 using (a);
@@ -94,7 +97,8 @@ WHERE t1.uniq_id = 4
ORDER BY t2.c_amount;
INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes');
-!$1062 INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes');
+--error 1062
+INSERT INTO t2 VALUES (2,3,3000,6000,0,0,746584,837484,'yes');
INSERT INTO t2 VALUES (7,3,1000,2000,0,0,746294,937484,'yes');
#3rd select should show that one record is returned with null entries for the
@@ -288,7 +292,8 @@ insert into t3 values (1);
insert into t4 values (1,1);
insert into t5 values (1,1);
-!$1120 explain select * from t3 left join t4 on t4.seq_1_id = t2.t2_id left join t1 on t1.t1_id = t4.seq_0_id left join t5 on t5.seq_0_id = t1.t1_id left join t2 on t2.t2_id = t5.seq_1_id where t3.t3_id = 23;
+--error 1120
+explain select * from t3 left join t4 on t4.seq_1_id = t2.t2_id left join t1 on t1.t1_id = t4.seq_0_id left join t5 on t5.seq_0_id = t1.t1_id left join t2 on t2.t2_id = t5.seq_1_id where t3.t3_id = 23;
drop table t1,t2,t3,t4,t5;
@@ -502,6 +507,82 @@ select s.*, '*', m.*, (s.match_1_h - m.home) UUX from
drop table t1, t2;
+# Tests for bugs #6307 and 6460
+
+create table t1 (a int, b int, unique index idx (a, b));
+create table t2 (a int, b int, c int, unique index idx (a, b));
+
+insert into t1 values (1, 10), (1,11), (2,10), (2,11);
+insert into t2 values (1,10,3);
+
+select t1.a, t1.b, t2.c from t1 left join t2
+ on t1.a=t2.a and t1.b=t2.b and t2.c=3
+ where t1.a=1 and t2.c is null;
+
+drop table t1, t2;
+
+CREATE TABLE t1 (
+ ts_id bigint(20) default NULL,
+ inst_id tinyint(4) default NULL,
+ flag_name varchar(64) default NULL,
+ flag_value text,
+ UNIQUE KEY ts_id (ts_id,inst_id,flag_name)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+CREATE TABLE t2 (
+ ts_id bigint(20) default NULL,
+ inst_id tinyint(4) default NULL,
+ flag_name varchar(64) default NULL,
+ flag_value text,
+ UNIQUE KEY ts_id (ts_id,inst_id,flag_name)
+) ENGINE=MyISAM DEFAULT CHARSET=utf8;
+
+INSERT INTO t1 VALUES
+ (111056548820001, 0, 'flag1', NULL),
+ (111056548820001, 0, 'flag2', NULL),
+ (2, 0, 'other_flag', NULL);
+
+INSERT INTO t2 VALUES
+ (111056548820001, 3, 'flag1', 'sss');
+
+SELECT t1.flag_name,t2.flag_value
+ FROM t1 LEFT JOIN t2
+ ON (t1.ts_id = t2.ts_id AND t1.flag_name = t2.flag_name AND
+ t2.inst_id = 3)
+ WHERE t1.inst_id = 0 AND t1.ts_id=111056548820001 AND
+ t2.flag_value IS NULL;
+
+DROP TABLE t1,t2;
+
+CREATE TABLE invoice (
+ id int(11) unsigned NOT NULL auto_increment,
+ text_id int(10) unsigned default NULL,
+ PRIMARY KEY (id)
+);
+
+INSERT INTO invoice VALUES("1", "0");
+INSERT INTO invoice VALUES("2", "10");
+
+CREATE TABLE text_table (
+ text_id char(3) NOT NULL default '',
+ language_id char(3) NOT NULL default '',
+ text_data text,
+ PRIMARY KEY (text_id,language_id)
+);
+
+INSERT INTO text_table VALUES("0", "EN", "0-EN");
+INSERT INTO text_table VALUES("0", "SV", "0-SV");
+INSERT INTO text_table VALUES("10", "EN", "10-EN");
+INSERT INTO text_table VALUES("10", "SV", "10-SV");
+
+SELECT invoice.id, invoice.text_id, text_table.text_data
+ FROM invoice LEFT JOIN text_table
+ ON invoice.text_id = text_table.text_id
+ AND text_table.language_id = 'SV'
+ WHERE (invoice.id LIKE '%' OR text_table.text_data LIKE '%');
+
+DROP TABLE invoice, text_table;
+
# Test for bug #5896
CREATE TABLE t0 (a0 int PRIMARY KEY);
diff --git a/mysql-test/t/key.test b/mysql-test/t/key.test
index 4a3631d3918..af3509c8454 100644
--- a/mysql-test/t/key.test
+++ b/mysql-test/t/key.test
@@ -150,7 +150,8 @@ create table t1
);
INSERT INTO t1 VALUES (1, 1, 1, 1, 'a');
INSERT INTO t1 VALUES (1, 1, 1, 1, 'b');
-!$1062 INSERT INTO t1 VALUES (1, 1, 1, 1, 'a');
+--error 1062
+INSERT INTO t1 VALUES (1, 1, 1, 1, 'a');
drop table t1;
#
@@ -298,5 +299,28 @@ drop table t1;
# create dedicated error code for this and
# and change my_printf_error() to my_error
---error 1105
+--error 1391
create table t1 (c char(10), index (c(0)));
+
+#
+# Bug #6126: Duplicate columns in keys should fail
+# Bug #6252: (dup)
+#
+--error 1060
+create table t1 (c char(10), index (c,c));
+--error 1060
+create table t1 (c1 char(10), c2 char(10), index (c1,c2,c1));
+--error 1060
+create table t1 (c1 char(10), c2 char(10), index (c1,c1,c2));
+--error 1060
+create table t1 (c1 char(10), c2 char(10), index (c2,c1,c1));
+create table t1 (c1 char(10), c2 char(10));
+--error 1060
+alter table t1 add key (c1,c1);
+--error 1060
+alter table t1 add key (c2,c1,c1);
+--error 1060
+alter table t1 add key (c1,c2,c1);
+--error 1060
+alter table t1 add key (c1,c1,c2);
+drop table t1;
diff --git a/mysql-test/t/key_cache.test b/mysql-test/t/key_cache.test
index 9d3125efa61..6dee87ec5a6 100644
--- a/mysql-test/t/key_cache.test
+++ b/mysql-test/t/key_cache.test
@@ -156,3 +156,14 @@ set global keycache2.key_buffer_size=0;
# Test to set up a too small size for a key cache (bug #2064)
set global keycache3.key_buffer_size=100;
set global keycache3.key_buffer_size=0;
+
+# Test case for buf 6447
+
+create table t1 (mytext text, FULLTEXT (mytext));
+insert t1 values ('aaabbb');
+
+check table t1;
+set GLOBAL key_cache_block_size=2048;
+check table t1;
+
+drop table t1;
diff --git a/mysql-test/t/lowercase_view.test b/mysql-test/t/lowercase_view.test
index 2a2757650ae..4b688cfb922 100644
--- a/mysql-test/t/lowercase_view.test
+++ b/mysql-test/t/lowercase_view.test
@@ -32,3 +32,18 @@ delete from v2aA where col1 = (select max(col1) from v1aA);
insert into v2aA values ((select max(col1) from v1aA));
drop view v2Aa,v1Aa;
drop table t1Aa,t2Aa;
+
+#
+# aliases in VIEWs
+#
+create table t1Aa (col1 int);
+create view v1Aa as select col1 from t1Aa as AaA;
+show create view v1AA;
+drop view v1AA;
+select Aaa.col1 from t1Aa as AaA;
+create view v1Aa as select Aaa.col1 from t1Aa as AaA;
+drop view v1AA;
+create view v1Aa as select AaA.col1 from t1Aa as AaA;
+show create view v1AA;
+drop view v1AA;
+drop table t1Aa;
diff --git a/mysql-test/t/mix_innodb_myisam_binlog-master.opt b/mysql-test/t/mix_innodb_myisam_binlog-master.opt
new file mode 100644
index 00000000000..cb48f1aaf60
--- /dev/null
+++ b/mysql-test/t/mix_innodb_myisam_binlog-master.opt
@@ -0,0 +1 @@
+--loose-innodb_lock_wait_timeout=2
diff --git a/mysql-test/t/mix_innodb_myisam_binlog.test b/mysql-test/t/mix_innodb_myisam_binlog.test
index 00be4c83efc..11d3af11c42 100644
--- a/mysql-test/t/mix_innodb_myisam_binlog.test
+++ b/mysql-test/t/mix_innodb_myisam_binlog.test
@@ -184,4 +184,36 @@ select a from t1 order by a; # check that savepoints work :)
--replace_column 5 #
show binlog events from 95;
+# Test for BUG#5714, where a MyISAM update in the transaction used to
+# release row-level locks in InnoDB
+
+connect (con3,localhost,root,,);
+
+connection con3;
+delete from t1;
+delete from t2;
+--disable_warnings
+alter table t2 type=MyISAM;
+--enable_warnings
+insert into t1 values (1);
+begin;
+select * from t1 for update;
+
+connection con2;
+select (@before:=unix_timestamp())*0; # always give repeatable output
+begin;
+send select * from t1 for update;
+
+connection con3;
+insert into t2 values (20);
+
+connection con2;
+--error 1205
+reap;
+select (@after:=unix_timestamp())*0; # always give repeatable output
+# verify that innodb_lock_wait_timeout was exceeded. When there was
+# the bug, the reap would return immediately after the insert into t2.
+select (@after-@before) >= 2;
+
+# cleanup
drop table t1,t2;
diff --git a/mysql-test/t/multi_update.test b/mysql-test/t/multi_update.test
index 8a213ab791c..ac60eef6d05 100644
--- a/mysql-test/t/multi_update.test
+++ b/mysql-test/t/multi_update.test
@@ -159,8 +159,6 @@ LOCK TABLES t1 write, t2 read;
DELETE t1.*, t2.* FROM t1,t2 where t1.n=t2.n;
--error 1099
UPDATE t1,t2 SET t1.d=t2.d,t2.d=30 WHERE t1.n=t2.n;
---QQ This should not generate an error
---error 1099
UPDATE t1,t2 SET t1.d=t2.d WHERE t1.n=t2.n;
unlock tables;
LOCK TABLES t1 write, t2 write;
@@ -428,7 +426,7 @@ drop table t1, t2, t3;
#
create table t1 (col1 int);
create table t2 (col1 int);
--- QQ The following should give error 1093
+-- error 1093
update t1,t2 set t1.col1 = (select max(col1) from t1) where t1.col1 = t2.col1;
-- error 1093
delete t1 from t1,t2 where t1.col1 < (select max(col1) from t1) and t1.col1 = t2.col1;
@@ -479,3 +477,35 @@ delete t1,t2 from t2,t1 where t1.a<'B' and t2.b=t1.b;
set @@storage_engine=@ttype_save;
drop table t1,t2;
+
+create table t1 (a int, b int);
+insert into t1 values (1, 2), (2, 3), (3, 4);
+create table t2 (a int);
+insert into t2 values (10), (20), (30);
+create view v1 as select a as b, a/10 as a from t2;
+
+connect (locker,localhost,root,,test);
+connection locker;
+lock table t1 write;
+
+connect (changer,localhost,root,,test);
+connection changer;
+send alter table t1 add column c int default 100 after a;
+
+connect (updater,localhost,root,,test);
+connection updater;
+send update t1, v1 set t1.b=t1.a+t1.b+v1.b where t1.a=v1.a;
+
+connection locker;
+sleep 2;
+unlock tables;
+
+connection changer;
+reap;
+
+connection updater;
+reap;
+select * from t1;
+select * from t2;
+drop view v1;
+drop table t1, t2;
diff --git a/mysql-test/t/myisam.test b/mysql-test/t/myisam.test
index f9081e8769b..44ff789632d 100644
--- a/mysql-test/t/myisam.test
+++ b/mysql-test/t/myisam.test
@@ -450,11 +450,14 @@ drop table t1;
# Test text and unique
#
create table t1 (a int not null auto_increment primary key, b text not null, unique b (b(20)));
-insert into t1 (b) values ('a'),('a '),('a ');
+insert into t1 (b) values ('a'),('b'),('c');
select concat(b,'.') from t1;
update t1 set b='b ' where a=2;
--error 1062
update t1 set b='b ' where a > 1;
+--error 1062
+insert into t1 (b) values ('b');
+select * from t1;
delete from t1 where b='b';
select a,concat(b,'.') from t1;
drop table t1;
@@ -498,11 +501,12 @@ alter table t1 disable keys;
show keys from t1;
create table t2 (a int);
let $i=1000;
+set @@rand_seed1=31415926,@@rand_seed2=2718281828;
--disable_query_log
while ($i)
{
dec $i;
- eval insert t2 values (rand()*100000);
+ insert t2 values (rand()*100000);
}
--enable_query_log
insert t1 select * from t2;
@@ -523,3 +527,15 @@ explain select count(*) from t1 where a is null;
select count(*) from t1 where a is null;
drop table t1;
+#
+# Test varchar
+#
+
+let $default=`select @@storage_engine`;
+set storage_engine=MyISAM;
+source include/varchar.inc;
+eval set storage_engine=$default;
+
+# MyISAM specific varchar tests
+--error 1118
+create table t1 (v varchar(65535));
diff --git a/mysql-test/t/mysqldump.test b/mysql-test/t/mysqldump.test
index e8bb98d5ae0..7a811e69147 100644
--- a/mysql-test/t/mysqldump.test
+++ b/mysql-test/t/mysqldump.test
@@ -136,3 +136,13 @@ create view v1 as select * from t1;
--exec $MYSQL_DUMP --skip-comments test
drop view v1;
drop table t1;
+
+#
+# Bug #6101: create database problem
+#
+
+--exec $MYSQL_DUMP --skip-comments --databases test
+
+create database mysqldump_test_db character set latin2 collate latin2_bin;
+--exec $MYSQL_DUMP --skip-comments --databases mysqldump_test_db;
+drop database mysqldump_test_db;
diff --git a/mysql-test/t/mysqltest.test b/mysql-test/t/mysqltest.test
index c18dfe1e25c..0802c18ed6c 100644
--- a/mysql-test/t/mysqltest.test
+++ b/mysql-test/t/mysqltest.test
@@ -6,17 +6,24 @@
# ============================================================================
# ----------------------------------------------------------------------------
+# $mysql_errno contains the return code of the last command
+# send to the server.
+# ----------------------------------------------------------------------------
+# get $mysql_errno before the first statement
+# $mysql_errno should be -1
+eval select $mysql_errno as "before_use_test" ;
+
+
+# ----------------------------------------------------------------------------
# Positive case(statement)
# ----------------------------------------------------------------------------
select otto from (select 1 as otto) as t1;
# expectation = response
-!$0 select otto from (select 1 as otto) as t1;
--error 0
select otto from (select 1 as otto) as t1;
# expectation <> response
--- // !$1054 select otto from (select 1 as otto) as t1;
-- // --error 1054
-- // select otto from (select 1 as otto) as t1;
@@ -29,12 +36,10 @@ select otto from (select 1 as otto) as t1;
# ----------------------------------------------------------------------------
# expectation <> response
-#!$0 select friedrich from (select 1 as otto) as t1;
#--error 0
#select friedrich from (select 1 as otto) as t1;
# expectation = response
-!$1054 select friedrich from (select 1 as otto) as t1;
--error 1054
select friedrich from (select 1 as otto) as t1;
@@ -76,3 +81,208 @@ select friedrich from (select 1 as otto) as t1;
#--error S00000
#select friedrich from (select 1 as otto) as t1;
+
+# ----------------------------------------------------------------------------
+# test cases for $mysql_errno
+#
+# $mysql_errno is a builtin variable of mysqltest and contains the return code
+# of the last command send to the server.
+#
+# The following test cases often initialize $mysql_errno to 1064 by
+# a command with wrong syntax.
+# Example: --error 1064 To prevent the abort after the error.
+# garbage ;
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# check mysql_errno = 0 after successful statement
+# ----------------------------------------------------------------------------
+select otto from (select 1 as otto) as t1;
+eval select $mysql_errno as "after_successful_stmt_errno" ;
+
+#----------------------------------------------------------------------------
+# check mysql_errno = 1064 after statement with wrong syntax
+# ----------------------------------------------------------------------------
+--error 1064
+garbage ;
+eval select $mysql_errno as "after_wrong_syntax_errno" ;
+
+# ----------------------------------------------------------------------------
+# check if let $my_var= 'abc' ; affects $mysql_errno
+# ----------------------------------------------------------------------------
+--error 1064
+garbage ;
+let $my_var= 'abc' ;
+eval select $mysql_errno as "after_let_var_equal_value" ;
+
+# ----------------------------------------------------------------------------
+# check if set @my_var= 'abc' ; affects $mysql_errno
+# ----------------------------------------------------------------------------
+--error 1064
+garbage ;
+set @my_var= 'abc' ;
+eval select $mysql_errno as "after_set_var_equal_value" ;
+
+# ----------------------------------------------------------------------------
+# check if the setting of --disable-warnings itself affects $mysql_errno
+# (May be --<whatever> modifies $mysql_errno.)
+# ----------------------------------------------------------------------------
+--error 1064
+garbage ;
+--disable_warnings
+eval select $mysql_errno as "after_disable_warnings_command" ;
+
+# ----------------------------------------------------------------------------
+# check if --disable-warnings + command with warning affects the errno
+# stored within $mysql_errno
+# (May be disabled warnings affect $mysql_errno.)
+# ----------------------------------------------------------------------------
+drop table if exists t1 ;
+--error 1064
+garbage ;
+drop table if exists t1 ;
+eval select $mysql_errno as "after_disable_warnings" ;
+--enable_warnings
+
+# ----------------------------------------------------------------------------
+# check if masked errors affect $mysql_errno
+# ----------------------------------------------------------------------------
+--error 1064
+garbage ;
+--error 1146
+select 3 from t1 ;
+eval select $mysql_errno as "after_minus_masked" ;
+--error 1064
+garbage ;
+--error 1146
+select 3 from t1 ;
+eval select $mysql_errno as "after_!_masked" ;
+
+# ----------------------------------------------------------------------------
+# Will manipulations of $mysql_errno be possible and visible ?
+# ----------------------------------------------------------------------------
+--error 1064
+garbage ;
+let $mysql_errno= -1;
+eval select $mysql_errno as "after_let_errno_equal_value" ;
+
+# ----------------------------------------------------------------------------
+# How affect actions on prepared statements $mysql_errno ?
+# ----------------------------------------------------------------------------
+# failing prepare
+--error 1064
+garbage ;
+--error 1146
+prepare stmt from "select 3 from t1" ;
+eval select $mysql_errno as "after_failing_prepare" ;
+create table t1 ( f1 char(10));
+
+# successful prepare
+--error 1064
+garbage ;
+prepare stmt from "select 3 from t1" ;
+eval select $mysql_errno as "after_successful_prepare" ;
+
+# successful execute
+--error 1064
+garbage ;
+execute stmt;
+eval select $mysql_errno as "after_successful_execute" ;
+
+# failing execute (table dropped)
+drop table t1;
+--error 1064
+garbage ;
+--error 1146
+execute stmt;
+eval select $mysql_errno as "after_failing_execute" ;
+
+# failing execute (unknown statement)
+--error 1064
+garbage ;
+--error 1243
+execute __stmt_;
+eval select $mysql_errno as "after_failing_execute" ;
+
+# successful deallocate
+--error 1064
+garbage ;
+deallocate prepare stmt;
+eval select $mysql_errno as "after_successful_deallocate" ;
+
+# failing deallocate ( statement handle does not exist )
+--error 1064
+garbage ;
+--error 1243
+deallocate prepare __stmt_;
+eval select $mysql_errno as "after_failing_deallocate" ;
+
+
+# ----------------------------------------------------------------------------
+# test cases for "--disable_abort_on_error"
+#
+# "--disable_abort_on_error" switches the abort of mysqltest
+# after "unmasked" failing statements off.
+#
+# The default is "--enable_abort_on_error".
+#
+# "Maskings" are
+# --error <error number> and --error <error number>
+# in the line before the failing statement.
+#
+# There are some additional test case for $mysql_errno
+# because "--disable_abort_on_error" enables a new situation.
+# Example: "unmasked" statement fails + analysis of $mysql_errno
+# ----------------------------------------------------------------------------
+
+# ----------------------------------------------------------------------------
+# Switch the abort on error off and check the effect on $mysql_errno
+# ----------------------------------------------------------------------------
+--error 1064
+garbage ;
+--disable_abort_on_error
+eval select $mysql_errno as "after_--disable_abort_on_error" ;
+
+# ----------------------------------------------------------------------------
+# "unmasked" failing statement should not cause an abort
+# ----------------------------------------------------------------------------
+select 3 from t1 ;
+
+# ----------------------------------------------------------------------------
+# masked failing statements
+# ----------------------------------------------------------------------------
+# expected error = response
+--error 1146
+select 3 from t1 ;
+--error 1146
+select 3 from t1 ;
+eval select $mysql_errno as "after_!errno_masked_error" ;
+# expected error <> response
+# --error 1000
+# select 3 from t1 ;
+# --error 1000
+# select 3 from t1 ;
+
+# ----------------------------------------------------------------------------
+# Switch the abort on error on and check the effect on $mysql_errno
+# ----------------------------------------------------------------------------
+--error 1064
+garbage ;
+--enable_abort_on_error
+eval select $mysql_errno as "after_--enable_abort_on_error" ;
+
+# ----------------------------------------------------------------------------
+# masked failing statements
+# ----------------------------------------------------------------------------
+# expected error = response
+--error 1146
+select 3 from t1 ;
+
+# ----------------------------------------------------------------------------
+# check that the old default behaviour is not changed
+# Please remove the '#' to get the abort on error
+# ----------------------------------------------------------------------------
+#--error 1064
+#select 3 from t1 ;
+#
+#select 3 from t1 ;
diff --git a/mysql-test/t/ndb_autodiscover.test b/mysql-test/t/ndb_autodiscover.test
index 95b616fc7b2..6551732adba 100644
--- a/mysql-test/t/ndb_autodiscover.test
+++ b/mysql-test/t/ndb_autodiscover.test
@@ -1,7 +1,7 @@
-- source include/have_ndb.inc
--disable_warnings
-drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9;
+drop table if exists t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
--enable_warnings
################################################
@@ -199,7 +199,7 @@ insert into t4 values (1, "Automatic");
select * from t4;
# Remove the table from NDB
-system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t4 > /dev/null ;
+system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 > /dev/null ;
#
# Test that correct error is returned
@@ -230,7 +230,7 @@ select * from t4;
flush tables;
# Remove the table from NDB
-system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t4 > /dev/null ;
+system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t4 > /dev/null ;
SHOW TABLES;
@@ -264,8 +264,8 @@ insert into t8 values (8, "myisam table 8");
insert into t9 values (9);
# Remove t3, t5 from NDB
-system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t3 > /dev/null ;
-system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t5 > /dev/null ;
+system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 > /dev/null ;
+system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 > /dev/null ;
# Remove t6, t7 from disk
system rm var/master-data/test/t6.frm > /dev/null ;
system rm var/master-data/test/t7.frm > /dev/null ;
@@ -306,8 +306,8 @@ insert into t8 values (8, "myisam table 8");
insert into t9 values (9);
# Remove t3, t5 from NDB
-system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t3 > /dev/null ;
-system exec $NDB_TOOLS_DIR/ndb_drop_table -d test t5 > /dev/null ;
+system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t3 > /dev/null ;
+system exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test t5 > /dev/null ;
# Remove t6, t7 from disk
system rm var/master-data/test/t6.frm > /dev/null ;
system rm var/master-data/test/t7.frm > /dev/null ;
@@ -472,5 +472,11 @@ system rm var/master-data/test/t9.frm ;
# MySQL Server will have been restarted because it has a
# ndb_autodiscover2-master.opt file.
+create table t10 (
+ a int not null primary key,
+ b blob
+) engine=ndb;
+insert into t10 values (1, 'kalle');
+--exec $NDB_TOOLS_DIR/ndb_drop_table --no-defaults -d test `$NDB_TOOLS_DIR/ndb_show_tables --no-defaults | grep BLOB` > /dev/null 2>&1 || true
diff --git a/mysql-test/t/ndb_autodiscover2.test b/mysql-test/t/ndb_autodiscover2.test
index cce75d5ca4f..11e1cc204f7 100644
--- a/mysql-test/t/ndb_autodiscover2.test
+++ b/mysql-test/t/ndb_autodiscover2.test
@@ -13,4 +13,7 @@ show status like 'handler_discover%';
drop table t9;
+--error 1296
+select * from t10;
+drop table t10;
diff --git a/mysql-test/t/ndb_basic.test b/mysql-test/t/ndb_basic.test
index e79815bbeb1..2671223ada8 100644
--- a/mysql-test/t/ndb_basic.test
+++ b/mysql-test/t/ndb_basic.test
@@ -36,6 +36,8 @@ UPDATE t1 SET pk1=2 WHERE attr1=1;
SELECT * FROM t1 ORDER BY pk1;
UPDATE t1 SET pk1=pk1 + 1;
SELECT * FROM t1 ORDER BY pk1;
+UPDATE t1 SET pk1=4 WHERE pk1 = 3;
+SELECT * FROM t1 ORDER BY pk1;
# Delete the record
DELETE FROM t1;
@@ -359,6 +361,21 @@ drop table test.t1, t2;
drop database mysqltest;
#
+# BUG#6031 - DROP DATABASE doesn't drop database on first try
+#
+
+--disable_warnings
+drop database if exists ndbtest1;
+--enable_warnings
+
+create database ndbtest1;
+use ndbtest1;
+create table t1(id int) engine=ndbcluster;
+drop database ndbtest1;
+--error 1008
+drop database ndbtest1;
+
+#
# test support of char(0)
#
@@ -371,3 +388,154 @@ select * from t1 order by b;
select * from t1 where b IS NULL;
select * from t1 where b IS NOT NULL;
drop table t1;
+
+#
+# test the limit of no of attributes in one table
+#
+
+create table t1 (
+c1 int,
+c2 int,
+c3 int,
+c4 int,
+c5 int,
+c6 int,
+c7 int,
+c8 int,
+c9 int,
+c10 int,
+c11 int,
+c12 int,
+c13 int,
+c14 int,
+c15 int,
+c16 int,
+c17 int,
+c18 int,
+c19 int,
+c20 int,
+c21 int,
+c22 int,
+c23 int,
+c24 int,
+c25 int,
+c26 int,
+c27 int,
+c28 int,
+c29 int,
+c30 int,
+c31 int,
+c32 int,
+c33 int,
+c34 int,
+c35 int,
+c36 int,
+c37 int,
+c38 int,
+c39 int,
+c40 int,
+c41 int,
+c42 int,
+c43 int,
+c44 int,
+c45 int,
+c46 int,
+c47 int,
+c48 int,
+c49 int,
+c50 int,
+c51 int,
+c52 int,
+c53 int,
+c54 int,
+c55 int,
+c56 int,
+c57 int,
+c58 int,
+c59 int,
+c60 int,
+c61 int,
+c62 int,
+c63 int,
+c64 int,
+c65 int,
+c66 int,
+c67 int,
+c68 int,
+c69 int,
+c70 int,
+c71 int,
+c72 int,
+c73 int,
+c74 int,
+c75 int,
+c76 int,
+c77 int,
+c78 int,
+c79 int,
+c80 int,
+c81 int,
+c82 int,
+c83 int,
+c84 int,
+c85 int,
+c86 int,
+c87 int,
+c88 int,
+c89 int,
+c90 int,
+c91 int,
+c92 int,
+c93 int,
+c94 int,
+c95 int,
+c96 int,
+c97 int,
+c98 int,
+c99 int,
+c100 int,
+c101 int,
+c102 int,
+c103 int,
+c104 int,
+c105 int,
+c106 int,
+c107 int,
+c108 int,
+c109 int,
+c110 int,
+c111 int,
+c112 int,
+c113 int,
+c114 int,
+c115 int,
+c116 int,
+c117 int,
+c118 int,
+c119 int,
+c120 int,
+c121 int,
+c122 int,
+c123 int,
+c124 int,
+c125 int,
+c126 int,
+c127 int,
+c128 int,
+primary key(c1)) engine=ndb;
+drop table t1;
+
+#
+# test max size of attribute name and truncation
+#
+
+create table t1 (
+a1234567890123456789012345678901234567890 int primary key,
+a12345678901234567890123456789a1234567890 int,
+index(a12345678901234567890123456789a1234567890)
+) engine=ndb;
+show tables;
+insert into t1 values (1,1),(2,1),(3,1),(4,1),(5,2),(6,1),(7,1);
+explain select * from t1 where a12345678901234567890123456789a1234567890=2;
+select * from t1 where a12345678901234567890123456789a1234567890=2;
+drop table t1;
diff --git a/mysql-test/t/ndb_blob.test b/mysql-test/t/ndb_blob.test
index 5454dd91d26..06ecbc66d97 100644
--- a/mysql-test/t/ndb_blob.test
+++ b/mysql-test/t/ndb_blob.test
@@ -2,7 +2,7 @@
--disable_warnings
drop table if exists t1;
-drop database if exists mysqltest;
+drop database if exists test2;
--enable_warnings
#
@@ -12,31 +12,7 @@ drop database if exists mysqltest;
# A prerequisite for this handler test is that "testBlobs" succeeds.
#
-# -- bug-5252 tinytext crashes --
-
-create table t1 (
- a int not null primary key,
- b tinytext
-) engine=ndbcluster;
-
-insert into t1 values(1, 'x');
-update t1 set b = 'y';
-select * from t1;
-delete from t1;
-drop table t1;
-
-# -- bug-5013 insert empty string to text --
-
-create table t1 (
- a int not null primary key,
- b text not null
-) engine=ndbcluster;
-
-insert into t1 values(1, '');
-select * from t1;
-drop table t1;
-
--- general test starts --
+# -- general test starts --
# make test harder with autocommit off
set autocommit=0;
@@ -117,7 +93,6 @@ from t1 where a=2;
# pk update to null
update t1 set d=null where a=1;
commit;
-# FIXME now fails at random due to weird mixup between the 2 rows
select a from t1 where d is null;
# pk delete
@@ -126,6 +101,49 @@ delete from t1 where a=2;
commit;
select count(*) from t1;
+# -- replace ( bug-6018 ) --
+
+# insert
+replace t1 set a=1,b=@b1,c=111,d=@d1;
+replace t1 set a=2,b=@b2,c=222,d=@d2;
+commit;
+explain select * from t1 where a = 1;
+
+# pk read
+select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3)
+from t1 where a=1;
+select a,length(b),substr(b,1+2*9000,2),length(d),substr(d,1+3*9000,3)
+from t1 where a=2;
+
+# update
+replace t1 set a=1,b=@b2,c=111,d=@d2;
+replace t1 set a=2,b=@b1,c=222,d=@d1;
+commit;
+select a,length(b),substr(b,1+2*9000,2),length(d),substr(d,1+3*9000,3)
+from t1 where a=1;
+select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3)
+from t1 where a=2;
+
+# update
+replace t1 set a=1,b=concat(@b2,@b2),c=111,d=concat(@d2,@d2);
+replace t1 set a=2,b=concat(@b1,@b1),c=222,d=concat(@d1,@d1);
+commit;
+select a,length(b),substr(b,1+4*9000,2),length(d),substr(d,1+6*9000,3)
+from t1 where a=1;
+select a,length(b),substr(b,1+4*900,2),length(d),substr(d,1+6*900,3)
+from t1 where a=2;
+
+# update to null
+replace t1 set a=1,b='xyz',c=111,d=null;
+commit;
+select a,b from t1 where d is null;
+
+# pk delete
+delete from t1 where a=1;
+delete from t1 where a=2;
+commit;
+select count(*) from t1;
+
# -- hash index ops --
insert into t1 values(1,@b1,111,@d1);
@@ -231,39 +249,6 @@ where c >= 100;
commit;
select * from t1 where c >= 100 order by a;
-# alter table
-
-select * from t1 order by a;
-alter table t1 add x int;
-select * from t1 order by a;
-alter table t1 drop x;
-select * from t1 order by a;
-
-# multi db
-
-create database mysqltest;
-use mysqltest;
-
-CREATE TABLE t2 (
- a bigint unsigned NOT NULL PRIMARY KEY,
- b int unsigned not null,
- c int unsigned
-) engine=ndbcluster;
-
-insert into t2 values (1,1,1),(2,2,2);
-select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a;
-
-drop table t2;
-use test;
-
-# alter table
-
-select * from t1 order by a;
-alter table t1 add x int;
-select * from t1 order by a;
-alter table t1 drop x;
-select * from t1 order by a;
-
# range scan delete
delete from t1 where c >= 100;
commit;
@@ -306,10 +291,82 @@ select a,length(b),substr(b,1+2*900,2),length(d),substr(d,1+3*900,3)
from t1 order by a;
rollback;
select count(*) from t1;
+
+# -- alter table and multi db --
+
+insert into t1 values(1,'b1',111,'dd1');
+insert into t1 values(2,'b2',222,'dd2');
+insert into t1 values(3,'b3',333,'dd3');
+insert into t1 values(4,'b4',444,'dd4');
+insert into t1 values(5,'b5',555,'dd5');
+insert into t1 values(6,'b6',666,'dd6');
+insert into t1 values(7,'b7',777,'dd7');
+insert into t1 values(8,'b8',888,'dd8');
+insert into t1 values(9,'b9',999,'dd9');
+commit;
+
+select * from t1 order by a;
+alter table t1 add x int;
+select * from t1 order by a;
+alter table t1 drop x;
+select * from t1 order by a;
+
+create database test2;
+use test2;
+
+CREATE TABLE t2 (
+ a bigint unsigned NOT NULL PRIMARY KEY,
+ b int unsigned not null,
+ c int unsigned
+) engine=ndbcluster;
+
+insert into t2 values (1,1,1),(2,2,2);
+select * from test.t1,t2 where test.t1.a = t2.a order by test.t1.a;
+
+drop table t2;
+use test;
+
+select * from t1 order by a;
+alter table t1 add x int;
+select * from t1 order by a;
+alter table t1 drop x;
+select * from t1 order by a;
+
+# -- end general test --
+
drop table t1;
-drop database mysqltest;
+drop database test2;
-# bug #5349
+# -- bug-5252 tinytext crashes plus no-commit result --
+
+set autocommit=0;
+create table t1 (
+ a int not null primary key,
+ b tinytext
+) engine=ndbcluster;
+
+insert into t1 values(1, 'x');
+update t1 set b = 'y';
+select * from t1;
+delete from t1;
+select * from t1;
+commit;
+drop table t1;
+
+# -- bug-5013 insert empty string to text --
+
+set autocommit=0;
+create table t1 (
+ a int not null primary key,
+ b text not null
+) engine=ndbcluster;
+
+insert into t1 values(1, '');
+select * from t1;
+commit;
+drop table t1;
+
+# -- bug #5349 --
set autocommit=1;
use test;
CREATE TABLE t1 (
@@ -327,7 +384,8 @@ select * from t1 order by a;
alter table t1 engine=ndb;
select * from t1 order by a;
-# bug #5872
+# -- bug #5872 --
+set autocommit=1;
alter table t1 engine=myisam;
select * from t1 order by a;
drop table t1;
diff --git a/mysql-test/t/ndb_charset.test b/mysql-test/t/ndb_charset.test
index b9f28ed0faf..1b9e7e8bfcc 100644
--- a/mysql-test/t/ndb_charset.test
+++ b/mysql-test/t/ndb_charset.test
@@ -86,9 +86,9 @@ create table t1 (
# ok
insert into t1 values(1, 'aAa');
# fail
---error 1169
+--error 1062
insert into t1 values(2, 'aaa');
---error 1169
+--error 1062
insert into t1 values(3, 'AAA');
# 1
select * from t1 order by p;
@@ -157,3 +157,13 @@ select * from t1 where a = 'AaA' order by p;
# 6
select * from t1 where a = 'AAA' order by p;
drop table t1;
+
+# bug
+create table t1 (
+ a varchar(10) primary key
+) engine=ndb;
+insert into t1 values ('jonas % ');
+replace into t1 values ('jonas % ');
+replace into t1 values ('jonas % ');
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/ndb_grant.later b/mysql-test/t/ndb_grant.later
new file mode 100644
index 00000000000..b4885d2c5fc
--- /dev/null
+++ b/mysql-test/t/ndb_grant.later
@@ -0,0 +1,383 @@
+-- source include/have_ndb.inc
+# Test of GRANT commands
+
+# Cleanup
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+SET NAMES binary;
+
+#
+# Alter mysql system tables to ndb
+# make sure you alter all back in the end
+#
+use mysql;
+alter table columns_priv engine=ndb;
+alter table db engine=ndb;
+alter table func engine=ndb;
+alter table help_category engine=ndb;
+alter table help_keyword engine=ndb;
+alter table help_relation engine=ndb;
+alter table help_topic engine=ndb;
+alter table host engine=ndb;
+alter table tables_priv engine=ndb;
+alter table time_zone engine=ndb;
+alter table time_zone_leap_second engine=ndb;
+alter table time_zone_name engine=ndb;
+alter table time_zone_transition engine=ndb;
+alter table time_zone_transition_type engine=ndb;
+alter table user engine=ndb;
+use test;
+
+#
+# Test that SSL options works properly
+#
+delete from mysql.user where user='mysqltest_1';
+delete from mysql.db where user='mysqltest_1';
+flush privileges;
+begin;
+grant select on mysqltest.* to mysqltest_1@localhost require cipher "EDH-RSA-DES-CBC3-SHA";
+commit;
+show grants for mysqltest_1@localhost;
+begin;
+grant delete on mysqltest.* to mysqltest_1@localhost;
+commit;
+select * from mysql.user where user="mysqltest_1";
+show grants for mysqltest_1@localhost;
+begin;
+revoke delete on mysqltest.* from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+begin;
+grant select on mysqltest.* to mysqltest_1@localhost require NONE;
+commit;
+show grants for mysqltest_1@localhost;
+begin;
+grant USAGE on mysqltest.* to mysqltest_1@localhost require cipher "EDH-RSA-DES-CBC3-SHA" AND SUBJECT "testsubject" ISSUER "MySQL AB";
+commit;
+show grants for mysqltest_1@localhost;
+begin;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+delete from mysql.user where user='mysqltest_1';
+flush privileges;
+
+#
+# Test that the new db privileges are stored/retrieved correctly
+#
+
+begin;
+grant CREATE TEMPORARY TABLES, LOCK TABLES on mysqltest.* to mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+flush privileges;
+show grants for mysqltest_1@localhost;
+begin;
+revoke CREATE TEMPORARY TABLES on mysqltest.* from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+begin;
+grant ALL PRIVILEGES on mysqltest.* to mysqltest_1@localhost with GRANT OPTION;
+commit;
+flush privileges;
+show grants for mysqltest_1@localhost;
+begin;
+revoke LOCK TABLES, ALTER on mysqltest.* from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+begin;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+commit;
+delete from mysql.user where user='mysqltest_1';
+flush privileges;
+begin;
+grant usage on test.* to mysqltest_1@localhost with grant option;
+commit;
+show grants for mysqltest_1@localhost;
+delete from mysql.user where user='mysqltest_1';
+delete from mysql.db where user='mysqltest_1';
+delete from mysql.tables_priv where user='mysqltest_1';
+delete from mysql.columns_priv where user='mysqltest_1';
+flush privileges;
+--error 1141
+show grants for mysqltest_1@localhost;
+
+#
+# Test what happens when you have same table and colum level grants
+#
+
+create table t1 (a int);
+begin;
+GRANT select,update,insert on t1 to mysqltest_1@localhost;
+GRANT select (a), update (a),insert(a), references(a) on t1 to mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
+begin;
+REVOKE select (a), update on t1 from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+begin;
+REVOKE select,update,insert,insert (a) on t1 from mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+begin;
+GRANT select,references on t1 to mysqltest_1@localhost;
+commit;
+select table_priv,column_priv from mysql.tables_priv where user="mysqltest_1";
+begin;
+grant all on test.* to mysqltest_3@localhost with grant option;
+revoke all on test.* from mysqltest_3@localhost;
+commit;
+show grants for mysqltest_3@localhost;
+begin;
+revoke grant option on test.* from mysqltest_3@localhost;
+commit;
+show grants for mysqltest_3@localhost;
+begin;
+grant all on test.t1 to mysqltest_2@localhost with grant option;
+revoke all on test.t1 from mysqltest_2@localhost;
+commit;
+show grants for mysqltest_2@localhost;
+begin;
+revoke grant option on test.t1 from mysqltest_2@localhost;
+commit;
+show grants for mysqltest_2@localhost;
+delete from mysql.user where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3";
+delete from mysql.db where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3";
+delete from mysql.tables_priv where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3";
+delete from mysql.columns_priv where user='mysqltest_1' or user="mysqltest_2" or user="mysqltest_3";
+flush privileges;
+drop table t1;
+
+#
+# Test some error conditions
+#
+begin;
+--error 1221
+GRANT FILE on mysqltest.* to mysqltest_1@localhost;
+commit;
+select 1; -- To test that the previous command didn't cause problems
+
+#
+# Bug#6123: GRANT USAGE inserts useless Db row
+#
+create database mysqltest1;
+begin;
+grant usage on mysqltest1.* to test6123 identified by 'magic123';
+commit;
+select host,db,user,select_priv,insert_priv from mysql.db where db="mysqltest1";
+delete from mysql.user where user='test6123';
+drop database mysqltest1;
+
+#
+# Test for 'drop user', 'revoke privileges, grant'
+#
+
+create table t1 (a int);
+begin;
+grant ALL PRIVILEGES on *.* to drop_user2@localhost with GRANT OPTION;
+commit;
+show grants for drop_user2@localhost;
+begin;
+revoke all privileges, grant option from drop_user2@localhost;
+commit;
+drop user drop_user2@localhost;
+
+begin;
+grant ALL PRIVILEGES on *.* to drop_user@localhost with GRANT OPTION;
+grant ALL PRIVILEGES on test.* to drop_user@localhost with GRANT OPTION;
+grant select(a) on test.t1 to drop_user@localhost;
+commit;
+show grants for drop_user@localhost;
+
+#
+# Bug3086
+#
+set sql_mode=ansi_quotes;
+show grants for drop_user@localhost;
+set sql_mode=default;
+
+set sql_quote_show_create=0;
+show grants for drop_user@localhost;
+set sql_mode="ansi_quotes";
+show grants for drop_user@localhost;
+set sql_quote_show_create=1;
+show grants for drop_user@localhost;
+set sql_mode="";
+show grants for drop_user@localhost;
+
+revoke all privileges, grant option from drop_user@localhost;
+show grants for drop_user@localhost;
+drop user drop_user@localhost;
+begin;
+--error 1269
+revoke all privileges, grant option from drop_user@localhost;
+commit;
+
+begin;
+grant select(a) on test.t1 to drop_user1@localhost;
+commit;
+flush privileges;
+begin;
+grant select on test.t1 to drop_user2@localhost;
+grant select on test.* to drop_user3@localhost;
+grant select on *.* to drop_user4@localhost;
+commit;
+flush privileges;
+# Drop user now implicitly revokes all privileges.
+drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
+drop_user4@localhost;
+begin;
+--error 1269
+revoke all privileges, grant option from drop_user1@localhost, drop_user2@localhost,
+drop_user3@localhost, drop_user4@localhost;
+commit;
+flush privileges;
+#--error 1268
+drop user drop_user1@localhost, drop_user2@localhost, drop_user3@localhost,
+drop_user4@localhost;
+drop table t1;
+begin;
+grant usage on *.* to mysqltest_1@localhost identified by "password";
+grant select, update, insert on test.* to mysqltest_1@localhost;
+commit;
+show grants for mysqltest_1@localhost;
+drop user mysqltest_1@localhost;
+
+#
+# Bug #3403 Wrong encodin in SHOW GRANTS output
+#
+SET NAMES koi8r;
+CREATE DATABASE ÂÄ;
+USE ÂÄ;
+CREATE TABLE ÔÁÂ (ËÏÌ int);
+
+begin;
+GRANT SELECT ON ÂÄ.* TO ÀÚÅÒ@localhost;
+commit;
+SHOW GRANTS FOR ÀÚÅÒ@localhost;
+begin;
+REVOKE SELECT ON ÂÄ.* FROM ÀÚÅÒ@localhost;
+commit;
+
+begin;
+GRANT SELECT ON ÂÄ.ÔÁÂ TO ÀÚÅÒ@localhost;
+commit;
+SHOW GRANTS FOR ÀÚÅÒ@localhost;
+begin;
+REVOKE SELECT ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost;
+commit;
+
+begin;
+GRANT SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ TO ÀÚÅÒ@localhost;
+commit;
+SHOW GRANTS FOR ÀÚÅÒ@localhost;
+begin;
+REVOKE SELECT (ËÏÌ) ON ÂÄ.ÔÁÂ FROM ÀÚÅÒ@localhost;
+commit;
+
+DROP DATABASE ÂÄ;
+SET NAMES latin1;
+
+#
+# Bug #5831: REVOKE ALL PRIVILEGES, GRANT OPTION does not revoke everything
+#
+USE test;
+CREATE TABLE t1 (a int );
+CREATE TABLE t2 LIKE t1;
+CREATE TABLE t3 LIKE t1;
+CREATE TABLE t4 LIKE t1;
+CREATE TABLE t5 LIKE t1;
+CREATE TABLE t6 LIKE t1;
+CREATE TABLE t7 LIKE t1;
+CREATE TABLE t8 LIKE t1;
+CREATE TABLE t9 LIKE t1;
+CREATE TABLE t10 LIKE t1;
+CREATE DATABASE testdb1;
+CREATE DATABASE testdb2;
+CREATE DATABASE testdb3;
+CREATE DATABASE testdb4;
+CREATE DATABASE testdb5;
+CREATE DATABASE testdb6;
+CREATE DATABASE testdb7;
+CREATE DATABASE testdb8;
+CREATE DATABASE testdb9;
+CREATE DATABASE testdb10;
+begin;
+GRANT ALL ON testdb1.* TO testuser@localhost;
+GRANT ALL ON testdb2.* TO testuser@localhost;
+GRANT ALL ON testdb3.* TO testuser@localhost;
+GRANT ALL ON testdb4.* TO testuser@localhost;
+GRANT ALL ON testdb5.* TO testuser@localhost;
+GRANT ALL ON testdb6.* TO testuser@localhost;
+GRANT ALL ON testdb7.* TO testuser@localhost;
+GRANT ALL ON testdb8.* TO testuser@localhost;
+GRANT ALL ON testdb9.* TO testuser@localhost;
+GRANT ALL ON testdb10.* TO testuser@localhost;
+GRANT SELECT ON test.t1 TO testuser@localhost;
+GRANT SELECT ON test.t2 TO testuser@localhost;
+GRANT SELECT ON test.t3 TO testuser@localhost;
+GRANT SELECT ON test.t4 TO testuser@localhost;
+GRANT SELECT ON test.t5 TO testuser@localhost;
+GRANT SELECT ON test.t6 TO testuser@localhost;
+GRANT SELECT ON test.t7 TO testuser@localhost;
+GRANT SELECT ON test.t8 TO testuser@localhost;
+GRANT SELECT ON test.t9 TO testuser@localhost;
+GRANT SELECT ON test.t10 TO testuser@localhost;
+GRANT SELECT (a) ON test.t1 TO testuser@localhost;
+GRANT SELECT (a) ON test.t2 TO testuser@localhost;
+GRANT SELECT (a) ON test.t3 TO testuser@localhost;
+GRANT SELECT (a) ON test.t4 TO testuser@localhost;
+GRANT SELECT (a) ON test.t5 TO testuser@localhost;
+GRANT SELECT (a) ON test.t6 TO testuser@localhost;
+GRANT SELECT (a) ON test.t7 TO testuser@localhost;
+GRANT SELECT (a) ON test.t8 TO testuser@localhost;
+GRANT SELECT (a) ON test.t9 TO testuser@localhost;
+GRANT SELECT (a) ON test.t10 TO testuser@localhost;
+commit;
+begin;
+REVOKE ALL PRIVILEGES, GRANT OPTION FROM testuser@localhost;
+commit;
+SHOW GRANTS FOR testuser@localhost;
+DROP USER testuser@localhost;
+DROP TABLE t1,t2,t3,t4,t5,t6,t7,t8,t9,t10;
+DROP DATABASE testdb1;
+DROP DATABASE testdb2;
+DROP DATABASE testdb3;
+DROP DATABASE testdb4;
+DROP DATABASE testdb5;
+DROP DATABASE testdb6;
+DROP DATABASE testdb7;
+DROP DATABASE testdb8;
+DROP DATABASE testdb9;
+DROP DATABASE testdb10;
+
+#
+# just SHOW PRIVILEGES test
+#
+SHOW PRIVILEGES;
+
+#
+# Alter mysql system tables back to myisam
+#
+use mysql;
+alter table columns_priv engine=myisam;
+alter table db engine=myisam;
+alter table func engine=myisam;
+alter table help_category engine=myisam;
+alter table help_keyword engine=myisam;
+alter table help_relation engine=myisam;
+alter table help_topic engine=myisam;
+alter table host engine=myisam;
+alter table tables_priv engine=myisam;
+alter table time_zone engine=myisam;
+alter table time_zone_leap_second engine=myisam;
+alter table time_zone_name engine=myisam;
+alter table time_zone_transition engine=myisam;
+alter table time_zone_transition_type engine=myisam;
+alter table user engine=myisam;
+use test;
+flush privileges;
diff --git a/mysql-test/t/ndb_index_ordered.test b/mysql-test/t/ndb_index_ordered.test
index 64291c8ab97..53177511bc6 100644
--- a/mysql-test/t/ndb_index_ordered.test
+++ b/mysql-test/t/ndb_index_ordered.test
@@ -1,7 +1,7 @@
-- source include/have_ndb.inc
--disable_warnings
-drop table if exists t1;
+drop table if exists t1, test1, test2;
--enable_warnings
#
@@ -146,3 +146,29 @@ select * from t1 use index (bc) where b IS NULL and c = 2 order by a;
select * from t1 use index (bc) where b < 4 order by a;
select * from t1 use index (bc) where b IS NOT NULL order by a;
drop table t1;
+
+#
+# Bug #6435
+CREATE TABLE test1 (
+SubscrID int(11) NOT NULL auto_increment,
+UsrID int(11) NOT NULL default '0',
+PRIMARY KEY (SubscrID),
+KEY idx_usrid (UsrID)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+
+INSERT INTO test1 VALUES (2,224),(3,224),(1,224);
+
+CREATE TABLE test2 (
+SbclID int(11) NOT NULL auto_increment,
+SbcrID int(11) NOT NULL default '0',
+PRIMARY KEY (SbclID),
+KEY idx_sbcrid (SbcrID)
+) ENGINE=ndbcluster DEFAULT CHARSET=latin1;
+
+INSERT INTO test2 VALUES (3,2),(1,1),(2,1),(4,2);
+select * from test1 order by 1;
+select * from test2 order by 1;
+SELECT s.SubscrID,l.SbclID FROM test1 s left JOIN test2 l ON
+l.SbcrID=s.SubscrID WHERE s.UsrID=224 order by 1, 2;
+drop table test1;
+drop table test2;
diff --git a/mysql-test/t/ndb_index_unique.test b/mysql-test/t/ndb_index_unique.test
index 4a0c689bafb..f235d1ffc30 100644
--- a/mysql-test/t/ndb_index_unique.test
+++ b/mysql-test/t/ndb_index_unique.test
@@ -21,7 +21,7 @@ select * from t1 where b = 4 order by b;
insert into t1 values(7,8,3);
select * from t1 where b = 4 order by a;
--- error 1169
+-- error 1062
insert into t1 values(8, 2, 3);
select * from t1 order by a;
delete from t1 where a = 1;
@@ -30,6 +30,32 @@ select * from t1 order by a;
drop table t1;
+#
+# Indexing NULL values
+#
+
+CREATE TABLE t1 (
+ a int unsigned NOT NULL PRIMARY KEY,
+ b int unsigned,
+ c int unsigned,
+ UNIQUE bc(b,c)
+) engine = ndb;
+
+insert into t1 values(1,1,1),(2,NULL,2),(3,NULL,NULL),(4,4,NULL);
+select * from t1 use index (bc) where b IS NULL order by a;
+
+select * from t1 use index (bc)order by a;
+select * from t1 use index (bc) order by a;
+select * from t1 use index (PRIMARY) where b IS NULL order by a;
+select * from t1 use index (bc) where b IS NULL order by a;
+select * from t1 use index (bc) where b IS NULL and c IS NULL order by a;
+select * from t1 use index (bc) where b IS NULL and c = 2 order by a;
+select * from t1 use index (bc) where b < 4 order by a;
+select * from t1 use index (bc) where b IS NOT NULL order by a;
+-- error 1062
+insert into t1 values(5,1,1);
+drop table t1;
+
#
# Show use of UNIQUE USING HASH indexes
@@ -49,7 +75,7 @@ select * from t2 where c = 6;
insert into t2 values(7,8,3);
select * from t2 where b = 4 order by a;
--- error 1169
+-- error 1062
insert into t2 values(8, 2, 3);
select * from t2 order by a;
delete from t2 where a = 1;
@@ -58,6 +84,14 @@ select * from t2 order by a;
drop table t2;
+-- error 1121
+CREATE TABLE t2 (
+ a int unsigned NOT NULL PRIMARY KEY,
+ b int unsigned not null,
+ c int unsigned,
+ UNIQUE USING HASH (b, c)
+) engine=ndbcluster;
+
#
# Show use of PRIMARY KEY USING HASH indexes
#
@@ -92,7 +126,7 @@ insert into t1 values (-1,NULL), (0,0), (1,NULL),(2,2),(3,NULL),(4,4);
select * from t1 order by pk;
---error 1169
+--error 1062
insert into t1 values (5,0);
select * from t1 order by pk;
delete from t1 where a = 0;
@@ -111,7 +145,7 @@ insert into t2 values (-1,1,17,NULL),(0,NULL,18,NULL),(1,3,19,'abc');
select * from t2 order by pk;
---error 1169
+--error 1062
insert into t2 values(2,3,19,'abc');
select * from t2 order by pk;
delete from t2 where c IS NOT NULL;
@@ -231,4 +265,24 @@ select * from t4 where rid = 2 order by cid;
drop table t1,t2,t3,t4,t5,t6,t7;
+# test null in indexes
+CREATE TABLE t1 (
+ a int unsigned NOT NULL PRIMARY KEY,
+ b int unsigned,
+ c int unsigned,
+ UNIQUE bc(b,c) ) engine = ndb;
+
+insert into t1 values(1,1,1),(2,NULL,2),(3,NULL,NULL),(4,4,NULL);
+select * from t1 where b=1 and c=1;
+select * from t1 where b is null and c is null;
+select * from t1 where b is null and c = 2;
+select * from t1 where b = 4 and c is null;
+create table t8 as
+select * from t1 where (b = 1 and c = 1)
+ or (b is null and c is null)
+ or (b is null and c = 2)
+ or (b = 4 and c is null);
+select * from t8 order by a;
+select * from t1 order by a;
+drop table t1, t8;
diff --git a/mysql-test/t/ndb_insert.test b/mysql-test/t/ndb_insert.test
index 310c16de3d8..611df3d84e9 100644
--- a/mysql-test/t/ndb_insert.test
+++ b/mysql-test/t/ndb_insert.test
@@ -564,22 +564,51 @@ select count(*) from t1;
--error 1062
insert into t1 select * from t1 where b < 10 order by pk1;
+DELETE FROM t1 WHERE pk1=2;
begin;
---error 1031
-INSERT IGNORE INTO t1 VALUES(1,2,3);
-commit;
-select * from t1 where pk1=1;
+INSERT IGNORE INTO t1 VALUES(1,2,3),(2,3,4);
+select * from t1 where pk1 < 3 order by pk1;
+rollback;
---error 1031
-INSERT IGNORE INTO t1 VALUES(1,2,3);
-select * from t1 where pk1=1;
+INSERT IGNORE INTO t1 VALUES(1,2,3),(2,3,4);
+select * from t1 where pk1 < 3 order by pk1;
-REPLACE INTO t1 values(1, 2, 3);
+REPLACE INTO t1 values(1, 78, 3);
select * from t1 where pk1=1;
---error 1031
-INSERT INTO t1 VALUES(1,1,1) ON DUPLICATE KEY UPDATE b=79;
-select * from t1 where pk1=1;
+INSERT INTO t1 VALUES(1,1,1),(3,4,5) ON DUPLICATE KEY UPDATE b=79;
+select * from t1 where pk1 < 4 order by pk1;
+
+INSERT INTO t1 VALUES(1,1,1),(3,4,5) ON DUPLICATE KEY UPDATE b=pk1+c;
+select * from t1 where pk1 < 4 order by pk1;
+
+DELETE FROM t1 WHERE pk1 = 2 OR pk1 = 4 OR pk1 = 6;
+INSERT INTO t1 VALUES(1,1,1),(2,2,17),(3,4,5) ON DUPLICATE KEY UPDATE pk1=b;
+select * from t1 where pk1 = b and b != c order by pk1;
+# The following test case currently does not work
+#DELETE FROM t1;
+#CREATE UNIQUE INDEX bi ON t1(b);
+#INSERT INTO t1 VALUES
+#(1,1,1),(2,2,2),(3,3,3),(4,4,4),(5,5,5),
+#(6,6,6),(7,7,7),(8,8,8),(9,9,9),(10,10,10);
+#INSERT INTO t1 VALUES(0,1,0),(21,21,21) ON DUPLICATE KEY UPDATE pk1=b+10,c=b+10;
+#select * from t1 order by pk1;
+
+DROP TABLE t1;
+
+#
+# Bug #6331: problem with 'insert ignore'
+#
+
+CREATE TABLE t1(a INT) ENGINE=ndb;
+INSERT IGNORE INTO t1 VALUES (1);
+INSERT IGNORE INTO t1 VALUES (1);
+INSERT IGNORE INTO t1 SELECT a FROM t1;
+INSERT IGNORE INTO t1 SELECT a FROM t1;
+INSERT IGNORE INTO t1 SELECT a FROM t1;
+INSERT IGNORE INTO t1 VALUES (1);
+INSERT IGNORE INTO t1 VALUES (1);
+SELECT * FROM t1;
DROP TABLE t1;
diff --git a/mysql-test/t/null.test b/mysql-test/t/null.test
index 027443c485a..4bc6a4f051a 100644
--- a/mysql-test/t/null.test
+++ b/mysql-test/t/null.test
@@ -122,3 +122,70 @@ explain select * from t1 where i=2 or i is null;
select count(*) from t1 where i=2 or i is null;
drop table t1;
+#
+# NULL has its own type BINARY(0) by default.
+# But NULL should be weaker than a constant
+# when mixing charsets/collations
+#
+set names latin2;
+# Check that result type is taken from a non-null string
+create table t1 select
+ null as c00,
+ if(1, null, 'string') as c01,
+ if(0, null, 'string') as c02,
+ ifnull(null, 'string') as c03,
+ ifnull('string', null) as c04,
+ case when 0 then null else 'string' end as c05,
+ case when 1 then null else 'string' end as c06,
+ coalesce(null, 'string') as c07,
+ coalesce('string', null) as c08,
+ least('string',null) as c09,
+ least(null, 'string') as c10,
+ greatest('string',null) as c11,
+ greatest(null, 'string') as c12,
+ nullif('string', null) as c13,
+ nullif(null, 'string') as c14,
+ trim('string' from null) as c15,
+ trim(null from 'string') as c16,
+ substring_index('string', null, 1) as c17,
+ substring_index(null, 'string', 1) as c18,
+ elt(1, null, 'string') as c19,
+ elt(1, 'string', null) as c20,
+ concat('string', null) as c21,
+ concat(null, 'string') as c22,
+ concat_ws('sep', 'string', null) as c23,
+ concat_ws('sep', null, 'string') as c24,
+ concat_ws(null, 'string', 'string') as c25,
+ make_set(3, 'string', null) as c26,
+ make_set(3, null, 'string') as c27,
+ export_set(3, null, 'off', 'sep') as c29,
+ export_set(3, 'on', null, 'sep') as c30,
+ export_set(3, 'on', 'off', null) as c31,
+ replace(null, 'from', 'to') as c32,
+ replace('str', null, 'to') as c33,
+ replace('str', 'from', null) as c34,
+ insert('str', 1, 2, null) as c35,
+ insert(null, 1, 2, 'str') as c36,
+ lpad('str', 10, null) as c37,
+ rpad(null, 10, 'str') as c38;
+
+show create table t1;
+drop table t1;
+
+#
+# Check that comparison is done according to
+# non-null string collation, i.e. case insensitively,
+# rather than according to NULL's collation, i.e. case sensitively
+#
+-- in field
+select
+ case 'str' when 'STR' then 'str' when null then 'null' end as c01,
+ case 'str' when null then 'null' when 'STR' then 'str' end as c02,
+ field(null, 'str1', 'str2') as c03,
+ field('str1','STR1', null) as c04,
+ field('str1', null, 'STR1') as c05,
+ 'string' in ('STRING', null) as c08,
+ 'string' in (null, 'STRING') as c09;
+
+# Restore charset to the default value.
+set names latin1;
diff --git a/mysql-test/t/openssl_1.test b/mysql-test/t/openssl_1.test
index 39612f680f3..912c9fb9bec 100644
--- a/mysql-test/t/openssl_1.test
+++ b/mysql-test/t/openssl_1.test
@@ -9,9 +9,9 @@ create table t1(f1 int);
insert into t1 values (5);
grant select on test.* to ssl_user1@localhost require SSL;
-grant select on test.* to ssl_user2@localhost require cipher "EDH-RSA-DES-CBC3-SHA";
-grant select on test.* to ssl_user3@localhost require cipher "EDH-RSA-DES-CBC3-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com";
-grant select on test.* to ssl_user4@localhost require cipher "EDH-RSA-DES-CBC3-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com";
+grant select on test.* to ssl_user2@localhost require cipher "DHE-RSA-AES256-SHA";
+grant select on test.* to ssl_user3@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com";
+grant select on test.* to ssl_user4@localhost require cipher "DHE-RSA-AES256-SHA" AND SUBJECT "/C=SE/L=Uppsala/O=MySQL AB/CN=MySQL Client/Email=abstract.mysql.developer@mysql.com" ISSUER "/C=SE/L=Uppsala/O=MySQL AB/CN=Abstract MySQL Developer/Email=abstract.mysql.developer@mysql.com";
flush privileges;
connect (con1,localhost,ssl_user1,,);
connect (con2,localhost,ssl_user2,,);
diff --git a/mysql-test/t/order_by.test b/mysql-test/t/order_by.test
index 988c106bf21..dd36cd95969 100644
--- a/mysql-test/t/order_by.test
+++ b/mysql-test/t/order_by.test
@@ -500,3 +500,9 @@ insert into t1 set a = concat(repeat('x', 19), 'aa');
set max_sort_length=20;
select a from t1 order by a;
drop table t1;
+
+create table t1 (a int not null, b int not null, c int not null);
+insert t1 values (1,1,1),(1,1,2),(1,2,1);
+select a, b from t1 group by a, b order by sum(c);
+drop table t1;
+
diff --git a/mysql-test/t/ps.test b/mysql-test/t/ps.test
index 978ce2bc2c3..157b125a13d 100644
--- a/mysql-test/t/ps.test
+++ b/mysql-test/t/ps.test
@@ -110,10 +110,6 @@ set @fvar= 123.4567;
--error 1064
prepare stmt1 from @fvar;
-set @str1 = 'select ?';
-set @str2 = convert(@str1 using ucs2);
-prepare stmt1 from @str2;
-execute stmt1 using @ivar;
drop table t1,t2;
#
@@ -462,3 +458,29 @@ EXECUTE stmt;
DEALLOCATE PREPARE stmt;
DROP TABLE t1;
+#
+# Bug#6297 "prepared statement, wrong handling of <parameter> IS NULL"
+# Test that placeholders work with IS NULL/IS NOT NULL clauses.
+#
+prepare stmt from "select ? is null, ? is not null, ?";
+select @no_such_var is null, @no_such_var is not null, @no_such_var;
+execute stmt using @no_such_var, @no_such_var, @no_such_var;
+set @var='abc';
+select @var is null, @var is not null, @var;
+execute stmt using @var, @var, @var;
+set @var=null;
+select @var is null, @var is not null, @var;
+execute stmt using @var, @var, @var;
+
+#
+# Bug#6102 "Server crash with prepared statement and blank after
+# function name"
+# ensure that stored functions are cached when preparing a statement
+# before we open tables
+#
+create table t1 (a varchar(20));
+insert into t1 values ('foo');
+--error 1305
+prepare stmt FROM 'SELECT char_length (a) FROM t1';
+drop table t1;
+
diff --git a/mysql-test/t/ps_10nestset.test b/mysql-test/t/ps_10nestset.test
index d2adaca689e..53e84f7a47d 100644
--- a/mysql-test/t/ps_10nestset.test
+++ b/mysql-test/t/ps_10nestset.test
@@ -61,12 +61,11 @@ while ($1)
select * from t1;
-# Waiting for the resolution of bug#6138
-# # Now, increase salary to a multiple of 50
-# prepare st_round from 'update t1 set salary = salary + ? - ( salary MOD ? )';
-# set @arg_round= 50;
-# execute st_round using @arg_round, @arg_round;
-#
-# select * from t1;
+# Now, increase salary to a multiple of 50 (checks for bug#6138)
+prepare st_round from 'update t1 set salary = salary + ? - ( salary MOD ? )';
+set @arg_round= 50;
+execute st_round using @arg_round, @arg_round;
+
+select * from t1;
drop table t1;
diff --git a/mysql-test/t/ps_1general.test b/mysql-test/t/ps_1general.test
index 89c49d087b7..f1d8d3f7386 100644
--- a/mysql-test/t/ps_1general.test
+++ b/mysql-test/t/ps_1general.test
@@ -8,7 +8,11 @@
# NOTE: PLEASE SEE THE DETAILED DESCRIPTION AT THE BOTTOM OF THIS FILE
# BEFORE ADDING NEW TEST CASES HERE !!!
-use test;
+--disable_warnings
+drop table if exists t5, t6, t7, t8;
+drop database if exists mysqltest ;
+--enable_warnings
+
--disable_query_log
select '------ basic tests ------' as test_sequence ;
--enable_query_log
@@ -290,12 +294,14 @@ execute stmt4;
prepare stmt4 from ' show table status from test like ''t2%'' ';
# egalize date and time values
--replace_column 12 # 13 # 14 #
+--replace_result 2147483647 64424509439
# Bug#4288 : prepared statement 'show table status ..', wrong output on execute
execute stmt4;
# try the same with the big table
prepare stmt4 from ' show table status from test like ''t9%'' ';
# egalize date and time values
--replace_column 12 # 13 # 14 #
+--replace_result 2147483647 4294967295
# Bug#4288
execute stmt4;
prepare stmt4 from ' show status like ''Threads_running'' ';
@@ -311,7 +317,7 @@ prepare stmt4 from ' show engine bdb logs ';
execute stmt4;
--enable_result_log
prepare stmt4 from ' show full processlist ';
---replace_column 1 number
+--replace_column 1 number 6 seconds
execute stmt4;
prepare stmt4 from ' show grants for user ';
--error 1295
@@ -585,12 +591,9 @@ rename table new_t2 to t2;
drop table t2;
## RENAME more than on TABLE within one statement
# cases derived from client_test.c: test_rename()
---disable_warnings
-drop table if exists t5, t6, t7, t8 ;
---enable_warnings
prepare stmt1 from ' rename table t5 to t6, t7 to t8 ' ;
create table t5 (a int) ;
-# rename must fail, tc does not exist
+# rename must fail, t7 does not exist
--error 1017
execute stmt1 ;
create table t7 (a int) ;
@@ -859,15 +862,23 @@ select '------ grant/revoke/drop affects a parallel session test ------'
--error 1141
show grants for second_user@localhost ;
## create a new user account by using GRANT statements on t9
-grant usage on test.* to second_user@localhost
+create database mysqltest;
+# create the tables (t1 and t9) used in many tests
+use mysqltest;
+--disable_query_log
+--source include/ps_create.inc
+--source include/ps_renew.inc
+--enable_query_log
+eval use $DB;
+grant usage on mysqltest.* to second_user@localhost
identified by 'looser' ;
-grant select on test.t9 to second_user@localhost
+grant select on mysqltest.t9 to second_user@localhost
identified by 'looser' ;
show grants for second_user@localhost ;
#### establish a second session to the new user account
-connect (con3,localhost,second_user,looser,test);
+connect (con3,localhost,second_user,looser,mysqltest);
## switch to the second session
connection con3;
# Who am I ?
@@ -885,10 +896,10 @@ select a as my_col from t1;
#### give access rights to t1 and drop table t9
## switch back to the first session
connection default;
-grant select on test.t1 to second_user@localhost
+grant select on mysqltest.t1 to second_user@localhost
identified by 'looser' ;
show grants for second_user@localhost ;
-drop table t9 ;
+drop table mysqltest.t9 ;
show grants for second_user@localhost ;
@@ -907,7 +918,7 @@ execute s_t9 ;
#### revoke the access rights to t1
## switch back to the first session
connection default;
-revoke all privileges on test.t1 from second_user@localhost
+revoke all privileges on mysqltest.t1 from second_user@localhost
identified by 'looser' ;
show grants for second_user@localhost ;
@@ -932,8 +943,8 @@ commit ;
--error 1141
show grants for second_user@localhost ;
-
-drop table t1 ;
+drop table t1,t9 ;
+drop database mysqltest;
##### RULES OF THUMB TO PRESERVE THE SYSTEMATICS OF THE PS TEST CASES #####
diff --git a/mysql-test/t/ps_4heap.test b/mysql-test/t/ps_4heap.test
index a7b2e332af4..04d995dacb9 100644
--- a/mysql-test/t/ps_4heap.test
+++ b/mysql-test/t/ps_4heap.test
@@ -33,9 +33,9 @@ eval create table t9
c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
c13 date, c14 datetime, c15 timestamp(14), c16 time,
c17 year, c18 bit, c19 bool, c20 char,
- c21 char(10), c22 varchar(30), c23 char(100), c24 char(100),
- c25 char(100), c26 char(100), c27 char(100), c28 char(100),
- c29 char(100), c30 char(100), c31 enum('one', 'two', 'three'),
+ c21 char(10), c22 varchar(30), c23 varchar(100), c24 varchar(100),
+ c25 varchar(100), c26 varchar(100), c27 varchar(100), c28 varchar(100),
+ c29 varchar(100), c30 varchar(100), c31 enum('one', 'two', 'three'),
c32 set('monday', 'tuesday', 'wednesday'),
primary key(c1)
) engine = $type ;
diff --git a/mysql-test/t/ps_7ndb.test b/mysql-test/t/ps_7ndb.test
index af669a26400..b558f2f3c21 100644
--- a/mysql-test/t/ps_7ndb.test
+++ b/mysql-test/t/ps_7ndb.test
@@ -12,365 +12,11 @@ use test;
-- source include/have_ndb.inc
let $type= 'NDB' ;
---disable_warnings
-drop table if exists t1, t9 ;
---enable_warnings
-eval create table t1
-(
- a int not null, b varchar(30),
- primary key(a)
-) engine = $type ;
-
---disable_warnings
-drop table if exists t9;
---enable_warnings
-# The used table type doesn't support BLOB/TEXT columns.
-# (The server would send error 1163 .)
-# So we use char(100) instead.
-eval create table t9
-(
- c1 tinyint not null, c2 smallint, c3 mediumint, c4 int,
- c5 integer, c6 bigint, c7 float, c8 double,
- c9 double precision, c10 real, c11 decimal(7, 4), c12 numeric(8, 4),
- c13 date, c14 datetime, c15 timestamp(14), c16 time,
- c17 year, c18 bit, c19 bool, c20 char,
- c21 char(10), c22 varchar(30), c23 char(100), c24 char(100),
- c25 char(100), c26 char(100), c27 char(100), c28 char(100),
- c29 char(100), c30 char(100), c31 enum('one', 'two', 'three'),
- c32 set('monday', 'tuesday', 'wednesday'),
- primary key(c1)
-) engine = $type ;
+-- source include/ps_create.inc
-- source include/ps_renew.inc
-- source include/ps_query.inc
-# The following line is deactivated, because the ndb storage engine is not able
-# to do primary key column updates .
-#-- source include/ps_modify.inc
-# let's include all statements which will work
---disable_query_log
-select '------ delete tests ------' as test_sequence ;
---enable_query_log
---source include/ps_renew.inc
-
-## delete without parameter
-prepare stmt1 from 'delete from t1 where a=2' ;
-execute stmt1;
-select a,b from t1 where a=2 order by b;
-# delete with row not found
-execute stmt1;
-
-## delete with one parameter in the where clause
-insert into t1 values(0,NULL);
-set @arg00=NULL;
-prepare stmt1 from 'delete from t1 where b=?' ;
-execute stmt1 using @arg00;
-select a,b from t1 where b is NULL ;
-set @arg00='one';
-execute stmt1 using @arg00;
-select a,b from t1 where b=@arg00;
-
-## truncate a table
---error 1295
-prepare stmt1 from 'truncate table t1' ;
-
-
---disable_query_log
-select '------ update tests ------' as test_sequence ;
---enable_query_log
---source include/ps_renew.inc
-
-## update without parameter
-prepare stmt1 from 'update t1 set b=''a=two'' where a=2' ;
-execute stmt1;
-select a,b from t1 where a=2;
-# dummy update
-execute stmt1;
-select a,b from t1 where a=2;
-
-## update with one parameter in the set clause
-set @arg00=NULL;
-prepare stmt1 from 'update t1 set b=? where a=2' ;
-execute stmt1 using @arg00;
-select a,b from t1 where a=2;
-set @arg00='two';
-execute stmt1 using @arg00;
-select a,b from t1 where a=2;
-
-## update with one parameter in the where cause
-set @arg00=2;
-prepare stmt1 from 'update t1 set b=NULL where a=?' ;
-execute stmt1 using @arg00;
-select a,b from t1 where a=@arg00;
-update t1 set b='two' where a=@arg00;
-# row not found in update
-set @arg00=2000;
-execute stmt1 using @arg00;
-select a,b from t1 where a=@arg00;
-
-## update on primary key column (two parameters)
-set @arg00=2;
-set @arg01=22;
-prepare stmt1 from 'update t1 set a=? where a=?' ;
-# dummy update
-execute stmt1 using @arg00, @arg00;
-select a,b from t1 where a=@arg00;
-# deactivated primary key column update
-# execute stmt1 using @arg01, @arg00;
-select a,b from t1 where a=@arg01;
-execute stmt1 using @arg00, @arg01;
-select a,b from t1 where a=@arg00;
-set @arg00=NULL;
-set @arg01=2;
-# deactivated primary key column update
-# execute stmt1 using @arg00, @arg01;
-select a,b from t1 order by a;
-set @arg00=0;
-execute stmt1 using @arg01, @arg00;
-select a,b from t1 order by a;
-
-## update with subquery and several parameters
-set @arg00=23;
-set @arg01='two';
-set @arg02=2;
-set @arg03='two';
-set @arg04=2;
---disable_warnings
-drop table if exists t2;
---enable_warnings
-# t2 will be of table type 'MYISAM'
-create table t2 as select a,b from t1 ;
-prepare stmt1 from 'update t1 set a=? where b=?
- and a in (select ? from t2
- where b = ? or a = ?)';
---enable_info
-# deactivated primary key column update
-# execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
---disable_info
-select a,b from t1 where a = @arg00 ;
-prepare stmt1 from 'update t1 set a=? where b=?
- and a not in (select ? from t2
- where b = ? or a = ?)';
---enable_info
-execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
---disable_info
-select a,b from t1 order by a;
-drop table t2 ;
-# t2 is now of table type '$type'
-# The test battery for table type 'MERGE' gets here only a 'MYISAM' table
-eval create table t2
-(
- a int not null, b varchar(30),
- primary key(a)
-) engine = $type ;
-insert into t2(a,b) select a, b from t1 ;
-prepare stmt1 from 'update t1 set a=? where b=?
- and a in (select ? from t2
- where b = ? or a = ?)';
---enable_info
-# deactivated primary key column update
-# execute stmt1 using @arg00, @arg01, @arg02, @arg03, @arg04 ;
---disable_info
-select a,b from t1 where a = @arg00 ;
-prepare stmt1 from 'update t1 set a=? where b=?
- and a not in (select ? from t2
- where b = ? or a = ?)';
---enable_info
-execute stmt1 using @arg04, @arg01, @arg02, @arg03, @arg00 ;
---disable_info
-select a,b from t1 order by a ;
-drop table t2 ;
-
-## update with parameters in limit
-set @arg00=1;
-prepare stmt1 from 'update t1 set b=''bla''
-where a=2
-limit 1';
-execute stmt1 ;
-select a,b from t1 where b = 'bla' ;
-# currently (May 2004, Version 4.1) it is impossible
--- error 1064
-prepare stmt1 from 'update t1 set b=''bla''
-where a=2
-limit ?';
-
---disable_query_log
-select '------ insert tests ------' as test_sequence ;
---enable_query_log
---source include/ps_renew.inc
-
-## insert without parameter
-prepare stmt1 from 'insert into t1 values(5, ''five'' )';
-execute stmt1;
-select a,b from t1 where a = 5;
-
-## insert with one parameter in values part
-set @arg00='six' ;
-prepare stmt1 from 'insert into t1 values(6, ? )';
-execute stmt1 using @arg00;
-select a,b from t1 where b = @arg00;
-# the second insert fails, because the first column is primary key
---error 1062
-execute stmt1 using @arg00;
-set @arg00=NULL ;
-prepare stmt1 from 'insert into t1 values(0, ? )';
-execute stmt1 using @arg00;
-select a,b from t1 where b is NULL;
-
-## insert with two parameter in values part
-set @arg00=8 ;
-set @arg01='eight' ;
-prepare stmt1 from 'insert into t1 values(?, ? )';
-execute stmt1 using @arg00, @arg01 ;
-select a,b from t1 where b = @arg01;
-# cases derived from client_test.c: test_null()
-set @NULL= null ;
-set @arg00= 'abc' ;
-# execute must fail, because first column is primary key (-> not null)
---error 1048
-execute stmt1 using @NULL, @NULL ;
---error 1048
-execute stmt1 using @NULL, @NULL ;
---error 1048
-execute stmt1 using @NULL, @arg00 ;
---error 1048
-execute stmt1 using @NULL, @arg00 ;
-let $1 = 2;
-while ($1)
-{
- eval set @arg01= 10000 + $1 ;
- execute stmt1 using @arg01, @arg00 ;
- dec $1;
-}
-select * from t1 where a > 10000 order by a ;
-delete from t1 where a > 10000 ;
-let $1 = 2;
-while ($1)
-{
- eval set @arg01= 10000 + $1 ;
- execute stmt1 using @arg01, @NULL ;
- dec $1;
-}
-select * from t1 where a > 10000 order by a ;
-delete from t1 where a > 10000 ;
-let $1 = 10;
-while ($1)
-{
- eval set @arg01= 10000 + $1 ;
- execute stmt1 using @arg01, @arg01 ;
- dec $1;
-}
-select * from t1 where a > 10000 order by a ;
-delete from t1 where a > 10000 ;
-
-
-## insert with two rows in values part
-set @arg00=81 ;
-set @arg01='8-1' ;
-set @arg02=82 ;
-set @arg03='8-2' ;
-prepare stmt1 from 'insert into t1 values(?,?),(?,?)';
-execute stmt1 using @arg00, @arg01, @arg02, @arg03 ;
-select a,b from t1 where a in (@arg00,@arg02) order by a ;
-
-## insert with two parameter in the set part
-set @arg00=9 ;
-set @arg01='nine' ;
-prepare stmt1 from 'insert into t1 set a=?, b=? ';
-execute stmt1 using @arg00, @arg01 ;
-select a,b from t1 where a = @arg00 ;
-
-## insert with parameters in the ON DUPLICATE KEY part
-set @arg00=6 ;
-set @arg01=1 ;
-prepare stmt1 from 'insert into t1 set a=?, b=''sechs''
- on duplicate key update a=a + ?, b=concat(b,''modified'') ';
-# There is no primary key collision, so there will be no key column update
-# If a key column update would be necessary occurs BUG#4312
-# deactivated, activate when BUG#4312: is solved
-# execute stmt1 using @arg00, @arg01;
-select * from t1 order by a;
-set @arg00=81 ;
-set @arg01=1 ;
-# deactivated, activate when BUG#4312: is solved
-# execute stmt1 using @arg00, @arg01;
-
-## insert, autoincrement column and ' SELECT LAST_INSERT_ID() '
-# cases derived from client_test.c: test_bug3117()
---disable_warnings
-drop table if exists t2 ;
---enable_warnings
-# The test battery for table type 'MERGE' gets here only a 'MYISAM' table
-eval create table t2 (id int auto_increment primary key)
-ENGINE= $type ;
-prepare stmt1 from ' select last_insert_id() ' ;
-insert into t2 values (NULL) ;
-execute stmt1 ;
-insert into t2 values (NULL) ;
-execute stmt1 ;
-drop table t2 ;
-
-## many parameters
-set @1000=1000 ;
-set @x1000_2="x1000_2" ;
-set @x1000_3="x1000_3" ;
-
-set @x1000="x1000" ;
-set @1100=1100 ;
-set @x1100="x1100" ;
-set @100=100 ;
-set @updated="updated" ;
-insert into t1 values(1000,'x1000_1') ;
-# deactivated, activate when BUG#4312: is solved
-# insert into t1 values(@1000,@x1000_2),(@1000,@x1000_3)
-# on duplicate key update a = a + @100, b = concat(b,@updated) ;
-select a,b from t1 where a >= 1000 order by a ;
-delete from t1 where a >= 1000 ;
-insert into t1 values(1000,'x1000_1') ;
-prepare stmt1 from ' insert into t1 values(?,?),(?,?)
- on duplicate key update a = a + ?, b = concat(b,?) ';
-# deactivated, activate when BUG#4312: is solved
-# execute stmt1 using @1000, @x1000_2, @1000, @x1000_3, @100, @updated ;
-select a,b from t1 where a >= 1000 order by a ;
-delete from t1 where a >= 1000 ;
-insert into t1 values(1000,'x1000_1') ;
-# deactivated, activate when BUG#4312: is solved
-# execute stmt1 using @1000, @x1000_2, @1100, @x1000_3, @100, @updated ;
-select a,b from t1 where a >= 1000 order by a ;
-delete from t1 where a >= 1000 ;
-
-## replace
---error 1295
-prepare stmt1 from ' replace into t1 (a,b) select 100, ''hundred'' ';
-
-## multi table statements
---disable_query_log
-select '------ multi table tests ------' as test_sequence ;
---enable_query_log
-# cases derived from client_test.c: test_multi
-delete from t1 ;
-delete from t9 ;
-insert into t1(a,b) values (1, 'one'), (2, 'two'), (3, 'three') ;
-insert into t9 (c1,c21)
- values (1, 'one'), (2, 'two'), (3, 'three') ;
-prepare stmt_delete from " delete t1, t9
- from t1, t9 where t1.a=t9.c1 and t1.b='updated' ";
-prepare stmt_update from " update t1, t9
- set t1.b='updated', t9.c21='updated'
- where t1.a=t9.c1 and t1.a=? ";
-prepare stmt_select1 from " select a, b from t1 order by a" ;
-prepare stmt_select2 from " select c1, c21 from t9 order by c1" ;
-set @arg00= 1 ;
-let $1= 3 ;
-while ($1)
-{
- execute stmt_update using @arg00 ;
- execute stmt_delete ;
- execute stmt_select1 ;
- execute stmt_select2 ;
- set @arg00= @arg00 + 1 ;
- dec $1 ;
-}
-
+-- source include/ps_modify.inc
-- source include/ps_modify1.inc
-- source include/ps_conv.inc
diff --git a/mysql-test/t/range.test b/mysql-test/t/range.test
index d8794b2f394..18cf614f338 100644
--- a/mysql-test/t/range.test
+++ b/mysql-test/t/range.test
@@ -181,8 +181,8 @@ create table t1 (x int, y int, index(x), index(y));
insert into t1 (x) values (1),(2),(3),(4),(5),(6),(7),(8),(9);
update t1 set y=x;
# between with only one end fixed
-explain select * from t1, t1 t2 where t1.y = 2 and t2.x between 7 and t1.y+0;
-explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= 7 and t2.x <= t1.y+0;
+explain select * from t1, t1 t2 where t1.y = 8 and t2.x between 7 and t1.y+0;
+explain select * from t1, t1 t2 where t1.y = 8 and t2.x >= 7 and t2.x <= t1.y+0;
# between with both expressions on both ends
explain select * from t1, t1 t2 where t1.y = 2 and t2.x between t1.y-1 and t1.y+1;
explain select * from t1, t1 t2 where t1.y = 2 and t2.x >= t1.y-1 and t2.x <= t1.y+1;
@@ -418,3 +418,18 @@ select count(*) from t2 where x > -16;
select count(*) from t2 where x = 18446744073709551601;
drop table t1,t2;
+#
+# Bug #6045: Binary Comparison regression in MySQL 4.1
+# Binary searches didn't use a case insensitive index.
+#
+set names latin1;
+create table t1 (a char(10), b text, key (a)) character set latin1;
+INSERT INTO t1 (a) VALUES
+('111'),('222'),('222'),('222'),('222'),('444'),('aaa'),('AAA'),('bbb');
+# all these three can be optimized
+explain select * from t1 where a='aaa';
+explain select * from t1 where a=binary 'aaa';
+explain select * from t1 where a='aaa' collate latin1_bin;
+# this one cannot:
+explain select * from t1 where a='aaa' collate latin1_german1_ci;
+drop table t1;
diff --git a/mysql-test/t/rpl000001.test b/mysql-test/t/rpl000001.test
index 2e0ba2fff25..835af92186f 100644
--- a/mysql-test/t/rpl000001.test
+++ b/mysql-test/t/rpl000001.test
@@ -98,7 +98,7 @@ wait_for_slave_to_stop;
# The following test can't be done because the result of Pos will differ
# on different computers
-# --replace_result 9306 9999 3334 9999 3335 9999
+# --replace_result $MASTER_MYPORT MASTER_PORT
# show slave status;
set global sql_slave_skip_counter=1;
diff --git a/mysql-test/t/rpl_auto_increment.test b/mysql-test/t/rpl_auto_increment.test
index cfe1d44b11a..71032404307 100644
--- a/mysql-test/t/rpl_auto_increment.test
+++ b/mysql-test/t/rpl_auto_increment.test
@@ -26,7 +26,7 @@ connection master;
drop table t1;
set @@session.auto_increment_increment=100, @@session.auto_increment_offset=10;
-show variables like "%auto%";
+show variables like "%auto_inc%";
create table t1 (a int not null auto_increment, primary key (a)) engine=myisam;
# Insert with 2 insert statements to get better testing of logging
diff --git a/mysql-test/t/rpl_charset.test b/mysql-test/t/rpl_charset.test
index 839fe5d377b..52ace9a6aa5 100644
--- a/mysql-test/t/rpl_charset.test
+++ b/mysql-test/t/rpl_charset.test
@@ -112,10 +112,10 @@ sync_slave_with_master;
# Check that we can't change global.collation_server
-error 1105;
+error 1387;
set global character_set_server=latin2;
connection master;
-error 1105;
+error 1387;
set global character_set_server=latin2;
# Check that SET ONE_SHOT is really one shot
@@ -129,7 +129,7 @@ select @@character_set_server;
select @@character_set_server;
# ONE_SHOT on not charset/collation stuff is not allowed
-error 1105;
+-- error 1382
set one_shot max_join_size=10;
# Test of wrong character set numbers;
@@ -155,14 +155,22 @@ select hex(c1), hex(c2) from t1;
stop slave;
delete from t1;
+# Slave is now supposed to have stopped _after_ the INSERT
# Note that the following positions may change between MySQL versions!
-# This position should be position for the SET
-change master to master_log_pos=6763;
+# This position should be position for the SET ONE SHOT CHARACTER_SET_CLIENT
+# command just before the INSERT.
+# You can find it by doing:
+# ../client/mysqlbinlog var/log/master-bin.000001 | grep -3 CHARACTER_SET | tail -7
+change master to master_log_pos=6809;
-# This position should be position of the INSERT command
-start slave until master_log_file='master-bin.000001', master_log_pos=6921;
+# This position should be position of the INSERT command.
+# You can find it by doing:
+#
+# ../client/mysqlbinlog var/log/master-bin.000001 | grep -3 INSERT | tail -4
+
+start slave until master_log_file='master-bin.000001', master_log_pos=6967;
# Slave is supposed to stop _after_ the INSERT, even though 'master_log_pos' is
# the position of the beginning of the INSERT; after SET slave is not
diff --git a/mysql-test/t/rpl_create_database-master.opt b/mysql-test/t/rpl_create_database-master.opt
new file mode 100644
index 00000000000..85660a17140
--- /dev/null
+++ b/mysql-test/t/rpl_create_database-master.opt
@@ -0,0 +1 @@
+--binlog-do-db=mysqltest_sisyfos --binlog-do-db=mysqltest_prometheus
diff --git a/mysql-test/t/rpl_create_database-slave.opt b/mysql-test/t/rpl_create_database-slave.opt
new file mode 100644
index 00000000000..96d630c9229
--- /dev/null
+++ b/mysql-test/t/rpl_create_database-slave.opt
@@ -0,0 +1 @@
+--replicate-do-db=mysqltest_sisyfos --replicate-do-db=mysqltest_prometheus
diff --git a/mysql-test/t/rpl_create_database.test b/mysql-test/t/rpl_create_database.test
new file mode 100644
index 00000000000..c63b0bc85ef
--- /dev/null
+++ b/mysql-test/t/rpl_create_database.test
@@ -0,0 +1,71 @@
+#
+# Tests for replication of statements that manipulate databases.
+#
+# For this test file, we have a number of databases. All databases
+# with "greek" names will be replicated on the slave, while other names
+# (e.g., american) will not be replicated.
+#
+
+source include/master-slave.inc;
+
+# Bug#6391 (binlog-do-db rules ignored)
+# In this case, 'mysqltest_bob' should not be replicated to the slave.
+--disable_warnings
+DROP DATABASE IF EXISTS mysqltest_prometheus;
+DROP DATABASE IF EXISTS mysqltest_sisyfos;
+DROP DATABASE IF EXISTS mysqltest_bob;
+sync_slave_with_master;
+# This database is not replicated
+DROP DATABASE IF EXISTS mysqltest_bob;
+--enable_warnings
+
+connection master;
+CREATE DATABASE mysqltest_prometheus;
+CREATE DATABASE mysqltest_sisyfos;
+CREATE DATABASE mysqltest_bob;
+
+USE mysqltest_sisyfos;
+# These should be replicated
+CREATE TABLE t1 (b int);
+INSERT INTO t1 VALUES(1);
+
+USE mysqltest_bob;
+# These should *not* be replicated
+CREATE TABLE t2 (b int);
+INSERT INTO t2 VALUES(2);
+
+# Current database is now 'mysqltest_bob'
+# The following should be replicated
+ALTER DATABASE mysqltest_sisyfos CHARACTER SET latin1;
+
+USE mysqltest_sisyfos;
+# The following should *not* be replicated
+ALTER DATABASE mysqltest_bob CHARACTER SET latin1;
+
+SHOW DATABASES;
+sync_slave_with_master;
+SHOW DATABASES;
+
+connection master;
+DROP DATABASE IF EXISTS mysqltest_sisyfos;
+USE mysqltest_prometheus;
+CREATE TABLE t1 (a INT);
+INSERT INTO t1 VALUES (1);
+CREATE DATABASE mysqltest_sisyfos;
+USE mysqltest_sisyfos;
+CREATE TABLE t2 (a INT);
+let $VERSION=`select version()`;
+--replace_result $VERSION VERSION
+--replace_column 2 # 5 #
+SHOW BINLOG EVENTS;
+SHOW DATABASES;
+sync_slave_with_master;
+SHOW DATABASES;
+SHOW CREATE TABLE mysqltest_prometheus.t1;
+SHOW CREATE TABLE mysqltest_sisyfos.t2;
+
+connection master;
+DROP DATABASE IF EXISTS mysqltest_prometheus;
+DROP DATABASE IF EXISTS mysqltest_sisyfos;
+DROP DATABASE IF EXISTS mysqltest_bob;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_failed_optimize-master.opt b/mysql-test/t/rpl_failed_optimize-master.opt
new file mode 100644
index 00000000000..3f82baff598
--- /dev/null
+++ b/mysql-test/t/rpl_failed_optimize-master.opt
@@ -0,0 +1 @@
+--loose-innodb-lock-wait-timeout=1
diff --git a/mysql-test/t/rpl_failed_optimize.test b/mysql-test/t/rpl_failed_optimize.test
new file mode 100644
index 00000000000..d245d1bacbb
--- /dev/null
+++ b/mysql-test/t/rpl_failed_optimize.test
@@ -0,0 +1,18 @@
+source include/have_innodb.inc;
+source include/master-slave.inc;
+
+#
+# BUG#5551 "Failed OPTIMIZE TABLE is logged to binary log"
+# Replication should work when OPTIMIZE TABLE timeouts, and
+# when OPTIMIZE TABLE is executed on a non-existing table
+#
+
+CREATE TABLE t1 ( a int ) ENGINE=InnoDB;
+BEGIN;
+INSERT INTO t1 VALUES (1);
+
+connection master1;
+OPTIMIZE TABLE t1;
+
+OPTIMIZE TABLE non_existing;
+sync_slave_with_master;
diff --git a/mysql-test/t/rpl_rewrite_db-slave.opt b/mysql-test/t/rpl_rewrite_db-slave.opt
new file mode 100644
index 00000000000..a462ad19ba0
--- /dev/null
+++ b/mysql-test/t/rpl_rewrite_db-slave.opt
@@ -0,0 +1 @@
+"--replicate-rewrite-db=test->rewrite" "--replicate-rewrite-db=mysqltest1->test"
diff --git a/mysql-test/t/rpl_rewrite_db.test b/mysql-test/t/rpl_rewrite_db.test
new file mode 100644
index 00000000000..b6118854037
--- /dev/null
+++ b/mysql-test/t/rpl_rewrite_db.test
@@ -0,0 +1,77 @@
+source include/master-slave.inc;
+--disable_warnings
+drop database if exists mysqltest1;
+--enable_warnings
+create database mysqltest1;
+
+use mysqltest1;
+create table t1 (a int);
+insert into t1 values(9);
+select * from mysqltest1.t1;
+sync_slave_with_master;
+show databases like 'mysqltest1'; # should be empty
+select * from test.t1;
+# cleanup
+connection master;
+drop table t1;
+drop database mysqltest1;
+sync_slave_with_master;
+
+#
+# BUG#6353:
+# Option --replicate-rewrite-db should work together with LOAD DATA INFILE
+#
+
+connection slave;
+--disable_warnings
+drop database if exists rewrite;
+--enable_warnings
+create database rewrite;
+
+connection master;
+use test;
+create table t1 (a date, b date, c date not null, d date);
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',';
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' IGNORE 2 LINES;
+sync_slave_with_master;
+
+connection slave;
+select * from rewrite.t1;
+
+connection master;
+truncate table t1;
+load data infile '../../std_data/loaddata1.dat' into table t1 fields terminated by ',' LINES STARTING BY ',' (b,c,d);
+sync_slave_with_master;
+
+connection slave;
+select * from rewrite.t1;
+
+connection master;
+drop table t1;
+create table t1 (a text, b text);
+load data infile '../../std_data/loaddata2.dat' into table t1 fields terminated by ',' enclosed by '''';
+sync_slave_with_master;
+
+connection slave;
+select concat('|',a,'|'), concat('|',b,'|') from rewrite.t1;
+
+connection master;
+drop table t1;
+create table t1 (a int, b char(10));
+load data infile '../../std_data/loaddata3.dat' into table t1 fields terminated by '' enclosed by '' ignore 1 lines;
+sync_slave_with_master;
+
+connection slave;
+select * from rewrite.t1;
+
+connection master;
+truncate table t1;
+load data infile '../../std_data/loaddata4.dat' into table t1 fields terminated by '' enclosed by '' lines terminated by '' ignore 1 lines;
+sync_slave_with_master;
+
+connection slave;
+# The empty line last comes from the end line field in the file
+select * from rewrite.t1;
+
+connection master;
+drop table t1;
diff --git a/mysql-test/t/rpl_rotate_logs.test b/mysql-test/t/rpl_rotate_logs.test
index c3c0ff5be10..63ddf495347 100644
--- a/mysql-test/t/rpl_rotate_logs.test
+++ b/mysql-test/t/rpl_rotate_logs.test
@@ -23,7 +23,8 @@ drop table if exists t1, t2, t3, t4;
# START SLAVE will fail because it can't read the file (mode 000)
# (system error 13)
---error 1201
+--replace_result $MYSQL_TEST_DIR TESTDIR
+--error 1105
start slave;
system chmod 600 var/slave-data/master.info;
# It will fail again because the file is empty so the slave cannot get valuable
diff --git a/mysql-test/t/rpl_start_stop_slave.test b/mysql-test/t/rpl_start_stop_slave.test
new file mode 100644
index 00000000000..903ff204194
--- /dev/null
+++ b/mysql-test/t/rpl_start_stop_slave.test
@@ -0,0 +1,34 @@
+source include/master-slave.inc;
+
+#
+# Bug#6148 ()
+#
+connection slave;
+stop slave;
+
+# Let the master do lots of insertions
+connection master;
+create table t1(n int);
+let $1=5000;
+disable_query_log;
+while ($1)
+{
+ eval insert into t1 values($1);
+ dec $1;
+}
+enable_query_log;
+save_master_pos;
+
+connection slave;
+start slave;
+sleep 1;
+stop slave io_thread;
+start slave io_thread;
+sync_with_master;
+
+connection master;
+drop table t1;
+save_master_pos;
+
+connection slave;
+sync_with_master;
diff --git a/mysql-test/t/rpl_timezone.test b/mysql-test/t/rpl_timezone.test
index 8dff90a84cf..ebb58a9c880 100644
--- a/mysql-test/t/rpl_timezone.test
+++ b/mysql-test/t/rpl_timezone.test
@@ -76,7 +76,7 @@ select * from t2;
# replication
#
connection master;
---error 1105
+--error 1387
set global time_zone='MET';
# Clean up
diff --git a/mysql-test/t/rpl_until.test b/mysql-test/t/rpl_until.test
index f7ca51ecabc..318cca600a3 100644
--- a/mysql-test/t/rpl_until.test
+++ b/mysql-test/t/rpl_until.test
@@ -43,7 +43,7 @@ show slave status;
# try replicate all until second insert to t2;
start slave until relay_log_file='slave-relay-bin.000004', relay_log_pos=710;
-sleep 2;
+sleep 4;
select * from t2;
--replace_result $MASTER_MYPORT MASTER_MYPORT
--replace_column 1 # 9 # 23 # 33 #
diff --git a/mysql-test/t/select.test b/mysql-test/t/select.test
index 3619cf116d1..e548aba29fe 100644
--- a/mysql-test/t/select.test
+++ b/mysql-test/t/select.test
@@ -1758,6 +1758,15 @@ DO 1;
DO benchmark(100,1+1),1,1;
#
+# Bug #6449: do default;
+#
+
+--error 1064
+do default;
+--error 1054
+do foobar;
+
+#
# random in WHERE clause
#
@@ -1891,6 +1900,20 @@ select * from t2,t3 where t2.s = t3.s;
drop table t1, t2, t3;
#
+# Bug #3759
+# Both queries should produce identical plans and results.
+#
+create table t1 (a integer, b integer, index(a), index(b));
+create table t2 (c integer, d integer, index(c), index(d));
+insert into t1 values (1,2), (2,2), (3,2), (4,2);
+insert into t2 values (1,3), (2,3), (3,4), (4,4);
+explain select * from t1 left join t2 on a=c where d in (4);
+select * from t1 left join t2 on a=c where d in (4);
+explain select * from t1 left join t2 on a=c where d = 4;
+select * from t1 left join t2 on a=c where d = 4;
+drop table t1, t2;
+
+#
# Covering index is mentioned in EXPLAIN output for const tables (bug #5333)
#
@@ -1907,6 +1930,40 @@ INSERT INTO t1 VALUES (3,'c');
EXPLAIN SELECT i FROM t1 WHERE i=1;
-EXPLAIN SELECT i FROM t1 WHERE i=1;
+DROP TABLE t1;
+
+#
+# Test for bug #6474
+#
+
+CREATE TABLE t1 (
+K2C4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '',
+K4N4 varchar(4) character set latin1 collate latin1_bin NOT NULL default '0000',
+F2I4 int(11) NOT NULL default '0'
+) ENGINE=MyISAM DEFAULT CHARSET=latin1;
+
+INSERT INTO t1 VALUES
+('W%RT', '0100', 1),
+('W-RT', '0100', 1),
+('WART', '0100', 1),
+('WART', '0200', 1),
+('WERT', '0100', 2),
+('WORT','0200', 2),
+('WT', '0100', 2),
+('W_RT', '0100', 2),
+('WaRT', '0100', 3),
+('WART', '0300', 3),
+('WRT' , '0400', 3),
+('WURM', '0500', 3),
+('W%T', '0600', 4),
+('WA%T', '0700', 4),
+('WA_T', '0800', 4);
+
+SELECT K2C4, K4N4, F2I4 FROM t1
+ WHERE K2C4 = 'WART' AND
+ (F2I4 = 2 AND K2C4 = 'WART' OR (F2I4 = 2 OR K4N4 = '0200'));
+
+SELECT K2C4, K4N4, F2I4 FROM t1
+ WHERE K2C4 = 'WART' AND (K2C4 = 'WART' OR K4N4 = '0200');
DROP TABLE t1;
diff --git a/mysql-test/t/show_check.test b/mysql-test/t/show_check.test
index 9e18f1cd88c..b09d7240721 100644
--- a/mysql-test/t/show_check.test
+++ b/mysql-test/t/show_check.test
@@ -21,7 +21,8 @@ check table t1 changed;
check table t1 medium;
check table t1 extended;
show index from t1;
-!$1062 insert into t1 values (5,5,5);
+--error 1062
+insert into t1 values (5,5,5);
optimize table t1;
optimize table t1;
drop table t1;
diff --git a/mysql-test/t/sp-error.test b/mysql-test/t/sp-error.test
index c04f8e6f9e9..c24f9df16be 100644
--- a/mysql-test/t/sp-error.test
+++ b/mysql-test/t/sp-error.test
@@ -632,6 +632,28 @@ end|
call bug3294()|
drop procedure bug3294|
+#
+# BUG#6807: Stored procedure crash if CREATE PROCEDURE ... KILL QUERY
+#
+--disable_warnings
+drop procedure if exists bug6807|
+--enable_warnings
+create procedure bug6807()
+begin
+ declare id int;
+
+ set id = connection_id();
+ kill query id;
+ select 'Not reached';
+end|
+
+--error 1317
+call bug6807()|
+--error 1317
+call bug6807()|
+
+drop procedure bug6807|
+
drop table t1|
diff --git a/mysql-test/t/sp-security.test b/mysql-test/t/sp-security.test
index 2b53bbc528a..d1119499cf1 100644
--- a/mysql-test/t/sp-security.test
+++ b/mysql-test/t/sp-security.test
@@ -58,7 +58,7 @@ select db1_secret.db();
select * from db1_secret.t1;
# ...and not this
---error 1049
+--error 1044
create procedure db1_secret.dummy() begin end;
--error 1305
drop procedure db1_secret.dummy;
@@ -78,7 +78,7 @@ select db1_secret.db();
select * from db1_secret.t1;
# ...and not this
---error 1049
+--error 1044
create procedure db1_secret.dummy() begin end;
--error 1305
drop procedure db1_secret.dummy;
diff --git a/mysql-test/t/sp.test b/mysql-test/t/sp.test
index 88d1b8c0356..ec1fb3e7452 100644
--- a/mysql-test/t/sp.test
+++ b/mysql-test/t/sp.test
@@ -1870,13 +1870,28 @@ create procedure bug4904()
begin
declare continue handler for sqlstate 'HY000' begin end;
- create table t2 as select * from t;
+ create table t2 as select * from t3;
end|
+-- error 1146
call bug4904()|
drop procedure bug4904|
+create table t3 (s1 char character set latin1, s2 char character set latin2)|
+
+create procedure bug4904 ()
+begin
+ declare continue handler for sqlstate 'HY000' begin end;
+
+ select s1 from t3 union select s2 from t3;
+end|
+
+call bug4904()|
+
+drop procedure bug4904|
+drop table t3|
+
#
# BUG#336
#
diff --git a/mysql-test/t/sql_mode.test b/mysql-test/t/sql_mode.test
index 26a5d07d951..fa5c6cb8a5b 100644
--- a/mysql-test/t/sql_mode.test
+++ b/mysql-test/t/sql_mode.test
@@ -30,6 +30,37 @@ show create table t1;
drop table t1;
#
+# Check that a binary collation adds 'binary'
+# suffix into a char() column definition in
+# mysql40 and mysql2323 modes. This allows
+# not to lose the column's case sensitivity
+# when loading the dump in pre-4.1 servers.
+#
+# Thus, in 4.0 and 3.23 modes we dump:
+#
+# 'char(10) collate xxx_bin' as 'char(10) binary'
+# 'binary(10)' as 'binary(10)'
+#
+# In mysql-4.1 these types are different, and they will
+# be recreated differently.
+#
+# In mysqld-4.0 the the above two types were the same,
+# so it will create a 'char(10) binary' column for both definitions.
+#
+CREATE TABLE t1 (
+ a char(10),
+ b char(10) collate latin1_bin,
+ c binary(10)
+) character set latin1;
+set @@sql_mode="";
+show create table t1;
+set @@sql_mode="mysql323";
+show create table t1;
+set @@sql_mode="mysql40";
+show create table t1;
+drop table t1;
+
+#
# BUG#5318 - failure: 'IGNORE_SPACE' affects numeric values after DEFAULT
#
# Force the usage of the default
diff --git a/mysql-test/t/strict.test b/mysql-test/t/strict.test
index d9f4f4f2d0c..42d5ca5e8e1 100644
--- a/mysql-test/t/strict.test
+++ b/mysql-test/t/strict.test
@@ -493,8 +493,8 @@ DROP TABLE t1;
# Test INSERT with FLOAT
CREATE TABLE t1 (col1 FLOAT, col2 FLOAT UNSIGNED);
-INSERT INTO t1 VALUES (-1.1E-38,0),(+3.4E+38,+3.4E+38);
-INSERT INTO t1 VALUES ('-1.1E-38',0),('+3.4E+38','+3.4E+38');
+INSERT INTO t1 VALUES (-1.1E-37,0),(+3.4E+38,+3.4E+38);
+INSERT INTO t1 VALUES ('-1.1E-37',0),('+3.4E+38','+3.4E+38');
# We don't give warnings for underflow
INSERT INTO t1 (col1) VALUES (3E-46);
--error 1264
@@ -527,8 +527,8 @@ DROP TABLE t1;
# Test INSERT with DOUBLE
CREATE TABLE t1 (col1 DOUBLE PRECISION, col2 DOUBLE PRECISION UNSIGNED);
-INSERT INTO t1 VALUES (-2.2E-308,0),(+1.7E+308,+1.7E+308);
-INSERT INTO t1 VALUES ('-2.2E-308',0),('+1.7E+308','+1.7E+308');
+INSERT INTO t1 VALUES (-2.2E-307,0),(+1.7E+308,+1.7E+308);
+INSERT INTO t1 VALUES ('-2.2E-307',0),('+1.7E+308','+1.7E+308');
# We don't give warnings for underflow
INSERT INTO t1 (col1) VALUES (-2.2E-330);
--error 1367
@@ -563,13 +563,15 @@ DROP TABLE t1;
# Testing INSERT with CHAR/VARCHAR
-CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(5));
-INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
+CREATE TABLE t1 (col1 CHAR(5), col2 VARCHAR(6));
+INSERT INTO t1 VALUES ('hello', 'hello'),('he', 'he'),('hello ', 'hello ');
--error 1265
INSERT INTO t1 (col1) VALUES ('hellobob');
--error 1265
INSERT INTO t1 (col2) VALUES ('hellobob');
--error 1265
+INSERT INTO t1 (col2) VALUES ('hello ');
+--error 1265
UPDATE t1 SET col1 ='hellobob' WHERE col1 ='he';
--error 1265
UPDATE t1 SET col2 ='hellobob' WHERE col2 ='he';
diff --git a/mysql-test/t/subselect.test b/mysql-test/t/subselect.test
index 16556c4864c..daef4c3e281 100644
--- a/mysql-test/t/subselect.test
+++ b/mysql-test/t/subselect.test
@@ -1287,3 +1287,57 @@ INSERT INTO `t2` VALUES (6,5,12,7,'a'),(12,0,0,7,'a'),(12,1,0,7,'a'),(12,5,5,7,'
SELECT b.sc FROM (SELECT (SELECT a.access FROM t1 a WHERE a.map = op.map AND a.slave = op.pid AND a.master = 1) ac FROM t2 op WHERE op.id = 12 AND op.map = 0) b;
SELECT b.ac FROM (SELECT (SELECT a.access FROM t1 a WHERE a.map = op.map AND a.slave = op.pid AND a.master = 1) ac FROM t2 op WHERE op.id = 12 AND op.map = 0) b;
drop tables t1,t2;
+
+#
+# Test for bug #6462. "Same request on same data returns different
+# results." a.k.a. "Proper cleanup of subqueries is missing for
+# SET and DO statements".
+#
+create table t1 (a int not null, b int not null, c int, primary key (a,b));
+insert into t1 values (1,1,1), (2,2,2), (3,3,3);
+set @b:= 0;
+# Let us check that subquery will use covering index
+explain select sum(a) from t1 where b > @b;
+# This should not crash -debug server due to failing assertion
+set @a:= (select sum(a) from t1 where b > @b);
+# And this should not falsely report index usage
+explain select a from t1 where c=2;
+# Same for DO statement
+do @a:= (select sum(a) from t1 where b > @b);
+explain select a from t1 where c=2;
+drop table t1;
+
+#
+# Subselect in non-select command just after connection
+#
+connect (root,localhost,root,,test,$MASTER_MYPORT,$MASTER_MYSOCK);
+connection root;
+set @got_val= (SELECT 1 FROM (SELECT 'A' as my_col) as T1 ) ;
+
+#
+# primary query with temporary table and subquery with groupping
+#
+create table t1 (a int, b int);
+create table t2 (a int, b int);
+insert into t1 values (1,1),(1,2),(1,3),(2,4),(2,5);
+insert into t2 values (1,3),(2,1);
+select distinct a,b, (select max(b) from t2 where t1.b=t2.a) from t1 order by t1.b;
+drop table t1, t2;
+
+#
+# subqueries with full text search
+#
+create table t1 (id int);
+create table t2 (id int, body text, fulltext (body));
+insert into t1 values(1),(2),(3);
+insert into t2 values (1,'test'), (2,'mysql'), (3,'test'), (4,'test');
+select count(distinct id) from t1 where id in (select id from t2 where match(body) against ('mysql' in boolean mode));
+drop table t2,t1;
+
+#
+# Equal operation under row and empty subquery
+#
+create table t1 (s1 int,s2 int);
+insert into t1 values (20,15);
+select * from t1 where (('a',null) <=> (select 'a',s2 from t1 where s1 = 0));
+drop table t1;
diff --git a/mysql-test/t/subselect_innodb.test b/mysql-test/t/subselect_innodb.test
index 5f4badb3624..aa7fe138876 100644
--- a/mysql-test/t/subselect_innodb.test
+++ b/mysql-test/t/subselect_innodb.test
@@ -125,3 +125,23 @@ INSERT INTO `t2` VALUES ('yy','xx');
SELECT R.unit, R.ingredient FROM t1 R WHERE R.ingredient IN (SELECT N.ingredient FROM t2 N WHERE N.unit = R.unit);
drop table t1, t2;
+
+#
+# possible early unlock
+#
+CREATE TABLE t1 (
+ id INT NOT NULL auto_increment,
+ date1 DATE, coworkerid INT,
+ description VARCHAR(255),
+ sum_used DOUBLE,
+ sum_remaining DOUBLE,
+ comments VARCHAR(255),
+ PRIMARY KEY(id)
+) engine=innodb;
+insert into t1 values (NULL, '1999-01-01', 1,'test', 22, 33, 'comment'), (NULL, '1999-01-01', 1,'test', 22, 33, 'comment'), (NULL, '1999-01-01', 1,'test', 22, 33, 'comment'), (NULL, '1998-01-01', 1,'test', 22, 33, 'comment'), (NULL, '1998-01-01', 1,'test', 22, 33, 'comment'), (NULL, '2004-01-01', 1,'test', 22, 33, 'comment'), (NULL, '2004-01-01', 1,'test', 22, 33, 'comment');
+SELECT DISTINCT
+ (SELECT sum(sum_used) FROM t1 WHERE sum_used > 0 AND year(date1) <= '2004') as somallontvangsten,
+ (SELECT sum(sum_used) FROM t1 WHERE sum_used < 0 AND year(date1) <= '2004') as somalluitgaven
+ FROM t1;
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/temp_table.test b/mysql-test/t/temp_table.test
index 2181d3eb74c..74276c7668c 100644
--- a/mysql-test/t/temp_table.test
+++ b/mysql-test/t/temp_table.test
@@ -20,8 +20,10 @@ create TEMPORARY TABLE t2 engine=heap select * from t1;
create TEMPORARY TABLE IF NOT EXISTS t2 (a int) engine=heap;
# This should give errors
-!$1050 CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null);
-!$1050 ALTER TABLE t1 RENAME t2;
+--error 1050
+CREATE TEMPORARY TABLE t1 (a int not null, b char (10) not null);
+--error 1050
+ALTER TABLE t1 RENAME t2;
select * from t2;
alter table t2 add primary key (a,b);
diff --git a/mysql-test/t/timezone3-master.opt b/mysql-test/t/timezone3-master.opt
new file mode 100644
index 00000000000..6910e6e6e8d
--- /dev/null
+++ b/mysql-test/t/timezone3-master.opt
@@ -0,0 +1 @@
+--timezone=:$MYSQL_TEST_DIR/std_data/Moscow_leap
diff --git a/mysql-test/t/timezone3.test b/mysql-test/t/timezone3.test
new file mode 100644
index 00000000000..8910783cd85
--- /dev/null
+++ b/mysql-test/t/timezone3.test
@@ -0,0 +1,59 @@
+#
+# Test of handling time zone with leap seconds.
+#
+# This test should be run with TZ=:$MYSQL_TEST_DIR/std_data/Moscow_leap
+# This implies that this test should be run only on systems that interpret
+# characters after colon in TZ variable as path to zoneinfo file.
+#
+# Check that we have successfully set time zone with leap seconds.
+--require r/have_moscow_leap_timezone.require
+disable_query_log;
+select from_unixtime(1072904422);
+enable_query_log;
+
+# Initial clean-up
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+#
+# Let us check behavior of conversion from broken-down representation
+# to time_t representation, for normal, non-existent and ambigious dates
+# (This check is similar to the one in timezone2.test in 4.1)
+#
+create table t1 (i int, c varchar(20));
+# Normal value without DST
+insert into t1 values
+ (unix_timestamp("2004-01-01 00:00:00"), "2004-01-01 00:00:00");
+# Values around and in spring time-gap
+insert into t1 values
+ (unix_timestamp("2004-03-28 01:59:59"), "2004-03-28 01:59:59"),
+ (unix_timestamp("2004-03-28 02:30:00"), "2004-03-28 02:30:00"),
+ (unix_timestamp("2004-03-28 03:00:00"), "2004-03-28 03:00:00");
+# Normal value with DST
+insert into t1 values
+ (unix_timestamp('2004-05-01 00:00:00'),'2004-05-01 00:00:00');
+# Ambiguos values (also check for determenism)
+insert into t1 values
+ (unix_timestamp('2004-10-31 01:00:00'),'2004-10-31 01:00:00'),
+ (unix_timestamp('2004-10-31 02:00:00'),'2004-10-31 02:00:00'),
+ (unix_timestamp('2004-10-31 02:59:59'),'2004-10-31 02:59:59'),
+ (unix_timestamp('2004-10-31 04:00:00'),'2004-10-31 04:00:00'),
+ (unix_timestamp('2004-10-31 02:59:59'),'2004-10-31 02:59:59');
+# Test of leap
+insert into t1 values
+ (unix_timestamp('1981-07-01 03:59:59'),'1981-07-01 03:59:59'),
+ (unix_timestamp('1981-07-01 04:00:00'),'1981-07-01 04:00:00');
+
+select i, from_unixtime(i), c from t1;
+drop table t1;
+
+#
+# Test for bug #6387 "Queried timestamp values do not match the
+# inserted". my_gmt_sec() function was not working properly if we
+# had time zone with leap seconds
+#
+create table t1 (ts timestamp);
+insert into t1 values (19730101235900), (20040101235900);
+select * from t1;
+drop table t1;
diff --git a/mysql-test/t/trigger.test b/mysql-test/t/trigger.test
index f842d561dc1..d4879b22bae 100644
--- a/mysql-test/t/trigger.test
+++ b/mysql-test/t/trigger.test
@@ -161,8 +161,10 @@ create trigger trg before update on t1 for each row set old.i:=1;
create trigger trg before delete on t1 for each row set new.i:=1;
--error 1362
create trigger trg after update on t1 for each row set new.i:=1;
-# TODO: We should also test wrong field names here, we don't do it now
-# because proper error handling is not in place yet.
+--error 1054
+create trigger trg before update on t1 for each row set new.j:=1;
+--error 1054
+create trigger trg before update on t1 for each row set @a:=old.j;
#
@@ -207,3 +209,20 @@ create trigger tx1 before insert on t1 for each row set new.x1col = 'x';
insert into t1 values ('y');
drop trigger t1.tx1;
drop table t1;
+
+#
+# Test for bug #5890 "Triggers fail for DELETE without WHERE".
+# If we are going to delete all rows in table but DELETE triggers exist
+# we should perform row-by-row deletion instead of using optimized
+# delete_all_rows() method.
+#
+create table t1 (i int) engine=myisam;
+insert into t1 values (1), (2);
+create trigger trg1 before delete on t1 for each row set @del_before:= @del_before + old.i;
+create trigger trg2 after delete on t1 for each row set @del_after:= @del_after + old.i;
+set @del_before:=0, @del_after:= 0;
+delete from t1;
+select @del_before, @del_after;
+drop trigger t1.trg1;
+drop trigger t1.trg2;
+drop table t1;
diff --git a/mysql-test/t/type_blob.test b/mysql-test/t/type_blob.test
index b67fa7a552d..085cad8cffa 100644
--- a/mysql-test/t/type_blob.test
+++ b/mysql-test/t/type_blob.test
@@ -18,12 +18,14 @@ CREATE TABLE t1 (a blob, b text, c blob(250), d text(70000), e text(70000000));
show columns from t1;
# PS doesn't give errors on prepare yet
--disable_ps_protocol
-CREATE TABLE t2 (a char(257), b varbinary(70000), c varchar(70000000));
+CREATE TABLE t2 (a char(255), b varbinary(70000), c varchar(70000000));
+CREATE TABLE t4 (c varchar(65530) character set utf8 not null);
--enable_ps_protocol
show columns from t2;
create table t3 (a long, b long byte);
show create TABLE t3;
-drop table t1,t2,t3
+show create TABLE t4;
+drop table t1,t2,t3,t4;
#
# Check errors with blob
@@ -31,6 +33,10 @@ drop table t1,t2,t3
--error 1074
CREATE TABLE t1 (a char(257) default "hello");
+--error 1074
+CREATE TABLE t2 (a char(256));
+--error 1074
+CREATE TABLE t1 (a varchar(70000) default "hello");
--error 1101
CREATE TABLE t2 (a blob default "hello");
@@ -316,10 +322,16 @@ drop table t1;
#
# Test blob's with end space (Bug #1651)
+# This is a bit changed since we now have true varchar
#
create table t1 (id integer primary key auto_increment, txt text not null, unique index txt_index (txt (20)));
+--error 1062
insert into t1 (txt) values ('Chevy'), ('Chevy ');
+--error 1062
+insert into t1 (txt) values ('Chevy'), ('CHEVY');
+alter table t1 drop index txt_index, add index txt_index (txt(20));
+insert into t1 (txt) values ('Chevy ');
select * from t1 where txt='Chevy';
select * from t1 where txt='Chevy ';
select * from t1 where txt='Chevy ' or txt='Chevy';
@@ -340,7 +352,7 @@ select * from t1 where txt > 'Chevy';
select * from t1 where txt >= 'Chevy';
drop table t1;
-create table t1 (id integer primary key auto_increment, txt text, unique index txt_index (txt (20)));
+create table t1 (id integer primary key auto_increment, txt text, index txt_index (txt (20)));
insert into t1 (txt) values ('Chevy'), ('Chevy '), (NULL);
select * from t1 where txt='Chevy' or txt is NULL;
explain select * from t1 where txt='Chevy' or txt is NULL;
@@ -369,8 +381,8 @@ explain select * from t1 where txt='Chevy' or txt is NULL order by txt;
select * from t1 where txt='Chevy' or txt is NULL order by txt;
drop table t1;
-CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, PRIMARY KEY (i), KEY (c(1),c(1)));
-INSERT t1 VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
+CREATE TABLE t1 ( i int(11) NOT NULL default '0', c text NOT NULL, d varchar(1) NOT NULL DEFAULT ' ', PRIMARY KEY (i), KEY (c(1),d));
+INSERT t1 (i, c) VALUES (1,''),(2,''),(3,'asdfh'),(4,'');
select max(i) from t1 where c = '';
drop table t1;
diff --git a/mysql-test/t/type_datetime.test b/mysql-test/t/type_datetime.test
index 47866058524..04e4a73554a 100644
--- a/mysql-test/t/type_datetime.test
+++ b/mysql-test/t/type_datetime.test
@@ -77,10 +77,13 @@ drop table t1;
# warnings (for both strings and numbers)
#
create table t1 (t datetime);
-insert into t1 values (20030102030460),(20030102036301),(20030102240401),(20030132030401),(20031302030460);
+insert into t1 values (20030102030460),(20030102036301),(20030102240401),
+ (20030132030401),(20031302030401),(100001202030401);
select * from t1;
delete from t1;
-insert into t1 values ("20030102030460"),("20030102036301"),("20030102240401"),("20030132030401"),("20031302030460");
+insert into t1 values
+ ("2003-01-02 03:04:60"),("2003-01-02 03:63:01"),("2003-01-02 24:04:01"),
+ ("2003-01-32 03:04:01"),("2003-13-02 03:04:01"), ("10000-12-02 03:04:00");
select * from t1;
delete from t1;
insert into t1 values ("0000-00-00 00:00:00 some trailer"),("2003-01-01 00:00:00 some trailer");
diff --git a/mysql-test/t/type_enum.test b/mysql-test/t/type_enum.test
index dc2e4d0f469..3a5b12b91e4 100644
--- a/mysql-test/t/type_enum.test
+++ b/mysql-test/t/type_enum.test
@@ -72,3 +72,44 @@ CREATE TABLE t1 (c enum('ae','oe','ue','ss') collate latin1_german2_ci);
INSERT INTO t1 VALUES ('ä'),('ö'),('ü'),('ß');
SELECT * FROM t1;
DROP TABLE t1;
+
+#
+# Bug #6379: ENUM values are incorrectly converted
+#
+# Check latin1 -> utf8 conversion
+#
+CREATE TABLE t1 (
+ a ENUM('ä','ö','ü') character set utf8 default 'ü'
+);
+show create table t1;
+insert into t1 values ('ä'), ('ö'), ('ü');
+select a from t1 order by a;
+drop table t1;
+
+#
+# Now check utf8 -> latin1 conversion
+# This test emulates loading a script generated with mysqldump
+#
+set names utf8;
+CREATE TABLE t1 (
+ a ENUM('ä','ö','ü') character set latin1 default 'ü'
+);
+insert into t1 values ('ä'),('ö'),('ü');
+# Now check what has been loaded
+set names latin1;
+show create table t1;
+select a from t1 order by a;
+drop table t1;
+
+#
+# Test bug where enum fields where extended for each ALTER TABLE
+#
+
+create table t1 (a enum ('Y','N') CHARACTER SET utf8 COLLATE utf8_bin);
+insert into t1 values ('Y');
+alter table t1 add b set ('Y','N') CHARACTER SET utf8 COLLATE utf8_bin;
+alter table t1 add c enum ('Y','N') CHARACTER SET utf8 COLLATE utf8_bin;
+--enable_metadata
+select * from t1;
+--disable metadata
+drop table t1;
diff --git a/mysql-test/t/type_float.test b/mysql-test/t/type_float.test
index 216d5bbd286..26ac272c6d4 100644
--- a/mysql-test/t/type_float.test
+++ b/mysql-test/t/type_float.test
@@ -6,7 +6,9 @@
drop table if exists t1;
--enable_warnings
+--replace_result e-0 e- e+0 e+
SELECT 10,10.0,10.,.1e+2,100.0e-1;
+--replace_result e-00 e-0
SELECT 6e-05, -6e-05, --6e-05, -6e-05+1.000000;
SELECT 1e1,1.e1,1.0e1,1e+1,1.e+1,1.0e+1,1e-1,1.e-1,1.0e-1;
@@ -14,6 +16,7 @@ create table t1 (f1 float(24),f2 float(52));
show full columns from t1;
insert into t1 values(10,10),(1e+5,1e+5),(1234567890,1234567890),(1e+10,1e+10),(1e+15,1e+15),(1e+20,1e+20),(1e+50,1e+50),(1e+150,1e+150);
insert into t1 values(-10,-10),(1e-5,1e-5),(1e-10,1e-10),(1e-15,1e-15),(1e-20,1e-20),(1e-50,1e-50),(1e-150,1e-150);
+--replace_result e-0 e- e+0 e+
select * from t1;
drop table t1;
diff --git a/mysql-test/t/type_ranges.test b/mysql-test/t/type_ranges.test
index 09b5867e7a8..5f035921064 100644
--- a/mysql-test/t/type_ranges.test
+++ b/mysql-test/t/type_ranges.test
@@ -127,15 +127,16 @@ select t1.auto,t2.auto from t1,t2 where t1.auto=t2.auto and not (t1.string<=>t2.
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 from t1;
+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;
-select * from t2;
+select t1,t2,length(t3),length(t4),length(t5),length(t6),t7,t8 from t2;
drop table t1,t2;
create table t1 (c int);
insert into t1 values(1),(2);
create table t2 select * from t1;
-!$1060 create table t3 select * from t1, t2; # Should give an error
+--error 1060
+create table t3 select * from t1, t2; # Should give an error
create table t3 select t1.c AS c1, t2.c AS c2,1 as "const" from t1, t2;
show full columns from t3;
drop table t1,t2,t3;
diff --git a/mysql-test/t/type_varchar.test b/mysql-test/t/type_varchar.test
new file mode 100644
index 00000000000..526a35c9257
--- /dev/null
+++ b/mysql-test/t/type_varchar.test
@@ -0,0 +1,21 @@
+--disable_warnings
+drop table if exists t1;
+--enable_warnings
+
+create table t1 (v varchar(30), c char(3), e enum('abc','def','ghi'), t text);
+system cp std_data/vchar.frm var/master-data/test/;
+truncate table vchar;
+show create table t1;
+show create table vchar;
+insert into t1 values ('abc', 'de', 'ghi', 'jkl');
+insert into t1 values ('abc ', 'de ', 'ghi', 'jkl ');
+insert into t1 values ('abc ', 'd ', 'ghi', 'jkl ');
+insert into vchar values ('abc', 'de', 'ghi', 'jkl');
+insert into vchar values ('abc ', 'de ', 'ghi', 'jkl ');
+insert into vchar values ('abc ', 'd ', 'ghi', 'jkl ');
+select length(v),length(c),length(e),length(t) from t1;
+select length(v),length(c),length(e),length(t) from vchar;
+alter table vchar add i int;
+show create table vchar;
+select length(v),length(c),length(e),length(t) from vchar;
+drop table t1, vchar;
diff --git a/mysql-test/t/union.test b/mysql-test/t/union.test
index 36027e8c4cb..468a88b83db 100644
--- a/mysql-test/t/union.test
+++ b/mysql-test/t/union.test
@@ -652,5 +652,11 @@ create table t1 as
(select b collate latin1_german1_ci from t2);
show create table t1;
drop table t1;
+create table t1 as
+(select a from t2) union
+(select b from t2) union
+(select 'c' collate latin1_german1_ci from t2);
+show create table t1;
+drop table t1;
drop table t2;
diff --git a/mysql-test/t/user_var.test b/mysql-test/t/user_var.test
index 48ca9e0ba32..ae8e3ccf841 100644
--- a/mysql-test/t/user_var.test
+++ b/mysql-test/t/user_var.test
@@ -109,15 +109,18 @@ SET @`a b`='hello';
INSERT INTO t1 VALUES(@`a b`);
set @var1= "';aaa";
insert into t1 values (@var1);
-create table t2 (c char(30)) charset=ucs2;
-set @v=convert('abc' using ucs2);
-insert into t2 values (@v);
show binlog events from 95;
# more important than SHOW BINLOG EVENTS, mysqlbinlog (where we
# absolutely need variables names to be quoted and strings to be
# escaped).
--replace_result $MYSQL_TEST_DIR MYSQL_TEST_DIR
--exec $MYSQL_BINLOG --short-form $MYSQL_TEST_DIR/var/log/master-bin.000001
-drop table t1, t2;
+drop table t1;
+#
+# Bug #6321 strange error:
+# string function FIELD(<uservariable content NULL>, ...)
+#
+set @var= NULL ;
+select FIELD( @var,'1it','Hit') as my_column;
diff --git a/mysql-test/t/variables.test b/mysql-test/t/variables.test
index 67a05768595..6563f7117cd 100644
--- a/mysql-test/t/variables.test
+++ b/mysql-test/t/variables.test
@@ -20,6 +20,7 @@ select @test, @`test`, @TEST, @`TEST`, @"teSt";
set @select=2,@t5=1.23456;
select @`select`,@not_used;
set @test_int=10,@test_double=1e-10,@test_string="abcdeghi",@test_string2="abcdefghij",@select=NULL;
+--replace_result e-0 e- e+0 e+
select @test_int,@test_double,@test_string,@test_string2,@select;
set @test_int="hello",@test_double="hello",@test_string="hello",@test_string2="hello";
select @test_int,@test_double,@test_string,@test_string2;
diff --git a/mysql-test/t/view.test b/mysql-test/t/view.test
index 17077d1d086..65f464fc77b 100644
--- a/mysql-test/t/view.test
+++ b/mysql-test/t/view.test
@@ -9,12 +9,12 @@ use test;
# some basic test of views and its functionality
#
-# create view on unexistence table
+# create view on nonexistent table
-- error 1146
create view v1 (c,d) as select a,b from t1;
create temporary table t1 (a int, b int);
-#view on temporary table
+# view on temporary table
-- error 1352
create view v1 (c) as select b+1 from t1;
drop table t1;
@@ -22,7 +22,7 @@ drop table t1;
create table t1 (a int, b int);
insert into t1 values (1,2), (1,3), (2,4), (2,5), (3,10);
-#view with variable
+# view with variable
-- error 1351
create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
@@ -30,7 +30,7 @@ create view v1 (c,d) as select a,b+@@global.max_user_connections from t1;
create view v1 (c) as select b+1 from t1;
select c from v1;
-#tamporary table should not shade (hide) table of view
+# temporary table should not hide table of view
create temporary table t1 (a int, b int);
# this is empty
select * from t1;
@@ -42,7 +42,7 @@ show create view v1;
show create view t1;
drop table t1;
-# try to use fields from underlaid table
+# try to use fields from underlying table
-- error 1054
select a from v1;
-- error 1054
@@ -52,14 +52,14 @@ select b from v1;
-- error 1054
select v1.b from v1;
-# view with different algorithms (explain out put are differ)
+# view with different algorithms (explain output differs)
explain extended select c from v1;
create algorithm=temptable view v2 (c) as select b+1 from t1;
show create view v2;
select c from v2;
explain extended select c from v2;
-# try to use underlaid table fields in VIEW creation process
+# try to use underlying table fields in VIEW creation process
-- error 1054
create view v3 (c) as select a+1 from v1;
-- error 1054
@@ -84,6 +84,7 @@ explain extended select c from v6;
show tables;
show full tables;
--replace_column 12 # 13 #
+--replace_result 2147483647 38654705663
show table status;
drop view v1,v2,v3,v4,v5,v6;
@@ -127,19 +128,19 @@ show grants for test@localhost;
revoke create view on test.* from test@localhost;
show grants for test@localhost;
-#try to drop unexisten VIEW
+# try to drop nonexistent VIEW
-- error 1051
drop view v100;
-#try to drop table with DROP VIEW
+# try to drop table with DROP VIEW
-- error 1347
drop view t1;
-#try to drop VIEW with DROP TABLE
+# try to drop VIEW with DROP TABLE
-- error 1051
drop table v1;
-#try to drop table with DROP VIEW
+# try to drop table with DROP VIEW
drop view v1,v2;
drop table t1;
@@ -213,7 +214,7 @@ grant select (c) on mysqltest.v1 to mysqltest_1@localhost;
connection user1;
select c from mysqltest.v1;
-# there are not privilege ob column 'd'
+# there are no privileges on column 'd'
-- error 1143
select d from mysqltest.v1;
@@ -233,7 +234,7 @@ grant select (c) on mysqltest.v1 to mysqltest_1@localhost;
connection user1;
select c from mysqltest.v1;
-# there are not privilege ob column 'd'
+# there are no privileges on column 'd'
-- error 1143
select d from mysqltest.v1;
@@ -288,7 +289,7 @@ explain select c from mysqltest.v4;
-- error 1142
show create view mysqltest.v4;
-# allow to see one of underlaing table
+# allow to see one of underlying table
connection root;
grant select on mysqltest.t1 to mysqltest_1@localhost;
connection user1;
@@ -328,7 +329,7 @@ delete from mysql.user where user='mysqltest_1';
drop database mysqltest;
#
-# QUERY CHECHE options for VIEWs
+# QUERY CACHE options for VIEWs
#
set GLOBAL query_cache_size=1355776;
flush status;
@@ -425,7 +426,7 @@ drop table t1;
drop view v1,v2;
#
-# LIMIT clasuse test
+# LIMIT clause test
#
create table t1 (a int);
insert into t1 values (1), (2), (3), (4);
@@ -538,7 +539,7 @@ REVOKE ALL PRIVILEGES, GRANT OPTION FROM mysqltest_1@localhost;
drop database mysqltest;
#
-# MEREGE VIEW with WHERE clause
+# MERGE VIEW with WHERE clause
#
create table t1 (a int, b int, primary key(b));
insert into t1 values (1,20), (2,30), (3,40), (4,50), (5,100);
@@ -811,7 +812,7 @@ create view mysqltest.v1 as select * from mysqltest.t1;
-- error 1143
create view v3 as select a from mysqltest.t2;
-# give CRETEA VIEW privileges (without any privileges for result colemn)
+# give CREATE VIEW privileges (without any privileges for result column)
connection root;
create table mysqltest.v3 (b int);
grant create view on mysqltest.v3 to mysqltest_1@localhost;
@@ -826,7 +827,7 @@ drop view mysqltest.v3;
connection user1;
create view mysqltest.v3 as select b from mysqltest.t2;
-# give UPDATE and INSERT privilege (to get more privileges then anderlying
+# give UPDATE and INSERT privilege (to get more privileges then underlying
# table)
connection root;
grant create view, update, insert on mysqltest.v3 to mysqltest_1@localhost;
@@ -836,8 +837,8 @@ connection user1;
create view mysqltest.v3 as select b from mysqltest.t2;
-# If give other privileges for VIEW then underlaying table have =>
-# creation prohibited
+# If we would get more privileges on VIEW then we have on
+# underlying tables => creation prohibited
connection root;
create table mysqltest.v3 (b int);
grant select(b) on mysqltest.v3 to mysqltest_1@localhost;
@@ -897,7 +898,7 @@ drop view v1;
drop table `t1a``b`;
#
-# Changing of underlaying table
+# Changing of underlying table
#
create table t1 (col1 char(5),col2 char(5));
create view v1 as select * from t1;
@@ -927,7 +928,7 @@ call p1();
drop procedure p1;
#
-# updateablity should be transitive
+# updatablity should be transitive
#
create table t1 (col1 int,col2 char(22));
insert into t1 values(5,'Hello, world of views');
@@ -960,7 +961,7 @@ drop view v1;
drop table t1;
#
-# Test of view updatebility in prepared statement
+# Test of view updatability in prepared statement
#
create table t1 (a int);
create view v1 as select a from t1;
@@ -1162,7 +1163,7 @@ drop view v1;
drop table t1;
#
-# VIEW over droped function
+# VIEW over dropped function
#
create function x1 () returns int return 5;
create table t1 (s1 int);
@@ -1171,14 +1172,13 @@ drop function x1;
-- error 1305
select * from v1;
--replace_column 12 # 13 #
-show table status;
---replace_column 12 # 13 #
+--replace_result "2147483647 " "21474836479 "
show table status;
drop view v1;
drop table t1;
#
-# VIEW with floating point (long bumber) as column
+# VIEW with floating point (long number) as column
#
create view v1 as select 99999999999999999999999999999999999999999999999999999 as col1;
show create view v1;
@@ -1213,7 +1213,7 @@ select * from v1;
drop view v1;
#
-# bug handlimg from VIEWs
+# bug handling from VIEWs
#
create view v1 as select 'a',1;
create view v2 as select * from v1 union all select * from v1;
@@ -1300,13 +1300,9 @@ update v1,t1 set v1.s1='c' where t1.s1=v1.s1;
select * from v1;
prepare stmt1 from "update v1,t1 set v1.s1=? where t1.s1=v1.s1";
set @arg='d';
--- QQ This should not generate an error
---error 1036
execute stmt1 using @arg;
select * from v1;
set @arg='e';
--- QQ This should not generate an error
---error 1036
execute stmt1 using @arg;
select * from v1;
deallocate prepare stmt1;
@@ -1558,3 +1554,160 @@ select concat('|',a,'|'), concat('|',b,'|') from v1;
drop view v1;
drop table t1;
+#
+# user with global DB privileges
+#
+connection root;
+--disable_warnings
+create database mysqltest;
+--enable_warnings
+create table mysqltest.t1 (a int);
+grant all privileges on mysqltest.* to mysqltest_1@localhost;
+
+connection user1;
+use mysqltest;
+create view v1 as select * from t1;
+
+connection root;
+revoke all privileges on mysqltest.* from mysqltest_1@localhost;
+drop database mysqltest;
+
+#
+# Trys update table from which we select using views and subqueries
+#
+create table t1 (s1 smallint);
+create view v1 as select * from t1 where 20 < (select (s1) from t1);
+-- error 1288
+insert into v1 values (30);
+create view v2 as select * from t1;
+create view v3 as select * from t1 where 20 < (select (s1) from v2);
+-- error 1288
+insert into v3 values (30);
+create view v4 as select * from v2 where 20 < (select (s1) from t1);
+-- error 1093
+insert into v4 values (30);
+drop view v4, v3, v2, v1;
+drop table t1;
+
+#
+# CHECK TABLE with VIEW
+#
+create table t1 (a int);
+create view v1 as select * from t1;
+check table t1,v1;
+check table v1,t1;
+drop table t1;
+check table v1;
+drop view v1;
+
+#
+# merge of VIEW with several tables
+#
+create table t1 (a int);
+create table t2 (a int);
+create table t3 (a int);
+insert into t1 values (1), (2), (3);
+insert into t2 values (1), (3);
+insert into t3 values (1), (2), (4);
+# view over tables
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1 left join t2 on (t1.a=t2.a);
+select * from t3 left join v3 on (t3.a = v3.a);
+explain extended select * from t3 left join v3 on (t3.a = v3.a);
+# view over views
+create view v1 (a) as select a from t1;
+create view v2 (a) as select a from t2;
+create view v4 (a,b) as select v1.a as a, v2.a as b from v1 left join v2 on (v1.a=v2.a);
+select * from t3 left join v4 on (t3.a = v4.a);
+explain extended select * from t3 left join v4 on (t3.a = v4.a);
+# PS with view over views
+prepare stmt1 from "select * from t3 left join v4 on (t3.a = v4.a);";
+execute stmt1;
+execute stmt1;
+deallocate prepare stmt1;
+drop view v4,v3,v2,v1;
+drop tables t1,t2,t3;
+
+#
+# updating of join view
+#
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a));
+insert into t1 values (1,100), (2,200);
+insert into t2 values (1), (3);
+# legal view for update
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+update v3 set a= 10 where a=1;
+select * from t1;
+select * from t2;
+# view without primary key
+create view v2 (a,b) as select t1.b as a, t2.a as b from t1, t2;
+set updatable_views_with_limit=NO;
+-- error 1288
+update v2 set a= 10 where a=200 limit 1;
+set updatable_views_with_limit=DEFAULT;
+# just view selects
+select * from v3;
+select * from v2;
+# prepare statement with updating join view
+set @a= 10;
+set @b= 100;
+prepare stmt1 from "update v3 set a= ? where a=?";
+execute stmt1 using @a,@b;
+select * from v3;
+set @a= 300;
+set @b= 10;
+execute stmt1 using @a,@b;
+select * from v3;
+deallocate prepare stmt1;
+drop view v3,v2;
+drop tables t1,t2;
+
+#
+# inserting/deleting join view
+#
+create table t1 (a int, primary key (a), b int);
+create table t2 (a int, primary key (a), b int);
+insert into t2 values (1000, 2000);
+create view v3 (a,b) as select t1.a as a, t2.a as b from t1, t2;
+# inserting into join view without field list
+-- error 1394
+insert into v3 values (1,2);
+-- error 1394
+insert into v3 select * from t2;
+# inserting in several tables of join view
+-- error 1393
+insert into v3(a,b) values (1,2);
+-- error 1393
+insert into v3(a,b) select * from t2;
+# correct inserts into join view
+insert into v3(a) values (1);
+insert into v3(b) values (10);
+insert into v3(a) select a from t2;
+insert into v3(b) select b from t2;
+insert into v3(a) values (1) on duplicate key update a=a+10000+VALUES(a);
+select * from t1;
+select * from t2;
+# try delete from join view
+-- error 1395
+delete from v3;
+-- error 1395
+delete v3,t1 from v3,t1;
+# delete from t1 just to reduce result set size
+delete from t1;
+# prepare statement with insert join view
+prepare stmt1 from "insert into v3(a) values (?);";
+set @a= 100;
+execute stmt1 using @a;
+set @a= 300;
+execute stmt1 using @a;
+deallocate prepare stmt1;
+prepare stmt1 from "insert into v3(a) select ?;";
+set @a= 101;
+execute stmt1 using @a;
+set @a= 301;
+execute stmt1 using @a;
+deallocate prepare stmt1;
+select * from v3;
+
+drop view v3;
+drop tables t1,t2;
diff --git a/mysys/Makefile.am b/mysys/Makefile.am
index 3ffeeab0411..6a118df03cc 100644
--- a/mysys/Makefile.am
+++ b/mysys/Makefile.am
@@ -26,7 +26,7 @@ noinst_HEADERS = mysys_priv.h my_static.h \
my_os2cond.c my_os2dirsrch.c my_os2dirsrch.h \
my_os2dlfcn.c my_os2file64.c my_os2mutex.c \
my_os2thread.c my_os2tls.c
-libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
+libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c my_mmap.c \
mf_path.c mf_loadpath.c my_file.c \
my_open.c my_create.c my_dup.c my_seek.c my_read.c \
my_pread.c my_write.c \
@@ -57,7 +57,6 @@ libmysys_a_SOURCES = my_init.c my_getwd.c mf_getdate.c \
EXTRA_DIST = thr_alarm.c thr_lock.c my_pthread.c my_thr_init.c \
thr_mutex.c thr_rwlock.c
libmysys_a_LIBADD = @THREAD_LOBJECTS@
-noinst_PROGRAMS = charset2html @THREAD_LPROGRAMS@
# test_dir_DEPENDENCIES= $(LIBRARIES)
# testhash_DEPENDENCIES= $(LIBRARIES)
# test_charset_DEPENDENCIES= $(LIBRARIES)
@@ -105,9 +104,6 @@ test_dir$(EXEEXT): test_dir.c $(LIBRARIES)
test_charset$(EXEEXT): test_charset.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/test_charset.c $(LDADD) $(LIBS)
-charset2html$(EXEEXT): charset2html.c $(LIBRARIES)
- $(LINK) $(FLAGS) -DMAIN $(srcdir)/charset2html.c $(LDADD) $(LIBS)
-
testhash$(EXEEXT): testhash.c $(LIBRARIES)
$(LINK) $(FLAGS) -DMAIN $(srcdir)/testhash.c $(LDADD) $(LIBS)
diff --git a/mysys/charset.c b/mysys/charset.c
index 1388fc40c6d..cb2379f8723 100644
--- a/mysys/charset.c
+++ b/mysys/charset.c
@@ -228,6 +228,7 @@ static int add_collation(CHARSET_INFO *cs)
}
else
{
+ uchar *sort_order= all_charsets[cs->number]->sort_order;
simple_cs_init_functions(all_charsets[cs->number]);
new->mbminlen= 1;
new->mbmaxlen= 1;
@@ -236,6 +237,16 @@ static int add_collation(CHARSET_INFO *cs)
all_charsets[cs->number]->state |= MY_CS_LOADED;
}
all_charsets[cs->number]->state|= MY_CS_AVAILABLE;
+
+ /*
+ Check if case sensitive sort order: A < a < B.
+ We need MY_CS_FLAG for regex library, and for
+ case sensitivity flag for 5.0 client protocol,
+ to support isCaseSensitive() method in JDBC driver
+ */
+ if (sort_order && sort_order['A'] < sort_order['a'] &&
+ sort_order['a'] < sort_order['B'])
+ all_charsets[cs->number]->state|= MY_CS_CSSORT;
}
}
else
diff --git a/mysys/default.c b/mysys/default.c
index 198a6402b8b..d6d84f65d8b 100644
--- a/mysys/default.c
+++ b/mysys/default.c
@@ -37,6 +37,9 @@
#include "m_string.h"
#include "m_ctype.h"
#include <my_dir.h>
+#ifdef __WIN__
+#include <winbase.h>
+#endif
char *defaults_extra_file=0;
@@ -60,10 +63,10 @@ DATADIR,
NullS,
};
-#define default_ext ".cnf" /* extension for config file */
#ifdef __WIN__
-#include <winbase.h>
-#define windows_ext ".ini"
+static const char *f_extensions[]= { ".ini", ".cnf", 0 };
+#else
+static const char *f_extensions[]= { ".cnf", 0 };
#endif
/*
@@ -81,8 +84,11 @@ struct handle_option_ctx
};
static int search_default_file(Process_option_func func, void *func_ctx,
- const char *dir, const char *config_file,
- const char *ext);
+ const char *dir, const char *config_file);
+static int search_default_file_with_ext(Process_option_func func,
+ void *func_ctx,
+ const char *dir, const char *ext,
+ const char *config_file);
static char *remove_end_comment(char *ptr);
@@ -137,8 +143,8 @@ static int search_files(const char *conf_file, int *argc, char ***argv,
if (forced_default_file)
{
- if ((error= search_default_file(func, func_ctx, "",
- forced_default_file, "")) < 0)
+ if ((error= search_default_file_with_ext(func, func_ctx, "", "",
+ forced_default_file)) < 0)
goto err;
if (error > 0)
{
@@ -149,8 +155,7 @@ static int search_files(const char *conf_file, int *argc, char ***argv,
}
else if (dirname_length(conf_file))
{
- if ((error= search_default_file(func, func_ctx, NullS, conf_file,
- default_ext)) < 0)
+ if ((error= search_default_file(func, func_ctx, NullS, conf_file)) < 0)
goto err;
}
else
@@ -158,28 +163,30 @@ static int search_files(const char *conf_file, int *argc, char ***argv,
#ifdef __WIN__
char system_dir[FN_REFLEN];
GetWindowsDirectory(system_dir,sizeof(system_dir));
- if ((search_default_file(func, func_ctx, system_dir, conf_file,
- windows_ext)))
+ if ((search_default_file(func, func_ctx, system_dir, conf_file)))
goto err;
#endif
#if defined(__EMX__) || defined(OS2)
- if (getenv("ETC") &&
- (search_default_file(func, func_ctx, getenv("ETC"), conf_file,
- default_ext)) < 0)
+ {
+ const char *etc;
+ if ((etc= getenv("ETC")) &&
+ (search_default_file(func, func_ctx, etc, conf_file)) < 0)
goto err;
+ }
#endif
for (dirs= default_directories ; *dirs; dirs++)
{
if (**dirs)
{
- if (search_default_file(func, func_ctx, *dirs, conf_file, default_ext) < 0)
+ if (search_default_file(func, func_ctx, *dirs, conf_file) < 0)
goto err;
}
else if (defaults_extra_file)
{
- if (search_default_file(func, func_ctx, NullS, defaults_extra_file,
- default_ext) < 0)
+ if (search_default_file(func, func_ctx, NullS,
+ defaults_extra_file) < 0)
goto err; /* Fatal error */
+
}
}
}
@@ -226,22 +233,23 @@ int process_default_option_files(const char *conf_file,
return search_files(conf_file, &argc, NULL, &args_used, func, func_ctx);
}
+
/*
The option handler for load_defaults.
SYNOPSIS
- handle_deault_option()
- in_ctx Handler context. In this case it is a
+ handle_deault_option()
+ in_ctx Handler context. In this case it is a
handle_option_ctx structure.
- group_name The name of the group the option belongs to.
- option The very option to be processed. It is already
+ group_name The name of the group the option belongs to.
+ option The very option to be processed. It is already
prepared to be used in argv (has -- prefix)
DESCRIPTION
-
- This handler checks whether a group is one of the listed and adds an option
- to the array if yes. Some other handler can record, for instance, all groups
- and their options, not knowing in advance the names and amount of groups.
+ This handler checks whether a group is one of the listed and adds an option
+ to the array if yes. Some other handler can record, for instance, all
+ groups and their options, not knowing in advance the names and amount of
+ groups.
RETURN
0 - ok
@@ -249,12 +257,12 @@ int process_default_option_files(const char *conf_file,
*/
static int handle_default_option(void *in_ctx, const char *group_name,
- const char *option)
+ const char *option)
{
char *tmp;
- struct handle_option_ctx *ctx;
- ctx= (struct handle_option_ctx *) in_ctx;
- if(find_type((char *)group_name, ctx->group, 3))
+ struct handle_option_ctx *ctx= (struct handle_option_ctx *) in_ctx;
+
+ if (find_type((char *)group_name, ctx->group, 3))
{
if (!(tmp= alloc_root(ctx->alloc, (uint) strlen(option) + 1)))
return 1;
@@ -299,7 +307,7 @@ static int handle_default_option(void *in_ctx, const char *group_name,
int load_defaults(const char *conf_file, const char **groups,
- int *argc, char ***argv)
+ int *argc, char ***argv)
{
DYNAMIC_ARRAY args;
TYPELIB group;
@@ -405,18 +413,37 @@ void free_defaults(char **argv)
}
+static int search_default_file(Process_option_func opt_handler,
+ void *handler_ctx,
+ const char *dir,
+ const char *config_file)
+{
+ char **ext;
+
+ for (ext= (char**) f_extensions; *ext; *ext++)
+ {
+ int error;
+ if ((error= search_default_file_with_ext(opt_handler, handler_ctx,
+ dir, *ext,
+ config_file)) < 0)
+ return error;
+ }
+ return 0;
+}
+
+
/*
Open a configuration file (if exists) and read given options from it
SYNOPSIS
- search_default_file()
+ search_default_file_with_ext()
opt_handler Option handler function. It is used to process
every separate option.
handler_ctx Pointer to the structure to store actual
parameters of the function.
dir directory to read
- config_file Name of configuration file
ext Extension for configuration file
+ config_file Name of configuration file
group groups to read
RETURN
@@ -425,9 +452,11 @@ void free_defaults(char **argv)
1 File not found (Warning)
*/
-static int search_default_file(Process_option_func opt_handler, void *handler_ctx,
- const char *dir, const char *config_file,
- const char *ext)
+static int search_default_file_with_ext(Process_option_func opt_handler,
+ void *handler_ctx,
+ const char *dir,
+ const char *ext,
+ const char *config_file)
{
char name[FN_REFLEN+10], buff[4096], curr_gr[4096], *ptr, *end;
char *value, option[4096];
@@ -618,10 +647,11 @@ static char *remove_end_comment(char *ptr)
void print_defaults(const char *conf_file, const char **groups)
{
#ifdef __WIN__
- bool have_ext=fn_ext(conf_file)[0] != 0;
+ my_bool have_ext= fn_ext(conf_file)[0] != 0;
#endif
- char name[FN_REFLEN];
+ char name[FN_REFLEN], **ext;
const char **dirs;
+
puts("\nDefault options are read from the following files in the given order:");
if (dirname_length(conf_file))
@@ -630,27 +660,43 @@ void print_defaults(const char *conf_file, const char **groups)
{
#ifdef __WIN__
GetWindowsDirectory(name,sizeof(name));
- printf("%s\\%s%s ",name,conf_file,have_ext ? "" : windows_ext);
+ if (!have_ext)
+ {
+ for (ext= (char**) f_extensions; *ext; *ext++)
+ printf("%s\\%s%s ", name, conf_file, *ext);
+ }
+ else
+ printf("%s\\%s ", name, conf_file);
#endif
#if defined(__EMX__) || defined(OS2)
- if (getenv("ETC"))
- printf("%s\\%s%s ", getenv("ETC"), conf_file, default_ext);
+ {
+ const char *etc;
+
+ if ((etc= getenv("ETC")))
+ {
+ for (ext= (char**) f_extensions; *ext; *ext++)
+ printf("%s\\%s%s ", etc, conf_file, *ext);
+ }
+ }
#endif
for (dirs=default_directories ; *dirs; dirs++)
{
- const char *pos;
- char *end;
- if (**dirs)
- pos= *dirs;
- else if (defaults_extra_file)
- pos= defaults_extra_file;
- else
- continue;
- end=convert_dirname(name, pos, NullS);
- if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
- *end++='.';
- strxmov(end,conf_file,default_ext," ",NullS);
- fputs(name,stdout);
+ for (ext= (char**) f_extensions; *ext; *ext++)
+ {
+ const char *pos;
+ char *end;
+ if (**dirs)
+ pos= *dirs;
+ else if (defaults_extra_file)
+ pos= defaults_extra_file;
+ else
+ continue;
+ end= convert_dirname(name, pos, NullS);
+ if (name[0] == FN_HOMELIB) /* Add . to filenames in home */
+ *end++='.';
+ strxmov(end, conf_file, *ext, " ", NullS);
+ fputs(name,stdout);
+ }
}
puts("");
}
diff --git a/mysys/mf_keycache.c b/mysys/mf_keycache.c
index 11aadbed6c1..052d6c79ab9 100644
--- a/mysys/mf_keycache.c
+++ b/mysys/mf_keycache.c
@@ -1699,11 +1699,12 @@ byte *key_cache_read(KEY_CACHE *keycache,
keycache_pthread_mutex_unlock(&keycache->cache_lock);
goto no_key_cache;
}
- read_length= length > keycache->key_cache_block_size ?
- keycache->key_cache_block_size : length;
- KEYCACHE_DBUG_ASSERT(read_length > 0);
offset= (uint) (filepos & (keycache->key_cache_block_size-1));
filepos-= offset;
+ read_length= length;
+ set_if_smaller(read_length, keycache->key_cache_block_size-offset);
+ KEYCACHE_DBUG_ASSERT(read_length > 0);
+
#ifndef THREAD
if (block_length > keycache->key_cache_block_size || offset)
return_buffer=0;
@@ -1773,7 +1774,7 @@ byte *key_cache_read(KEY_CACHE *keycache,
return (block->buffer);
#endif
buff+= read_length;
- filepos+= read_length;
+ filepos+= read_length+offset;
} while ((length-= read_length));
DBUG_RETURN(start);
@@ -1835,12 +1836,12 @@ int key_cache_insert(KEY_CACHE *keycache,
keycache_pthread_mutex_unlock(&keycache->cache_lock);
DBUG_RETURN(0);
}
- read_length= length > keycache->key_cache_block_size ?
- keycache->key_cache_block_size : length;
- KEYCACHE_DBUG_ASSERT(read_length > 0);
offset= (uint) (filepos & (keycache->key_cache_block_size-1));
/* Read data into key cache from buff in key_cache_block_size incr. */
filepos-= offset;
+ read_length= length;
+ set_if_smaller(read_length, keycache->key_cache_block_size-offset);
+ KEYCACHE_DBUG_ASSERT(read_length > 0);
inc_counter_for_resize_op(keycache);
keycache->global_cache_r_requests++;
@@ -1882,7 +1883,7 @@ int key_cache_insert(KEY_CACHE *keycache,
DBUG_RETURN(1);
buff+= read_length;
- filepos+= read_length;
+ filepos+= read_length+offset;
} while ((length-= read_length));
}
@@ -1959,12 +1960,12 @@ int key_cache_write(KEY_CACHE *keycache,
keycache_pthread_mutex_unlock(&keycache->cache_lock);
goto no_key_cache;
}
- read_length= length > keycache->key_cache_block_size ?
- keycache->key_cache_block_size : length;
- KEYCACHE_DBUG_ASSERT(read_length > 0);
offset= (uint) (filepos & (keycache->key_cache_block_size-1));
/* Write data in key_cache_block_size increments */
filepos-= offset;
+ read_length= length;
+ set_if_smaller(read_length, keycache->key_cache_block_size-offset);
+ KEYCACHE_DBUG_ASSERT(read_length > 0);
inc_counter_for_resize_op(keycache);
keycache->global_cache_w_requests++;
@@ -2032,7 +2033,7 @@ int key_cache_write(KEY_CACHE *keycache,
next_block:
buff+= read_length;
- filepos+= read_length;
+ filepos+= read_length+offset;
offset= 0;
} while ((length-= read_length));
diff --git a/mysys/mf_keycaches.c b/mysys/mf_keycaches.c
index 20465f3d23b..8bf203e249f 100644
--- a/mysys/mf_keycaches.c
+++ b/mysys/mf_keycaches.c
@@ -309,7 +309,7 @@ void multi_keycache_free(void)
Get a key cache to be used for a specific table.
SYNOPSIS
- multi_key_cache_get()
+ multi_key_cache_search()
key key to find (usually table path)
uint length Length of key.
diff --git a/mysys/my_chsize.c b/mysys/my_chsize.c
index cf26428d65f..c258121226d 100644
--- a/mysys/my_chsize.c
+++ b/mysys/my_chsize.c
@@ -48,9 +48,9 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_PRINT("info",("old_size: %ld", (ulong) oldsize));
if (oldsize > newlength)
+ {
#if defined(HAVE_SETFILEPOINTER)
/* This is for the moment only true on windows */
- {
long is_success;
HANDLE win_file= (HANDLE) _get_osfhandle(fd);
long length_low, length_high;
@@ -63,35 +63,29 @@ int my_chsize(File fd, my_off_t newlength, int filler, myf MyFlags)
DBUG_RETURN(0);
my_errno= GetLastError();
goto err;
- }
#elif defined(HAVE_FTRUNCATE)
- {
if (ftruncate(fd, (off_t) newlength))
{
my_errno= errno;
goto err;
}
DBUG_RETURN(0);
- }
#elif defined(HAVE_CHSIZE)
- {
if (chsize(fd, (off_t) newlength))
{
my_errno=errno;
goto err;
}
DBUG_RETURN(0);
- }
#else
- {
/*
Fill space between requested length and true length with 'filler'
We should never come here on any modern machine
*/
VOID(my_seek(fd, newlength, MY_SEEK_SET, MYF(MY_WME+MY_FAE)));
swap_variables(my_off_t, newlength, oldsize);
- }
#endif
+ }
/* Full file with 'filler' until it's as big as requested */
bfill(buff, IO_SIZE, filler);
diff --git a/mysys/my_error.c b/mysys/my_error.c
index 8a377f63c7e..175f8cf516b 100644
--- a/mysys/my_error.c
+++ b/mysys/my_error.c
@@ -22,6 +22,15 @@
/* Define some external variables for error handling */
+/*
+ WARNING!
+ my_error family functions have to be used according following rules:
+ - if message have not parameters use my_message(ER_CODE, ER(ER_CODE), MYF(N))
+ - if message registered use my_error(ER_CODE, MYF(N), ...).
+ - With some special text of errror message use:
+ my_printf_error(ER_CODE, format, MYF(N), ...)
+*/
+
const char ** NEAR my_errmsg[MAXMAPS]={0,0,0,0};
char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
@@ -41,107 +50,22 @@ char NEAR errbuff[NRERRBUFFS][ERRMSGSIZE];
the length value is ignored.
*/
-int my_error(int nr,myf MyFlags, ...)
+int my_error(int nr, myf MyFlags, ...)
{
- va_list ap;
- uint olen, plen;
- reg1 const char *tpos;
- reg2 char *endpos;
- char * par;
- char ebuff[ERRMSGSIZE+20];
- int prec_chars; /* output precision */
- my_bool prec_supplied;
+ const char *format;
+ va_list args;
+ char ebuff[ERRMSGSIZE + 20];
DBUG_ENTER("my_error");
- LINT_INIT(prec_chars); /* protected by prec_supplied */
- va_start(ap,MyFlags);
DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d", nr, MyFlags, errno));
if (nr / ERRMOD == GLOB && my_errmsg[GLOB] == 0)
init_glob_errs();
+ format= my_errmsg[nr / ERRMOD][nr % ERRMOD];
- olen=(uint) strlen(tpos=my_errmsg[nr / ERRMOD][nr % ERRMOD]);
- endpos=ebuff;
-
- while (*tpos)
- {
- if (tpos[0] != '%')
- {
- *endpos++= *tpos++; /* Copy ordinary char */
- continue;
- }
- if (*++tpos == '%') /* test if %% */
- {
- olen--;
- }
- else
- {
- /*
- Skip size/precision flags to be compatible with printf.
- The only size/precision flag supported is "%.*s".
- If "%.*u" or "%.*d" are encountered, the precision number is read
- from the variable argument list but its value is ignored.
- */
- prec_supplied= 0;
- if (*tpos== '.')
- {
- tpos++;
- olen--;
- if (*tpos == '*')
- {
- tpos++;
- olen--;
- prec_chars= va_arg(ap, int); /* get length parameter */
- prec_supplied= 1;
- }
- }
-
- if (!prec_supplied)
- {
- while (my_isdigit(&my_charset_latin1, *tpos) || *tpos == '.' ||
- *tpos == '-')
- tpos++;
-
- if (*tpos == 'l') /* Skip 'l' argument */
- tpos++;
- }
-
- if (*tpos == 's') /* String parameter */
- {
- par= va_arg(ap, char *);
- plen= (uint) strlen(par);
- if (prec_supplied && prec_chars > 0)
- plen= min((uint)prec_chars, plen);
- if (olen + plen < ERRMSGSIZE+2) /* Replace if possible */
- {
- strmake(endpos, par, plen);
- endpos+= plen;
- tpos++;
- olen+= plen-2;
- continue;
- }
- }
- else if (*tpos == 'd' || *tpos == 'u') /* Integer parameter */
- {
- register int iarg;
- iarg= va_arg(ap, int);
- if (*tpos == 'd')
- plen= (uint) (int10_to_str((long) iarg, endpos, -10) - endpos);
- else
- plen= (uint) (int10_to_str((long) (uint) iarg, endpos, 10) - endpos);
- if (olen + plen < ERRMSGSIZE+2) /* Replace parameter if possible */
- {
- endpos+= plen;
- tpos++;
- olen+= plen-2;
- continue;
- }
- }
- }
- *endpos++= '%'; /* % used as % or unknown code */
- }
- *endpos= '\0'; /* End of errmessage */
- va_end(ap);
+ va_start(args,MyFlags);
+ (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
+ va_end(args);
DBUG_RETURN((*error_handler_hook)(nr, ebuff, MyFlags));
}
@@ -160,11 +84,14 @@ int my_printf_error(uint error, const char *format, myf MyFlags, ...)
{
va_list args;
char ebuff[ERRMSGSIZE+20];
+ DBUG_ENTER("my_printf_error");
+ DBUG_PRINT("my", ("nr: %d MyFlags: %d errno: %d Format: %s",
+ error, MyFlags, errno, format));
va_start(args,MyFlags);
- (void) vsprintf (ebuff,format,args);
+ (void) my_vsnprintf (ebuff, sizeof(ebuff), format, args);
va_end(args);
- return (*error_handler_hook)(error, ebuff, MyFlags);
+ DBUG_RETURN((*error_handler_hook)(error, ebuff, MyFlags));
}
/*
diff --git a/mysys/my_handler.c b/mysys/my_handler.c
index 00f25924e69..cf8bde31e73 100644
--- a/mysys/my_handler.c
+++ b/mysys/my_handler.c
@@ -21,11 +21,11 @@ int mi_compare_text(CHARSET_INFO *charset_info, uchar *a, uint a_length,
uchar *b, uint b_length, my_bool part_key,
my_bool skip_end_space)
{
- if (skip_end_space)
+ if (!part_key)
return charset_info->coll->strnncollsp(charset_info, a, a_length,
- b, b_length);
+ b, b_length, !skip_end_space);
return charset_info->coll->strnncoll(charset_info, a, a_length,
- b, b_length, part_key);
+ b, b_length, part_key);
}
@@ -208,11 +208,9 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
break;
case HA_KEYTYPE_VARTEXT:
{
- int a_length,full_a_length,b_length,full_b_length,pack_length;
+ int a_length,b_length,pack_length;
get_key_length(a_length,a);
get_key_pack_length(b_length,pack_length,b);
- full_a_length= a_length;
- full_b_length= b_length;
next_key_length=key_length-b_length-pack_length;
if (piks &&
@@ -221,10 +219,12 @@ int ha_key_cmp(register HA_KEYSEG *keyseg, register uchar *a,
next_key_length <= 0),
(my_bool) ((nextflag & (SEARCH_FIND |
SEARCH_UPDATE)) ==
- SEARCH_FIND))))
+ SEARCH_FIND &&
+ ! (keyseg->flag &
+ HA_END_SPACE_ARE_EQUAL)))))
return ((keyseg->flag & HA_REVERSE_SORT) ? -flag : flag);
- a+= full_a_length;
- b+= full_b_length;
+ a+= a_length;
+ b+= b_length;
break;
}
break;
diff --git a/mysys/my_init.c b/mysys/my_init.c
index 0ef938b434c..c32fcfe6a09 100644
--- a/mysys/my_init.c
+++ b/mysys/my_init.c
@@ -42,8 +42,8 @@ static void netware_init();
#define netware_init()
#endif
-
-my_bool my_init_done=0;
+my_bool my_init_done= 0;
+uint mysys_usage_id= 0; /* Incremented for each my_init() */
static ulong atoi_octal(const char *str)
{
@@ -51,7 +51,7 @@ static ulong atoi_octal(const char *str)
while (*str && my_isspace(&my_charset_latin1, *str))
str++;
str2int(str,
- (*str == '0' ? 8 : 10), /* Octalt or decimalt */
+ (*str == '0' ? 8 : 10), /* Octalt or decimalt */
0, INT_MAX, &tmp);
return (ulong) tmp;
}
@@ -74,6 +74,9 @@ my_bool my_init(void)
if (my_init_done)
return 0;
my_init_done=1;
+ mysys_usage_id++;
+ my_umask= 0660; /* Default umask for new files */
+ my_umask_dir= 0700; /* Default umask for new directories */
#if defined(THREAD) && defined(SAFE_MUTEX)
safe_mutex_global_init(); /* Must be called early */
#endif
diff --git a/mysys/my_mmap.c b/mysys/my_mmap.c
new file mode 100644
index 00000000000..883181edd6c
--- /dev/null
+++ b/mysys/my_mmap.c
@@ -0,0 +1,89 @@
+/* Copyright (C) 2000-2003 MySQL AB
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include "mysys_priv.h"
+
+#ifdef HAVE_MMAP
+
+/*
+ system msync() only syncs mmap'ed area to fs cache.
+ fsync() is required to really sync to disc
+*/
+int my_msync(int fd, void *addr, size_t len, int flags)
+{
+ msync(addr, len, flags);
+ return my_sync(fd, MYF(0));
+}
+
+#else
+#ifdef __WIN__
+
+static SECURITY_ATTRIBUTES mmap_security_attributes=
+ {sizeof(SECURITY_ATTRIBUTES), 0, TRUE};
+
+int my_getpagesize(void)
+{
+ SYSTEM_INFO si;
+ GetSystemInfo(&si);
+ return si.dwPageSize;
+}
+
+void *my_mmap(void *addr, size_t len, int prot,
+ int flags, int fd, my_off_t offset)
+{
+ DWORD flProtect=0;
+ HANDLE hFileMap;
+ LPVOID ptr;
+
+ flProtect|=SEC_COMMIT;
+
+ hFileMap=CreateFileMapping(fd, NULL, &mmap_security_attributes,
+ PAGE_READWRITE, 0, len, 0);
+ if (hFileMap == 0)
+ return MAP_FAILED;
+
+ ptr=MapViewOfFile(hFileMap,
+ flags & PROT_WRITE ? FILE_MAP_WRITE : FILE_MAP_READ,
+ (DWORD)(offset >> 32), (DWORD)offset, len);
+
+ /*
+ MSDN explicitly states that it's possible to close File Mapping Object
+ even when a view is not unmapped - then the object will be held open
+ implicitly until unmap, as every view stores internally a handler of
+ a corresponding File Mapping Object
+ */
+ CloseHandle(hFileMap);
+
+ if (ptr)
+ return ptr;
+
+ return MAP_FAILED;
+}
+
+int my_munmap(void *addr, size_t len)
+{
+ return UnmapViewOfFile(addr) ? 0 : -1;
+}
+
+int my_msync(int fd, void *addr, size_t len, int flags)
+{
+ return FlushViewOfFile(addr, len) ? 0 : -1;
+}
+
+#endif
+#error "no mmap!"
+#endif
+
diff --git a/mysys/ptr_cmp.c b/mysys/ptr_cmp.c
index 5fc7ccab4fa..57778574bb6 100644
--- a/mysys/ptr_cmp.c
+++ b/mysys/ptr_cmp.c
@@ -21,6 +21,7 @@
*/
#include "mysys_priv.h"
+#include <myisampack.h>
static int ptr_compare(uint *compare_length, uchar **a, uchar **b);
static int ptr_compare_0(uint *compare_length, uchar **a, uchar **b);
@@ -152,3 +153,41 @@ static int ptr_compare_3(uint *compare_length,uchar **a, uchar **b)
}
return (0);
}
+
+void my_store_ptr(byte *buff, uint pack_length, my_off_t pos)
+{
+ switch (pack_length) {
+#if SIZEOF_OFF_T > 4
+ case 8: mi_int8store(buff,pos); break;
+ case 7: mi_int7store(buff,pos); break;
+ case 6: mi_int6store(buff,pos); break;
+ case 5: mi_int5store(buff,pos); break;
+#endif
+ case 4: mi_int4store(buff,pos); break;
+ case 3: mi_int3store(buff,pos); break;
+ case 2: mi_int2store(buff,pos); break;
+ case 1: buff[0]= (uchar) pos; break;
+ default: DBUG_ASSERT(0);
+ }
+ return;
+}
+
+my_off_t my_get_ptr(byte *ptr, uint pack_length)
+{
+ my_off_t pos;
+ switch (pack_length) {
+#if SIZEOF_OFF_T > 4
+ case 8: pos= (my_off_t) mi_uint8korr(ptr); break;
+ case 7: pos= (my_off_t) mi_uint7korr(ptr); break;
+ case 6: pos= (my_off_t) mi_uint6korr(ptr); break;
+ case 5: pos= (my_off_t) mi_uint5korr(ptr); break;
+#endif
+ case 4: pos= (my_off_t) mi_uint4korr(ptr); break;
+ case 3: pos= (my_off_t) mi_uint3korr(ptr); break;
+ case 2: pos= (my_off_t) mi_uint2korr(ptr); break;
+ case 1: pos= (my_off_t) mi_uint2korr(ptr); break;
+ default: DBUG_ASSERT(0);
+ }
+ return pos;
+}
+
diff --git a/ndb/config/type_ndbapitools.mk.am b/ndb/config/type_ndbapitools.mk.am
index ed6d8699e05..d4eb090112d 100644
--- a/ndb/config/type_ndbapitools.mk.am
+++ b/ndb/config/type_ndbapitools.mk.am
@@ -11,4 +11,5 @@ INCLUDES += -I$(srcdir) -I$(top_srcdir)/include \
-I$(top_srcdir)/ndb/include/util \
-I$(top_srcdir)/ndb/include/portlib \
-I$(top_srcdir)/ndb/test/include \
- -I$(top_srcdir)/ndb/include/mgmapi
+ -I$(top_srcdir)/ndb/include/mgmapi \
+ -I$(top_srcdir)/ndb/include/kernel
diff --git a/ndb/docs/wl2077.txt b/ndb/docs/wl2077.txt
new file mode 100644
index 00000000000..f56d84c9ab9
--- /dev/null
+++ b/ndb/docs/wl2077.txt
@@ -0,0 +1,43 @@
+
+100' * (select 1 from T1 (1M rows) where key = rand());
+1 host, 1 ndbd, api co-hosted
+results in 1000 rows / sec
+
+ wo/reset bounds w/ rb
+4.1-read committed a) 4.9 b) 7.4
+4.1-read hold lock c) 4.7 d) 6.7
+
+wl2077-read committed 6.4 (+30%) 10.8 (+45%)
+wl2077-read hold lock 4.6 (-1%) 6.7 (+ 0%)
+
+5.0-ndb batch read committed f) 50' (+680%) g) 50' (+360%)
+5.0-ndb batch read hold lock h) 12' (+160%) i) 13' (+79%)
+
+
+-- Comparision e)
+serial pk: 10.9'
+batched (1000): 59'
+serial uniq index: 8.4'
+batched (1000): 33'
+index range (1000): 186'
+
+----
+
+load) testScanPerf -c 1 -d 1 T1
+a) testScanPerf -s 100000 -c 0 -d 0 -a 1 -l 0 -r 2 -q 0 T1
+b) testScanPerf -s 100000 -c 0 -d 0 -a 1 -l 0 -r 2 -q 1 T1
+c) testScanPerf -s 100000 -c 0 -d 0 -a 1 -l 1 -r 2 -q 0 T1
+d) testScanPerf -s 100000 -c 0 -d 0 -a 1 -l 1 -r 2 -q 1 T1
+e) testReadPerf -i 25 -c 0 -d 0 T1
+f) testScanPerf -s 100000 -c 0 -d 0 -a 1 -l 0 -r 3 -q 0 -m 1000 -i 10 T1
+g) testScanPerf -s 100000 -c 0 -d 0 -a 1 -l 0 -r 3 -q 1 -m 1000 -i 10 T1
+
+--- music join 1db-co 2db-co
+
+4.1 13s 14s
+4.1 wo/ blobs 1.7s 3.2s
+
+wl2077 12s 14s
+wl2077 wo/ blobs 1.2s (-30%) 2.5s (-22%)
+
+pekka-blob-fix 1.3s
diff --git a/ndb/home/bin/cvschk b/ndb/home/bin/cvschk
deleted file mode 100755
index 4510cc30888..00000000000
--- a/ndb/home/bin/cvschk
+++ /dev/null
@@ -1,569 +0,0 @@
-#!/usr/bin/perl -w
-#
-# cvschk -- fast offline check for new files and modifications of files
-
-# cvschk : A perl program which checks the status of the CVS controlled
-# files and gives an ASCII table sorted after the status of files.
-#
-# If you have used CVS, then you know that it is hard to
-# get a good overview the CVS-status of the files in you
-# directories. Any new files? Any files changes?
-# cvschk will help the programmer get the overview in the
-# situation, where we do not have access to the CVS repository.
-#
-# Note that the program does only local checks of the files
-# If you have fast access to the CVS repositiory, then consider
-# the cvsstat-program - which additionally can tell if other
-# people have made newer versions of the files.
-#
-# The program requires Perl 5.004 (maybe previous versions also work).
-#
-# It is tuned to parse the output of cvs(1) version 1.9.
-# Earlier and later versions may require modifications to the script.
-#
-# ** Note that the first line might be wrong depending **
-# ** on the location of your perl program. **
-#
-# Sample output:
-# The directory ./mytempdir is not under CVS control
-#
-# Changed files
-# ---------------
-# ./cvs2html
-# ./cvschk
-# ./cvsstat
-#
-# New files
-# ---------------
-# ./.#cvschk
-# ./XX
-# ./cvs2html.ok
-#
-# Deleted files
-# ---------------
-# (none)
-
-# Changelog:
-#
-# Ver Date Author Changelog
-# --- ---------- -------------------- -------------------------------------
-# 1.12 2002-01-04 Michael Kohne Fixed a $foo=<> warning for
-# 5.004_01 with defined($foo=<>)
-# Added a --tabular|-t switch
-#
-# 1.11 2001-12-27 Michael Kohne Added cvsignore functionality
-# Handling of 'dummy timestamp'
-# Handling of 'Result of Merge'
-#
-# 1.10 2001-11-06 Michael Kohne Added -r and -l options
-#
-# 1.9 2001-08-03 Lars G. T. Jørgensen Hack to allow special entry-line
-#
-# 1.8 2001-06-07 Peter Toft Back to the same as 1.6
-# CVS is my friend
-#
-# 1.7 2001-06-04 Peter Toft Peter was very tired and
-# applied a wrong patch -
-# version 1.7 is crap
-#
-# 1.6 2000-12-17 Peter Toft Better description added
-#
-# 1.5 2000-11-04 Peter Toft URL of cvsstat changed
-#
-# 1.4 2000-09-20 Peter Toft Must show deleted files also
-# as the default
-#
-# 1.3 2000-08-08 Ole Tange and Initial version
-# Peter Toft
-# ---- ---------- -------------------- -------------------------------------
-#
-# -----------------------------------------------------------------------------
-#
-# This program is protected by the GPL, and all modifications of
-# general interest should be emailed to the maintainer (pto@sslug.dk).
-#
-# This program also uses code parts from cvsstat
-# (same homepage as cvschk)
-#
-# Copyright 2000,2001 by Peter Toft <pto@sslug.dk> and Ole Tange <ole@tange.dk>
-# as well as
-# Lars G. T. Jørgensen <larsj@diku.dk>
-#
-# The URL of the home page of cvschk is shown below.
-
-
-use Time::Local;
-use strict;
-use Getopt::Long;
-
-my $startdir = ".";
-
-my $debug = 0;
-my (%files,%filesok,%seen,%skip);
-
-
-# Michael Kohne 12/16/01
-#
-# Simulation of .cvsignore as CVS does it...
-#
-# using .cvsignore handling makes cvschk take from 2 to 3 times
-# longer to run over the same set of files.
-# in my tests, disabling cvsignore altogether, cvschk takes .2
-# seconds on my working directory. Adding cvsignore,takes
-# .4 seconds.
-# Note that I do not use individual .cvsignore files - if there
-# are a lot of them in your directory tree, it will add run time
-#
-# variables used for .cvsignore handling
-my $initcvsignoreregex;# regex holding all startup cvsignore pattersn (no ())
-my $cvsignoreregex;# one regex holding all current cvsignore patterns
-my $disable_cvsignore=0;# set to 1 to disable cvsignore emulation
- # (available in case it's REALLY screwed up)
-my $disable_ind_cvsignore=0;# set to 1 to disable finding .cvsignore files
- # in each directory.
-my $debug_cvsignore = 0; # For debugging .cvsignore problems
-
-my %mon;
-@mon{qw(Jan Feb Mar Apr May Jun Jul Aug Sep Oct Nov Dec)}=
- 0..11; # Perl months are 0 .. 11
-
-my ($version) = ('$Revision: 1.12 $ ' =~ /^\$\w+: (.*) \$ $/);
-my $URL = "http://cvs.sslug.dk/cvs2html";
-my $version_line = "cvschk version $version (see $URL)\n";
-
-my $opt_all;
-my $restrict;
-my $local;
-my $tabular;
-
-my $opt_restrict;
-
-sub show_version {print $version_line}
-
-sub die_version {die $version_line}
-
-sub die_usage {
- my $bundled = ($] > 5.00399
- ? "can be bundled"
- : "can't be bundled, because your Perl is too old");
- die <<END_OF_USAGE; # Help in the style of GNU `ls --help' or `make --help'
-Usage: $0 [OPTION]...
- Show the CVS status of FILEs (the current directory by default),
- traversing directories recursively and telling if new files exist
- in the repository.
-Options:
- -a, --all Show all statistics, including the names of files that
- are up to date, used tags, ignored patterns and more
- -r, --restrict Don't show the names of the unknown files
- (useful if you have many temporary files)
- -t, --tabular Show one file per line, each preceeded with a status word,
- Sorted by filename.
- -l, --local Don't descend into sub-directories
- -d, --debug Debug info
- -h, --help Show this help end exit immediately
- -V, --version Show the version line and exit immediately
-The one-letter options $bundled.
-END_OF_USAGE
-}
-
-sub die_help {show_version; die_usage}
-
-# Let `-ar' mean `-a -r' and require `--all' (or -a) instead of `-all'.
-if ($] > 5.00399) { # This requires 5.004, so silently skip it for older Perls.
- eval {Getopt::Long::config("bundling")}; # avoid 5.003 compilation error
- warn $@ if $@; # For Perl 5.004+ we do want to see any compilation error
-}
-
-
-GetOptions( "all|a" => \$opt_all,
- "tabular|t" => \$tabular,
- "restrict|r" => \$restrict,
- "local|l" => \$local,
- "help|h" => \&die_help,
- "debug|d" => \$debug,
- "version|V" => \&die_version,
- ) or die_usage;
-
-sub cvs_changed_in_dir($); #define prototype (for recursion)
-
-# functions for .cvsignore handling
-
-# converts a given filename pattern
-# (of the sort that sh(1) takes) to
-# a perl regex of similar meaning.
-#
-# It works by doing the following:
-#
-# change:
-# . to \.
-# $ to \$
-# * to .*
-# ? to .
-#
-sub fpat_to_regex($)
-{
- my $fexp;
- $fexp = shift;
- $fexp =~ s/\./\\\./g;#change . to \.
- $fexp =~ s/\$/\\\$/g;#change dollar sign to \dollar sign
- $fexp =~ s/\*/.*/g;# change * to .*
- $fexp =~ s/\?/./g; # change ? to .
- return $fexp;
-}
-
-# copy the input list to one single regex,
-# items seperated by | symbols.
-# return the regex string
-sub do_regex_convert
-{
- my $rx = "";
- my $first = 1;#true for first element only
-
-
- # convert each element of cvsignore into a regex
- # this makes the patterns usable in perl
- my $cp;
- foreach $cp (@_) {
- if (not $first) { $rx = $rx . "|"; }
- if ($first) { $first = 0; }
- $rx = $rx . fpat_to_regex($cp);
- }
-
- return $rx;
-}
-
-# first parameter is a reference to the array
-# to be loaded
-# the rest of the parameters are just items
-# that need to be loaded into the array.
-# Note that if a ! is found, the list is
-# emptied, then further items are added.
-# returns true if a ! was found
-sub load_list_from_list
-{
- my $arref = shift;# get reference to array from front
- my $item;
- my $ret=0;#false means no ! found
-
- chomp @_;#kill newlines
- foreach $item (@_) {
- $item =~ s/^\s*(.*?)\s*$/$1/;#kill leading/trailing whitespace
- if ($item) { # empty string is false
- push @$arref,$item;
- }
- if ($item eq "!") {
- @$arref = ();# '!' causes list to clear
- $ret = 1;# ! found
- }
- }
-
- return $ret;
-}
-
-# loads the given list with lines from the
-# specified file. Note that if a '!' is found
-# all prior patterns are removed from the list
-# before the following patterns are loaded
-# first param is the filename,
-# second param is a reference to an array
-# that the data is to go into
-# returns true if a ! was found
-sub load_list_from_file
-{
- my @inlist;
- my $fname = shift;#filename to read from
- #if (not -e $fname) { return; }
- my $arref = shift;#array to store into
- open CVSIGNORE,"$fname" or return;#file might not exist, that's OK
- @inlist = <CVSIGNORE>;
- close CVSIGNORE;
- return load_list_from_list($arref,@inlist);
-}
-
-# loads $cvsignoreregex from
-# $initcvsignoreregex and the .cvsignore file
-# in the local directory
-sub load_cvsignore
-{
- if ($disable_ind_cvsignore) {return;}#don't look for local .cvsignore files
- if ($disable_cvsignore) {return;}#don't do anything
-
- my $dir = shift;
- my @cvsignore;
-
- # bang will be true if a ! was found. In such cases, I need
- # to not use the pre-exisitng regex list.
- my $bang = load_list_from_file("$dir/.cvsignore",\@cvsignore);
-
- # if we get a local cvsignore list, then...
- my $rx = do_regex_convert(@cvsignore);
- if ($rx) {
- $cvsignoreregex = "(";
- if (not $bang) {$cvsignoreregex = $cvsignoreregex . $initcvsignoreregex . "|";}
- $cvsignoreregex = $cvsignoreregex . $rx . ")";
- } else {
- if ($bang) {$cvsignoreregex = "";}
- else {$cvsignoreregex = "(" . $initcvsignoreregex . ")";}
- }
-
- if ($debug_cvsignore) {print $dir,":",$cvsignoreregex, "\n";}
-}
-
-
-# loads all of the cvsignore patterns that
-# can be loaded at script startup
-sub load_initial_cvsignore()
-{
- #load the default patterns
- # (taken from http://www.gnu.org/manual/cvs-1.9/html_node/cvs_141.html#IDX399)
- #
- # this gives you the patterns that cvs normally starts with
- my @initcvsignore;
- push @initcvsignore,("RCS");
- push @initcvsignore,("SCCS");
- push @initcvsignore,("CVS");
- push @initcvsignore,("CVS.adm");
- push @initcvsignore,("RCSLOG");
- push @initcvsignore,("cvslog.*");
- push @initcvsignore,("tags");
- push @initcvsignore,("TAGS");
- push @initcvsignore,(".make.state");
- push @initcvsignore,(".nse_depinfo");
- push @initcvsignore,("*~");
- push @initcvsignore,("\#*");
- push @initcvsignore,(".\#*");
- push @initcvsignore,("\,*");
- push @initcvsignore,("_\$\*");
- push @initcvsignore,("*\$");
- push @initcvsignore,("*.old");
- push @initcvsignore,("*.bak");
- push @initcvsignore,("*.BAK");
- push @initcvsignore,("*.orig");
- push @initcvsignore,("*.rej");
- push @initcvsignore,(".del-*");
- push @initcvsignore,("*.a");
- push @initcvsignore,("*.olb");
- push @initcvsignore,("*.o");
- push @initcvsignore,("*.obj");
- push @initcvsignore,("*.so");
- push @initcvsignore,("*.exe");
- push @initcvsignore,("*.Z");
- push @initcvsignore,("*.elc");
- push @initcvsignore,("*.ln");
- push @initcvsignore,("core");
-
-
- # now, load (in proper order!)
- # each of the possible cvsignore files
-
- # there are 4 possible .cvsignore files:
-
- # $CVSROOT/CVSROOT/cvsignore
- # ~/.cvsignore
- # $CVSIGNORE environment variable
- # .cvsignore in current directory
-
- # The first (CVSROOT/cvsignore) would require calling cvs, so
- # we won't do that one.
- # The last (.cvsignore in current directory) is done
- # for each directory. It's handled in the load_cvsignore routine.
-
- # ~/.cvsignore
- my @inlist;
- my $item;
- my $HOME=$ENV{"HOME"};
- if (not $HOME) {$HOME = ".";}
- load_list_from_file("$HOME/.cvsignore",\@initcvsignore);
-
- # $CVSIGNORE environment variable
- my $igstr = $ENV{"CVSIGNORE"}; # get env var
- if ($igstr) {
- my @iglist = split(/\s+/, $igstr); #if it exists, convert to list
- load_list_from_list(\@initcvsignore,@iglist);
- }
-
- # now that @initcvsignore is setup,
- # turn it into a regex string
- $initcvsignoreregex = do_regex_convert(@initcvsignore);
-
- # now preset the cvsignore regex string to match
- # @initcvsignore. That way, if we aren't using local
- # cvsignore files, we do nothing.
- $cvsignoreregex = "(" . $initcvsignoreregex . ")";
-}
-# routine to see if the given name is in the cvsignore regex
-# returns true if it is, false if it's not
-sub ignore_file($)
-{
- #allow user to disable the cvsignore stuff
- if ($disable_cvsignore) {return 0;}
- if (not $cvsignoreregex) {return 0;}# if regex is empty, nothing matches the regex
- my $filename = shift;
-
- if ($debug_cvsignore) {print "ignore_file:",$filename,"\n";}
-
- if ($filename =~ $cvsignoreregex) {
- if ($debug_cvsignore) {print $filename," matches\n";}
- return 1;
- }
-
- if ($debug_cvsignore) {print $filename," doesn't match\n";}
- return 0;
-}
-
-sub cvs_changed_in_dir($) {
- my $dir = shift;
-
- my ($line,$filename,$version,$mtime,$date,
- $dir_filename,$cvstime,@subdirs,
- @new_in_dir,$i);
-
- # Examine status of files in CVS/Entries
- if(not open(ENTRIES,"$dir/CVS/Entries")) {
- if ($tabular) {
- push @{$files{Unknown}}, $dir;
- }
- else {
- warn "The directory $dir is not under CVS control\n";
- }
- } else {
- load_cvsignore($dir);#load up proper cvsignore for given directory
-
- while(defined ($line=<ENTRIES>)) {
- # Parse CVS/Entries-line
- $line=~m!^/(.*)/(.*)/(.*)/.*/! or do {
- $debug and warn("Skipping entry-line $line");
- next;
- };
- ($filename,$version,$date) = ($1,$2,$3);
- $dir_filename=$dir."/".$filename;
-
- # Mark this file as seen
- $seen{$dir_filename}=1;
-
- # if not exists: Deleted
- if(not -e $dir_filename) {
- push @{$files{Deleted}}, $dir_filename; next;
- }
- # if dir: save name for recursion
- -d $dir_filename and do {
- push @subdirs, $dir_filename; next;
- };
-
- # modification time of $dir_filename
- $mtime= (stat $dir_filename)[9];
-
-
- if($date eq "dummy timestamp") {
- # dummy timestamp means it's new to the repository.
- push @{$files{Changed}}, $dir_filename;
- if ($debug) {
- print "$dir_filename is changed\n";
- }
- }
- elsif($date eq "Result of merge") {
- # result of merge means it's changed, then updated.
- push @{$files{Changed}}, $dir_filename;
- if ($debug) {
- print "$dir_filename is changed\n";
- }
- }
- elsif(not
- $date=~/... (...)\s+(\d+)\s+(\d+):(\d+):(\d+) (\d{4})/)
- {
- #bogus entry in Entires
- warn "Warning: $dir_filename -> '$date' ".
- "not in ctime(3) format\n";
- } else {
- $cvstime=timegm($5,$4,$3,$2,$mon{$1},$6);
- if($cvstime != $mtime) {
- push @{$files{Changed}}, $dir_filename;
- if ($debug) {
- print "$dir_filename is changed\n";
- }
- } else {
- push @{$files{Unchanged}}, $dir_filename;
- if ($debug) {
- print "$dir_filename is Unchanged\n";
- }
- }
- }
- }
- close ENTRIES;
-
- # Locate any new files/dirs
- if(not opendir(D,$dir)) {
- warn("Cannot open $dir");
- @new_in_dir= ();
- } else {
- @skip{qw(. .. CVS)}=1..3; # Filenames that that we want to ignore
- #(note: these are exact filenames)
- @new_in_dir=
- (grep { not $seen{$_} } # files we have not already processed
- map { $dir."/".$_ } # map from file to dir/file
- grep { not ignore_file($_) } # ignore files in the cvsignore list
- grep { not $skip{$_} } # skip files to be ignored
- readdir(D));
- closedir(D);
- }
-
- # Remember new files (actually non-directories)
- push @{$files{New}}, grep { not -d $_ } @new_in_dir;
- if ($debug) { print "@{$files{New}} are new in $dir\n"; }
-
- # Remember new subdirs
- push @subdirs, grep { -d $_ } @new_in_dir;
-
- # Recurse all subdirs
- if (not $local) {
- for $i (@subdirs) { cvs_changed_in_dir($i); }
- }
- }
-}
-
-sub print_status()
-{
- my $k;
- my %show_these_states = ("Changed" => 1);
- if(not $restrict) {
- $show_these_states{"New"} = 1;
- $show_these_states{"Deleted"} = 1;
- }
-
- if($opt_all) { $show_these_states{"Unchanged"} = 1; }
-
- if ($tabular) {
- my %allfiles; # key: filesname, value: state
- my ($file, $state, $statefiles);
-
- $show_these_states{"Unknown"} = 1;
- while (($state, $statefiles) = each %files) {
- for my $f (@{$statefiles}) {
- $allfiles{$f} = $state;
- }
- }
- for $file (sort keys %allfiles) {
- $state = $allfiles{$file};
- printf("%-10s %s\n", $state, $file) if $show_these_states{$state};
- }
- }
- else {
- print "\n";
- for $k (keys %show_these_states) {
- if(not $files{$k} or not @{$files{$k}}) {
- # no files
- $files{$k}=["(none)"];
- }
- print("$k files\n",
- "---------------\n",
- map { "$_\n" } sort @{$files{$k}});
- print "\n";
- }
- }
-}
-
-load_initial_cvsignore();
-if ($debug_cvsignore) {print "initial regex:",$cvsignoreregex,"\n";}
-cvs_changed_in_dir($startdir);
-print_status();
-
diff --git a/ndb/include/Makefile.am b/ndb/include/Makefile.am
index 7b3f80b5560..61f55cf9d61 100644
--- a/ndb/include/Makefile.am
+++ b/ndb/include/Makefile.am
@@ -29,13 +29,13 @@ ndbapi/ndberror.h
mgmapiinclude_HEADERS = \
mgmapi/mgmapi.h \
-mgmapi/mgmapi_debug.h
+mgmapi/mgmapi_debug.h \
+mgmapi/mgmapi_config_parameters.h \
+mgmapi/mgmapi_config_parameters_debug.h
noinst_HEADERS = \
ndb_global.h \
-ndb_net.h \
-mgmapi/mgmapi_config_parameters.h \
-mgmapi/mgmapi_config_parameters_debug.h
+ndb_net.h
EXTRA_DIST = debugger editline kernel logger mgmcommon \
portlib transporter util
diff --git a/ndb/include/kernel/ndb_limits.h b/ndb/include/kernel/ndb_limits.h
index 88fcff22da7..48a56c019bb 100644
--- a/ndb/include/kernel/ndb_limits.h
+++ b/ndb/include/kernel/ndb_limits.h
@@ -117,4 +117,9 @@
*/
#define NDB_BLOB_HEAD_SIZE 2 /* sizeof(NdbBlob::Head) >> 2 */
+/*
+ * Long signals
+ */
+#define NDB_SECTION_SEGMENT_SZ 60
+
#endif
diff --git a/ndb/include/kernel/signaldata/AccScan.hpp b/ndb/include/kernel/signaldata/AccScan.hpp
index eab1c3262fc..b0050d71f41 100644
--- a/ndb/include/kernel/signaldata/AccScan.hpp
+++ b/ndb/include/kernel/signaldata/AccScan.hpp
@@ -51,11 +51,9 @@ private:
* Previously there where also a scan type
*/
static Uint32 getLockMode(const Uint32 & requestInfo);
- static Uint32 getKeyinfoFlag(const Uint32 & requestInfo);
static Uint32 getReadCommittedFlag(const Uint32 & requestInfo);
static void setLockMode(Uint32 & requestInfo, Uint32 lockMode);
- static void setKeyinfoFlag(Uint32 & requestInfo, Uint32 keyinfo);
static void setReadCommittedFlag(Uint32 & requestInfo, Uint32 readCommitted);
};
@@ -63,17 +61,14 @@ private:
* Request Info
*
* l = Lock Mode - 1 Bit 2
- * k = Keyinfo - 1 Bit 4
* h = Read Committed - 1 Bit 5
*
* 1111111111222222222233
* 01234567890123456789012345678901
- * l kh
+ * l h
*/
#define AS_LOCK_MODE_SHIFT (2)
#define AS_LOCK_MODE_MASK (1)
-
-#define AS_KEYINFO_SHIFT (4)
#define AS_READ_COMMITTED_SHIFT (5)
inline
@@ -84,12 +79,6 @@ AccScanReq::getLockMode(const Uint32 & requestInfo){
inline
Uint32
-AccScanReq::getKeyinfoFlag(const Uint32 & requestInfo){
- return (requestInfo >> AS_KEYINFO_SHIFT) & 1;
-}
-
-inline
-Uint32
AccScanReq::getReadCommittedFlag(const Uint32 & requestInfo){
return (requestInfo >> AS_READ_COMMITTED_SHIFT) & 1;
}
@@ -103,13 +92,6 @@ AccScanReq::setLockMode(UintR & requestInfo, UintR val){
inline
void
-AccScanReq::setKeyinfoFlag(UintR & requestInfo, UintR val){
- ASSERT_BOOL(val, "AccScanReq::setKeyinfoFlag");
- requestInfo |= (val << AS_KEYINFO_SHIFT);
-}
-
-inline
-void
AccScanReq::setReadCommittedFlag(UintR & requestInfo, UintR val){
ASSERT_BOOL(val, "AccScanReq::setReadCommittedFlag");
requestInfo |= (val << AS_READ_COMMITTED_SHIFT);
diff --git a/ndb/include/kernel/signaldata/ArbitSignalData.hpp b/ndb/include/kernel/signaldata/ArbitSignalData.hpp
index f255b8dcbbe..34b73644a13 100644
--- a/ndb/include/kernel/signaldata/ArbitSignalData.hpp
+++ b/ndb/include/kernel/signaldata/ArbitSignalData.hpp
@@ -94,13 +94,14 @@ public:
// arbitration result
LoseNodes = 41, // lose on ndb node count
- WinGroups = 42, // we win, no need for arbitration
- LoseGroups = 43, // we lose, missing node group
- Partitioning = 44, // possible network partitioning
- WinChoose = 45, // positive reply
- LoseChoose = 46, // negative reply
- LoseNorun = 47, // arbitrator required but not running
- LoseNocfg = 48, // arbitrator required but none configured
+ WinNodes = 42, // win on ndb node count
+ WinGroups = 43, // we win, no need for arbitration
+ LoseGroups = 44, // we lose, missing node group
+ Partitioning = 45, // possible network partitioning
+ WinChoose = 46, // positive reply
+ LoseChoose = 47, // negative reply
+ LoseNorun = 48, // arbitrator required but not running
+ LoseNocfg = 49, // arbitrator required but none configured
// general error codes
ErrTicket = 91, // invalid arbitrator-ticket
diff --git a/ndb/include/kernel/signaldata/BackupImpl.hpp b/ndb/include/kernel/signaldata/BackupImpl.hpp
index 1872069daa7..2ac91570aad 100644
--- a/ndb/include/kernel/signaldata/BackupImpl.hpp
+++ b/ndb/include/kernel/signaldata/BackupImpl.hpp
@@ -78,15 +78,15 @@ public:
STATIC_CONST( SignalLength = 3 );
enum ErrorCode {
- Undefined = 200,
- FailedToAllocateBuffers = 202,
- FailedToSetupFsBuffers = 203,
- FailedToAllocateTables = 204,
- FailedInsertFileHeader = 205,
- FailedInsertTableList = 206,
- FailedAllocateTableMem = 207,
- FailedToAllocateFileRecord = 208,
- FailedToAllocateAttributeRecord = 209
+ Undefined = 1340,
+ FailedToAllocateBuffers = 1342,
+ FailedToSetupFsBuffers = 1343,
+ FailedToAllocateTables = 1344,
+ FailedInsertFileHeader = 1345,
+ FailedInsertTableList = 1346,
+ FailedAllocateTableMem = 1347,
+ FailedToAllocateFileRecord = 1348,
+ FailedToAllocateAttributeRecord = 1349
};
private:
Uint32 backupId;
diff --git a/ndb/include/kernel/signaldata/BackupSignalData.hpp b/ndb/include/kernel/signaldata/BackupSignalData.hpp
index 42eb8464d53..fb018026a49 100644
--- a/ndb/include/kernel/signaldata/BackupSignalData.hpp
+++ b/ndb/include/kernel/signaldata/BackupSignalData.hpp
@@ -119,12 +119,13 @@ public:
private:
enum ErrorCodes {
- Undefined = 100,
- IAmNotMaster = 101,
- OutOfBackupRecord = 102,
- OutOfResources = 103,
- SequenceFailure = 104,
- BackupDefinitionNotImplemented = 105
+ Undefined = 1300,
+ IAmNotMaster = 1301,
+ OutOfBackupRecord = 1302,
+ OutOfResources = 1303,
+ SequenceFailure = 1304,
+ BackupDefinitionNotImplemented = 1305,
+ CannotBackupDiskless = 1306
};
Uint32 senderData;
Uint32 errorCode;
@@ -232,13 +233,13 @@ public:
STATIC_CONST( SignalLength = 3 );
enum RequestType {
- ClientAbort = 1,
- BackupComplete = 2,
- BackupFailure = 3, // General backup failure coordinator -> slave
- LogBufferFull = 4, // slave -> coordinator
- FileOrScanError = 5, // slave -> coordinator
- BackupFailureDueToNodeFail = 6, // slave -> slave
- OkToClean = 7 // master -> slave
+ ClientAbort = 1321,
+ BackupComplete = 1322,
+ BackupFailure = 1323, // General backup failure coordinator -> slave
+ LogBufferFull = 1324, // slave -> coordinator
+ FileOrScanError = 1325, // slave -> coordinator
+ BackupFailureDueToNodeFail = 1326, // slave -> slave
+ OkToClean = 1327 // master -> slave
};
private:
Uint32 requestType;
diff --git a/ndb/include/kernel/signaldata/DictTabInfo.hpp b/ndb/include/kernel/signaldata/DictTabInfo.hpp
index 6b4a3f34553..ae78c023c2a 100644
--- a/ndb/include/kernel/signaldata/DictTabInfo.hpp
+++ b/ndb/include/kernel/signaldata/DictTabInfo.hpp
@@ -51,7 +51,6 @@ class DictTabInfo {
friend class Trix;
friend class DbUtil;
// API
- friend class Table;
friend class NdbSchemaOp;
/**
diff --git a/ndb/include/kernel/signaldata/ScanTab.hpp b/ndb/include/kernel/signaldata/ScanTab.hpp
index 2029b16197e..ca70b8c62a9 100644
--- a/ndb/include/kernel/signaldata/ScanTab.hpp
+++ b/ndb/include/kernel/signaldata/ScanTab.hpp
@@ -65,7 +65,12 @@ private:
UintR buddyConPtr; // DATA 8
UintR batch_byte_size; // DATA 9
UintR first_batch_size; // DATA 10
-
+
+ /**
+ * Optional
+ */
+ Uint32 distributionKey;
+
/**
* Get:ers for requestInfo
*/
@@ -76,6 +81,7 @@ private:
static Uint8 getRangeScanFlag(const UintR & requestInfo);
static Uint8 getKeyinfoFlag(const UintR & requestInfo);
static Uint16 getScanBatch(const UintR & requestInfo);
+ static Uint8 getDistributionKeyFlag(const UintR & requestInfo);
/**
* Set:ers for requestInfo
@@ -88,6 +94,7 @@ private:
static void setRangeScanFlag(UintR & requestInfo, Uint32 flag);
static void setKeyinfoFlag(UintR & requestInfo, Uint32 flag);
static void setScanBatch(Uint32& requestInfo, Uint32 sz);
+ static void setDistributionKeyFlag(Uint32& requestInfo, Uint32 flag);
};
/**
@@ -100,6 +107,7 @@ private:
k = Keyinfo - 1 Bit 12
x = Range Scan (TUX) - 1 Bit 15
b = Scan batch - 10 Bit 16-25 (max 1023)
+ d = Distribution key flag
1111111111222222222233
01234567890123456789012345678901
@@ -127,6 +135,8 @@ private:
#define SCAN_BATCH_SHIFT (16)
#define SCAN_BATCH_MASK (1023)
+#define SCAN_DISTR_KEY_SHIFT (26)
+
inline
Uint8
ScanTabReq::getParallelism(const UintR & requestInfo){
@@ -225,6 +235,18 @@ ScanTabReq::setKeyinfoFlag(UintR & requestInfo, Uint32 flag){
requestInfo |= (flag << KEYINFO_SHIFT);
}
+inline
+Uint8
+ScanTabReq::getDistributionKeyFlag(const UintR & requestInfo){
+ return (Uint8)((requestInfo >> SCAN_DISTR_KEY_SHIFT) & 1);
+}
+
+inline
+void
+ScanTabReq::setDistributionKeyFlag(UintR & requestInfo, Uint32 flag){
+ ASSERT_BOOL(flag, "ScanTabReq::setKeyinfoFlag");
+ requestInfo |= (flag << SCAN_DISTR_KEY_SHIFT);
+}
/**
*
diff --git a/ndb/include/kernel/signaldata/TcIndx.hpp b/ndb/include/kernel/signaldata/TcIndx.hpp
index 764d4e9fcd7..f82cd95878e 100644
--- a/ndb/include/kernel/signaldata/TcIndx.hpp
+++ b/ndb/include/kernel/signaldata/TcIndx.hpp
@@ -18,379 +18,7 @@
#define TC_INDX_H
#include "SignalData.hpp"
-
-class TcIndxReq {
- /**
- * Reciver(s)
- */
- friend class Dbtc; // Reciver
-
- /**
- * Sender(s)
- */
- friend class NdbIndexOperation;
-
- /**
- * For printing
- */
- friend bool printTCINDXREQ(FILE *, const Uint32 *, Uint32, Uint16);
-
-public:
- /**
- * Length of signal
- */
- STATIC_CONST( StaticLength = 8 );
- STATIC_CONST( SignalLength = 25 );
- STATIC_CONST( MaxKeyInfo = 8 );
- STATIC_CONST( MaxAttrInfo = 5 );
-
-private:
-
- enum CommitType {
- CommitIfFailFree = 0,
- TryCommit = 1,
- CommitAsMuchAsPossible = 2
- };
-
- /**
- * DATA VARIABLES
- */
-//-------------------------------------------------------------
-// Unconditional part. First 8 words
-//-------------------------------------------------------------
- UintR apiConnectPtr; // DATA 0
- UintR senderData; // DATA 1
- UintR attrLen; // DATA 2 (including API Version)
- UintR indexId; // DATA 3
- UintR requestInfo; // DATA 4
- UintR indexSchemaVersion; // DATA 5
- UintR transId1; // DATA 6
- UintR transId2; // DATA 7
-//-------------------------------------------------------------
-// Conditional part. Those four words will be sent only if their
-// indicator is set.
-//-------------------------------------------------------------
- UintR scanInfo; // DATA 8
- UintR distrGroupHashValue; // DATA 9
- UintR distributionKeySize; // DATA 10
- UintR storedProcId; // DATA 11
-
-//-------------------------------------------------------------
-// Variable sized key and attrinfo part. Those will be placed to
-// pack the signal in an appropriate manner.
-//-------------------------------------------------------------
- UintR keyInfo[MaxKeyInfo]; // DATA 12 - 19
- UintR attrInfo[MaxAttrInfo]; // DATA 20 - 24
-
- static Uint8 getAPIVersion(const UintR & attrLen);
-
- /**
- * Get:ers for requestInfo
- */
- static Uint8 getCommitFlag(const UintR & requestInfo);
- static Uint8 getCommitType(const UintR & requestInfo);
- static Uint8 getStartFlag(const UintR & requestInfo);
- static Uint8 getSimpleFlag(const UintR & requestInfo);
- static Uint8 getDirtyFlag(const UintR & requestInfo);
- static Uint8 getInterpretedFlag(const UintR & requestInfo);
- static Uint8 getDistributionGroupFlag(const UintR & requestInfo);
- static Uint8 getDistributionGroupTypeFlag(const UintR & requestInfo);
- static Uint8 getDistributionKeyFlag(const UintR & requestInfo);
- static Uint8 getScanIndFlag(const UintR & requestInfo);
-
- static Uint8 getOperationType(const UintR & requestInfo);
-
- static Uint16 getIndexLength(const UintR & requestInfo);
- static Uint8 getAIInTcIndxReq(const UintR & requestInfo);
-
- /**
- * Get:ers for scanInfo
- */
-
- static void setAPIVersion(UintR & attrLen, Uint16 apiVersion);
-
- /**
- * Set:ers for requestInfo
- */
- static void clearRequestInfo(UintR & requestInfo);
- static void setCommitType(UintR & requestInfo, Uint32 type);
- static void setCommitFlag(UintR & requestInfo, Uint32 flag);
- static void setStartFlag(UintR & requestInfo, Uint32 flag);
- static void setSimpleFlag(UintR & requestInfo, Uint32 flag);
- static void setDirtyFlag(UintR & requestInfo, Uint32 flag);
- static void setInterpretedFlag(UintR & requestInfo, Uint32 flag);
- static void setDistributionGroupFlag(UintR & requestInfo, Uint32 flag);
- static void setDistributionGroupTypeFlag(UintR & requestInfo, Uint32 flag);
- static void setDistributionKeyFlag(UintR & requestInfo, Uint32 flag);
- static void setScanIndFlag(UintR & requestInfo, Uint32 flag);
-
- static void setOperationType(UintR & requestInfo, Uint32 type);
-
- static void setIndexLength(UintR & requestInfo, Uint32 len);
- static void setAIInTcIndxReq(UintR & requestInfo, Uint32 len);
-
- /**
- * Set:ers for scanInfo
- */
-
-};
-
-#define API_VER_NO_SHIFT (16)
-#define API_VER_NO_MASK (65535)
-
-/**
- * Request Info
- *
- a = Attr Info in TCINDXREQ - 3 Bits -> Max 7 (Bit 16-18)
- b = Distribution Key Ind - 1 Bit 2
- c = Commit Indicator - 1 Bit 4
- d = Dirty Indicator - 1 Bit 0
- e = Scan Indicator - 1 Bit 14
- g = Distribution Group Ind - 1 Bit 1
- i = Interpreted Indicator - 1 Bit 15
- k = Index lengt - 12 Bits -> Max 4095 (Bit 20 - 31)
- o = Operation Type - 3 Bits -> Max 7 (Bit 5-7)
- p = Simple Indicator - 1 Bit 8
- s = Start Indicator - 1 Bit 11
- t = Distribution GroupType - 1 Bit 3
- y = Commit Type - 2 Bit 12-13
- x = Last Op in execute - 1 Bit 19
-
- 1111111111222222222233
- 01234567890123456789012345678901
- dgbtcooop syyeiaaa-kkkkkkkkkkkk
-*/
-
-#define COMMIT_SHIFT (4)
-#define START_SHIFT (11)
-#define SIMPLE_SHIFT (8)
-#define DIRTY_SHIFT (0)
-#define INTERPRETED_SHIFT (15)
-#define DISTR_GROUP_SHIFT (1)
-#define DISTR_GROUP_TYPE_SHIFT (3)
-#define DISTR_KEY_SHIFT (2)
-#define SCAN_SHIFT (14)
-
-#define OPERATION_SHIFT (5)
-#define OPERATION_MASK (7)
-
-#define AINFO_SHIFT (16)
-#define AINFO_MASK (7)
-
-#define INDEX_LEN_SHIFT (20)
-#define INDEX_LEN_MASK (4095)
-
-#define COMMIT_TYPE_SHIFT (12)
-#define COMMIT_TYPE_MASK (3)
-
-#define LAST_OP_IN_EXEC_SHIFT (19)
-
-/**
- * Scan Info
- *
-
-
- 1111111111222222222233
- 01234567890123456789012345678901
-
-*/
-
-inline
-Uint8
-TcIndxReq::getCommitFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> COMMIT_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getCommitType(const UintR & requestInfo){
- return (Uint8)((requestInfo >> COMMIT_TYPE_SHIFT) & COMMIT_TYPE_MASK);
-}
-
-inline
-Uint8
-TcIndxReq::getStartFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> START_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getSimpleFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> SIMPLE_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDirtyFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> DIRTY_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getInterpretedFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> INTERPRETED_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDistributionGroupFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> DISTR_GROUP_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDistributionGroupTypeFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> DISTR_GROUP_TYPE_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getDistributionKeyFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> DISTR_KEY_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getScanIndFlag(const UintR & requestInfo){
- return (Uint8)((requestInfo >> SCAN_SHIFT) & 1);
-}
-
-inline
-Uint8
-TcIndxReq::getOperationType(const UintR & requestInfo){
- return (Uint8)((requestInfo >> OPERATION_SHIFT) & OPERATION_MASK);
-}
-
-inline
-Uint16
-TcIndxReq::getIndexLength(const UintR & requestInfo){
- return (Uint16)((requestInfo >> INDEX_LEN_SHIFT) & INDEX_LEN_MASK);
-}
-
-inline
-Uint8
-TcIndxReq::getAIInTcIndxReq(const UintR & requestInfo){
- return (Uint8)((requestInfo >> AINFO_SHIFT) & AINFO_MASK);
-}
-
-inline
-void
-TcIndxReq::clearRequestInfo(UintR & requestInfo){
- requestInfo = 0;
-}
-
-inline
-void
-TcIndxReq::setCommitType(UintR & requestInfo, Uint32 type){
- ASSERT_MAX(type, COMMIT_TYPE_MASK, "TcIndxReq::setCommitType");
- requestInfo |= (type << COMMIT_TYPE_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setCommitFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setCommitFlag");
- requestInfo &= ~(1 << COMMIT_SHIFT);
- requestInfo |= (flag << COMMIT_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setStartFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setStartFlag");
- requestInfo &= ~(1 << START_SHIFT);
- requestInfo |= (flag << START_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setSimpleFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setSimpleFlag");
- requestInfo &= ~(1 << SIMPLE_SHIFT);
- requestInfo |= (flag << SIMPLE_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setDirtyFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setDirtyFlag");
- requestInfo &= ~(1 << DIRTY_SHIFT);
- requestInfo |= (flag << DIRTY_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setInterpretedFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setInterpretedFlag");
- requestInfo &= ~(1 << INTERPRETED_SHIFT);
- requestInfo |= (flag << INTERPRETED_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setDistributionGroupTypeFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setDistributionGroupTypeFlag");
- requestInfo &= ~(1 << DISTR_GROUP_TYPE_SHIFT);
- requestInfo |= (flag << DISTR_GROUP_TYPE_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setDistributionGroupFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setDistributionGroupFlag");
- requestInfo &= ~(1 << DISTR_GROUP_SHIFT);
- requestInfo |= (flag << DISTR_GROUP_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setDistributionKeyFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setDistributionKeyFlag");
- requestInfo &= ~(1 << DISTR_KEY_SHIFT);
- requestInfo |= (flag << DISTR_KEY_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setScanIndFlag(UintR & requestInfo, Uint32 flag){
- ASSERT_BOOL(flag, "TcIndxReq::setScanIndFlag");
- requestInfo &= ~(1 << SCAN_SHIFT);
- requestInfo |= (flag << SCAN_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setOperationType(UintR & requestInfo, Uint32 type){
- ASSERT_MAX(type, OPERATION_MASK, "TcIndxReq::setOperationType");
- requestInfo |= (type << OPERATION_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setIndexLength(UintR & requestInfo, Uint32 len){
- ASSERT_MAX(len, INDEX_LEN_MASK, "TcIndxReq::setKeyLength");
- requestInfo |= (len << INDEX_LEN_SHIFT);
-}
-
-inline
-void
-TcIndxReq::setAIInTcIndxReq(UintR & requestInfo, Uint32 len){
- ASSERT_MAX(len, AINFO_MASK, "TcIndxReq::setAIInTcIndxReq");
- requestInfo |= (len << AINFO_SHIFT);
-}
-
-inline
-Uint8
-TcIndxReq::getAPIVersion(const UintR & anAttrLen){
- return (Uint16)((anAttrLen >> API_VER_NO_SHIFT) & API_VER_NO_MASK);
-}
-
-inline
-void
-TcIndxReq::setAPIVersion(UintR & anAttrLen, Uint16 apiVersion){
-// ASSERT_MAX(apiVersion, API_VER_NO_MASK, "TcIndxReq::setAPIVersion");
- anAttrLen |= (apiVersion << API_VER_NO_SHIFT);
-}
+#include "TcKeyReq.hpp"
class TcIndxConf {
diff --git a/ndb/include/kernel/signaldata/TcKeyReq.hpp b/ndb/include/kernel/signaldata/TcKeyReq.hpp
index 9e42f2a70d5..d7c11ca773c 100644
--- a/ndb/include/kernel/signaldata/TcKeyReq.hpp
+++ b/ndb/include/kernel/signaldata/TcKeyReq.hpp
@@ -142,7 +142,7 @@ private:
* Get:ers for scanInfo
*/
static Uint8 getTakeOverScanFlag(const UintR & scanInfo);
- static Uint16 getTakeOverScanNode(const UintR & scanInfo);
+ static Uint16 getTakeOverScanFragment(const UintR & scanInfo);
static Uint32 getTakeOverScanInfo(const UintR & scanInfo);
@@ -171,7 +171,7 @@ private:
* Set:ers for scanInfo
*/
static void setTakeOverScanFlag(UintR & scanInfo, Uint8 flag);
- static void setTakeOverScanNode(UintR & scanInfo, Uint16 node);
+ static void setTakeOverScanFragment(UintR & scanInfo, Uint16 fragment);
static void setTakeOverScanInfo(UintR & scanInfo, Uint32 aScanInfo);
};
@@ -238,8 +238,8 @@ private:
#define TAKE_OVER_SHIFT (0)
-#define TAKE_OVER_NODE_SHIFT (20)
-#define TAKE_OVER_NODE_MASK (4095)
+#define TAKE_OVER_FRAG_SHIFT (20)
+#define TAKE_OVER_FRAG_MASK (4095)
#define SCAN_INFO_SHIFT (1)
#define SCAN_INFO_MASK (262143)
@@ -485,8 +485,8 @@ TcKeyReq::getTakeOverScanFlag(const UintR & scanInfo){
inline
Uint16
-TcKeyReq::getTakeOverScanNode(const UintR & scanInfo){
- return (Uint16)((scanInfo >> TAKE_OVER_NODE_SHIFT) & TAKE_OVER_NODE_MASK);
+TcKeyReq::getTakeOverScanFragment(const UintR & scanInfo){
+ return (Uint16)((scanInfo >> TAKE_OVER_FRAG_SHIFT) & TAKE_OVER_FRAG_MASK);
}
inline
@@ -505,9 +505,9 @@ TcKeyReq::setTakeOverScanFlag(UintR & scanInfo, Uint8 flag){
inline
void
-TcKeyReq::setTakeOverScanNode(UintR & scanInfo, Uint16 node){
+TcKeyReq::setTakeOverScanFragment(UintR & scanInfo, Uint16 node){
// ASSERT_MAX(node, TAKE_OVER_NODE_MASK, "TcKeyReq::setTakeOverScanNode");
- scanInfo |= (node << TAKE_OVER_NODE_SHIFT);
+ scanInfo |= (node << TAKE_OVER_FRAG_SHIFT);
}
inline
diff --git a/ndb/include/kernel/signaldata/TupFrag.hpp b/ndb/include/kernel/signaldata/TupFrag.hpp
index c1e861c5dff..c132b19c50a 100644
--- a/ndb/include/kernel/signaldata/TupFrag.hpp
+++ b/ndb/include/kernel/signaldata/TupFrag.hpp
@@ -132,9 +132,10 @@ class TupAddAttrConf {
friend class Dblqh;
friend class Dbtup;
public:
- STATIC_CONST( SignalLength = 1 );
+ STATIC_CONST( SignalLength = 2 );
private:
Uint32 userPtr;
+ Uint32 lastAttr; // bool: got last attr and closed frag op
};
class TupAddAttrRef {
@@ -171,9 +172,10 @@ class TuxAddAttrConf {
friend class Dblqh;
friend class Dbtux;
public:
- STATIC_CONST( SignalLength = 1 );
+ STATIC_CONST( SignalLength = 2 );
private:
Uint32 userPtr;
+ Uint32 lastAttr; // bool: got last attr and closed frag op
};
class TuxAddAttrRef {
diff --git a/ndb/include/kernel/signaldata/TuxBound.hpp b/ndb/include/kernel/signaldata/TuxBound.hpp
index 87ce3c3c098..d829d6e82dd 100644
--- a/ndb/include/kernel/signaldata/TuxBound.hpp
+++ b/ndb/include/kernel/signaldata/TuxBound.hpp
@@ -50,6 +50,8 @@ private:
* Number of words of bound info included after fixed signal data.
*/
Uint32 boundAiLength;
+
+ Uint32 data[1];
};
#endif
diff --git a/ndb/include/mgmapi/mgmapi.h b/ndb/include/mgmapi/mgmapi.h
index 6dcf58b44e2..dc4f745adb2 100644
--- a/ndb/include/mgmapi/mgmapi.h
+++ b/ndb/include/mgmapi/mgmapi.h
@@ -356,11 +356,27 @@ extern "C" {
/**
* Create a handle to a management server
*
- * @return A management handle<br>
- * or NULL if no management handle could be created.
+ * @return A management handle<br>
+ * or NULL if no management handle could be created.
*/
NdbMgmHandle ndb_mgm_create_handle();
+ /**
+ * Set connecst string to management server
+ *
+ * @param handle Management handle
+ * @param connect_string Connect string to the management server,
+ *
+ * @return -1 on error.
+ */
+ int ndb_mgm_set_connectstring(NdbMgmHandle handle,
+ const char *connect_string);
+
+ int ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle);
+ int ndb_mgm_get_connected_port(NdbMgmHandle handle);
+ const char *ndb_mgm_get_connected_host(NdbMgmHandle handle);
+ const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz);
+
/**
* Destroy a management server handle
*
@@ -378,11 +394,10 @@ extern "C" {
* Connect to a management server
*
* @param handle Management handle.
- * @param mgmsrv Hostname and port of the management server,
- * "hostname:port".
* @return -1 on error.
*/
- int ndb_mgm_connect(NdbMgmHandle handle, const char * mgmsrv);
+ int ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
+ int retry_delay_in_seconds, int verbose);
/**
* Disconnect from a management server
@@ -709,9 +724,7 @@ extern "C" {
void ndb_mgm_destroy_configuration(struct ndb_mgm_configuration *);
int ndb_mgm_alloc_nodeid(NdbMgmHandle handle,
- unsigned version,
- unsigned *pnodeid,
- int nodetype);
+ unsigned version, int nodetype);
/**
* Config iterator
*/
@@ -733,6 +746,8 @@ extern "C" {
int param, unsigned long long * value);
int ndb_mgm_get_string_parameter(const ndb_mgm_configuration_iterator*,
int param, const char ** value);
+ int ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **);
+ int ndb_mgm_check_connection(NdbMgmHandle handle);
#ifdef __cplusplus
}
#endif
diff --git a/ndb/include/mgmcommon/ConfigRetriever.hpp b/ndb/include/mgmcommon/ConfigRetriever.hpp
index 6c32255e921..8461658748e 100644
--- a/ndb/include/mgmcommon/ConfigRetriever.hpp
+++ b/ndb/include/mgmcommon/ConfigRetriever.hpp
@@ -20,7 +20,6 @@
#include <ndb_types.h>
#include <mgmapi.h>
#include <BaseString.hpp>
-#include <LocalConfig.hpp>
/**
* @class ConfigRetriever
@@ -28,10 +27,11 @@
*/
class ConfigRetriever {
public:
- ConfigRetriever(LocalConfig &local_config, Uint32 version, Uint32 nodeType);
+ ConfigRetriever(const char * _connect_string,
+ Uint32 version, Uint32 nodeType);
~ConfigRetriever();
- int do_connect(int exit_on_connect_failure= false);
+ int do_connect(int no_retries, int retry_delay_in_seconds, int verbose);
/**
* Get configuration for current node.
@@ -46,12 +46,14 @@ public:
*/
struct ndb_mgm_configuration * getConfig();
+ void resetError();
+ int hasError();
const char * getErrorString();
/**
* @return Node id of this node (as stated in local config or connectString)
*/
- Uint32 allocNodeId();
+ Uint32 allocNodeId(int no_retries, int retry_delay_in_seconds);
/**
* Get config using socket
@@ -68,22 +70,27 @@ public:
*/
bool verifyConfig(const struct ndb_mgm_configuration *, Uint32 nodeid);
- Uint32 get_mgmd_port() const {return m_mgmd_port;};
- const char *get_mgmd_host() const {return m_mgmd_host;};
+ Uint32 get_mgmd_port() const;
+ const char *get_mgmd_host() const;
+ const char *get_connectstring(char *buf, int buf_sz) const;
+
+ Uint32 get_configuration_nodeid() const;
private:
BaseString errorString;
enum ErrorType {
- CR_ERROR = 0,
- CR_RETRY = 1
+ CR_NO_ERROR = 0,
+ CR_ERROR = 1,
+ CR_RETRY = 2
};
ErrorType latestErrorType;
void setError(ErrorType, const char * errorMsg);
- struct LocalConfig& _localConfig;
- Uint32 _ownNodeId;
+ Uint32 _ownNodeId;
+ /*
Uint32 m_mgmd_port;
const char *m_mgmd_host;
+ */
Uint32 m_version;
Uint32 m_node_type;
diff --git a/ndb/include/ndb_global.h b/ndb/include/ndb_global.h
index 09559f6ddff..bdd4e503cc5 100644
--- a/ndb/include/ndb_global.h
+++ b/ndb/include/ndb_global.h
@@ -82,19 +82,12 @@ extern "C" {
/* call in main() - does not return on error */
extern int ndb_init(void);
extern void ndb_end(int);
+#define NDB_INIT(prog_name) {my_progname=(prog_name); ndb_init();}
#ifndef HAVE_STRDUP
extern char * strdup(const char *s);
#endif
-#ifndef HAVE_STRLCPY
-extern size_t strlcpy (char *dst, const char *src, size_t dst_sz);
-#endif
-
-#ifndef HAVE_STRLCAT
-extern size_t strlcat (char *dst, const char *src, size_t dst_sz);
-#endif
-
#ifndef HAVE_STRCASECMP
extern int strcasecmp(const char *s1, const char *s2);
extern int strncasecmp(const char *s1, const char *s2, size_t n);
diff --git a/ndb/include/ndb_types.h b/ndb/include/ndb_types.h
index a2988dbae78..64b3f517934 100644
--- a/ndb/include/ndb_types.h
+++ b/ndb/include/ndb_types.h
@@ -21,11 +21,11 @@
#ifndef NDB_TYPES_H
#define NDB_TYPES_H
-typedef char Int8;
+typedef signed char Int8;
typedef unsigned char Uint8;
-typedef short Int16;
+typedef signed short Int16;
typedef unsigned short Uint16;
-typedef int Int32;
+typedef signed int Int32;
typedef unsigned int Uint32;
typedef unsigned int UintR;
@@ -45,10 +45,10 @@ typedef uintptr_t UintPtr;
#if defined(WIN32) || defined(NDB_WIN32)
typedef unsigned __int64 Uint64;
-typedef __int64 Int64;
+typedef signed __int64 Int64;
#else
typedef unsigned long long Uint64;
-typedef long long Int64;
+typedef signed long long Int64;
#endif
#endif
diff --git a/ndb/include/ndbapi/NdbBlob.hpp b/ndb/include/ndbapi/NdbBlob.hpp
index 5df61a0806c..0fb63015da2 100644
--- a/ndb/include/ndbapi/NdbBlob.hpp
+++ b/ndb/include/ndbapi/NdbBlob.hpp
@@ -36,7 +36,7 @@ class NdbColumnImpl;
* Blob data is stored in 2 places:
*
* - "header" and "inline bytes" stored in the blob attribute
- * - "blob parts" stored in a separate table NDB$BLOB_<t>_<v>_<c>
+ * - "blob parts" stored in a separate table NDB$BLOB_<tid>_<cid>
*
* Inline and part sizes can be set via NdbDictionary::Column methods
* when the table is created.
@@ -74,23 +74,21 @@ class NdbColumnImpl;
* NdbBlob methods return -1 on error and 0 on success, and use output
* parameters when necessary.
*
- * Notes:
- * - table and its blob part tables are not created atomically
- * - scan must use the "new" interface NdbScanOperation
- * - to update a blob in a read op requires exclusive tuple lock
- * - update op in scan must do its own getBlobHandle
- * - delete creates implicit, not-accessible blob handles
- * - NdbOperation::writeTuple does not support blobs
- * - there is no support for an asynchronous interface
+ * Operation types:
+ * - insertTuple must use setValue if blob column is non-nullable
+ * - readTuple with exclusive lock can also update existing value
+ * - updateTuple can overwrite with setValue or update existing value
+ * - writeTuple always overwrites and must use setValue if non-nullable
+ * - deleteTuple creates implicit non-accessible blob handles
+ * - scan with exclusive lock can also update existing value
+ * - scan "lock takeover" update op must do its own getBlobHandle
*
* Bugs / limitations:
- * - scan must use exclusive locking for now
- *
- * Todo:
- * - add scan method hold-read-lock + return-keyinfo
- * - check keyinfo length when setting keys
- * - check allowed blob ops vs locking mode
- * - overload control (too many pending ops)
+ * - lock mode upgrade should be handled automatically
+ * - lock mode vs allowed operation is not checked
+ * - too many pending blob ops can blow up i/o buffers
+ * - table and its blob part tables are not created atomically
+ * - there is no support for an asynchronous interface
*/
class NdbBlob {
public:
@@ -173,19 +171,11 @@ public:
*/
int readData(void* data, Uint32& bytes);
/**
- * Read at given position. Does not use or update current position.
- */
- int readData(Uint64 pos, void* data, Uint32& bytes);
- /**
* Write at current position and set new position to first byte after
* the data written. A write past blob end extends the blob value.
*/
int writeData(const void* data, Uint32 bytes);
/**
- * Write at given position. Does not use or update current position.
- */
- int writeData(Uint64 pos, const void* data, Uint32 bytes);
- /**
* Return the blob column.
*/
const NdbDictionary::Column* getColumn();
@@ -266,14 +256,17 @@ private:
Buf();
~Buf();
void alloc(unsigned n);
+ void copyfrom(const Buf& src);
};
Buf theKeyBuf;
Buf theAccessKeyBuf;
Buf theHeadInlineBuf;
+ Buf theHeadInlineCopyBuf; // for writeTuple
Buf thePartBuf;
Head* theHead;
char* theInlineData;
NdbRecAttr* theHeadInlineRecAttr;
+ NdbOperation* theHeadInlineReadOp;
bool theHeadInlineUpdateFlag;
// length and read/write position
int theNullFlag;
@@ -294,6 +287,7 @@ private:
bool isReadOp();
bool isInsertOp();
bool isUpdateOp();
+ bool isWriteOp();
bool isDeleteOp();
bool isScanOp();
// computations
@@ -309,12 +303,13 @@ private:
void getHeadFromRecAttr();
int setHeadInlineValue(NdbOperation* anOp);
// data operations
- int readDataPrivate(Uint64 pos, char* buf, Uint32& bytes);
- int writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes);
+ int readDataPrivate(char* buf, Uint32& bytes);
+ int writeDataPrivate(const char* buf, Uint32 bytes);
int readParts(char* buf, Uint32 part, Uint32 count);
int insertParts(const char* buf, Uint32 part, Uint32 count);
int updateParts(const char* buf, Uint32 part, Uint32 count);
int deleteParts(Uint32 part, Uint32 count);
+ int deletePartsUnknown(Uint32 part);
// pending ops
int executePendingBlobReads();
int executePendingBlobWrites();
diff --git a/ndb/include/ndbapi/NdbConnection.hpp b/ndb/include/ndbapi/NdbConnection.hpp
index 92b940e96f7..f0f44170ed7 100644
--- a/ndb/include/ndbapi/NdbConnection.hpp
+++ b/ndb/include/ndbapi/NdbConnection.hpp
@@ -178,11 +178,23 @@ public:
NdbOperation* getNdbOperation(const char* aTableName);
/**
+ * Get an NdbOperation for a table.
+ * Note that the operation has to be defined before it is executed.
+ *
+ * @note All operations within the same transaction need to
+ * be initialized with this method.
+ *
+ * @param aTable A table object (fetched by NdbDictionary::Dictionary::getTable)
+ * @return Pointer to an NdbOperation object if successful, otherwise NULL.
+ */
+ NdbOperation* getNdbOperation(const NdbDictionary::Table * aTable);
+
+ /**
* Get an operation from NdbScanOperation idlelist and
* get the NdbConnection object which
* was fetched by startTransaction pointing to this operation.
*
- * @param aTableName a table name.
+ * @param aTableName The table name.
* @return pointer to an NdbOperation object if successful, otherwise NULL
*/
NdbScanOperation* getNdbScanOperation(const char* aTableName);
@@ -192,25 +204,60 @@ public:
* get the NdbConnection object which
* was fetched by startTransaction pointing to this operation.
*
+ * @param aTable A table object (fetched by NdbDictionary::Dictionary::getTable)
+ * @return pointer to an NdbOperation object if successful, otherwise NULL
+ */
+ NdbScanOperation* getNdbScanOperation(const NdbDictionary::Table * aTable);
+
+ /**
+ * Get an operation from NdbIndexScanOperation idlelist and
+ * get the NdbConnection object which
+ * was fetched by startTransaction pointing to this operation.
+ *
* @param anIndexName The index name.
- * @param aTableName a table name.
+ * @param aTableName The table name.
* @return pointer to an NdbOperation object if successful, otherwise NULL
*/
NdbIndexScanOperation* getNdbIndexScanOperation(const char* anIndexName,
const char* aTableName);
/**
+ * Get an operation from NdbIndexScanOperation idlelist and
+ * get the NdbConnection object which
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param anIndex An index object (fetched by NdbDictionary::Dictionary::getIndex).
+ * @param aTable A table object (fetched by NdbDictionary::Dictionary::getTable).
+ * @return pointer to an NdbOperation object if successful, otherwise NULL
+ */
+ NdbIndexScanOperation* getNdbIndexScanOperation(const NdbDictionary::Index * anIndex,
+ const NdbDictionary::Table * aTable);
+
+ /**
* Get an operation from NdbIndexOperation idlelist and
* get the NdbConnection object that
* was fetched by startTransaction pointing to this operation.
*
- * @param indexName An index name (as created by createIndex).
- * @param tableName A table name.
+ * @param anIndexName The index name (as created by createIndex).
+ * @param aTableName The table name.
* @return Pointer to an NdbIndexOperation object if
* successful, otherwise NULL
*/
- NdbIndexOperation* getNdbIndexOperation(const char* indexName,
- const char* tableName);
+ NdbIndexOperation* getNdbIndexOperation(const char* anIndexName,
+ const char* aTableName);
+
+ /**
+ * Get an operation from NdbIndexOperation idlelist and
+ * get the NdbConnection object that
+ * was fetched by startTransaction pointing to this operation.
+ *
+ * @param anIndex An index object (fetched by NdbDictionary::Dictionary::getIndex).
+ * @param aTable A table object (fetched by NdbDictionary::Dictionary::getTable).
+ * @return Pointer to an NdbIndexOperation object if
+ * successful, otherwise NULL
+ */
+ NdbIndexOperation* getNdbIndexOperation(const NdbDictionary::Index * anIndex,
+ const NdbDictionary::Table * aTable);
/**
* @name Execute Transaction
@@ -441,14 +488,6 @@ public:
*/
int executePendingBlobOps(Uint8 flags = 0xFF);
- // Fast path calls for MySQL ha_ndbcluster
- NdbOperation* getNdbOperation(const NdbDictionary::Table * table);
- NdbIndexOperation* getNdbIndexOperation(const NdbDictionary::Index *,
- const NdbDictionary::Table * table);
- NdbScanOperation* getNdbScanOperation(const NdbDictionary::Table * table);
- NdbIndexScanOperation* getNdbIndexScanOperation(const NdbDictionary::Index * index,
- const NdbDictionary::Table * table);
-
private:
/**
* Release completed operations
@@ -526,7 +565,7 @@ private:
int sendCOMMIT(); // Send a TC_COMMITREQ signal;
void setGCI(int GCI); // Set the global checkpoint identity
- int OpCompleteFailure(Uint8 abortoption);
+ int OpCompleteFailure(Uint8 abortoption, bool setFailure = true);
int OpCompleteSuccess();
void CompletedOperations(); // Move active ops to list of completed
@@ -552,7 +591,7 @@ private:
void setOperationErrorCode(int anErrorCode);
// Indicate something went wrong in the definition phase
- void setOperationErrorCodeAbort(int anErrorCode);
+ void setOperationErrorCodeAbort(int anErrorCode, int abortOption = -1);
int checkMagicNumber(); // Verify correct object
NdbOperation* getNdbOperation(const class NdbTableImpl* aTable,
@@ -607,8 +646,8 @@ private:
NdbOperation* theLastExecOpInList; // Last executing operation in list.
- NdbOperation* theCompletedFirstOp; // First operation in completed
- // operation list.
+ NdbOperation* theCompletedFirstOp; // First & last operation in completed
+ NdbOperation* theCompletedLastOp; // operation list.
Uint32 theNoOfOpSent; // How many operations have been sent
Uint32 theNoOfOpCompleted; // How many operations have completed
diff --git a/ndb/include/ndbapi/NdbDictionary.hpp b/ndb/include/ndbapi/NdbDictionary.hpp
index 51a6895648f..4acca0f3d96 100644
--- a/ndb/include/ndbapi/NdbDictionary.hpp
+++ b/ndb/include/ndbapi/NdbDictionary.hpp
@@ -369,18 +369,8 @@ public:
*/
bool getDistributionKey() const;
/** @} *******************************************************************/
-
-#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
- void setTupleKey(bool);
- bool getTupleKey() const;
-
- void setDistributionGroup(bool, int bits = 16);
- bool getDistributionGroup() const;
- int getDistributionGroupBits() const;
-
- void setIndexOnlyStorage(bool);
- bool getIndexOnlyStorage() const;
+#ifndef DOXYGEN_SHOULD_SKIP_INTERNAL
const Table * getBlobTable() const;
/**
@@ -490,6 +480,18 @@ public:
* Get column definition via index in table.
* @return null if none existing name
*/
+ Column* getColumn(const int attributeId);
+
+ /**
+ * Get column definition via name.
+ * @return null if none existing name
+ */
+ Column* getColumn(const char * name);
+
+ /**
+ * Get column definition via index in table.
+ * @return null if none existing name
+ */
const Column* getColumn(const int attributeId) const;
/** @} *******************************************************************/
diff --git a/ndb/include/ndbapi/NdbIndexOperation.hpp b/ndb/include/ndbapi/NdbIndexOperation.hpp
index 7612fe54d1b..4c81282caa9 100644
--- a/ndb/include/ndbapi/NdbIndexOperation.hpp
+++ b/ndb/include/ndbapi/NdbIndexOperation.hpp
@@ -49,6 +49,9 @@ public:
* @{
*/
+ /** insert is not allowed */
+ int insertTuple();
+
/**
* Define the NdbIndexOperation to be a standard operation of type readTuple.
* When calling NdbConnection::execute, this operation
@@ -173,29 +176,17 @@ private:
NdbIndexOperation(Ndb* aNdb);
~NdbIndexOperation();
- void closeScan();
-
int receiveTCINDXREF(NdbApiSignal* aSignal);
- // Overloaded method from NdbOperation
- void setLastFlag(NdbApiSignal* signal, Uint32 lastFlag);
-
- // Overloaded methods from NdbCursorOperation
- int executeCursor(int ProcessorId);
-
// Overloaded methods from NdbCursorOperation
int indxInit(const class NdbIndexImpl* anIndex,
const class NdbTableImpl* aTable,
NdbConnection* myConnection);
- int equal_impl(const class NdbColumnImpl*, const char* aValue, Uint32 len);
int prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId);
// Private attributes
const NdbIndexImpl* m_theIndex;
- Uint32 m_theIndexDefined[NDB_MAX_ATTRIBUTES_IN_INDEX][3];
- Uint32 m_theIndexLen; // Length of the index in words
- Uint32 m_theNoOfIndexDefined; // The number of index attributes
};
#endif
diff --git a/ndb/include/ndbapi/NdbIndexScanOperation.hpp b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
index 66b3fc9d43b..07cef442411 100644
--- a/ndb/include/ndbapi/NdbIndexScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbIndexScanOperation.hpp
@@ -113,7 +113,13 @@ public:
* Reset bounds and put operation in list that will be
* sent on next execute
*/
- int reset_bounds();
+ int reset_bounds(bool forceSend = false);
+
+ /**
+ * Set new bound on operation,
+ * used when batching index reads
+ */
+ int set_new_bound();
bool getSorted() const { return m_ordered; }
private:
@@ -127,11 +133,14 @@ private:
virtual NdbRecAttr* getValue_impl(const NdbColumnImpl*, char*);
void fix_get_values();
- int next_result_ordered(bool fetchAllowed);
- int send_next_scan_ordered(Uint32 idx);
+ int next_result_ordered(bool fetchAllowed, bool forceSend = false);
+ int send_next_scan_ordered(Uint32 idx, bool forceSend = false);
int compare(Uint32 key, Uint32 cols, const NdbReceiver*, const NdbReceiver*);
Uint32 m_sort_columns;
+
+ Uint32 m_this_bound_start;
+ Uint32 * m_first_bound_word;
};
#endif
diff --git a/ndb/include/ndbapi/NdbOperation.hpp b/ndb/include/ndbapi/NdbOperation.hpp
index 8e0294e41e6..f32a418f6d2 100644
--- a/ndb/include/ndbapi/NdbOperation.hpp
+++ b/ndb/include/ndbapi/NdbOperation.hpp
@@ -719,6 +719,15 @@ public:
LockMode getLockMode() const { return theLockMode; }
+ /**
+ * Set/get distribution/partition key
+ */
+ void setPartitionId(Uint32 id);
+ void setPartitionHash(Uint32 key);
+ void setPartitionHash(const Uint64 *, Uint32 len);
+ Uint32 getPartitionId() const;
+protected:
+ int handle_distribution_key(const Uint64 *, Uint32 len);
protected:
/******************************************************************************
* These are the methods used to create and delete the NdbOperation objects.
@@ -810,13 +819,12 @@ protected:
int branch_col_null(Uint32 type, Uint32 col, Uint32 Label);
// Handle ATTRINFO signals
- int insertATTRINFO(Uint32 aData);
- int insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength);
-
- int insertKEYINFO(const char* aValue,
- Uint32 aStartPosition,
- Uint32 aKeyLenInByte,
- Uint32 anAttrBitsInLastWord);
+ int insertATTRINFO(Uint32 aData);
+ int insertATTRINFOloop(const Uint32* aDataPtr, Uint32 aLength);
+
+ int insertKEYINFO(const char* aValue,
+ Uint32 aStartPosition,
+ Uint32 aKeyLenInByte);
virtual void setErrorCode(int aErrorCode);
virtual void setErrorCodeAbort(int aErrorCode);
@@ -850,14 +858,18 @@ protected:
Ndb* theNdb; // Point back to the Ndb object.
NdbConnection* theNdbCon; // Point back to the connection object.
NdbOperation* theNext; // Next pointer to operation.
- NdbApiSignal* theTCREQ; // The TC[KEY/INDX]REQ signal object
+
+ union {
+ NdbApiSignal* theTCREQ; // The TC[KEY/INDX]REQ signal object
+ NdbApiSignal* theSCAN_TABREQ;
+ };
+
NdbApiSignal* theFirstATTRINFO; // The first ATTRINFO signal object
NdbApiSignal* theCurrentATTRINFO; // The current ATTRINFO signal object
Uint32 theTotalCurrAI_Len; // The total number of attribute info
// words currently defined
Uint32 theAI_LenInCurrAI; // The number of words defined in the
// current ATTRINFO signal
- NdbApiSignal* theFirstKEYINFO; // The first KEYINFO signal object
NdbApiSignal* theLastKEYINFO; // The first KEYINFO signal object
class NdbLabel* theFirstLabel;
@@ -874,8 +886,8 @@ protected:
Uint32* theKEYINFOptr; // Pointer to where to write KEYINFO
Uint32* theATTRINFOptr; // Pointer to where to write ATTRINFO
- const class NdbTableImpl* m_currentTable; // The current table
- const class NdbTableImpl* m_accessTable;
+ const class NdbTableImpl* m_currentTable; // The current table
+ const class NdbTableImpl* m_accessTable; // Index table (== current for pk)
// Set to TRUE when a tuple key attribute has been defined.
Uint32 theTupleKeyDefined[NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY][3];
@@ -883,18 +895,18 @@ protected:
Uint32 theTotalNrOfKeyWordInSignal; // The total number of
// keyword in signal.
- Uint32 theTupKeyLen; // Length of the tuple key in words
- Uint32 theNoOfTupKeyDefined; // The number of tuple key attributes
- // currently defined
- OperationType theOperationType; // Read Request, Update Req......
-
+ Uint32 theTupKeyLen; // Length of the tuple key in words
+ // left until done
+ Uint8 theNoOfTupKeyLeft; // The number of tuple key attributes
+ OperationType theOperationType; // Read Request, Update Req......
+
LockMode theLockMode; // Can be set to WRITE if read operation
OperationStatus theStatus; // The status of the operation.
+
Uint32 theMagicNumber; // Magic number to verify that object
// is correct
Uint32 theScanInfo; // Scan info bits (take over flag etc)
- Uint32 theDistrKeySize; // Distribution Key size if used
- Uint32 theDistributionGroup; // Distribution Group if used
+ Uint32 theDistributionKey; // Distribution Key size if used
Uint32 theSubroutineSize; // Size of subroutines for interpretation
Uint32 theInitialReadSize; // Size of initial reads for interpretation
@@ -902,14 +914,12 @@ protected:
Uint32 theFinalUpdateSize; // Size of final updates for interpretation
Uint32 theFinalReadSize; // Size of final reads for interpretation
- Uint8 theStartIndicator; // Indicator of whether start operation
- Uint8 theCommitIndicator; // Indicator of whether commit operation
- Uint8 theSimpleIndicator; // Indicator of whether simple operation
- Uint8 theDirtyIndicator; // Indicator of whether dirty operation
- Uint8 theInterpretIndicator; // Indicator of whether interpreted operation
- Uint8 theDistrGroupIndicator; // Indicates whether distribution grp is used
- Uint8 theDistrGroupType; // Type of distribution group used
- Uint8 theDistrKeyIndicator; // Indicates whether distr. key is used
+ Uint8 theStartIndicator; // Indicator of whether start operation
+ Uint8 theCommitIndicator; // Indicator of whether commit operation
+ Uint8 theSimpleIndicator; // Indicator of whether simple operation
+ Uint8 theDirtyIndicator; // Indicator of whether dirty operation
+ Uint8 theInterpretIndicator; // Indicator of whether interpreted operation
+ Int8 theDistrKeyIndicator_; // Indicates whether distr. key is used
Uint16 m_tcReqGSN;
Uint16 m_keyInfoGSN;
@@ -918,6 +928,13 @@ protected:
// Blobs in this operation
NdbBlob* theBlobList;
+ /*
+ * Abort option per operation, used by blobs. Default -1. If set,
+ * overrides abort option on connection level. If set to IgnoreError,
+ * does not cause execute() to return failure. This is different from
+ * IgnoreError on connection level.
+ */
+ Int8 m_abortOption;
};
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -1160,5 +1177,3 @@ NdbOperation::setValue(Uint32 anAttrId, double aPar)
}
#endif
-
-
diff --git a/ndb/include/ndbapi/NdbResultSet.hpp b/ndb/include/ndbapi/NdbResultSet.hpp
index 478daf8aad2..dc0288a380c 100644
--- a/ndb/include/ndbapi/NdbResultSet.hpp
+++ b/ndb/include/ndbapi/NdbResultSet.hpp
@@ -89,17 +89,17 @@ public:
* - 1: if there are no more tuples to scan.
* - 2: if there are no more cached records in NdbApi
*/
- int nextResult(bool fetchAllowed = true);
+ int nextResult(bool fetchAllowed = true, bool forceSend = false);
/**
* Close result set (scan)
*/
- void close();
+ void close(bool forceSend = false);
/**
* Restart
*/
- int restart();
+ int restart(bool forceSend = false);
/**
* Transfer scan operation to an updating transaction. Use this function
diff --git a/ndb/include/ndbapi/NdbScanOperation.hpp b/ndb/include/ndbapi/NdbScanOperation.hpp
index 2e4d173ac75..1bd90f9d8ec 100644
--- a/ndb/include/ndbapi/NdbScanOperation.hpp
+++ b/ndb/include/ndbapi/NdbScanOperation.hpp
@@ -90,11 +90,11 @@ protected:
NdbScanOperation(Ndb* aNdb);
virtual ~NdbScanOperation();
- int nextResult(bool fetchAllowed = true);
+ int nextResult(bool fetchAllowed = true, bool forceSend = false);
virtual void release();
- void closeScan();
- int close_impl(class TransporterFacade*);
+ void closeScan(bool forceSend = false);
+ int close_impl(class TransporterFacade*, bool forceSend = false);
// Overloaded methods from NdbCursorOperation
int executeCursor(int ProcessorId);
@@ -103,6 +103,7 @@ protected:
int init(const NdbTableImpl* tab, NdbConnection* myConnection);
int prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId);
int doSend(int ProcessorId);
+ void checkForceSend(bool forceSend);
virtual void setErrorCode(int aErrorCode);
virtual void setErrorCodeAbort(int aErrorCode);
@@ -114,7 +115,6 @@ protected:
// Scan related variables
Uint32 theParallelism;
Uint32 m_keyInfo;
- NdbApiSignal* theSCAN_TABREQ;
int getFirstATTRINFOScan();
int doSendScan(int ProcessorId);
@@ -127,18 +127,27 @@ protected:
NdbReceiver** m_receivers; // All receivers
Uint32* m_prepared_receivers; // These are to be sent
-
+
+ /**
+ * owned by API/user thread
+ */
Uint32 m_current_api_receiver;
Uint32 m_api_receivers_count;
NdbReceiver** m_api_receivers; // These are currently used by api
+ /**
+ * owned by receiver thread
+ */
Uint32 m_conf_receivers_count; // NOTE needs mutex to access
NdbReceiver** m_conf_receivers; // receive thread puts them here
+ /**
+ * owned by receiver thread
+ */
Uint32 m_sent_receivers_count; // NOTE needs mutex to access
NdbReceiver** m_sent_receivers; // receive thread puts them here
- int send_next_scan(Uint32 cnt, bool close);
+ int send_next_scan(Uint32 cnt, bool close, bool forceSend = false);
void receiver_delivered(NdbReceiver*);
void receiver_completed(NdbReceiver*);
void execCLOSE_SCAN_REP();
@@ -148,7 +157,7 @@ protected:
Uint32 m_ordered;
- int restart();
+ int restart(bool forceSend = false);
};
inline
diff --git a/ndb/include/ndbapi/ndb_cluster_connection.hpp b/ndb/include/ndbapi/ndb_cluster_connection.hpp
index f8e6f25ce73..6fa25caf5d0 100644
--- a/ndb/include/ndbapi/ndb_cluster_connection.hpp
+++ b/ndb/include/ndbapi/ndb_cluster_connection.hpp
@@ -19,7 +19,6 @@
#define CLUSTER_CONNECTION_HPP
class TransporterFacade;
-class LocalConfig;
class ConfigRetriever;
class NdbThread;
@@ -31,14 +30,15 @@ class Ndb_cluster_connection {
public:
Ndb_cluster_connection(const char * connect_string = 0);
~Ndb_cluster_connection();
- int connect(int reconnect= 0);
+ int connect(int no_retries, int retry_delay_in_seconds, int verbose);
int start_connect_thread(int (*connect_callback)(void)= 0);
+ const char *get_connectstring(char *buf, int buf_sz) const;
+ int get_connected_port() const;
+ const char *get_connected_host() const;
private:
friend void* run_ndb_cluster_connection_connect_thread(void*);
void connect_thread();
- char *m_connect_string;
TransporterFacade *m_facade;
- LocalConfig *m_local_config;
ConfigRetriever *m_config_retriever;
NdbThread *m_connect_thread;
int (*m_connect_callback)(void);
diff --git a/ndb/include/ndbapi/ndbapi_limits.h b/ndb/include/ndbapi/ndbapi_limits.h
index 1cf2d9b342d..d1cb135b39d 100644
--- a/ndb/include/ndbapi/ndbapi_limits.h
+++ b/ndb/include/ndbapi/ndbapi_limits.h
@@ -22,12 +22,13 @@
#define NDB_MAX_DATABASE_NAME_SIZE 128
#define NDB_MAX_SCHEMA_NAME_SIZE 128
#define NDB_MAX_TAB_NAME_SIZE 128
-#define NDB_MAX_ATTRIBUTES_IN_TABLE 91
+#define NDB_MAX_ATTR_NAME_SIZE 32
+#define NDB_MAX_ATTRIBUTES_IN_TABLE 128
-#define NDB_MAX_TUPLE_SIZE_IN_WORDS 1023
+#define NDB_MAX_TUPLE_SIZE_IN_WORDS 2013
#define NDB_MAX_KEYSIZE_IN_WORDS 1023
-#define NDB_MAX_KEY_SIZE NDB_MAX_KEYSIZE_IN_WORDS*sizeof(Uint32)
-#define NDB_MAX_TUPLE_SIZE NDB_MAX_TUPLE_SIZE_IN_WORDS*sizeof(uint32)
+#define NDB_MAX_KEY_SIZE (NDB_MAX_KEYSIZE_IN_WORDS*4)
+#define NDB_MAX_TUPLE_SIZE (NDB_MAX_TUPLE_SIZE_IN_WORDS*4)
#define NDB_MAX_ACTIVE_EVENTS 100
#endif
diff --git a/ndb/include/ndbapi/ndberror.h b/ndb/include/ndbapi/ndberror.h
index 5c2d85b82a6..ceb1881a4cc 100644
--- a/ndb/include/ndbapi/ndberror.h
+++ b/ndb/include/ndbapi/ndberror.h
@@ -46,7 +46,8 @@ typedef enum
ndberror_cl_internal_error = 12,
ndberror_cl_function_not_implemented = 13,
ndberror_cl_unknown_error_code = 14,
- ndberror_cl_node_shutdown = 15
+ ndberror_cl_node_shutdown = 15,
+ ndberror_cl_configuration = 16
} ndberror_classification_enum;
diff --git a/ndb/include/mgmcommon/NdbConfig.h b/ndb/include/portlib/NdbConfig.h
index 1bca825ab8d..1bca825ab8d 100644
--- a/ndb/include/mgmcommon/NdbConfig.h
+++ b/ndb/include/portlib/NdbConfig.h
diff --git a/ndb/include/util/Bitmask.hpp b/ndb/include/util/Bitmask.hpp
index bb217adab5f..19aa604e4a1 100644
--- a/ndb/include/util/Bitmask.hpp
+++ b/ndb/include/util/Bitmask.hpp
@@ -105,6 +105,11 @@ public:
static void bitXOR(unsigned size, Uint32 data[], const Uint32 data2[]);
/**
+ * bitXORC - Bitwise (x ^ ~y) into first operand.
+ */
+ static void bitXORC(unsigned size, Uint32 data[], const Uint32 data2[]);
+
+ /**
* contains - Check if all bits set in data2 are set in data
*/
static bool contains(unsigned size, Uint32 data[], const Uint32 data2[]);
@@ -261,6 +266,14 @@ BitmaskImpl::bitXOR(unsigned size, Uint32 data[], const Uint32 data2[])
}
}
+inline void
+BitmaskImpl::bitXORC(unsigned size, Uint32 data[], const Uint32 data2[])
+{
+ for (unsigned i = 0; i < size; i++) {
+ data[i] ^= ~data2[i];
+ }
+}
+
inline bool
BitmaskImpl::contains(unsigned size, Uint32 data[], const Uint32 data2[])
{
@@ -452,6 +465,12 @@ public:
BitmaskPOD<size>& bitXOR(const BitmaskPOD<size>& mask2);
/**
+ * bitXORC - Bitwise (x ^ ~y) into first operand.
+ */
+ static void bitXORC(Uint32 data[], const Uint32 data2[]);
+ BitmaskPOD<size>& bitXORC(const BitmaskPOD<size>& mask2);
+
+ /**
* contains - Check if all bits set in data2 (that) are also set in data (this)
*/
static bool contains(Uint32 data[], const Uint32 data2[]);
@@ -713,6 +732,21 @@ BitmaskPOD<size>::bitXOR(const BitmaskPOD<size>& mask2)
}
template <unsigned size>
+inline void
+BitmaskPOD<size>::bitXORC(Uint32 data[], const Uint32 data2[])
+{
+ BitmaskImpl::bitXORC(size,data, data2);
+}
+
+template <unsigned size>
+inline BitmaskPOD<size>&
+BitmaskPOD<size>::bitXORC(const BitmaskPOD<size>& mask2)
+{
+ BitmaskPOD<size>::bitXORC(rep.data, mask2.rep.data);
+ return *this;
+}
+
+template <unsigned size>
char *
BitmaskPOD<size>::getText(const Uint32 data[], char* buf)
{
diff --git a/ndb/include/util/SocketServer.hpp b/ndb/include/util/SocketServer.hpp
index 3860b9ca84b..2fad991e5f8 100644
--- a/ndb/include/util/SocketServer.hpp
+++ b/ndb/include/util/SocketServer.hpp
@@ -37,7 +37,7 @@ public:
public:
virtual ~Session() {}
virtual void runSession(){}
- virtual void stopSession(){}
+ virtual void stopSession(){ m_stop = true; }
protected:
friend class SocketServer;
friend void* sessionThread_C(void*);
@@ -98,6 +98,8 @@ public:
*/
void stopSessions(bool wait = false);
+ void foreachSession(void (*f)(SocketServer::Session*, void*), void *data);
+
private:
struct SessionInstance {
Service * m_service;
diff --git a/ndb/include/util/md5_hash.hpp b/ndb/include/util/md5_hash.hpp
index 4c3cf239881..b79dce3b5a9 100644
--- a/ndb/include/util/md5_hash.hpp
+++ b/ndb/include/util/md5_hash.hpp
@@ -20,6 +20,15 @@
#include <ndb_types.h>
// External declaration of hash function
-Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words);
+void md5_hash(Uint32 result[4], const Uint64* keybuf, Uint32 no_of_32_words);
+
+inline
+Uint32
+md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
+{
+ Uint32 result[4];
+ md5_hash(result, keybuf, no_of_32_words);
+ return result[0];
+}
#endif
diff --git a/ndb/include/util/ndb_opts.h b/ndb/include/util/ndb_opts.h
new file mode 100644
index 00000000000..f7ae3b5489e
--- /dev/null
+++ b/ndb/include/util/ndb_opts.h
@@ -0,0 +1,63 @@
+/* Copyright (C) 2003 MySQL AB
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#ifndef _NDB_OPTS_H
+#define _NDB_OPTS_H
+
+#include <my_sys.h>
+#include <my_getopt.h>
+#include <mysql_version.h>
+#include <ndb_version.h>
+
+#ifndef DBUG_OFF
+#define NDB_STD_OPTS(prog_name) \
+ { "debug", '#', "Output debug log. Often this is 'd:t:o,filename'.", \
+ 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 }, \
+ { "usage", '?', "Display this help and exit.", \
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \
+ { "help", '?', "Display this help and exit.", \
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \
+ { "version", 'V', "Output version information and exit.", 0, 0, 0, \
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \
+ { "ndb-connectstring", 'c', \
+ "Set connect string for connecting to ndb_mgmd. " \
+ "Syntax: \"[nodeid=<id>;][host=]<hostname>[:<port>]\". " \
+ "Overides specifying entries in NDB_CONNECTSTRING and Ndb.cfg", \
+ (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0, \
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\
+ { "connect-string", 'c', "same as --ndb-connectstring",\
+ (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0, \
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }
+#else
+#define NDB_STD_OPTS(prog_name) \
+ { "usage", '?', "Display this help and exit.", \
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \
+ { "help", '?', "Display this help and exit.", \
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \
+ { "version", 'V', "Output version information and exit.", 0, 0, 0, \
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 }, \
+ { "ndb-connectstring", 'c', \
+ "Set connect string for connecting to ndb_mgmd. " \
+ "Syntax: \"[nodeid=<id>;][host=]<hostname>[:<port>]\". " \
+ "Overides specifying entries in NDB_CONNECTSTRING and Ndb.cfg", \
+ (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0, \
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },\
+ { "connect-string", 'c', "same as --ndb-connectstring",\
+ (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0,\
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 }
+#endif
+
+#endif /*_NDB_OPTS_H */
diff --git a/ndb/src/Makefile.am b/ndb/src/Makefile.am
index bed43438e91..36a4c3f247f 100644
--- a/ndb/src/Makefile.am
+++ b/ndb/src/Makefile.am
@@ -11,8 +11,8 @@ libndbclient_la_LIBADD = \
common/transporter/libtransporter.la \
common/debugger/libtrace.la \
common/debugger/signaldata/libsignaldataprint.la \
- common/mgmcommon/libmgmsrvcommon.la \
mgmapi/libmgmapi.la \
+ common/mgmcommon/libmgmsrvcommon.la \
common/logger/liblogger.la \
common/portlib/libportlib.la \
common/util/libgeneral.la
diff --git a/ndb/src/common/Makefile.am b/ndb/src/common/Makefile.am
index 7fcf2cab636..8733205eca2 100644
--- a/ndb/src/common/Makefile.am
+++ b/ndb/src/common/Makefile.am
@@ -1,4 +1,4 @@
-SUBDIRS = portlib debugger util logger transporter mgmcommon editline
+SUBDIRS = portlib debugger util logger transporter mgmcommon
noinst_LTLIBRARIES = libcommon.la
diff --git a/ndb/src/common/Makefile_old b/ndb/src/common/Makefile_old
deleted file mode 100644
index ebde75bf3ec..00000000000
--- a/ndb/src/common/Makefile_old
+++ /dev/null
@@ -1,15 +0,0 @@
-include .defs.mk
-
-LIB_DIRS := \
- portlib \
- debugger \
- util \
- logger
-
-ifneq ($(USE_EDITLINE), N)
-LIB_DIRS += editline
-endif
-
-DIRS := transporter mgmcommon
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/common/debugger/EventLogger.cpp b/ndb/src/common/debugger/EventLogger.cpp
index 8a09be9a0a7..59be0affcb4 100644
--- a/ndb/src/common/debugger/EventLogger.cpp
+++ b/ndb/src/common/debugger/EventLogger.cpp
@@ -421,6 +421,11 @@ EventLogger::getText(char * m_text, size_t m_text_len,
"%sArbitration check lost - less than 1/2 nodes left",
theNodeId);
break;
+ case ArbitCode::WinNodes:
+ BaseString::snprintf(m_text, m_text_len,
+ "%sArbitration check won - all node groups and more than 1/2 nodes left",
+ theNodeId);
+ break;
case ArbitCode::WinGroups:
BaseString::snprintf(m_text, m_text_len,
"%sArbitration check won - node group majority",
diff --git a/ndb/src/common/debugger/Makefile_old b/ndb/src/common/debugger/Makefile_old
deleted file mode 100644
index ac3a4475a54..00000000000
--- a/ndb/src/common/debugger/Makefile_old
+++ /dev/null
@@ -1,11 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-DIRS := signaldata
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := trace
-
-SOURCES = SignalLoggerManager.cpp DebuggerNames.cpp BlockNames.cpp LogLevel.cpp EventLogger.cpp GrepError.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/common/debugger/signaldata/Makefile_old b/ndb/src/common/debugger/signaldata/Makefile_old
deleted file mode 100644
index bd00667b482..00000000000
--- a/ndb/src/common/debugger/signaldata/Makefile_old
+++ /dev/null
@@ -1,33 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := signaldataprint
-
-SOURCES = TcKeyReq.cpp TcKeyConf.cpp TcKeyRef.cpp \
- TcRollbackRep.cpp \
- TupKey.cpp TupCommit.cpp LqhKey.cpp \
- FsOpenReq.cpp FsCloseReq.cpp FsRef.cpp FsConf.cpp FsReadWriteReq.cpp\
- SignalDataPrint.cpp SignalNames.cpp \
- ContinueB.cpp DihContinueB.cpp NdbfsContinueB.cpp \
- CloseComReqConf.cpp PackedSignal.cpp PrepFailReqRef.cpp \
- GCPSave.cpp DictTabInfo.cpp \
- AlterTable.cpp AlterTab.cpp \
- CreateTrig.cpp AlterTrig.cpp DropTrig.cpp \
- FireTrigOrd.cpp TrigAttrInfo.cpp \
- CreateIndx.cpp AlterIndx.cpp DropIndx.cpp TcIndx.cpp \
- IndxKeyInfo.cpp IndxAttrInfo.cpp \
- FsAppendReq.cpp ScanTab.cpp \
- BackupImpl.cpp BackupSignalData.cpp \
- UtilSequence.cpp UtilPrepare.cpp UtilDelete.cpp UtilExecute.cpp \
- LqhFrag.cpp DropTab.cpp PrepDropTab.cpp LCP.cpp MasterLCP.cpp \
- CopyGCI.cpp SystemError.cpp StartRec.cpp NFCompleteRep.cpp \
- FailRep.cpp DisconnectRep.cpp SignalDroppedRep.cpp \
- SumaImpl.cpp NdbSttor.cpp CreateFragmentation.cpp \
- CntrStart.cpp ReadNodesConf.cpp \
- UtilLock.cpp TuxMaint.cpp TupAccess.cpp AccLock.cpp \
- LqhTrans.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/src/common/debugger/signaldata/ScanTab.cpp b/ndb/src/common/debugger/signaldata/ScanTab.cpp
index 72a4d9f94b9..0755ee0a856 100644
--- a/ndb/src/common/debugger/signaldata/ScanTab.cpp
+++ b/ndb/src/common/debugger/signaldata/ScanTab.cpp
@@ -30,13 +30,14 @@ printSCANTABREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiv
fprintf(output, " apiConnectPtr: H\'%.8x",
sig->apiConnectPtr);
fprintf(output, " requestInfo: H\'%.8x:\n", requestInfo);
- fprintf(output, " Parallellism: %u, Batch: %u LockMode: %u, Keyinfo: %u Holdlock: %u, RangeScan: %u\n",
+ fprintf(output, " Parallellism: %u, Batch: %u LockMode: %u, Keyinfo: %u Holdlock: %u, RangeScan: %u ReadCommitted: %u\n",
sig->getParallelism(requestInfo),
sig->getScanBatch(requestInfo),
sig->getLockMode(requestInfo),
+ sig->getKeyinfoFlag(requestInfo),
sig->getHoldLockFlag(requestInfo),
sig->getRangeScanFlag(requestInfo),
- sig->getKeyinfoFlag(requestInfo));
+ sig->getReadCommittedFlag(requestInfo));
Uint32 keyLen = (sig->attrLenKeyLen >> 16);
Uint32 attrLen = (sig->attrLenKeyLen & 0xFFFF);
diff --git a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
index 3314f0bd097..e879b7b9206 100644
--- a/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
+++ b/ndb/src/common/debugger/signaldata/SignalDataPrint.cpp
@@ -16,65 +16,9 @@
-#include "GlobalSignalNumbers.h"
-#include "signaldata/SignalDataPrint.hpp"
-#include "signaldata/TcKeyReq.hpp"
-#include "signaldata/TcKeyConf.hpp"
-#include "signaldata/TcKeyRef.hpp"
-#include "signaldata/LqhKey.hpp"
-#include "signaldata/TupKey.hpp"
-#include "signaldata/TupCommit.hpp"
-#include "signaldata/FsOpenReq.hpp"
-#include "signaldata/FsCloseReq.hpp"
-#include "signaldata/FsReadWriteReq.hpp"
-#include "signaldata/FsRef.hpp"
-#include "signaldata/FsConf.hpp"
-#include "signaldata/CloseComReqConf.hpp"
-#include "signaldata/PackedSignal.hpp"
-#include "signaldata/PrepFailReqRef.hpp"
-#include "signaldata/DictTabInfo.hpp"
-#include "signaldata/AlterTable.hpp"
-#include "signaldata/AlterTab.hpp"
-#include "signaldata/CreateTrig.hpp"
-#include "signaldata/AlterTrig.hpp"
-#include "signaldata/DropTrig.hpp"
-#include "signaldata/FireTrigOrd.hpp"
-#include "signaldata/TrigAttrInfo.hpp"
-#include "signaldata/CreateIndx.hpp"
-#include "signaldata/AlterIndx.hpp"
-#include "signaldata/DropIndx.hpp"
-#include "signaldata/TcIndx.hpp"
-#include "signaldata/IndxKeyInfo.hpp"
-#include "signaldata/IndxAttrInfo.hpp"
-#include <signaldata/FsAppendReq.hpp>
-#include <signaldata/BackupSignalData.hpp>
-#include <signaldata/BackupImpl.hpp>
-#include <signaldata/UtilSequence.hpp>
-#include <signaldata/UtilPrepare.hpp>
-#include <signaldata/UtilExecute.hpp>
-#include <signaldata/ScanTab.hpp>
-#include <signaldata/ScanFrag.hpp>
-#include <signaldata/LqhFrag.hpp>
-#include <signaldata/LqhTransConf.hpp>
-#include <signaldata/DropTab.hpp>
-#include <signaldata/PrepDropTab.hpp>
-#include <signaldata/LCP.hpp>
-#include <signaldata/MasterLCP.hpp>
-#include <signaldata/CopyGCIReq.hpp>
-#include <signaldata/SystemError.hpp>
-#include <signaldata/StartRec.hpp>
-#include <signaldata/NFCompleteRep.hpp>
-#include <signaldata/SignalDroppedRep.hpp>
-#include <signaldata/FailRep.hpp>
-#include <signaldata/DisconnectRep.hpp>
-#include <signaldata/SumaImpl.hpp>
-#include <signaldata/NdbSttor.hpp>
-#include <signaldata/CreateFragmentation.hpp>
-#include <signaldata/UtilLock.hpp>
-#include <signaldata/CntrStart.hpp>
-#include <signaldata/ReadNodesConf.hpp>
-#include <signaldata/TuxMaint.hpp>
-#include <signaldata/AccLock.hpp>
+#include <GlobalSignalNumbers.h>
+#include <signaldata/SignalData.hpp>
+#include <signaldata/SignalDataPrint.hpp>
/**
* This is the register
@@ -83,6 +27,7 @@
const NameFunctionPair
SignalDataPrintFunctions[] = {
{ GSN_TCKEYREQ, printTCKEYREQ },
+ { GSN_TCINDXREQ, printTCKEYREQ },
{ GSN_TCKEYCONF, printTCKEYCONF },
{ GSN_TCKEYREF, printTCKEYREF },
{ GSN_LQHKEYREQ, printLQHKEYREQ },
@@ -138,14 +83,10 @@ SignalDataPrintFunctions[] = {
{ GSN_ALTER_INDX_REQ, printALTER_INDX_REQ },
{ GSN_ALTER_INDX_CONF, printALTER_INDX_CONF },
{ GSN_ALTER_INDX_REF, printALTER_INDX_REF },
- { GSN_TCINDXREQ, printTCINDXREQ },
{ GSN_TCINDXCONF, printTCINDXCONF },
{ GSN_TCINDXREF, printTCINDXREF },
{ GSN_INDXKEYINFO, printINDXKEYINFO },
{ GSN_INDXATTRINFO, printINDXATTRINFO },
- //{ GSN_TCINDXNEXTREQ, printTCINDXNEXTREQ },
- //{ GSN_TCINDEXNEXTCONF, printTCINDEXNEXTCONF },
- //{ GSN_TCINDEXNEXREF, printTCINDEXNEXREF },
{ GSN_FSAPPENDREQ, printFSAPPENDREQ },
{ GSN_BACKUP_REQ, printBACKUP_REQ },
{ GSN_BACKUP_DATA, printBACKUP_DATA },
@@ -254,9 +195,11 @@ SignalDataPrintFunctions[] = {
,{ 0, 0 }
};
-template class Bitmask<1>;
-template class Bitmask<2>;
-template class Bitmask<4>;
+#include <Bitmask.hpp>
+
template struct BitmaskPOD<1>;
template struct BitmaskPOD<2>;
template struct BitmaskPOD<4>;
+template class Bitmask<1>;
+template class Bitmask<2>;
+template class Bitmask<4>;
diff --git a/ndb/src/common/debugger/signaldata/TcIndx.cpp b/ndb/src/common/debugger/signaldata/TcIndx.cpp
index 6bfa29eff15..b0578f5b646 100644
--- a/ndb/src/common/debugger/signaldata/TcIndx.cpp
+++ b/ndb/src/common/debugger/signaldata/TcIndx.cpp
@@ -18,91 +18,6 @@
#include <signaldata/TcKeyReq.hpp>
#include <BlockNumbers.h>
-bool
-printTCINDXREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){
-
- const TcIndxReq * const sig = (TcIndxReq *) theData;
-
- UintR requestInfo = sig->requestInfo;
- UintR scanInfo = sig->scanInfo;
-
- fprintf(output, " apiConnectPtr: H\'%.8x, senderData: H\'%.8x\n",
- sig->apiConnectPtr, sig->senderData);
-
- fprintf(output, " Operation: %s, Flags: ",
- sig->getOperationType(requestInfo) == ZREAD ? "Read" :
- sig->getOperationType(requestInfo) == ZREAD_EX ? "Read-Ex" :
- sig->getOperationType(requestInfo) == ZUPDATE ? "Update" :
- sig->getOperationType(requestInfo) == ZINSERT ? "Insert" :
- sig->getOperationType(requestInfo) == ZDELETE ? "Delete" :
- sig->getOperationType(requestInfo) == ZWRITE ? "Write" :
- "Unknown");
-
- {
- if(sig->getDirtyFlag(requestInfo)){
- fprintf(output, "Dirty ");
- }
- if(sig->getStartFlag(requestInfo)){
- fprintf(output, "Start ");
- }
- if (TcKeyReq::getExecuteFlag(sig->requestInfo)) {
- fprintf(output, "Execute ");
- }
- if(sig->getCommitFlag(requestInfo)){
- fprintf(output, "Commit, Type = ");
- UintR TcommitType = sig->getCommitType(requestInfo);
- if (TcommitType == TcIndxReq::CommitIfFailFree) {
- fprintf(output, "FailFree ");
- } else if (TcommitType == TcIndxReq::TryCommit) {
- fprintf(output, "TryCommit ");
- } else if (TcommitType == TcIndxReq::CommitAsMuchAsPossible) {
- fprintf(output, "Always ");
- }//if
- }
- if(sig->getSimpleFlag(requestInfo)){
- fprintf(output, "Simple ");
- }
- if(sig->getInterpretedFlag(requestInfo)){
- fprintf(output, "Interpreted ");
- }
- if(sig->getDistributionGroupFlag(requestInfo)){
- fprintf(output, "DGroup = %d ", sig->distrGroupHashValue);
- }
- if(sig->getDistributionKeyFlag(sig->requestInfo)){
- fprintf(output, "DKey = %d ", sig->distributionKeySize);
- }
- fprintf(output, "\n");
- }
-
- const int indexLen = sig->getIndexLength(requestInfo);
- const int attrInThis = sig->getAIInTcIndxReq(requestInfo);
- fprintf(output,
- " indexLen: %d, attrLen: %d, AI in this: %d, indexId: %d, "
- "indexSchemaVer: %d, API Ver: %d\n",
- indexLen, sig->attrLen, attrInThis,
- sig->indexId, sig->indexSchemaVersion, sig->getAPIVersion(scanInfo));
-
- fprintf(output, " transId(1, 2): (H\'%.8x, H\'%.8x)\n -- Variable Data --\n",
- sig->transId1, sig->transId2);
-
- Uint32 restLen = (len - 8);
- const Uint32 * rest = &sig->scanInfo;
- while(restLen >= 7){
- fprintf(output,
- " H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x H\'%.8x\n",
- rest[0], rest[1], rest[2], rest[3],
- rest[4], rest[5], rest[6]);
- restLen -= 7;
- rest += 7;
- }
- if(restLen > 0){
- for(Uint32 i = 0; i<restLen; i++)
- fprintf(output, " H\'%.8x", rest[i]);
- fprintf(output, "\n");
- }
-
- return true;
-}
bool
printTCINDXCONF(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiverBlockNo){
diff --git a/ndb/src/common/debugger/signaldata/TcKeyReq.cpp b/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
index 7304872ff9c..3918bd5db26 100644
--- a/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
+++ b/ndb/src/common/debugger/signaldata/TcKeyReq.cpp
@@ -68,11 +68,8 @@ printTCKEYREQ(FILE * output, const Uint32 * theData, Uint32 len, Uint16 receiver
if(sig->getInterpretedFlag(requestInfo)){
fprintf(output, "Interpreted ");
}
- if(sig->getDistributionGroupFlag(requestInfo)){
- fprintf(output, "DGroup = %d ", sig->distrGroupHashValue);
- }
if(sig->getDistributionKeyFlag(sig->requestInfo)){
- fprintf(output, "DKey = %d ", sig->distributionKeySize);
+ fprintf(output, " d-key");
}
fprintf(output, "\n");
}
diff --git a/ndb/src/common/editline/MANIFEST b/ndb/src/common/editline/MANIFEST
deleted file mode 100644
index dc8b4b36f88..00000000000
--- a/ndb/src/common/editline/MANIFEST
+++ /dev/null
@@ -1,15 +0,0 @@
-File Name Description
---------------------------------------------------------
-README Release notes and copyright
-MANIFEST This shipping list
-Make.os9 OS-9 makefile
-Makefile Unix makefile
-complete.c Filename completion routines
-editline.3 Manual page for editline library
-editline.c Line-editing routines
-editline_internal.h Internal library header file
-os9.h OS-9-specific declarations
-sysos9.c OS-9-specific routines
-sysunix.c Unix-specific routines
-testit.c Test driver
-unix.h Unix-specific declarations
diff --git a/ndb/src/common/editline/Makefile.am b/ndb/src/common/editline/Makefile.am
deleted file mode 100644
index 4f53bdc6326..00000000000
--- a/ndb/src/common/editline/Makefile.am
+++ /dev/null
@@ -1,10 +0,0 @@
-
-noinst_LIBRARIES = libeditline.a
-
-libeditline_a_SOURCES = complete.c editline.c sysunix.c
-
-INCLUDES = -I$(top_srcdir)/include -I$(top_srcdir)/ndb/include
-DEFS = -DANSI_ARROWS -DHAVE_TCGETATTR -DSYS_UNIX
-
-# Don't update the files from bitkeeper
-%::SCCS/s.%
diff --git a/ndb/src/common/editline/Makefile_old b/ndb/src/common/editline/Makefile_old
deleted file mode 100644
index 800df8f0f31..00000000000
--- a/ndb/src/common/editline/Makefile_old
+++ /dev/null
@@ -1,18 +0,0 @@
-include .defs.mk
-
-TYPE :=
-
-ARCHIVE_TARGET := editline
-
-CFLAGS += -DANSI_ARROWS -DHAVE_TCGETATTR -DSYS_UNIX
-
-ifeq ($(NDB_OS), WIN32)
-SOURCES = editline_win32.c
-else
-SOURCES = complete.c editline.c sysunix.c
-endif
-
-DIRS := test
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/src/common/editline/README b/ndb/src/common/editline/README
deleted file mode 100644
index 537c7bd8611..00000000000
--- a/ndb/src/common/editline/README
+++ /dev/null
@@ -1,53 +0,0 @@
---
-NOTE: This version has been modified by Ericsson/Alzato. Please
-see the cvs changelog for more details.
---
-
-$Revision: 1.2 $
-
-This is a line-editing library. It can be linked into almost any
-program to provide command-line editing and recall.
-
-It is call-compatible with the FSF readline library, but it is a
-fraction of the size (and offers fewer features). It does not use
-standard I/O. It is distributed under a "C News-like" copyright.
-
-Configuration is done in the Makefile. Type "make testit" to get
-a small slow shell for testing.
-
-This contains some changes since the posting to comp.sources.misc:
- - Bugfix for completion on absolute pathnames.
- - Better handling of M-n versus showing raw 8bit chars.
- - Better signal handling.
- - Now supports termios/termio/sgttyb ioctl's.
- - Add M-m command to toggle how 8bit data is displayed.
-The following changes, made since the last public release, come from
-J.G. Vons <vons@cesar.crbca1.sinet.slb.com>:
- - History-searching no longer redraws the line wrong
- - Added ESC-ESC as synonym for ESC-?
- - SIGQUIT (normally ^\) now sends a signal, not indicating EOF.
- - Fixed some typo's and unclear wording in the manpage.
- - Fixed completion when all entries shared a common prefix.
- - Fixed some meta-char line-redrawing bugs.
-
-Enjoy,
- Rich $alz
- <rsalz@osf.org>
-
- Copyright 1992,1993 Simmule Turner and Rich Salz. All rights reserved.
-
- This software is not subject to any license of the American Telephone
- and Telegraph Company or of the Regents of the University of California.
-
- Permission is granted to anyone to use this software for any purpose on
- any computer system, and to alter it and redistribute it freely, subject
- to the following restrictions:
- 1. The authors are not responsible for the consequences of use of this
- software, no matter how awful, even if they arise from flaws in it.
- 2. The origin of this software must not be misrepresented, either by
- explicit claim or by omission. Since few users ever read sources,
- credits must appear in the documentation.
- 3. Altered versions must be plainly marked as such, and must not be
- misrepresented as being the original software. Since few users
- ever read sources, credits must appear in the documentation.
- 4. This notice may not be removed or altered.
diff --git a/ndb/src/common/editline/complete.c b/ndb/src/common/editline/complete.c
deleted file mode 100644
index d1f8b1d3ff4..00000000000
--- a/ndb/src/common/editline/complete.c
+++ /dev/null
@@ -1,211 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* -*- c-basic-offset: 4; -*-
-** $Revision: 1.8 $
-**
-** History and file completion functions for editline library.
-*/
-#include "editline_internal.h"
-
-
-/*
-** strcmp-like sorting predicate for qsort.
-*/
-static int
-compare(const void *p1, const void *p2)
-{
- const char **v1;
- const char **v2;
-
- v1 = (const char **)p1;
- v2 = (const char **)p2;
- return strcmp(*v1, *v2);
-}
-
-/*
-** Fill in *avp with an array of names that match file, up to its length.
-** Ignore . and .. .
-*/
-static int
-FindMatches(char *dir, char *file, char ***avp)
-{
- char **av;
- char **new;
- char *p;
- DIR *dp;
- struct dirent *ep;
- size_t ac;
- size_t len;
-
- if ((dp = opendir(dir)) == NULL)
- return 0;
-
- av = NULL;
- ac = 0;
- len = strlen(file);
- while ((ep = readdir(dp)) != NULL) {
- p = ep->d_name;
- if (p[0] == '.' && (p[1] == '\0' || (p[1] == '.' && p[2] == '\0')))
- continue;
- if (len && strncmp(p, file, len) != 0)
- continue;
-
- if ((ac % MEM_INC) == 0) {
- if ((new = malloc(sizeof(char*) * (ac + MEM_INC))) == NULL)
- break;
- if (ac) {
- memcpy(new, av, ac * sizeof (char **));
- free(av);
- }
- *avp = av = new;
- }
-
- if ((av[ac] = strdup(p)) == NULL) {
- if (ac == 0)
- free(av);
- break;
- }
- ac++;
- }
-
- /* Clean up and return. */
- (void)closedir(dp);
- if (ac)
- qsort(av, ac, sizeof (char **), compare);
- return ac;
-}
-
-/*
-** Split a pathname into allocated directory and trailing filename parts.
-*/
-static int
-SplitPath(char *path, char **dirpart, char ** filepart)
-{
- static char DOT[] = ".";
- char *dpart;
- char *fpart;
-
- if ((fpart = strrchr(path, '/')) == NULL) {
- if ((dpart = strdup(DOT)) == NULL)
- return -1;
- if ((fpart = strdup(path)) == NULL) {
- free(dpart);
- return -1;
- }
- }
- else {
- if ((dpart = strdup(path)) == NULL)
- return -1;
- dpart[fpart - path + 1] = '\0';
- if ((fpart = strdup(++fpart)) == NULL) {
- free(dpart);
- return -1;
- }
- }
- *dirpart = dpart;
- *filepart = fpart;
- return 0;
-}
-
-/*
-** Attempt to complete the pathname, returning an allocated copy.
-** Fill in *unique if we completed it, or set it to 0 if ambiguous.
-*/
-char *
-rl_complete(char *pathname,int *unique)
-{
- char **av;
- char *dir;
- char *file;
- char *new;
- char *p;
- size_t ac;
- size_t end;
- size_t i;
- size_t j;
- size_t len;
- size_t new_len;
- size_t p_len;
-
- if (SplitPath(pathname, &dir, &file) < 0)
- return NULL;
- if ((ac = FindMatches(dir, file, &av)) == 0) {
- free(dir);
- free(file);
- return NULL;
- }
-
- p = NULL;
- len = strlen(file);
- if (ac == 1) {
- /* Exactly one match -- finish it off. */
- *unique = 1;
- j = strlen(av[0]) - len + 2;
- p_len = sizeof(char) * (j + 1);
- if ((p = malloc(p_len)) != NULL) {
- memcpy(p, av[0] + len, j);
- new_len = sizeof(char) * (strlen(dir) + strlen(av[0]) + 2);
- new = malloc(new_len);
- if(new != NULL) {
- snprintf(new, new_len, "%s/%s", dir, av[0]);
- rl_add_slash(new, p, p_len);
- free(new);
- }
- }
- }
- else {
- /* Find largest matching substring. */
- for (*unique = 0, i = len, end = strlen(av[0]); i < end; i++)
- for (j = 1; j < ac; j++)
- if (av[0][i] != av[j][i])
- goto breakout;
-breakout:
- if (i > len) {
- j = i - len + 1;
- if ((p = malloc(sizeof(char) * j)) != NULL) {
- memcpy(p, av[0] + len, j);
- p[j - 1] = '\0';
- }
- }
- }
-
- /* Clean up and return. */
- free(dir);
- free(file);
- for (i = 0; i < ac; i++)
- free(av[i]);
- free(av);
- return p;
-}
-
-/*
-** Return all possible completions.
-*/
-int
-rl_list_possib(char *pathname, char ***avp)
-{
- char *dir;
- char *file;
- int ac;
-
- if (SplitPath(pathname, &dir, &file) < 0)
- return 0;
- ac = FindMatches(dir, file, avp);
- free(dir);
- free(file);
- return ac;
-}
diff --git a/ndb/src/common/editline/editline.3 b/ndb/src/common/editline/editline.3
deleted file mode 100644
index 159cc7f87bb..00000000000
--- a/ndb/src/common/editline/editline.3
+++ /dev/null
@@ -1,178 +0,0 @@
-.\" $Revision: 1.1 $
-.TH EDITLINE 3
-.SH NAME
-editline \- command-line editing library with history
-.SH SYNOPSIS
-.nf
-.B "char *"
-.B "readline(prompt)"
-.B " char *prompt;"
-
-.B "void"
-.B "add_history(line)"
-.B " char *line;"
-.fi
-.SH DESCRIPTION
-.I Editline
-is a library that provides an line-editing interface with text recall.
-It is intended to be compatible with the
-.I readline
-library provided by the Free Software Foundation, but much smaller.
-The bulk of this manual page describes the user interface.
-.PP
-The
-.I readline
-routine returns a line of text with the trailing newline removed.
-The data is returned in a buffer allocated with
-.IR malloc (3),
-so the space should be released with
-.IR free (3)
-when the calling program is done with it.
-Before accepting input from the user, the specified
-.I prompt
-is displayed on the terminal.
-.PP
-The
-.I add_history
-routine makes a copy of the specified
-.I line
-and adds it to the internal history list.
-.SS "User Interface"
-A program that uses this library provides a simple emacs-like editing
-interface to its users.
-A line may be edited before it is sent to the calling program by typing either
-control characters or escape sequences.
-A control character, shown as a caret followed by a letter, is typed by
-holding down the ``control'' key while the letter is typed.
-For example, ``^A'' is a control-A.
-An escape sequence is entered by typing the ``escape'' key followed by one or
-more characters.
-The escape key is abbreviated as ``ESC''.
-Note that unlike control keys, case matters in escape sequences; ``ESC\ F''
-is not the same as ``ESC\ f''.
-.PP
-An editing command may be typed anywhere on the line, not just at the
-beginning.
-In addition, a return may also be typed anywhere on the line, not just at
-the end.
-.PP
-Most editing commands may be given a repeat count,
-.IR n ,
-where
-.I n
-is a number.
-To enter a repeat count, type the escape key, the number, and then
-the command to execute.
-For example, ``ESC\ 4\ ^f'' moves forward four characters.
-If a command may be given a repeat count then the text ``[n]'' is given at the
-end of its description.
-.PP
-The following control characters are accepted:
-.RS
-.nf
-.ta \w'ESC DEL 'u
-^A Move to the beginning of the line
-^B Move left (backwards) [n]
-^D Delete character [n]
-^E Move to end of line
-^F Move right (forwards) [n]
-^G Ring the bell
-^H Delete character before cursor (backspace key) [n]
-^I Complete filename (tab key); see below
-^J Done with line (return key)
-^K Kill to end of line (or column [n])
-^L Redisplay line
-^M Done with line (alternate return key)
-^N Get next line from history [n]
-^P Get previous line from history [n]
-^R Search backward (forward if [n]) through history for text;
-\& prefixing the string with a caret (^) forces it to
-\& match only at the beginning of a history line
-^T Transpose characters
-^V Insert next character, even if it is an edit command
-^W Wipe to the mark
-^X^X Exchange current location and mark
-^Y Yank back last killed text
-^[ Start an escape sequence (escape key)
-^]c Move forward to next character ``c''
-^? Delete character before cursor (delete key) [n]
-.fi
-.RE
-.PP
-The following escape sequences are provided.
-.RS
-.nf
-.ta \w'ESC DEL 'u
-ESC\ ^H Delete previous word (backspace key) [n]
-ESC\ DEL Delete previous word (delete key) [n]
-ESC\ ESC Show possible completions; see below
-ESC\ SP Set the mark (space key); see ^X^X and ^Y above
-ESC\ . Get the last (or [n]'th) word from previous line
-ESC\ ? Show possible completions; see below
-ESC\ < Move to start of history
-ESC\ > Move to end of history
-ESC\ b Move backward a word [n]
-ESC\ d Delete word under cursor [n]
-ESC\ f Move forward a word [n]
-ESC\ l Make word lowercase [n]
-ESC\ m Toggle if 8bit chars display as themselves or with
-\& an ``M\-'' prefix
-ESC\ u Make word uppercase [n]
-ESC\ y Yank back last killed text
-ESC\ w Make area up to mark yankable
-ESC\ nn Set repeat count to the number nn
-ESC\ C Read from environment variable ``_C_'', where C is
-\& an uppercase letter
-.fi
-.RE
-.PP
-The
-.I editline
-library has a small macro facility.
-If you type the escape key followed by an uppercase letter,
-.IR C ,
-then the contents of the environment variable
-.I _C_
-are read in as if you had typed them at the keyboard.
-For example, if the variable
-.I _L_
-contains the following:
-.RS
-^A^Kecho '^V^[[H^V^[[2J'^M
-.RE
-Then typing ``ESC L'' will move to the beginning of the line, kill the
-entire line, enter the echo command needed to clear the terminal (if your
-terminal is like a VT-100), and send the line back to the shell.
-.PP
-The
-.I editline
-library also does filename completion.
-Suppose the root directory has the following files in it:
-.RS
-.nf
-.ta \w'core 'u
-bin vmunix
-core vmunix.old
-.fi
-.RE
-If you type ``rm\ /v'' and then the tab key.
-.I Editline
-will then finish off as much of the name as possible by adding ``munix''.
-Because the name is not unique, it will then beep.
-If you type the escape key followed by either a question mark or another
-escape, it will display the two choices.
-If you then type a period and a tab, the library will finish off the filename
-for you:
-.RS
-.nf
-.RI "rm /v[TAB]" munix ".[TAB]" old
-.fi
-.RE
-The tab key is shown by ``[TAB]'' and the automatically-entered text
-is shown in italics.
-.SH "BUGS AND LIMITATIONS"
-Cannot handle lines more than 80 columns.
-.SH AUTHORS
-Simmule R. Turner <uunet.uu.net!capitol!sysgo!simmy>
-and Rich $alz <rsalz@osf.org>.
-Original manual page by DaviD W. Sanderson <dws@ssec.wisc.edu>.
diff --git a/ndb/src/common/editline/editline.c b/ndb/src/common/editline/editline.c
deleted file mode 100644
index 1e4c1ecba76..00000000000
--- a/ndb/src/common/editline/editline.c
+++ /dev/null
@@ -1,1514 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* -*- c-basic-offset: 4; -*-
-** $Revision: 1.6 $
-**
-** Main editing routines for editline library.
-*/
-#include <ndb_global.h>
-
-#include "editline_internal.h"
-#include <signal.h>
-
-/*
-** Manifest constants.
-*/
-#define SCREEN_WIDTH 80
-#define SCREEN_ROWS 24
-#define NO_ARG (-1)
-#define DEL 127
-#define TAB '\t'
-#define CTL(x) ((x) & 0x1F)
-#define ISCTL(x) ((x) && (x) < ' ')
-#define UNCTL(x) ((x) + 64)
-#define META(x) ((x) | 0x80)
-#define ISMETA(x) ((x) & 0x80)
-#define UNMETA(x) ((x) & 0x7F)
-#define MAPSIZE 32
-#define METAMAPSIZE 16
-#if !defined(HIST_SIZE)
-#define HIST_SIZE 20
-#endif /* !defined(HIST_SIZE) */
-
-/*
-** Command status codes.
-*/
-typedef enum _STATUS {
- CSdone, CSeof, CSmove, CSdispatch, CSstay, CSsignal
-} STATUS;
-
-/*
-** The type of case-changing to perform.
-*/
-typedef enum _CASE {
- TOupper, TOlower
-} CASE;
-
-/*
-** Key to command mapping.
-*/
-typedef struct _KEYMAP {
- char Key;
- char Active;
- STATUS (*Function)();
-} KEYMAP;
-
-/*
-** Command history structure.
-*/
-typedef struct _HISTORY {
- int Size;
- int Pos;
- char *Lines[HIST_SIZE];
-} HISTORY;
-
-/*
-** Globals.
-*/
-int rl_eof;
-int rl_erase;
-int rl_intr;
-int rl_kill;
-int rl_quit;
-#if defined(DO_SIGTSTP)
-int rl_susp;
-#endif /* defined(DO_SIGTSTP) */
-
-static char NIL[] = "";
-static const char *Input = NIL;
-static char *Line;
-static const char *Prompt;
-static char *Yanked;
-static char *Screen;
-static char NEWLINE[]= CRLF;
-static HISTORY H;
-static int Repeat;
-static int End;
-static int Mark;
-static int OldPoint;
-static int Point;
-static int PushBack;
-static int Pushed;
-static int Signal;
-static KEYMAP Map[MAPSIZE];
-static KEYMAP MetaMap[METAMAPSIZE];
-static size_t Length;
-static size_t ScreenCount;
-static size_t ScreenSize;
-static char *backspace;
-static int TTYwidth;
-static int TTYrows;
-
-/* Display print 8-bit chars as `M-x' or as the actual 8-bit char? */
-int rl_meta_chars = 1;
-
-/*
-** Declarations.
-*/
-static char *editinput();
-
-#if defined(USE_TERMCAP)
-extern char *getenv();
-extern char *tgetstr();
-extern int tgetent();
-extern int tgetnum();
-#endif /* defined(USE_TERMCAP) */
-
-/*
-** TTY input/output functions.
-*/
-
-static void
-TTYflush()
-{
- if (ScreenCount) {
- (void)write(1, Screen, ScreenCount);
- ScreenCount = 0;
- }
-}
-
-static void
-TTYput(const char c)
-{
- Screen[ScreenCount] = c;
- if (++ScreenCount >= ScreenSize - 1) {
- ScreenSize += SCREEN_INC;
- Screen = realloc(Screen, sizeof(char) * ScreenSize);
- /* XXX what to do if realloc failes? */
- }
-}
-
-static void
-TTYputs(const char *p)
-{
- while (*p)
- TTYput(*p++);
-}
-
-static void
-TTYshow(char c)
-{
- if (c == DEL) {
- TTYput('^');
- TTYput('?');
- }
- else if (c == TAB) {
- /* XXX */
- }
- else if (ISCTL(c)) {
- TTYput('^');
- TTYput(UNCTL(c));
- }
- else if (rl_meta_chars && ISMETA(c)) {
- TTYput('M');
- TTYput('-');
- TTYput(UNMETA(c));
- }
- else
- TTYput(c);
-}
-
-static void
-TTYstring(char *p)
-{
- while (*p)
- TTYshow(*p++);
-}
-
-static int
-TTYget()
-{
- char c;
-
- TTYflush();
- if (Pushed) {
- Pushed = 0;
- return PushBack;
- }
- if (*Input)
- return *Input++;
- return read(0, &c, (size_t)1) == 1 ? c : EOF;
-}
-
-#define TTYback() (backspace ? TTYputs((const char *)backspace) : TTYput('\b'))
-
-static void
-TTYbackn(int n)
-{
- while (--n >= 0)
- TTYback();
-}
-
-static void
-TTYinfo()
-{
- static int init;
-#if defined(USE_TERMCAP)
- char *term;
- char buff[2048];
- char *bp;
- char *p;
-#endif /* defined(USE_TERMCAP) */
-#if defined(TIOCGWINSZ)
- struct winsize W;
-#endif /* defined(TIOCGWINSZ) */
-
- if (init) {
-#if defined(TIOCGWINSZ)
- /* Perhaps we got resized. */
- if (ioctl(0, TIOCGWINSZ, &W) >= 0
- && W.ws_col > 0 && W.ws_row > 0) {
- TTYwidth = (int)W.ws_col;
- TTYrows = (int)W.ws_row;
- }
-#endif /* defined(TIOCGWINSZ) */
- return;
- }
- init++;
-
- TTYwidth = TTYrows = 0;
-#if defined(USE_TERMCAP)
- bp = &buff[0];
- if ((term = getenv("TERM")) == NULL)
- term = "dumb";
- if (tgetent(buff, term) < 0) {
- TTYwidth = SCREEN_WIDTH;
- TTYrows = SCREEN_ROWS;
- return;
- }
- p = tgetstr("le", &bp);
- backspace = p ? strdup(p) : NULL;
- TTYwidth = tgetnum("co");
- TTYrows = tgetnum("li");
-#endif /* defined(USE_TERMCAP) */
-
-#if defined(TIOCGWINSZ)
- if (ioctl(0, TIOCGWINSZ, &W) >= 0) {
- TTYwidth = (int)W.ws_col;
- TTYrows = (int)W.ws_row;
- }
-#endif /* defined(TIOCGWINSZ) */
-
- if (TTYwidth <= 0 || TTYrows <= 0) {
- TTYwidth = SCREEN_WIDTH;
- TTYrows = SCREEN_ROWS;
- }
-}
-
-
-/*
-** Print an array of words in columns.
-*/
-static void
-columns(int ac, char **av)
-{
- char *p;
- int i;
- int j;
- int k;
- int len;
- int skip;
- int longest;
- int cols;
-
- /* Find longest name, determine column count from that. */
- for (longest = 0, i = 0; i < ac; i++)
- if ((j = strlen((char *)av[i])) > longest)
- longest = j;
- cols = TTYwidth / (longest + 3);
-
- TTYputs((const char *)NEWLINE);
- for (skip = ac / cols + 1, i = 0; i < skip; i++) {
- for (j = i; j < ac; j += skip) {
- for (p = av[j], len = strlen((char *)p), k = len; --k >= 0; p++)
- TTYput(*p);
- if (j + skip < ac)
- while (++len < longest + 3)
- TTYput(' ');
- }
- TTYputs((const char *)NEWLINE);
- }
-}
-
-static void
-reposition()
-{
- int i;
- char *p;
-
- TTYput('\r');
- TTYputs((const char *)Prompt);
- for (i = Point, p = Line; --i >= 0; p++)
- TTYshow(*p);
-}
-
-static void
-left(STATUS Change)
-{
- char c;
-
- TTYback();
- if (Point) {
- c = Line[Point - 1];
- if (c == TAB) {
- /* XXX */
- }
- else if (ISCTL(c))
- TTYback();
- else if (rl_meta_chars && ISMETA(c)) {
- TTYback();
- TTYback();
- }
- }
- if (Change == CSmove)
- Point--;
-}
-
-static void
-right(STATUS Change)
-{
- TTYshow(Line[Point]);
- if (Change == CSmove)
- Point++;
-}
-
-static STATUS
-ring_bell()
-{
- TTYput('\07');
- TTYflush();
- return CSstay;
-}
-
-static STATUS
-do_macro(int c)
-{
- char name[4];
-
- name[0] = '_';
- name[1] = c;
- name[2] = '_';
- name[3] = '\0';
-
- if ((Input = (char *)getenv((char *)name)) == NULL) {
- Input = NIL;
- return ring_bell();
- }
- return CSstay;
-}
-
-static STATUS
-do_forward(STATUS move)
-{
- int i;
- char *p;
-
- i = 0;
- do {
- p = &Line[Point];
- for ( ; Point < End && (*p == ' ' || !isalnum((int)*p)); Point++, p++)
- if (move == CSmove)
- right(CSstay);
-
- for (; Point < End && isalnum((int)*p); Point++, p++)
- if (move == CSmove)
- right(CSstay);
-
- if (Point == End)
- break;
- } while (++i < Repeat);
-
- return CSstay;
-}
-
-static STATUS
-do_case(CASE type)
-{
- int i;
- int end;
- int count;
- char *p;
-
- (void)do_forward(CSstay);
- if (OldPoint != Point) {
- if ((count = Point - OldPoint) < 0)
- count = -count;
- Point = OldPoint;
- if ((end = Point + count) > End)
- end = End;
- for (i = Point, p = &Line[i]; i < end; i++, p++) {
- if (type == TOupper) {
- if (islower((int)*p))
- *p = toupper((int)*p);
- }
- else if (isupper((int)*p))
- *p = tolower((int)*p);
- right(CSmove);
- }
- }
- return CSstay;
-}
-
-static STATUS
-case_down_word()
-{
- return do_case(TOlower);
-}
-
-static STATUS
-case_up_word()
-{
- return do_case(TOupper);
-}
-
-static void
-ceol()
-{
- int extras;
- int i;
- char *p;
-
- for (extras = 0, i = Point, p = &Line[i]; i <= End; i++, p++) {
- TTYput(' ');
- if (*p == TAB) {
- /* XXX */
- }
- else if (ISCTL(*p)) {
- TTYput(' ');
- extras++;
- }
- else if (rl_meta_chars && ISMETA(*p)) {
- TTYput(' ');
- TTYput(' ');
- extras += 2;
- }
- }
-
- for (i += extras; i > Point; i--)
- TTYback();
-}
-
-static void
-clear_line()
-{
- Point = -strlen(Prompt);
- TTYput('\r');
- ceol();
- Point = 0;
- End = 0;
- Line[0] = '\0';
-}
-
-static STATUS
-insert_string(char *p)
-{
- size_t len;
- int i;
- char *new;
- char *q;
-
- len = strlen((char *)p);
- if (End + len >= Length) {
- if ((new = malloc(sizeof(char) * (Length + len + MEM_INC))) == NULL)
- return CSstay;
- if (Length) {
- memcpy(new, Line, Length);
- free(Line);
- }
- Line = new;
- Length += len + MEM_INC;
- }
-
- for (q = &Line[Point], i = End - Point; --i >= 0; )
- q[len + i] = q[i];
- memcpy(&Line[Point], p, len);
- End += len;
- Line[End] = '\0';
- TTYstring(&Line[Point]);
- Point += len;
-
- return Point == End ? CSstay : CSmove;
-}
-
-static STATUS
-redisplay()
-{
- TTYputs((const char *)NEWLINE);
- TTYputs((const char *)Prompt);
- TTYstring(Line);
- return CSmove;
-}
-
-static STATUS
-redisplay_no_nl()
-{
- TTYput('\r');
- TTYputs((const char *)Prompt);
- TTYstring(Line);
- return CSmove;
-}
-
-static STATUS
-toggle_meta_mode()
-{
- rl_meta_chars = !rl_meta_chars;
- return redisplay();
-}
-
-
-static char *
-next_hist()
-{
- return H.Pos >= H.Size - 1 ? NULL : H.Lines[++H.Pos];
-}
-
-static char *
-prev_hist()
-{
- return H.Pos == 0 ? NULL : H.Lines[--H.Pos];
-}
-
-static STATUS
-do_insert_hist(char *p)
-{
- if (p == NULL)
- return ring_bell();
- Point = 0;
- reposition();
- ceol();
- End = 0;
- return insert_string(p);
-}
-
-static STATUS
-do_hist(char *(*move)())
-{
- char *p;
- int i;
-
- i = 0;
- do {
- if ((p = (*move)()) == NULL)
- return ring_bell();
- } while (++i < Repeat);
- return do_insert_hist(p);
-}
-
-static STATUS
-h_next()
-{
- return do_hist(next_hist);
-}
-
-static STATUS
-h_prev()
-{
- return do_hist(prev_hist);
-}
-
-static STATUS
-h_first()
-{
- return do_insert_hist(H.Lines[H.Pos = 0]);
-}
-
-static STATUS
-h_last()
-{
- return do_insert_hist(H.Lines[H.Pos = H.Size - 1]);
-}
-
-/*
-** Return zero if pat appears as a substring in text.
-*/
-static int
-substrcmp(char *text, char *pat,int len)
-{
- char c;
-
- if ((c = *pat) == '\0')
- return *text == '\0';
- for ( ; *text; text++)
- if (*text == c && strncmp(text, pat, len) == 0)
- return 0;
- return 1;
-}
-
-static char *
-search_hist(char *search,char *(*move)())
-{
- static char *old_search;
- int len;
- int pos;
- int (*match)();
- char *pat;
-
- /* Save or get remembered search pattern. */
- if (search && *search) {
- if (old_search)
- free(old_search);
- old_search = strdup(search);
- }
- else {
- if (old_search == NULL || *old_search == '\0')
- return NULL;
- search = old_search;
- }
-
- /* Set up pattern-finder. */
- if (*search == '^') {
- match = strncmp;
- pat = (char *)(search + 1);
- }
- else {
- match = substrcmp;
- pat = (char *)search;
- }
- len = strlen(pat);
-
- for (pos = H.Pos; (*move)() != NULL; )
- if ((*match)((char *)H.Lines[H.Pos], pat, len) == 0)
- return H.Lines[H.Pos];
- H.Pos = pos;
- return NULL;
-}
-
-static STATUS
-h_search()
-{
- static int Searching;
- const char *old_prompt;
- char *(*move)();
- char *p;
-
- if (Searching)
- return ring_bell();
- Searching = 1;
-
- clear_line();
- old_prompt = Prompt;
- Prompt = "Search: ";
- TTYputs((const char *)Prompt);
- move = Repeat == NO_ARG ? prev_hist : next_hist;
- p = editinput();
- Searching = 0;
- if (p == NULL && Signal > 0) {
- Signal = 0;
- clear_line();
- Prompt = old_prompt;
- return redisplay_no_nl();
- }
- p = search_hist(p, move);
- clear_line();
- Prompt = old_prompt;
- if (p == NULL) {
- (void)ring_bell();
- return redisplay_no_nl();
- }
- return do_insert_hist(p);
-}
-
-static STATUS
-fd_char()
-{
- int i;
-
- i = 0;
- do {
- if (Point >= End)
- break;
- right(CSmove);
- } while (++i < Repeat);
- return CSstay;
-}
-
-static void
-save_yank(int begin, int i)
-{
- if (Yanked) {
- free(Yanked);
- Yanked = NULL;
- }
-
- if (i < 1)
- return;
-
- if ((Yanked = malloc(sizeof(char) * (i + 1))) != NULL) {
- memcpy(Yanked, &Line[begin], i);
- Yanked[i] = '\0';
- }
-}
-
-static STATUS
-delete_string(int count)
-{
- int i;
- char *p;
-
- if (count <= 0 || End == Point)
- return ring_bell();
-
- if (count == 1 && Point == End - 1) {
- /* Optimize common case of delete at end of line. */
- End--;
- p = &Line[Point];
- i = 1;
- TTYput(' ');
- if (*p == TAB) {
- /* XXX */
- }
- else if (ISCTL(*p)) {
- i = 2;
- TTYput(' ');
- }
- else if (rl_meta_chars && ISMETA(*p)) {
- i = 3;
- TTYput(' ');
- TTYput(' ');
- }
- TTYbackn(i);
- *p = '\0';
- return CSmove;
- }
- if (Point + count > End && (count = End - Point) <= 0)
- return CSstay;
-
- if (count > 1)
- save_yank(Point, count);
-
- ceol();
- for (p = &Line[Point], i = End - (Point + count) + 1; --i >= 0; p++)
- p[0] = p[count];
- End -= count;
- TTYstring(&Line[Point]);
- return CSmove;
-}
-
-static STATUS
-bk_char()
-{
- int i;
-
- i = 0;
- do {
- if (Point == 0)
- break;
- left(CSmove);
- } while (++i < Repeat);
-
- return CSstay;
-}
-
-static STATUS
-bk_del_char()
-{
- int i;
-
- i = 0;
- do {
- if (Point == 0)
- break;
- left(CSmove);
- } while (++i < Repeat);
-
- return delete_string(i);
-}
-
-static STATUS
-kill_line()
-{
- int i;
-
- if (Repeat != NO_ARG) {
- if (Repeat < Point) {
- i = Point;
- Point = Repeat;
- reposition();
- (void)delete_string(i - Point);
- }
- else if (Repeat > Point) {
- right(CSmove);
- (void)delete_string(Repeat - Point - 1);
- }
- return CSmove;
- }
-
- save_yank(Point, End - Point);
- ceol();
- Line[Point] = '\0';
- End = Point;
- return CSstay;
-}
-
-static STATUS
-insert_char(int c)
-{
- STATUS s;
- char buff[2];
- char *p;
- char *q;
- int i;
-
- if (Repeat == NO_ARG || Repeat < 2) {
- buff[0] = c;
- buff[1] = '\0';
- return insert_string(buff);
- }
-
- if ((p = malloc(sizeof(char) * (Repeat + 1))) == NULL)
- return CSstay;
- for (i = Repeat, q = p; --i >= 0; )
- *q++ = c;
- *q = '\0';
- Repeat = 0;
- s = insert_string(p);
- free(p);
- return s;
-}
-
-static STATUS
-meta()
-{
- int c;
- KEYMAP *kp;
-
- if ((c = TTYget()) == EOF)
- return CSeof;
-#if defined(ANSI_ARROWS)
- /* Also include VT-100 arrows. */
- if (c == '[' || c == 'O')
- switch ((int)(c = TTYget())) {
- default: return ring_bell();
- case EOF: return CSeof;
- case 'A': return h_prev();
- case 'B': return h_next();
- case 'C': return fd_char();
- case 'D': return bk_char();
- }
-#endif /* defined(ANSI_ARROWS) */
-
- if (isdigit(c)) {
- for (Repeat = c - '0'; (c = TTYget()) != EOF && isdigit(c); )
- Repeat = Repeat * 10 + c - '0';
- Pushed = 1;
- PushBack = c;
- return CSstay;
- }
-
- if (isupper(c))
- return do_macro(c);
- for (OldPoint = Point, kp = MetaMap; kp < &MetaMap[METAMAPSIZE]; kp++)
- if (kp->Key == c && kp->Active)
- return (*kp->Function)();
-
- return ring_bell();
-}
-
-static STATUS
-emacs(int c)
-{
- STATUS s;
- KEYMAP *kp;
-
-#if 0
- /* This test makes it impossible to enter eight-bit characters when
- * meta-char mode is enabled. */
- if (rl_meta_chars && ISMETA(c)) {
- Pushed = 1;
- PushBack = UNMETA(c);
- return meta();
- }
-#endif /* 0 */
- for (kp = Map; kp < &Map[MAPSIZE]; kp++)
- if (kp->Key == c && kp->Active)
- break;
- s = kp < &Map[MAPSIZE] ? (*kp->Function)() : insert_char((int)c);
- if (!Pushed)
- /* No pushback means no repeat count; hacky, but true. */
- Repeat = NO_ARG;
- return s;
-}
-
-static STATUS
-TTYspecial(int c)
-{
- if (rl_meta_chars && ISMETA(c))
- return CSdispatch;
-
- if (c == rl_erase || c == DEL)
- return bk_del_char();
- if (c == rl_kill) {
- if (Point != 0) {
- Point = 0;
- reposition();
- }
- Repeat = NO_ARG;
- return kill_line();
- }
- if (c == rl_eof && Point == 0 && End == 0)
- return CSeof;
- if (c == rl_intr) {
- Signal = SIGINT;
- return CSsignal;
- }
- if (c == rl_quit) {
- Signal = SIGQUIT;
- return CSsignal;
- }
-#if defined(DO_SIGTSTP)
- if (c == rl_susp) {
- Signal = SIGTSTP;
- return CSsignal;
- }
-#endif /* defined(DO_SIGTSTP) */
-
- return CSdispatch;
-}
-
-static char *
-editinput()
-{
- int c;
-
- Repeat = NO_ARG;
- OldPoint = Point = Mark = End = 0;
- Line[0] = '\0';
-
- Signal = -1;
- while ((c = TTYget()) != EOF)
- switch (TTYspecial(c)) {
- case CSdone:
- return Line;
- case CSeof:
- return NULL;
- case CSsignal:
- return (char *)"";
- case CSmove:
- reposition();
- break;
- case CSdispatch:
- switch (emacs(c)) {
- case CSdone:
- return Line;
- case CSeof:
- return NULL;
- case CSsignal:
- return (char *)"";
- case CSmove:
- reposition();
- break;
- case CSdispatch:
- case CSstay:
- break;
- }
- break;
- case CSstay:
- break;
- }
- return NULL;
-}
-
-static void
-hist_add(char *p)
-{
- int i;
-
- if ((p = strdup(p)) == NULL)
- return;
- if (H.Size < HIST_SIZE)
- H.Lines[H.Size++] = p;
- else {
- free(H.Lines[0]);
- for (i = 0; i < HIST_SIZE - 1; i++)
- H.Lines[i] = H.Lines[i + 1];
- H.Lines[i] = p;
- }
- H.Pos = H.Size - 1;
-}
-
-static char *
-read_redirected()
-{
- int size;
- char *p;
- char *line;
- char *end;
-
- for (size = MEM_INC, p = line = malloc(sizeof(char) * size), end = p + size; ; p++) {
- if (p == end) {
- size += MEM_INC;
- p = line = realloc(line, size);
- end = p + size;
- }
- if (read(0, p, 1) <= 0) {
- /* Ignore "incomplete" lines at EOF, just like we do for a tty. */
- free(line);
- return NULL;
- }
- if (*p == '\n')
- break;
- }
- *p = '\0';
- return line;
-}
-
-/*
-** For compatibility with FSF readline.
-*/
-/* ARGSUSED0 */
-void
-rl_reset_terminal(char *p)
-{
- (void)p; /* Suppress warning */
-}
-
-void
-rl_initialize()
-{
-}
-
-int
-rl_insert(int count, int c)
-{
- if (count > 0) {
- Repeat = count;
- (void)insert_char(c);
- (void)redisplay_no_nl();
- }
- return 0;
-}
-
-int (*rl_event_hook)();
-
-int
-rl_key_action(int c, char flag)
-{
- KEYMAP *kp;
- int size;
-
- (void)flag; /* Suppress warning */
-
- if (ISMETA(c)) {
- kp = MetaMap;
- size = METAMAPSIZE;
- }
- else {
- kp = Map;
- size = MAPSIZE;
- }
- for ( ; --size >= 0; kp++)
- if (kp->Key == c) {
- kp->Active = c ? 1 : 0;
- return 1;
- }
- return -1;
-}
-
-char *
-readline(const char *prompt)
-{
- char *line;
- int s;
-
- if (!isatty(0)) {
- TTYflush();
- return read_redirected();
- }
-
- if (Line == NULL) {
- Length = MEM_INC;
- if ((Line = malloc(sizeof(char) * Length)) == NULL)
- return NULL;
- }
-
- TTYinfo();
- rl_ttyset(0);
- hist_add(NIL);
- ScreenSize = SCREEN_INC;
- Screen = malloc(sizeof(char) * ScreenSize);
- Prompt = prompt ? prompt : (char *)NIL;
- TTYputs((const char *)Prompt);
- if ((line = editinput()) != NULL) {
- line = strdup(line);
- TTYputs((const char *)NEWLINE);
- TTYflush();
- }
- rl_ttyset(1);
- free(Screen);
- free(H.Lines[--H.Size]);
- if (Signal > 0) {
- s = Signal;
- Signal = 0;
- (void)kill(getpid(), s);
- }
- return (char *)line;
-}
-
-void
-add_history(char *p)
-{
- if (p == NULL || *p == '\0')
- return;
-
-#if defined(UNIQUE_HISTORY)
- if (H.Size && strcmp(p, H.Lines[H.Size - 1]) == 0)
- return;
-#endif /* defined(UNIQUE_HISTORY) */
- hist_add((char *)p);
-}
-
-
-static STATUS
-beg_line()
-{
- if (Point) {
- Point = 0;
- return CSmove;
- }
- return CSstay;
-}
-
-static STATUS
-del_char()
-{
- return delete_string(Repeat == NO_ARG ? 1 : Repeat);
-}
-
-static STATUS
-end_line()
-{
- if (Point != End) {
- Point = End;
- return CSmove;
- }
- return CSstay;
-}
-
-/*
-** Return allocated copy of word under cursor, moving cursor after the
-** word.
-*/
-static char *
-find_word()
-{
- static char SEPS[] = "\"#;&|^$=`'{}()<>\n\t ";
- char *p;
- char *new;
- size_t len;
-
- /* Move forward to end of word. */
- p = &Line[Point];
- for ( ; Point < End && strchr(SEPS, (char)*p) == NULL; Point++, p++)
- right(CSstay);
-
- /* Back up to beginning of word. */
- for (p = &Line[Point]; p > Line && strchr(SEPS, (char)p[-1]) == NULL; p--)
- continue;
- len = Point - (p - Line) + 1;
- if ((new = malloc(sizeof(char) * len)) == NULL)
- return NULL;
- memcpy(new, p, len);
- new[len - 1] = '\0';
- return new;
-}
-
-static STATUS
-c_complete()
-{
- char *p;
- char *word;
- int unique;
-
- word = find_word();
- p = (char *)rl_complete((char *)word, &unique);
- if (word)
- free(word);
- if (p && *p) {
- (void)insert_string(p);
- if (!unique)
- (void)ring_bell();
- free(p);
- return redisplay_no_nl();
- }
- return ring_bell();
-}
-
-static STATUS
-c_possible()
-{
- char **av;
- char *word;
- int ac;
-
- word = find_word();
- ac = rl_list_possib((char *)word, (char ***)&av);
- if (word)
- free(word);
- if (ac) {
- columns(ac, av);
- while (--ac >= 0)
- free(av[ac]);
- free(av);
- return redisplay_no_nl();
- }
- return ring_bell();
-}
-
-static STATUS
-accept_line()
-{
- Line[End] = '\0';
- return CSdone;
-}
-
-static STATUS
-transpose()
-{
- char c;
-
- if (Point) {
- if (Point == End)
- left(CSmove);
- c = Line[Point - 1];
- left(CSstay);
- Line[Point - 1] = Line[Point];
- TTYshow(Line[Point - 1]);
- Line[Point++] = c;
- TTYshow(c);
- }
- return CSstay;
-}
-
-static STATUS
-quote()
-{
- int c;
-
- return (c = TTYget()) == EOF ? CSeof : insert_char((int)c);
-}
-
-static STATUS
-wipe()
-{
- int i;
-
- if (Mark > End)
- return ring_bell();
-
- if (Point > Mark) {
- i = Point;
- Point = Mark;
- Mark = i;
- reposition();
- }
-
- return delete_string(Mark - Point);
-}
-
-static STATUS
-mk_set()
-{
- Mark = Point;
- return CSstay;
-}
-
-static STATUS
-exchange()
-{
- int c;
-
- if ((c = TTYget()) != CTL('X'))
- return c == EOF ? CSeof : ring_bell();
-
- if ((c = Mark) <= End) {
- Mark = Point;
- Point = c;
- return CSmove;
- }
- return CSstay;
-}
-
-static STATUS
-yank()
-{
- if (Yanked && *Yanked)
- return insert_string(Yanked);
- return CSstay;
-}
-
-static STATUS
-copy_region()
-{
- if (Mark > End)
- return ring_bell();
-
- if (Point > Mark)
- save_yank(Mark, Point - Mark);
- else
- save_yank(Point, Mark - Point);
-
- return CSstay;
-}
-
-static STATUS
-move_to_char()
-{
- int c;
- int i;
- char *p;
-
- if ((c = TTYget()) == EOF)
- return CSeof;
- for (i = Point + 1, p = &Line[i]; i < End; i++, p++)
- if (*p == c) {
- Point = i;
- return CSmove;
- }
- return CSstay;
-}
-
-static STATUS
-fd_word()
-{
- return do_forward(CSmove);
-}
-
-static STATUS
-fd_kill_word()
-{
- int i;
-
- (void)do_forward(CSstay);
- if (OldPoint != Point) {
- i = Point - OldPoint;
- Point = OldPoint;
- return delete_string(i);
- }
- return CSstay;
-}
-
-static STATUS
-bk_word()
-{
- int i;
- char *p;
-
- i = 0;
- do {
- for (p = &Line[Point]; p > Line && !isalnum((int)p[-1]); p--)
- left(CSmove);
-
- for (; p > Line && p[-1] != ' ' && isalnum((int)p[-1]); p--)
- left(CSmove);
-
- if (Point == 0)
- break;
- } while (++i < Repeat);
-
- return CSstay;
-}
-
-static STATUS
-bk_kill_word()
-{
- (void)bk_word();
- if (OldPoint != Point)
- return delete_string(OldPoint - Point);
- return CSstay;
-}
-
-static int
-argify(char *line, char ***avp)
-{
- char *c;
- char **p;
- char **new;
- int ac;
- int i;
-
- i = MEM_INC;
- if ((*avp = p = malloc(sizeof(char*) * i))== NULL)
- return 0;
-
- for (c = line; isspace((int)*c); c++)
- continue;
- if (*c == '\n' || *c == '\0')
- return 0;
-
- for (ac = 0, p[ac++] = c; *c && *c != '\n'; ) {
- if (isspace((int)*c)) {
- *c++ = '\0';
- if (*c && *c != '\n') {
- if (ac + 1 == i) {
- new = malloc(sizeof(char*) * (i + MEM_INC));
- if (new == NULL) {
- p[ac] = NULL;
- return ac;
- }
- memcpy(new, p, i * sizeof (char **));
- i += MEM_INC;
- free(p);
- *avp = p = new;
- }
- p[ac++] = c;
- }
- }
- else
- c++;
- }
- *c = '\0';
- p[ac] = NULL;
- return ac;
-}
-
-static STATUS
-last_argument()
-{
- char **av;
- char *p;
- STATUS s;
- int ac;
-
- if (H.Size == 1 || (p = H.Lines[H.Size - 2]) == NULL)
- return ring_bell();
-
- if ((p = strdup(p)) == NULL)
- return CSstay;
- ac = argify(p, &av);
-
- if (Repeat != NO_ARG)
- s = Repeat < ac ? insert_string(av[Repeat]) : ring_bell();
- else
- s = ac ? insert_string(av[ac - 1]) : CSstay;
-
- if (ac)
- free(av);
- free(p);
- return s;
-}
-
-static KEYMAP Map[MAPSIZE] = {
- { CTL('@'), 1, ring_bell },
- { CTL('A'), 1, beg_line },
- { CTL('B'), 1, bk_char },
- { CTL('D'), 1, del_char },
- { CTL('E'), 1, end_line },
- { CTL('F'), 1, fd_char },
- { CTL('G'), 1, ring_bell },
- { CTL('H'), 1, bk_del_char },
- { CTL('I'), 1, c_complete },
- { CTL('J'), 1, accept_line },
- { CTL('K'), 1, kill_line },
- { CTL('L'), 1, redisplay },
- { CTL('M'), 1, accept_line },
- { CTL('N'), 1, h_next },
- { CTL('O'), 1, ring_bell },
- { CTL('P'), 1, h_prev },
- { CTL('Q'), 1, ring_bell },
- { CTL('R'), 1, h_search },
- { CTL('S'), 1, ring_bell },
- { CTL('T'), 1, transpose },
- { CTL('U'), 1, ring_bell },
- { CTL('V'), 1, quote },
- { CTL('W'), 1, wipe },
- { CTL('X'), 1, exchange },
- { CTL('Y'), 1, yank },
- { CTL('Z'), 1, ring_bell },
- { CTL('['), 1, meta },
- { CTL(']'), 1, move_to_char },
- { CTL('^'), 1, ring_bell },
- { CTL('_'), 1, ring_bell },
-};
-
-static KEYMAP MetaMap[16]= {
- { CTL('H'), 1, bk_kill_word },
- { CTL('['), 1, c_possible },
- { DEL, 1, bk_kill_word },
- { ' ', 1, mk_set },
- { '.', 1, last_argument },
- { '<', 1, h_first },
- { '>', 1, h_last },
- { '?', 1, c_possible },
- { 'b', 1, bk_word },
- { 'd', 1, fd_kill_word },
- { 'f', 1, fd_word },
- { 'l', 1, case_down_word },
- { 'm', 1, toggle_meta_mode},
- { 'u', 1, case_up_word },
- { 'y', 1, yank },
- { 'w', 1, copy_region },
-};
diff --git a/ndb/src/common/editline/editline_internal.h b/ndb/src/common/editline/editline_internal.h
deleted file mode 100644
index 5ed2b32a873..00000000000
--- a/ndb/src/common/editline/editline_internal.h
+++ /dev/null
@@ -1,46 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* $Revision: 1.2 $
-**
-** Internal header file for editline library.
-*/
-
-#include <ndb_global.h>
-
-#if defined(SYS_UNIX)
-#include "unix.h"
-#endif /* defined(SYS_UNIX) */
-
-#define MEM_INC 64
-#define SCREEN_INC 256
-
-/*
-** Variables and routines internal to this package.
-*/
-extern int rl_eof;
-extern int rl_erase;
-extern int rl_intr;
-extern int rl_kill;
-extern int rl_quit;
-#if defined(DO_SIGTSTP)
-extern int rl_susp;
-#endif /* defined(DO_SIGTSTP) */
-extern char *rl_complete();
-extern int rl_list_possib();
-extern void rl_ttyset();
-extern void rl_add_slash();
-
diff --git a/ndb/src/common/editline/sysunix.c b/ndb/src/common/editline/sysunix.c
deleted file mode 100644
index 000bca78dfc..00000000000
--- a/ndb/src/common/editline/sysunix.c
+++ /dev/null
@@ -1,143 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* $Revision: 1.4 $
-**
-** Unix system-dependant routines for editline library.
-*/
-#include "editline_internal.h"
-
-#if defined(HAVE_TCGETATTR)
-#include <termios.h>
-
-void
-rl_ttyset(int Reset)
-{
- static struct termios old;
- struct termios new;
-
- if (Reset == 0) {
- if (tcgetattr(0, &old) < 0) perror("tcgetattr");
- rl_erase = old.c_cc[VERASE];
- rl_kill = old.c_cc[VKILL];
- rl_eof = old.c_cc[VEOF];
- rl_intr = old.c_cc[VINTR];
- rl_quit = old.c_cc[VQUIT];
-#if defined(DO_SIGTSTP)
- rl_susp = old.c_cc[VSUSP];
-#endif /* defined(DO_SIGTSTP) */
-
- new = old;
- new.c_lflag &= ~(ECHO | ICANON | ISIG);
- new.c_iflag &= ~(ISTRIP | INPCK);
- new.c_cc[VMIN] = 1;
- new.c_cc[VTIME] = 0;
- if (tcsetattr(0, TCSADRAIN, &new) < 0) perror("tcsetattr");
- }
- else
- (void)tcsetattr(0, TCSADRAIN, &old);
-}
-
-#else
-#if defined(HAVE_TERMIO)
-#include <termio.h>
-
-void
-rl_ttyset(int Reset)
-{
- static struct termio old;
- struct termio new;
-
- if (Reset == 0) {
- (void)ioctl(0, TCGETA, &old);
- rl_erase = old.c_cc[VERASE];
- rl_kill = old.c_cc[VKILL];
- rl_eof = old.c_cc[VEOF];
- rl_intr = old.c_cc[VINTR];
- rl_quit = old.c_cc[VQUIT];
-#if defined(DO_SIGTSTP)
- rl_susp = old.c_cc[VSUSP];
-#endif /* defined(DO_SIGTSTP) */
-
- new = old;
- new.c_lflag &= ~(ECHO | ICANON | ISIG);
- new.c_iflag &= ~(ISTRIP | INPCK);
- new.c_cc[VMIN] = 1;
- new.c_cc[VTIME] = 0;
- (void)ioctl(0, TCSETAW, &new);
- }
- else
- (void)ioctl(0, TCSETAW, &old);
-}
-
-#else
-#include <sgtty.h>
-
-void
-rl_ttyset(int Reset)
-{
- static struct sgttyb old_sgttyb;
- static struct tchars old_tchars;
- struct sgttyb new_sgttyb;
- struct tchars new_tchars;
-#if defined(DO_SIGTSTP)
- struct ltchars old_ltchars;
-#endif /* defined(DO_SIGTSTP) */
-
- if (Reset == 0) {
- (void)ioctl(0, TIOCGETP, &old_sgttyb);
- rl_erase = old_sgttyb.sg_erase;
- rl_kill = old_sgttyb.sg_kill;
-
- (void)ioctl(0, TIOCGETC, &old_tchars);
- rl_eof = old_tchars.t_eofc;
- rl_intr = old_tchars.t_intrc;
- rl_quit = old_tchars.t_quitc;
-
-#if defined(DO_SIGTSTP)
- (void)ioctl(0, TIOCGLTC, &old_ltchars);
- rl_susp = old_ltchars.t_suspc;
-#endif /* defined(DO_SIGTSTP) */
-
- new_sgttyb = old_sgttyb;
- new_sgttyb.sg_flags &= ~ECHO;
- new_sgttyb.sg_flags |= RAW;
-#if defined(PASS8)
- new_sgttyb.sg_flags |= PASS8;
-#endif /* defined(PASS8) */
- (void)ioctl(0, TIOCSETP, &new_sgttyb);
-
- new_tchars = old_tchars;
- new_tchars.t_intrc = -1;
- new_tchars.t_quitc = -1;
- (void)ioctl(0, TIOCSETC, &new_tchars);
- }
- else {
- (void)ioctl(0, TIOCSETP, &old_sgttyb);
- (void)ioctl(0, TIOCSETC, &old_tchars);
- }
-}
-#endif /* defined(HAVE_TERMIO) */
-#endif /* defined(HAVE_TCGETATTR) */
-
-void
-rl_add_slash(char *path, char *p, size_t p_len)
-{
- struct stat Sb;
-
- if (stat(path, &Sb) >= 0)
- (void)strlcat(p, S_ISDIR(Sb.st_mode) ? "/" : " ", p_len);
-}
diff --git a/ndb/src/common/editline/test/Makefile b/ndb/src/common/editline/test/Makefile
deleted file mode 100644
index 20229d0aa62..00000000000
--- a/ndb/src/common/editline/test/Makefile
+++ /dev/null
@@ -1,10 +0,0 @@
-include .defs.mk
-
-TYPE := util
-
-BIN_TARGET := editline_test
-BIN_TARGET_ARCHIVES := editline
-
-SOURCES = testit.c
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/common/editline/test/testit.c b/ndb/src/common/editline/test/testit.c
deleted file mode 100644
index 4058f8ae660..00000000000
--- a/ndb/src/common/editline/test/testit.c
+++ /dev/null
@@ -1,55 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/* -*- c-basic-offset: 4; -*-
-** $Revision: 1.5 $
-**
-** A "micro-shell" to test editline library.
-** If given any arguments, commands aren't executed.
-*/
-#include <ndb_global.h>
-#include <editline/editline.h>
-
-int
-main(int argc, char **argv)
-{
- char *prompt;
- char *p;
- int doit;
-
- (void)argv; /* Suppress warning */
-
- doit = argc == 1;
- if ((prompt = getenv("TESTPROMPT")) == NULL)
- prompt = "testit> ";
-
- while ((p = readline(prompt)) != NULL) {
- (void)printf("\t\t\t|%s|\n", p);
- if (doit) {
- if (strncmp(p, "cd ", 3) == 0) {
- if (chdir(&p[3]) < 0)
- perror(&p[3]);
- } else {
- if (system(p) != 0)
- perror(p);
- }
- }
- add_history(p);
- free(p);
- }
-
- return 0;
-}
diff --git a/ndb/src/common/logger/LogHandler.cpp b/ndb/src/common/logger/LogHandler.cpp
index 4fab957fc50..a76cb622878 100644
--- a/ndb/src/common/logger/LogHandler.cpp
+++ b/ndb/src/common/logger/LogHandler.cpp
@@ -117,10 +117,9 @@ LogHandler::parseParams(const BaseString &_params) {
_params.split(v_args, ",");
for(size_t i=0; i < v_args.size(); i++) {
Vector<BaseString> v_param_value;
-
- v_args[i].split(v_param_value, "=", 2);
- if(v_param_value.size() == 2 &&
- !setParam(v_param_value[0], v_param_value[1]))
+ if(v_args[i].split(v_param_value, "=", 2) != 2)
+ ret = false;
+ else if (!setParam(v_param_value[0], v_param_value[1]))
ret = false;
}
diff --git a/ndb/src/common/logger/Logger.cpp b/ndb/src/common/logger/Logger.cpp
index 00a2fae67bc..f6f70fbeff7 100644
--- a/ndb/src/common/logger/Logger.cpp
+++ b/ndb/src/common/logger/Logger.cpp
@@ -169,10 +169,13 @@ Logger::addHandler(const BaseString &logstring) {
size_t i;
Vector<BaseString> logdest;
Vector<LogHandler *>loghandlers;
+ DBUG_ENTER("Logger::addHandler");
logstring.split(logdest, ";");
for(i = 0; i < logdest.size(); i++) {
+ DBUG_PRINT("info",("adding: %s",logdest[i].c_str()));
+
Vector<BaseString> v_type_args;
logdest[i].split(v_type_args, ":", 2);
@@ -191,16 +194,16 @@ Logger::addHandler(const BaseString &logstring) {
handler = new ConsoleLogHandler();
if(handler == NULL)
- return false;
+ DBUG_RETURN(false);
if(!handler->parseParams(params))
- return false;
+ DBUG_RETURN(false);
loghandlers.push_back(handler);
}
for(i = 0; i < loghandlers.size(); i++)
addHandler(loghandlers[i]);
- return true; /* @todo handle errors */
+ DBUG_RETURN(true); /* @todo handle errors */
}
bool
diff --git a/ndb/src/common/logger/Makefile_old b/ndb/src/common/logger/Makefile_old
deleted file mode 100644
index 994eb86ba35..00000000000
--- a/ndb/src/common/logger/Makefile_old
+++ /dev/null
@@ -1,27 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := logger
-
-DIRS := loggertest
-
-SOURCES := Logger.cpp LogHandlerList.cpp LogHandler.cpp \
- ConsoleLogHandler.cpp FileLogHandler.cpp
-
-ifeq ($(NDB_OS), OSE)
-NO_SYSLOG := Y
-endif
-
-ifeq ($(NDB_OS), WIN32)
-NO_SYSLOG := Y
-endif
-
-ifneq ($(NO_SYSLOG), Y)
-SOURCES += SysLogHandler.cpp
-endif
-
-include $(NDB_TOP)/Epilogue.mk
-
-
diff --git a/ndb/src/common/mgmcommon/ConfigRetriever.cpp b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
index d8417ac146a..744412870f5 100644
--- a/ndb/src/common/mgmcommon/ConfigRetriever.cpp
+++ b/ndb/src/common/mgmcommon/ConfigRetriever.cpp
@@ -20,7 +20,6 @@
#include <ConfigRetriever.hpp>
#include <SocketServer.hpp>
-#include "LocalConfig.hpp"
#include <NdbSleep.h>
#include <NdbOut.hpp>
@@ -45,90 +44,67 @@
//****************************************************************************
//****************************************************************************
-ConfigRetriever::ConfigRetriever(LocalConfig &local_config,
+ConfigRetriever::ConfigRetriever(const char * _connect_string,
Uint32 version, Uint32 node_type)
- : _localConfig(local_config)
{
- m_handle= 0;
m_version = version;
m_node_type = node_type;
- _ownNodeId = _localConfig._ownNodeId;
-}
+ _ownNodeId= 0;
+
+ m_handle= ndb_mgm_create_handle();
-ConfigRetriever::~ConfigRetriever(){
+ if (m_handle == 0) {
+ setError(CR_ERROR, "Unable to allocate mgm handle");
+ return;
+ }
+
+ if (ndb_mgm_set_connectstring(m_handle, _connect_string))
+ {
+ setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
+ return;
+ }
+ resetError();
+}
+ConfigRetriever::~ConfigRetriever()
+{
if (m_handle) {
ndb_mgm_disconnect(m_handle);
ndb_mgm_destroy_handle(&m_handle);
}
}
+Uint32
+ConfigRetriever::get_configuration_nodeid() const
+{
+ return ndb_mgm_get_configuration_nodeid(m_handle);
+}
+
+Uint32 ConfigRetriever::get_mgmd_port() const
+{
+ return ndb_mgm_get_connected_port(m_handle);
+}
+
+const char *ConfigRetriever::get_mgmd_host() const
+{
+ return ndb_mgm_get_connected_host(m_handle);
+}
+
+const char *ConfigRetriever::get_connectstring(char *buf, int buf_sz) const
+{
+ return ndb_mgm_get_connectstring(m_handle, buf, buf_sz);
+}
//****************************************************************************
//****************************************************************************
int
-ConfigRetriever::do_connect(int exit_on_connect_failure){
-
- m_mgmd_port= 0;
- m_mgmd_host= 0;
-
- if(!m_handle)
- m_handle= ndb_mgm_create_handle();
-
- if (m_handle == 0) {
- setError(CR_ERROR, "Unable to allocate mgm handle");
- return -1;
- }
-
- int retry = 1;
- int retry_max = 12; // Max number of retry attempts
- int retry_interval= 5; // Seconds between each retry
- while(retry < retry_max){
- Uint32 type = CR_ERROR;
- BaseString tmp;
- for (unsigned int i = 0; i<_localConfig.ids.size(); i++){
- MgmtSrvrId * m = &_localConfig.ids[i];
- DBUG_PRINT("info",("trying %s:%d",
- m->name.c_str(),
- m->port));
- switch(m->type){
- case MgmId_TCP:
- tmp.assfmt("%s:%d", m->name.c_str(), m->port);
- if (ndb_mgm_connect(m_handle, tmp.c_str()) == 0) {
- m_mgmd_port= m->port;
- m_mgmd_host= m->name.c_str();
- DBUG_PRINT("info",("connected to ndb_mgmd at %s:%d",
- m_mgmd_host,
- m_mgmd_port));
- return 0;
- }
- setError(CR_RETRY, ndb_mgm_get_latest_error_desc(m_handle));
- case MgmId_File:
- break;
- }
- }
- if(latestErrorType == CR_RETRY){
- DBUG_PRINT("info",("CR_RETRY"));
- if (exit_on_connect_failure)
- return 1;
- REPORT_WARNING("Failed to retrieve cluster configuration");
- ndbout << "(Cause of failure: " << getErrorString() << ")" << endl;
- ndbout << "Attempt " << retry << " of " << retry_max << ". "
- << "Trying again in "<< retry_interval <<" seconds..."
- << endl << endl;
- NdbSleep_SecSleep(retry_interval);
- } else {
- break;
- }
- retry++;
- }
-
- ndb_mgm_destroy_handle(&m_handle);
- m_handle= 0;
- m_mgmd_port= 0;
- m_mgmd_host= 0;
- return -1;
+ConfigRetriever::do_connect(int no_retries,
+ int retry_delay_in_seconds, int verbose)
+{
+ return
+ (ndb_mgm_connect(m_handle,no_retries,retry_delay_in_seconds,verbose)==0) ?
+ 0 : -1;
}
//****************************************************************************
@@ -140,22 +116,9 @@ ConfigRetriever::getConfig() {
struct ndb_mgm_configuration * p = 0;
- if(m_handle != 0){
+ if(m_handle != 0)
p = getConfig(m_handle);
- } else {
- for (unsigned int i = 0; i<_localConfig.ids.size(); i++){
- MgmtSrvrId * m = &_localConfig.ids[i];
- switch(m->type){
- case MgmId_File:
- p = getConfig(m->name.c_str());
- break;
- case MgmId_TCP:
- break;
- }
- if(p)
- break;
- }
- }
+
if(p == 0)
return 0;
@@ -227,6 +190,16 @@ ConfigRetriever::setError(ErrorType et, const char * s){
latestErrorType = et;
}
+void
+ConfigRetriever::resetError(){
+ setError(CR_NO_ERROR,0);
+}
+
+int
+ConfigRetriever::hasError()
+{
+ return latestErrorType != CR_NO_ERROR;
+}
const char *
ConfigRetriever::getErrorString(){
@@ -238,7 +211,8 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32
char buf[255];
ndb_mgm_configuration_iterator * it;
- it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf, CFG_SECTION_NODE);
+ it = ndb_mgm_create_configuration_iterator((struct ndb_mgm_configuration *)conf,
+ CFG_SECTION_NODE);
if(it == 0){
BaseString::snprintf(buf, 255, "Unable to create config iterator");
@@ -284,8 +258,14 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32
}
if(_type != m_node_type){
- BaseString::snprintf(buf, 255, "Supplied node type(%d) and config node type(%d) "
- " don't match", m_node_type, _type);
+ const char *type_s, *alias_s, *type_s2, *alias_s2;
+ alias_s= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)m_node_type,
+ &type_s);
+ alias_s2= ndb_mgm_get_node_type_alias_string((enum ndb_mgm_node_type)_type,
+ &type_s2);
+ BaseString::snprintf(buf, 255, "This node type %s(%s) and config "
+ "node type %s(%s) don't match for nodeid %d",
+ alias_s, type_s, alias_s2, type_s2, nodeid);
setError(CR_ERROR, buf);
return false;
}
@@ -334,16 +314,23 @@ ConfigRetriever::verifyConfig(const struct ndb_mgm_configuration * conf, Uint32
}
Uint32
-ConfigRetriever::allocNodeId(){
- unsigned nodeid= _ownNodeId;
-
- if(m_handle != 0){
- int res= ndb_mgm_alloc_nodeid(m_handle, m_version, &nodeid, m_node_type);
- if(res != 0) {
- setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
- return 0;
+ConfigRetriever::allocNodeId(int no_retries, int retry_delay_in_seconds)
+{
+ _ownNodeId= 0;
+ if(m_handle != 0)
+ {
+ while (1)
+ {
+ int res= ndb_mgm_alloc_nodeid(m_handle, m_version, m_node_type);
+ if(res >= 0)
+ return _ownNodeId= (Uint32)res;
+ if (no_retries == 0)
+ break;
+ no_retries--;
+ NdbSleep_SecSleep(retry_delay_in_seconds);
}
- }
-
- return _ownNodeId= nodeid;
+ setError(CR_ERROR, ndb_mgm_get_latest_error_desc(m_handle));
+ } else
+ setError(CR_ERROR, "management server handle not initialized");
+ return 0;
}
diff --git a/ndb/src/common/mgmcommon/Makefile.am b/ndb/src/common/mgmcommon/Makefile.am
index ed6a526eb47..a0aca3e68f1 100644
--- a/ndb/src/common/mgmcommon/Makefile.am
+++ b/ndb/src/common/mgmcommon/Makefile.am
@@ -1,14 +1,11 @@
noinst_LTLIBRARIES = libmgmsrvcommon.la
libmgmsrvcommon_la_SOURCES = \
- LocalConfig.cpp \
ConfigRetriever.cpp \
- IPCConfig.cpp NdbConfig.c
+ IPCConfig.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmapi -I$(top_srcdir)/ndb/src/mgmsrv
-DEFS_LOC = -DNDB_BASE_PORT="\"@ndb_port_base@\""
-
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
include $(top_srcdir)/ndb/config/type_mgmapiclient.mk.am
diff --git a/ndb/src/common/mgmcommon/Makefile_old b/ndb/src/common/mgmcommon/Makefile_old
deleted file mode 100644
index c7bfda7e3bf..00000000000
--- a/ndb/src/common/mgmcommon/Makefile_old
+++ /dev/null
@@ -1,29 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi mgmapiclient
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := mgmsrvcommon
-
-# Removed temporary
-DIRS := printConfig
-
-SOURCES = \
- LocalConfig.cpp \
- Config.cpp \
- ConfigInfo.cpp \
- ConfigRetriever.cpp \
- InitConfigFileParser.cpp \
- IPCConfig.cpp
-
-SOURCES.c = NdbConfig.c
-
-CFLAGS_IPCConfig.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
-
-include $(NDB_TOP)/Epilogue.mk
-
-
-
-
-
-
diff --git a/ndb/src/common/portlib/Makefile.am b/ndb/src/common/portlib/Makefile.am
index 6f3a3fe01a9..73125ad918d 100644
--- a/ndb/src/common/portlib/Makefile.am
+++ b/ndb/src/common/portlib/Makefile.am
@@ -5,7 +5,8 @@ noinst_LTLIBRARIES = libportlib.la
libportlib_la_SOURCES = \
NdbCondition.c NdbMutex.c NdbSleep.c NdbTick.c \
NdbEnv.c NdbThread.c NdbHost.c NdbTCP.cpp \
- NdbDaemon.c NdbMem.c
+ NdbDaemon.c NdbMem.c \
+ NdbConfig.c
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_util.mk.am
diff --git a/ndb/src/common/portlib/Makefile_old b/ndb/src/common/portlib/Makefile_old
deleted file mode 100644
index 48f4929a839..00000000000
--- a/ndb/src/common/portlib/Makefile_old
+++ /dev/null
@@ -1,21 +0,0 @@
-include .defs.mk
-
-DIRS :=
-
-ifeq ($(NDB_OS), SOFTOSE)
-DIRS += ose
-else
-ifeq ($(NDB_OS), OSE)
-DIRS += ose
-else
-ifeq ($(NDB_OS), WIN32)
-DIRS += win32
-else
-DIRS += unix
-endif
-endif
-endif
-
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/src/common/mgmcommon/NdbConfig.c b/ndb/src/common/portlib/NdbConfig.c
index e92f8fa8392..8adc4c20dff 100644
--- a/ndb/src/common/mgmcommon/NdbConfig.c
+++ b/ndb/src/common/portlib/NdbConfig.c
@@ -74,7 +74,7 @@ NdbConfig_NdbCfgName(int with_ndb_home){
static
char *get_prefix_buf(int len, int node_id)
{
- char tmp_buf[sizeof("ndb_pid#########")+1];
+ char tmp_buf[sizeof("ndb_pid#############")+1];
char *buf;
if (node_id > 0)
snprintf(tmp_buf, sizeof(tmp_buf), "ndb_%u", node_id);
diff --git a/ndb/src/common/portlib/NdbDaemon.c b/ndb/src/common/portlib/NdbDaemon.c
index c73b5927ff4..3f1c1998501 100644
--- a/ndb/src/common/portlib/NdbDaemon.c
+++ b/ndb/src/common/portlib/NdbDaemon.c
@@ -55,18 +55,21 @@ NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
"%s: lseek failed: %s", lockfile, strerror(errno));
return -1;
}
+#ifdef F_TLOCK
/* Test for lock before becoming daemon */
- if (lockf(lockfd, F_TEST, 0) == -1) {
- if (errno == EACCES || errno == EAGAIN) { /* results may vary */
+ if (lockf(lockfd, F_TLOCK, 0) == -1)
+ {
+ if (errno == EACCES || errno == EAGAIN) { /* results may vary */
snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: already locked by pid=%ld", lockfile, NdbDaemon_DaemonPid);
+ "%s: already locked by pid=%ld", lockfile, NdbDaemon_DaemonPid);
return -1;
}
NdbDaemon_ErrorCode = errno;
snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
- "%s: lock test failed: %s", lockfile, strerror(errno));
+ "%s: lock test failed: %s", lockfile, strerror(errno));
return -1;
}
+#endif
/* Test open log file before becoming daemon */
if (logfile != NULL) {
logfd = open(logfile, O_CREAT|O_WRONLY|O_APPEND, 0644);
@@ -77,6 +80,15 @@ NdbDaemon_Make(const char* lockfile, const char* logfile, unsigned flags)
return -1;
}
}
+#ifdef F_TLOCK
+ if (lockf(lockfd, F_ULOCK, 0) == -1)
+ {
+ snprintf(NdbDaemon_ErrorText, NdbDaemon_ErrorSize,
+ "%s: fail to unlock", lockfile);
+ return -1;
+ }
+#endif
+
/* Fork */
n = fork();
if (n == -1) {
diff --git a/ndb/src/common/portlib/old_dirs/unix/Makefile_old b/ndb/src/common/portlib/old_dirs/unix/Makefile_old
deleted file mode 100644
index 452196d9f08..00000000000
--- a/ndb/src/common/portlib/old_dirs/unix/Makefile_old
+++ /dev/null
@@ -1,27 +0,0 @@
-include .defs.mk
-
-TYPE := util
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := portlib
-
-SOURCES.c = NdbCondition.c \
- NdbMutex.c \
- NdbSleep.c \
- NdbTick.c \
- NdbEnv.c \
- NdbThread.c \
- NdbHost.c \
- NdbTCP.c \
- NdbDaemon.c
-
-ifeq ($(NDB_OS), SOFTOSE)
- SOURCES += NdbMem_SoftOse.cpp
-else
- SOURCES.c += NdbMem.c
-endif
-
-include $(NDB_TOP)/Epilogue.mk
-
-testNdbDaemon: NdbDaemon.c
- $(CC) -o $@ NdbDaemon.c $(CCFLAGS) -DNDB_DAEMON_TEST -L$(NDB_TOP)/lib
diff --git a/ndb/src/common/transporter/Makefile_old b/ndb/src/common/transporter/Makefile_old
deleted file mode 100644
index 372bf640566..00000000000
--- a/ndb/src/common/transporter/Makefile_old
+++ /dev/null
@@ -1,43 +0,0 @@
-include .defs.mk
-
-TYPE := util
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := transporter
-DIRS := basictest perftest
-
-# Source files of non-templated classes (.cpp files)
-SOURCES = \
- Transporter.cpp \
- SendBuffer.cpp \
- TCP_Transporter.cpp \
- TransporterRegistry.cpp \
- Packer.cpp
-
-DIRS := basictest perftest
-
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/kernel) \
- -I$(call fixpath,$(NDB_TOP)/include/transporter)
-
-
-ifeq ($(NDB_SHM), Y)
-SOURCES += SHM_Transporter.cpp
-ifeq ($(NDB_OS), WIN32)
-SOURCES += SHM_Transporter.win32.cpp
-else
-SOURCES += SHM_Transporter.unix.cpp
-endif
-endif
-
-ifeq ($(NDB_SCI), Y)
-SOURCES += SCI_Transporter.cpp
-endif
-
-ifneq ($(findstring OSE, $(NDB_OS)),)
- SOURCES += OSE_Transporter.cpp
- SOURCES += OSE_Receiver.cpp
-endif
-
-
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/common/transporter/TransporterRegistry.cpp b/ndb/src/common/transporter/TransporterRegistry.cpp
index cacbbed00f1..a2fab8f9806 100644
--- a/ndb/src/common/transporter/TransporterRegistry.cpp
+++ b/ndb/src/common/transporter/TransporterRegistry.cpp
@@ -467,8 +467,9 @@ TransporterRegistry::prepareSend(const SignalHeader * const signalHeader,
Transporter *t = theTransporters[nodeId];
if(t != NULL &&
(((ioStates[nodeId] != HaltOutput) && (ioStates[nodeId] != HaltIO)) ||
- (signalHeader->theReceiversBlockNumber == 252))) {
-
+ ((signalHeader->theReceiversBlockNumber == 252) ||
+ (signalHeader->theReceiversBlockNumber == 4002)))) {
+
if(t->isConnected()){
Uint32 lenBytes = t->m_packer.getMessageLength(signalHeader, ptr);
if(lenBytes <= MAX_MESSAGE_SIZE){
@@ -538,8 +539,9 @@ TransporterRegistry::prepareSend(const SignalHeader * const signalHeader,
Transporter *t = theTransporters[nodeId];
if(t != NULL &&
(((ioStates[nodeId] != HaltOutput) && (ioStates[nodeId] != HaltIO)) ||
- (signalHeader->theReceiversBlockNumber == 252))) {
-
+ ((signalHeader->theReceiversBlockNumber == 252)||
+ (signalHeader->theReceiversBlockNumber == 4002)))) {
+
if(t->isConnected()){
Uint32 lenBytes = t->m_packer.getMessageLength(signalHeader, ptr);
if(lenBytes <= MAX_MESSAGE_SIZE){
@@ -550,7 +552,7 @@ TransporterRegistry::prepareSend(const SignalHeader * const signalHeader,
return SEND_OK;
}
-
+
/**
* @note: on linux/i386 the granularity is 10ms
* so sleepTime = 2 generates a 10 ms sleep.
diff --git a/ndb/src/common/util/Makefile.am b/ndb/src/common/util/Makefile.am
index 0235adae7c9..61fd7992002 100644
--- a/ndb/src/common/util/Makefile.am
+++ b/ndb/src/common/util/Makefile.am
@@ -7,8 +7,8 @@ libgeneral_la_SOURCES = \
SocketServer.cpp SocketClient.cpp SocketAuthenticator.cpp\
OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \
NdbSqlUtil.cpp new.cpp \
- uucode.c random.c getarg.c version.c \
- strdup.c strlcat.c strlcpy.c \
+ uucode.c random.c version.c \
+ strdup.c \
ConfigValues.cpp ndb_init.c basestring_vsnprintf.c
include $(top_srcdir)/ndb/config/common.mk.am
diff --git a/ndb/src/common/util/Makefile_old b/ndb/src/common/util/Makefile_old
deleted file mode 100644
index 65093396246..00000000000
--- a/ndb/src/common/util/Makefile_old
+++ /dev/null
@@ -1,28 +0,0 @@
-include .defs.mk
-
-TYPE := util
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := general
-
-SOURCES = File.cpp md5_hash.cpp Properties.cpp socket_io.cpp \
- SimpleProperties.cpp Parser.cpp InputStream.cpp SocketServer.cpp \
- OutputStream.cpp NdbOut.cpp BaseString.cpp Base64.cpp \
- NdbSqlUtil.cpp ConfigValues.cpp new.cpp
-
-SOURCES.c = uucode.c random.c getarg.c version.c
-
-ifeq ($(NDB_OS), OSE)
- SOURCES += NdbErrHnd.cpp
-endif
-ifeq ($(NDB_OS), OSE)
- SOURCES += NdbErrHnd.cpp
-endif
- SOURCES.c += strdup.c strlcat.c strlcpy.c
-
-DIRS := testSimpleProperties testProperties testConfigValues
-
-include $(NDB_TOP)/Epilogue.mk
-
-testNdbSqlUtil: NdbSqlUtil.cpp
- $(CC) -o $@ NdbSqlUtil.cpp $(CCFLAGS) -DNDB_SQL_UTIL_TEST -L$(NDB_TOP)/lib -lportlib -lgeneral
diff --git a/ndb/src/common/util/NdbOut.cpp b/ndb/src/common/util/NdbOut.cpp
index fa74cb364f3..e20119a7987 100644
--- a/ndb/src/common/util/NdbOut.cpp
+++ b/ndb/src/common/util/NdbOut.cpp
@@ -54,7 +54,7 @@ NdbOut&
NdbOut::operator<<(unsigned long int v) { return *this << (Uint64) v; }
NdbOut&
-NdbOut::operator<<(const char* val){ m_out->print("%s", val); return * this; }
+NdbOut::operator<<(const char* val){ m_out->print("%s", val ? val : "(null)"); return * this; }
NdbOut&
NdbOut::operator<<(const void* val){ m_out->print("%p", val); return * this; }
NdbOut&
diff --git a/ndb/src/common/util/NdbSqlUtil.cpp b/ndb/src/common/util/NdbSqlUtil.cpp
index 6e4e5919e43..6798655a71a 100644
--- a/ndb/src/common/util/NdbSqlUtil.cpp
+++ b/ndb/src/common/util/NdbSqlUtil.cpp
@@ -410,7 +410,7 @@ NdbSqlUtil::cmpChar(const void* info, const Uint32* p1, const Uint32* p2, Uint32
CHARSET_INFO* cs = (CHARSET_INFO*)(info);
// length in bytes including null padding to Uint32
uint l1 = (full << 2);
- int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1);
+ int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1, 0);
return k < 0 ? -1 : k > 0 ? +1 : 0;
}
@@ -559,7 +559,7 @@ NdbSqlUtil::cmpText(const void* info, const Uint32* p1, const Uint32* p2, Uint32
CHARSET_INFO* cs = (CHARSET_INFO*)(info);
// length in bytes including null padding to Uint32
uint l1 = (full << 2);
- int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1);
+ int k = (*cs->coll->strnncollsp)(cs, u1.v, l1, u2.v, l1,0);
return k < 0 ? -1 : k > 0 ? +1 : 0;
}
return CmpUnknown;
@@ -582,7 +582,7 @@ NdbSqlUtil::usable_in_pk(Uint32 typeId, const void* info)
cs->cset != 0 &&
cs->coll != 0 &&
cs->coll->strnxfrm != 0 &&
- cs->strxfrm_multiply == 1; // current limitation
+ cs->strxfrm_multiply <= 1; // current limitation
}
break;
case Type::Varchar:
@@ -618,7 +618,7 @@ NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info)
cs->coll != 0 &&
cs->coll->strnxfrm != 0 &&
cs->coll->strnncollsp != 0 &&
- cs->strxfrm_multiply == 1; // current limitation
+ cs->strxfrm_multiply <= 1; // current limitation
}
break;
case Type::Varchar:
@@ -633,7 +633,7 @@ NdbSqlUtil::usable_in_ordered_index(Uint32 typeId, const void* info)
cs->coll != 0 &&
cs->coll->strnxfrm != 0 &&
cs->coll->strnncollsp != 0 &&
- cs->strxfrm_multiply == 1; // current limitation
+ cs->strxfrm_multiply <= 1; // current limitation
}
break;
default:
diff --git a/ndb/src/common/util/SocketServer.cpp b/ndb/src/common/util/SocketServer.cpp
index c3cffa1399b..8bee256684d 100644
--- a/ndb/src/common/util/SocketServer.cpp
+++ b/ndb/src/common/util/SocketServer.cpp
@@ -259,6 +259,15 @@ transfer(NDB_SOCKET_TYPE sock){
}
void
+SocketServer::foreachSession(void (*func)(SocketServer::Session*, void *), void *data)
+{
+ for(int i = m_sessions.size() - 1; i >= 0; i--){
+ (*func)(m_sessions[i].m_session, data);
+ }
+ checkSessions();
+}
+
+void
SocketServer::checkSessions(){
for(int i = m_sessions.size() - 1; i >= 0; i--){
if(m_sessions[i].m_session->m_stopped){
@@ -278,8 +287,10 @@ void
SocketServer::stopSessions(bool wait){
int i;
for(i = m_sessions.size() - 1; i>=0; i--)
- m_sessions[i].m_session->m_stop = true;
-
+ {
+ m_sessions[i].m_session->stopSession();
+ m_sessions[i].m_session->m_stop = true; // to make sure
+ }
for(i = m_services.size() - 1; i>=0; i--)
m_services[i].m_service->stopSessions();
diff --git a/ndb/src/common/util/basestring_vsnprintf.c b/ndb/src/common/util/basestring_vsnprintf.c
index 10932226d18..8a58ca0fe5c 100644
--- a/ndb/src/common/util/basestring_vsnprintf.c
+++ b/ndb/src/common/util/basestring_vsnprintf.c
@@ -18,7 +18,12 @@
#define _XOPEN_SOURCE 500
#include <stdio.h>
#include <basestring_vsnprintf.h>
+#include <my_config.h>
+
+/*
+ #define SNPRINTF_RETURN_TRUNC
+*/
int
basestring_snprintf(char *str, size_t size, const char *format, ...)
{
@@ -30,8 +35,43 @@ basestring_snprintf(char *str, size_t size, const char *format, ...)
return(ret);
}
+#ifdef HAVE_SNPRINTF
+ #define BASESTRING_VSNPRINTF_FUNC(a,b,c,d) vsnprintf(a,b,c,d)
+#else
+ #define SNPRINTF_RETURN_TRUNC
+ /* #define BASESTRING_VSNPRINTF_FUNC(a,b,c,d) my_vsnprintf(a,b,c,d)
+ * we would like to use my_vsnprintf but it does not have enough features
+ * Let's hope vsnprintf works anyways
+ */
+ #define BASESTRING_VSNPRINTF_FUNC(a,b,c,d) vsnprintf(a,b,c,d)
+#endif
+#ifdef SNPRINTF_RETURN_TRUNC
+static char basestring_vsnprintf_buf[16*1024];
+#endif
int
basestring_vsnprintf(char *str, size_t size, const char *format, va_list ap)
{
- return(vsnprintf(str, size, format, ap));
+ if (size == 0)
+ {
+#ifdef SNPRINTF_RETURN_TRUNC
+ return BASESTRING_VSNPRINTF_FUNC(basestring_vsnprintf_buf,
+ sizeof(basestring_vsnprintf_buf),
+ format, ap);
+#else
+ char buf[1];
+ return BASESTRING_VSNPRINTF_FUNC(buf, 1, format, ap);
+#endif
+ }
+ {
+ int ret= BASESTRING_VSNPRINTF_FUNC(str, size, format, ap);
+#ifdef SNPRINTF_RETURN_TRUNC
+ if (ret == size-1 || ret == -1)
+ {
+ ret= BASESTRING_VSNPRINTF_FUNC(basestring_vsnprintf_buf,
+ sizeof(basestring_vsnprintf_buf),
+ format, ap);
+ }
+#endif
+ return ret;
+ }
}
diff --git a/ndb/src/common/util/getarg.3 b/ndb/src/common/util/getarg.3
deleted file mode 100644
index 43aae5d7b31..00000000000
--- a/ndb/src/common/util/getarg.3
+++ /dev/null
@@ -1,315 +0,0 @@
-.\" Copyright (c) 1999 Kungliga Tekniska Högskolan
-.\" $KTH: getarg.3,v 1.1.4.1 2001/07/26 19:54:45 lha Exp $
-.Dd September 24, 1999
-.Dt GETARG 3
-.Os ROKEN
-.Sh NAME
-.Nm getarg ,
-.Nm arg_printusage
-.Nd collect command line options
-.Sh SYNOPSIS
-.Fd #include <getarg.h>
-
-.Ft int
-.Fn getarg "struct getargs *args" "size_t num_args" "int argc" "char **argv" "int *optind"
-
-.Ft void
-.Fn arg_printusage "struct getargs *args" "size_t num_args" "const char *progname" "const char *extra_string"
-
-.Sh DESCRIPTION
-.Fn getarg
-collects any command line options given to a program in an easily used way.
-.Fn arg_printusage
-pretty-prints the available options, with a short help text.
-.Pp
-.Fa args
-is the option specification to use, and it's an array of
-.Fa struct getargs
-elements.
-.Fa num_args
-is the size of
-.Fa args
-(in elements).
-.Fa argc
-and
-.Fa argv
-are the argument count and argument vector to extract option from.
-.Fa optind
-is a pointer to an integer where the index to the last processed
-argument is stored, it must be initialised to the first index (minus
-one) to process (normally 0) before the first call.
-.Pp
-.Fa arg_printusage
-take the same
-.Fa args
-and
-.Fa num_args
-as getarg;
-.Fa progname is the name of the program (to be used in the help text), and
-.Fa extra_string
-is a string to print after the actual options to indicate more
-arguments. The usefulness of this function is realised only be people
-who has used programs that has help strings that doesn't match what
-the code does.
-.Pp
-The
-.Fa getargs
-struct has the following elements.
-
-.Bd -literal
-struct getargs{
- const char *long_name;
- char short_name;
- enum { arg_integer,
- arg_string,
- arg_flag,
- arg_negative_flag,
- arg_strings,
- arg_double,
- arg_collect
- } type;
- void *value;
- const char *help;
- const char *arg_help;
-};
-.Ed
-.Pp
-.Fa long_name
-is the long name of the option, it can be
-.Dv NULL ,
-if you don't want a long name.
-.Fa short_name
-is the characted to use as short option, it can be zero. If the option
-has a value the
-.Fa value
-field gets filled in with that value interpreted as specified by the
-.Fa type
-field.
-.Fa help
-is a longer help string for the option as a whole, if it's
-.Dv NULL
-the help text for the option is omitted (but it's still displayed in
-the synopsis).
-.Fa arg_help
-is a description of the argument, if
-.Dv NULL
-a default value will be used, depending on the type of the option:
-.Pp
-.Bl -hang -width arg_negative_flag
-.It arg_integer
-the argument is a signed integer, and
-.Fa value
-should point to an
-.Fa int .
-.It Fa arg_string
-the argument is a string, and
-.Fa value
-should point to a
-.Fa char* .
-.It Fa arg_flag
-the argument is a flag, and
-.Fa value
-should point to a
-.Fa int .
-It gets filled in with either zero or one, depending on how the option
-is given, the normal case beeing one. Note that if the option isn't
-given, the value isn't altered, so it should be initialised to some
-useful default.
-.It Fa arg_negative_flag
-this is the same as
-.Fa arg_flag
-but it reverses the meaning of the flag (a given short option clears
-the flag), and the synopsis of a long option is negated.
-.It Fa arg_strings
-the argument can be given multiple times, and the values are collected
-in an array;
-.Fa value
-should be a pointer to a
-.Fa struct getarg_strings
-structure, which holds a length and a string pointer.
-.It Fa arg_double
-argument is a double precision floating point value, and
-.Fa value
-should point to a
-.Fa double .
-.It Fa arg_collect
-allows more fine-grained control of the option parsing process.
-.Fa value
-should be a pointer to a
-.Fa getarg_collect_info
-structure:
-.Bd -literal
-typedef int (*getarg_collect_func)(int short_opt,
- int argc,
- char **argv,
- int *optind,
- int *optarg,
- void *data);
-
-typedef struct getarg_collect_info {
- getarg_collect_func func;
- void *data;
-} getarg_collect_info;
-.Ed
-.Pp
-With the
-.Fa func
-member set to a function to call, and
-.Fa data
-to some application specific data. The parameters to the collect function are:
-.Bl -inset
-.It Fa short_flag
-non-zero if this call is via a short option flag, zero otherwise
-.It Fa argc , argv
-the whole argument list
-.It Fa optind
-pointer to the index in argv where the flag is
-.It Fa optarg
-pointer to the index in argv[*optind] where the flag name starts
-.It Fa data
-application specific data
-.El
-.Pp
-You can modify
-.Fa *optind ,
-and
-.Fa *optarg ,
-but to do this correct you (more or less) have to know about the inner
-workings of getarg.
-
-You can skip parts of arguments by increasing
-.Fa *optarg
-(you could
-implement the
-.Fl z Ns Ar 3
-set of flags from
-.Nm gzip
-with this), or whole argument strings by increasing
-.Fa *optind
-(let's say you want a flag
-.Fl c Ar x y z
-to specify a coordinate); if you also have to set
-.Fa *optarg
-to a sane value.
-.Pp
-The collect function should return one of
-.Dv ARG_ERR_NO_MATCH , ARG_ERR_BAD_ARG , ARG_ERR_NO_ARG
-on error, zero otherwise.
-.Pp
-For your convenience there is a function,
-.Fn getarg_optarg ,
-that returns the traditional argument string, and you pass it all
-arguments, sans data, that where given to the collection function.
-.Pp
-Don't use this more this unless you absolutely have to.
-.El
-.Pp
-Option parsing is similar to what
-.Xr getopt
-uses. Short options without arguments can be compressed
-.Pf ( Fl xyz
-is the same as
-.Fl x y z ) ,
-and short
-options with arguments take these as either the rest of the
-argv-string or as the next option
-.Pf ( Fl o Ns Ar foo ,
-or
-.Fl o Ar foo ) .
-.Pp
-Long option names are prefixed with -- (double dash), and the value
-with a = (equal),
-.Fl -foo= Ns Ar bar .
-Long option flags can either be specified as they are
-.Pf ( Fl -help ) ,
-or with an (boolean parsable) option
-.Pf ( Fl -help= Ns Ar yes ,
-.Fl -help= Ns Ar true ,
-or similar), or they can also be negated
-.Pf ( Fl -no-help
-is the same as
-.Fl -help= Ns no ) ,
-and if you're really confused you can do it multiple times
-.Pf ( Fl -no-no-help= Ns Ar false ,
-or even
-.Fl -no-no-help= Ns Ar maybe ) .
-.Sh EXAMPLE
-.Bd -literal
-#include <stdio.h>
-#include <string.h>
-#include <getarg.h>
-
-char *source = "Ouagadougou";
-char *destination;
-int weight;
-int include_catalog = 1;
-int help_flag;
-
-struct getargs args[] = {
- { "source", 's', arg_string, &source,
- "source of shippment", "city" },
- { "destination", 'd', arg_string, &destination,
- "destination of shippment", "city" },
- { "weight", 'w', arg_integer, &weight,
- "weight of shippment", "tons" },
- { "catalog", 'c', arg_negative_flag, &include_catalog,
- "include product catalog" },
- { "help", 'h', arg_flag, &help_flag }
-};
-
-int num_args = sizeof(args) / sizeof(args[0]); /* number of elements in args */
-
-const char *progname = "ship++";
-
-int
-main(int argc, char **argv)
-{
- int optind = 0;
- if (getarg(args, num_args, argc, argv, &optind)) {
- arg_printusage(args, num_args, progname, "stuff...");
- exit (1);
- }
- if (help_flag) {
- arg_printusage(args, num_args, progname, "stuff...");
- exit (0);
- }
- if (destination == NULL) {
- fprintf(stderr, "%s: must specify destination\n", progname);
- exit(1);
- }
- if (strcmp(source, destination) == 0) {
- fprintf(stderr, "%s: destination must be different from source\n");
- exit(1);
- }
- /* include more stuff here ... */
- exit(2);
-}
-.Ed
-.Pp
-The output help output from this program looks like this:
-.Bd -literal
-$ ship++ --help
-Usage: ship++ [--source=city] [-s city] [--destination=city] [-d city]
- [--weight=tons] [-w tons] [--no-catalog] [-c] [--help] [-h] stuff...
--s city, --source=city source of shippment
--d city, --destination=city destination of shippment
--w tons, --weight=tons weight of shippment
--c, --no-catalog include product catalog
-.Ed
-
-.Sh BUGS
-It should be more flexible, so it would be possible to use other more
-complicated option syntaxes, such as what
-.Xr ps 1 ,
-and
-.Xr tar 1 ,
-uses, or the AFS model where you can skip the flag names as long as
-the options come in the correct order.
-.Pp
-Options with multiple arguments should be handled better.
-.Pp
-Should be integreated with SL.
-.Pp
-It's very confusing that the struct you pass in is called getargS.
-.Sh SEE ALSO
-.Xr getopt 3
diff --git a/ndb/src/common/util/getarg.3.ps b/ndb/src/common/util/getarg.3.ps
deleted file mode 100644
index 146fb8e4961..00000000000
--- a/ndb/src/common/util/getarg.3.ps
+++ /dev/null
@@ -1,458 +0,0 @@
-%!PS-Adobe-3.0
-%%Creator: groff version 1.15
-%%CreationDate: Thu Nov 7 12:53:13 2002
-%%DocumentNeededResources: font Times-Roman
-%%+ font Times-Bold
-%%+ font Courier-Bold
-%%+ font Courier-Oblique
-%%+ font Symbol
-%%+ font Courier
-%%DocumentSuppliedResources: procset grops 1.15 0
-%%Pages: 4
-%%PageOrder: Ascend
-%%Orientation: Portrait
-%%EndComments
-%%BeginProlog
-%%BeginResource: procset grops 1.15 0
-/setpacking where{
-pop
-currentpacking
-true setpacking
-}if
-/grops 120 dict dup begin
-/SC 32 def
-/A/show load def
-/B{0 SC 3 -1 roll widthshow}bind def
-/C{0 exch ashow}bind def
-/D{0 exch 0 SC 5 2 roll awidthshow}bind def
-/E{0 rmoveto show}bind def
-/F{0 rmoveto 0 SC 3 -1 roll widthshow}bind def
-/G{0 rmoveto 0 exch ashow}bind def
-/H{0 rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-/I{0 exch rmoveto show}bind def
-/J{0 exch rmoveto 0 SC 3 -1 roll widthshow}bind def
-/K{0 exch rmoveto 0 exch ashow}bind def
-/L{0 exch rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-/M{rmoveto show}bind def
-/N{rmoveto 0 SC 3 -1 roll widthshow}bind def
-/O{rmoveto 0 exch ashow}bind def
-/P{rmoveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-/Q{moveto show}bind def
-/R{moveto 0 SC 3 -1 roll widthshow}bind def
-/S{moveto 0 exch ashow}bind def
-/T{moveto 0 exch 0 SC 5 2 roll awidthshow}bind def
-/SF{
-findfont exch
-[exch dup 0 exch 0 exch neg 0 0]makefont
-dup setfont
-[exch/setfont cvx]cvx bind def
-}bind def
-/MF{
-findfont
-[5 2 roll
-0 3 1 roll
-neg 0 0]makefont
-dup setfont
-[exch/setfont cvx]cvx bind def
-}bind def
-/level0 0 def
-/RES 0 def
-/PL 0 def
-/LS 0 def
-/MANUAL{
-statusdict begin/manualfeed true store end
-}bind def
-/PLG{
-gsave newpath clippath pathbbox grestore
-exch pop add exch pop
-}bind def
-/BP{
-/level0 save def
-1 setlinecap
-1 setlinejoin
-72 RES div dup scale
-LS{
-90 rotate
-}{
-0 PL translate
-}ifelse
-1 -1 scale
-}bind def
-/EP{
-level0 restore
-showpage
-}bind def
-/DA{
-newpath arcn stroke
-}bind def
-/SN{
-transform
-.25 sub exch .25 sub exch
-round .25 add exch round .25 add exch
-itransform
-}bind def
-/DL{
-SN
-moveto
-SN
-lineto stroke
-}bind def
-/DC{
-newpath 0 360 arc closepath
-}bind def
-/TM matrix def
-/DE{
-TM currentmatrix pop
-translate scale newpath 0 0 .5 0 360 arc closepath
-TM setmatrix
-}bind def
-/RC/rcurveto load def
-/RL/rlineto load def
-/ST/stroke load def
-/MT/moveto load def
-/CL/closepath load def
-/FL{
-currentgray exch setgray fill setgray
-}bind def
-/BL/fill load def
-/LW/setlinewidth load def
-/RE{
-findfont
-dup maxlength 1 index/FontName known not{1 add}if dict begin
-{
-1 index/FID ne{def}{pop pop}ifelse
-}forall
-/Encoding exch def
-dup/FontName exch def
-currentdict end definefont pop
-}bind def
-/DEFS 0 def
-/EBEGIN{
-moveto
-DEFS begin
-}bind def
-/EEND/end load def
-/CNT 0 def
-/level1 0 def
-/PBEGIN{
-/level1 save def
-translate
-div 3 1 roll div exch scale
-neg exch neg exch translate
-0 setgray
-0 setlinecap
-1 setlinewidth
-0 setlinejoin
-10 setmiterlimit
-[]0 setdash
-/setstrokeadjust where{
-pop
-false setstrokeadjust
-}if
-/setoverprint where{
-pop
-false setoverprint
-}if
-newpath
-/CNT countdictstack def
-userdict begin
-/showpage{}def
-}bind def
-/PEND{
-clear
-countdictstack CNT sub{end}repeat
-level1 restore
-}bind def
-end def
-/setpacking where{
-pop
-setpacking
-}if
-%%EndResource
-%%IncludeResource: font Times-Roman
-%%IncludeResource: font Times-Bold
-%%IncludeResource: font Courier-Bold
-%%IncludeResource: font Courier-Oblique
-%%IncludeResource: font Symbol
-%%IncludeResource: font Courier
-grops begin/DEFS 1 dict def DEFS begin/u{.001 mul}bind def end/RES 72
-def/PL 792 def/LS false def/ENC0[/asciicircum/asciitilde/Scaron/Zcaron
-/scaron/zcaron/Ydieresis/trademark/quotesingle/.notdef/.notdef/.notdef
-/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
-/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef/.notdef
-/.notdef/.notdef/space/exclam/quotedbl/numbersign/dollar/percent
-/ampersand/quoteright/parenleft/parenright/asterisk/plus/comma/hyphen
-/period/slash/zero/one/two/three/four/five/six/seven/eight/nine/colon
-/semicolon/less/equal/greater/question/at/A/B/C/D/E/F/G/H/I/J/K/L/M/N/O
-/P/Q/R/S/T/U/V/W/X/Y/Z/bracketleft/backslash/bracketright/circumflex
-/underscore/quoteleft/a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y
-/z/braceleft/bar/braceright/tilde/.notdef/quotesinglbase/guillemotleft
-/guillemotright/bullet/florin/fraction/perthousand/dagger/daggerdbl
-/endash/emdash/ff/fi/fl/ffi/ffl/dotlessi/dotlessj/grave/hungarumlaut
-/dotaccent/breve/caron/ring/ogonek/quotedblleft/quotedblright/oe/lslash
-/quotedblbase/OE/Lslash/.notdef/exclamdown/cent/sterling/currency/yen
-/brokenbar/section/dieresis/copyright/ordfeminine/guilsinglleft
-/logicalnot/minus/registered/macron/degree/plusminus/twosuperior
-/threesuperior/acute/mu/paragraph/periodcentered/cedilla/onesuperior
-/ordmasculine/guilsinglright/onequarter/onehalf/threequarters
-/questiondown/Agrave/Aacute/Acircumflex/Atilde/Adieresis/Aring/AE
-/Ccedilla/Egrave/Eacute/Ecircumflex/Edieresis/Igrave/Iacute/Icircumflex
-/Idieresis/Eth/Ntilde/Ograve/Oacute/Ocircumflex/Otilde/Odieresis
-/multiply/Oslash/Ugrave/Uacute/Ucircumflex/Udieresis/Yacute/Thorn
-/germandbls/agrave/aacute/acircumflex/atilde/adieresis/aring/ae/ccedilla
-/egrave/eacute/ecircumflex/edieresis/igrave/iacute/icircumflex/idieresis
-/eth/ntilde/ograve/oacute/ocircumflex/otilde/odieresis/divide/oslash
-/ugrave/uacute/ucircumflex/udieresis/yacute/thorn/ydieresis]def
-/Courier@0 ENC0/Courier RE/Courier-Oblique@0 ENC0/Courier-Oblique RE
-/Courier-Bold@0 ENC0/Courier-Bold RE/Times-Bold@0 ENC0/Times-Bold RE
-/Times-Roman@0 ENC0/Times-Roman RE
-%%EndProlog
-%%Page: 1 1
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF(GET)72 48 Q -.834(ARG \( 3 \))-.93 F
-(OpenBSD Programmer')111.062 E 2.5(sM)-.55 G 108.562(anual GET)-2.5 F
--.834(ARG \( 3 \))-.93 F/F1 10/Times-Bold@0 SF -.2(NA)72 108 S(ME).2 E
-/F2 10/Courier-Bold@0 SF(getarg)102 120 Q F0(,)A F2(arg_printusage)2.5 E
-F0 2.5<ad63>2.5 G(ollect command line options)-2.5 E F1(SYNOPSIS)72 144
-Q F2(#include <getarg.h>)102 156 Q/F3 10/Courier-Oblique@0 SF(int)102
-186 Q F2(getarg)102 198 Q F0(\()A F3(struct getargs)A/F4 10/Symbol SF(*)
-6 E F3(args)A F0(,)1.666 E F3(size_t num_args)4.166 E F0(,)1.666 E F3
-(int argc)4.166 E F0(,)1.666 E F3(char)4.166 E F4(**)6 E F3(argv)A F0(,)
-1.666 E F3(int)151.666 210 Q F4(*)6 E F3(optind)A F0(\);)A F3(void)102
-240 Q F2(arg_printusage)102 252 Q F0(\()A F3(struct getargs)A F4(*)6 E
-F3(args)A F0(,)1.666 E F3(size_t num_args)4.166 E F0(,)1.666 E F3
-(const char)4.166 E F4(*)6 E F3(progname)A F0(,)1.666 E F3(const char)
-151.666 264 Q F4(*)6 E F3(extra_string)A F0(\);)A F1(DESCRIPTION)72 300
-Q F2(getarg)102 312 Q F0 2.721 1.666(\(\) c)D 6.053(ollects an)-1.666 F
-8.553(yc)-.15 G 6.053(ommand line options gi)-8.553 F -.15(ve)-.25 G
-8.552(nt).15 G 8.552(oap)-8.552 G 6.052(rogram in an easily used w)
--8.552 F(ay)-.1 E(.)-.65 E F2(arg_printusage)102 324 Q F0 -3.332 1.666
-(\(\) p)D(retty-prints the a)-1.666 E -.25(va)-.2 G
-(ilable options, with a short help te).25 E(xt.)-.15 E F3(args)102 342 Q
-F0 .855(is the option speci\214cation to use, and it')3.355 F 3.356(sa)
--.55 G 3.356(na)-3.356 G .856(rray of)-3.356 F F3 .856(struct getargs)
-3.356 F F0(elements.)3.356 E F3(num_args)5.856 E F0(is)3.356 E .344
-(the size of)102 354 R F3(args)2.844 E F0 .344(\(in elements\).)2.844 F
-F3(argc)5.344 E F0(and)2.844 E F3(argv)2.844 E F0 .344(are the ar)2.844
-F .344(gument count and ar)-.18 F .344(gument v)-.18 F .344(ector to e)
--.15 F .343(xtract op-)-.15 F 1.127(tion from.)102 366 R F3(optind)6.127
-E F0 1.127(is a pointer to an inte)3.627 F 1.127(ger where the inde)-.15
-F 3.627(xt)-.15 G 3.628(ot)-3.627 G 1.128(he last processed ar)-3.628 F
-1.128(gument is stored, it)-.18 F
-(must be initialised to the \214rst inde)102 378 Q 2.5(x\()-.15 G
-(minus one\) to process \(normally 0\) before the \214rst call.)-2.5 E
-F3(arg_printusage)102 396 Q F0(tak)4.178 E 4.178(et)-.1 G 1.678(he same)
--4.178 F F3(args)4.178 E F0(and)4.178 E F3(num_args)4.178 E F0 1.678
-(as getar)4.178 F(g;)-.18 E F3 1.677(progname is the name of)4.178 F
-6.381(the program \(to be)102 408 R F0(progname0)12.381 E F3(0)12.381 E
-F0(progname1)A F3(1)12.381 E F0(progname2)A F3(2)12.382 E F0(progname3)A
-F3(3)12.382 E F0(progname4)A F3(4)102 420 Q F0(progname5)A F3
-(extra_string)3.404 E F0 .904
-(is a string to print after the actual options to indicate more ar)3.404
-F .904(guments. The)-.18 F .025(usefulness of this function is realised\
- only be people who has used programs that has help strings that doesn')
-102 432 R(t)-.18 E(match what the code does.)102 444 Q(The)102 462 Q F3
-(getargs)2.5 E F0(struct has the follo)2.5 E(wing elements.)-.25 E/F5 10
-/Courier@0 SF(struct getargs{)102 504 Q(const char)126 516 Q F4(*)6 E F5
-(long_name;)A(char short_name;)126 528 Q(enum { arg_integer,)126 540 Q
-(arg_string,)165 552 Q(arg_flag,)165 564 Q(arg_negative_flag,)165 576 Q
-(arg_strings,)165 588 Q(arg_double,)165 600 Q(arg_collect)168 612 Q 6
-(}t)126 624 S(ype;)-6 E(void)126 636 Q F4(*)6 E F5(value;)A(const char)
-126 648 Q F4(*)6 E F5(help;)A(const char)126 660 Q F4(*)6 E F5
-(arg_help;)A(};)102 672 Q F3(long_name)102 690 Q F0 .207
-(is the long name of the option, it can be)2.707 F F5(NULL)2.706 E F0
-2.706(,i)C 2.706(fy)-2.706 G .206(ou don')-2.706 F 2.706(tw)-.18 G .206
-(ant a long name.)-2.806 F F3(short_name)5.206 E F0 .397(is the charact\
-ed to use as short option, it can be zero. If the option has a v)102 702
-R .398(alue the)-.25 F F3(value)2.898 E F0 .398
-(\214eld gets \214lled in)2.898 F -.4(RO)77 750 S 152.325(KEN September)
-.4 F(24, 1999)2.5 E(1)188.865 E EP
-%%Page: 2 2
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF(GET)72 48 Q -.834(ARG \( 3 \))-.93 F
-(OpenBSD Programmer')111.062 E 2.5(sM)-.55 G 108.562(anual GET)-2.5 F
--.834(ARG \( 3 \))-.93 F .737(with that v)102 96 R .737
-(alue interpreted as speci\214ed by the)-.25 F/F1 10/Courier-Oblique@0
-SF(type)3.237 E F0(\214eld.)3.237 E F1(help)5.737 E F0 .737
-(is a longer help string for the option as a)3.237 F 2.833
-(whole, if it')102 108 R(s)-.55 E/F2 10/Courier@0 SF(NULL)5.333 E F0
-2.833(the help te)5.333 F 2.833(xt for the option is omitted \(b)-.15 F
-2.834(ut it')-.2 F 5.334(ss)-.55 G 2.834
-(till displayed in the synopsis\).)-5.334 F F1(arg_help)102 120 Q F0
-.391(is a description of the ar)2.891 F .391(gument, if)-.18 F F2(NULL)
-2.891 E F0 2.891(ad)2.891 G(ef)-2.891 E .39(ault v)-.1 F .39
-(alue will be used, depending on the type of)-.25 F(the option:)102 132
-Q(ar)102 150 Q(g_inte)-.18 E 59.29(ger the)-.15 F(ar)2.5 E
-(gument is a signed inte)-.18 E(ger)-.15 E 2.5(,a)-.4 G(nd)-2.5 E F1
-(value)2.5 E F0(should point to an)2.5 E F1(int)2.5 E F0(.)A F1
-(arg_string)102 168 Q F0(the ar)47 E(gument is a string, and)-.18 E F1
-(value)2.5 E F0(should point to a)2.5 E F1(char)2.5 E/F3 10/Symbol SF(*)
-A F0(.)A F1(arg_flag)102 186 Q F0 .4(the ar)59 F .4
-(gument is a \215ag, and)-.18 F F1(value)2.9 E F0 .4(should point to a)
-2.9 F F1(int)2.9 E F0 2.9(.I)C 2.9(tg)-2.9 G .4
-(ets \214lled in with ei-)-2.9 F 1.154
-(ther zero or one, depending on ho)209 198 R 3.654(wt)-.25 G 1.153
-(he option is gi)-3.654 F -.15(ve)-.25 G 1.153
-(n, the normal case beeing).15 F .526(one. Note that if the option isn')
-209 210 R 3.026(tg)-.18 G -2.15 -.25(iv e)-3.026 H .526(n, the v).25 F
-.526(alue isn')-.25 F 3.026(ta)-.18 G .527(ltered, so it should be ini-)
--3.026 F(tialised to some useful def)209 222 Q(ault.)-.1 E F1
-(arg_negative_flag)102 240 Q F0 .058(this is the same as)2.558 F F1
-(arg_flag)2.558 E F0 -.2(bu)2.558 G 2.558(ti).2 G 2.558(tr)-2.558 G
--2.15 -.25(ev e)-2.558 H .057(rses the meaning of the \215ag \(a gi).25
-F -.15(ve)-.25 G 2.557(ns).15 G(hort)-2.557 E
-(option clears the \215ag\), and the synopsis of a long option is ne)209
-252 Q -.05(ga)-.15 G(ted.).05 E F1(arg_strings)102 270 Q F0 .195(the ar)
-41 F .195(gument can be gi)-.18 F -.15(ve)-.25 G 2.695(nm).15 G .195
-(ultiple times, and the v)-2.695 F .195
-(alues are collected in an array;)-.25 F F1(value)209 282 Q F0 .947
-(should be a pointer to a)3.447 F F1 .947(struct getarg_strings)3.447 F
-F0 .947(structure, which)3.447 F(holds a length and a string pointer)209
-294 Q(.)-.55 E F1(arg_double)102 312 Q F0(ar)47 E .538
-(gument is a double precision \215oating point v)-.18 F .539(alue, and)
--.25 F F1(value)3.039 E F0 .539(should point to a)3.039 F F1(double)209
-324 Q F0(.)A F1(arg_collect)102 342 Q F0(allo)41 E .345
-(ws more \214ne-grained control of the option parsing process.)-.25 F F1
-(value)5.344 E F0 .344(should be)2.844 F 2.5(ap)209 354 S(ointer to a)
--2.5 E F1(getarg_collect_info)2.5 E F0(structure:)2.5 E F2
-(typedef int \()209 372 Q F3(*)A F2
-(getarg_collect_func\)\(int short_opt,)A(int argc,)407 384 Q(char)407
-396 Q F3(**)6 E F2(argv,)A(int)407 408 Q F3(*)6 E F2(optind,)A(int)407
-420 Q F3(*)6 E F2(optarg,)A(void)407 432 Q F3(*)6 E F2(data\);)A
-(typedef struct getarg_collect_info {)209 456 Q
-(getarg_collect_func func;)233 468 Q(void)233 480 Q F3(*)6 E F2(data;)A
-6(}g)209 492 S(etarg_collect_info;)-6 E F0 -.4(Wi)209 510 S 1.018
-(th the).4 F F1(func)3.518 E F0 1.019
-(member set to a function to call, and)3.518 F F1(data)3.519 E F0 1.019
-(to some application)3.519 F
-(speci\214c data. The parameters to the collect function are:)209 522 Q
-F1(short_flag)209 540 Q F0
-(non-zero if this call is via a short option \215ag, zero otherwise)2.5
-E F1(argc)209 558 Q F0(,)A F1(argv)6 E F0(the whole ar)2.5 E
-(gument list)-.18 E F1(optind)209 576 Q F0(pointer to the inde)2.5 E 2.5
-(xi)-.15 G 2.5(na)-2.5 G -.18(rg)-2.5 G 2.5(vw).18 G(here the \215ag is)
--2.5 E F1(optarg)209 594 Q F0(pointer to the inde)2.5 E 2.5(xi)-.15 G
-2.5(na)-2.5 G -.18(rg)-2.5 G(v[).18 E F3(*)A F0
-(optind] where the \215ag name starts)A F1(data)209 612 Q F0
-(application speci\214c data)2.5 E -1.1(Yo)209 630 S 3.915(uc)1.1 G
-1.415(an modify)-3.915 F F3(*)3.915 E F1(optind)A F0 3.915(,a)C(nd)
--3.915 E F3(*)3.915 E F1(optarg)A F0 3.915(,b)C 1.414
-(ut to do this correct you \(more or)-4.115 F(less\) ha)209 642 Q .3
--.15(ve t)-.2 H 2.5(ok).15 G(no)-2.5 E 2.5(wa)-.25 G(bout the inner w)
--2.5 E(orkings of getar)-.1 E(g.)-.18 E -1.1(Yo)209 666 S 3.604(uc)1.1 G
-1.104(an skip parts of ar)-3.604 F 1.105(guments by increasing)-.18 F F3
-(*)3.605 E F1(optarg)A F0 1.105(\(you could implement)3.605 F(the)209
-678 Q/F4 10/Courier-Bold@0 SF<ad7a>4.567 E F1(3)A F0 .401
-(set of \215ags from)2.901 F F4(gzip)2.9 E F0 .4
-(with this\), or whole ar)2.9 F .4(gument strings by increas-)-.18 F
-(ing)209 690 Q F3(*)3.275 E F1(optind)A F0(\(let')3.275 E 3.276(ss)-.55
-G .776(ay you w)-3.276 F .776(ant a \215ag)-.1 F F4<ad63>4.942 E F1
-6.776(xyz)6.776 G F0 .776(to specify a coordinate\); if)-3.5 F
-(you also ha)209 702 Q .3 -.15(ve t)-.2 H 2.5(os).15 G(et)-2.5 E F3(*)
-2.5 E F1(optarg)A F0(to a sane v)2.5 E(alue.)-.25 E -.4(RO)77 750 S
-152.325(KEN September).4 F(24, 1999)2.5 E(2)188.865 E EP
-%%Page: 3 3
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF(GET)72 48 Q -.834(ARG \( 3 \))-.93 F
-(OpenBSD Programmer')111.062 E 2.5(sM)-.55 G 108.562(anual GET)-2.5 F
--.834(ARG \( 3 \))-.93 F 9.449
-(The collect function should return one of)209 96 R/F1 10/Courier@0 SF
-(ARG_ERR_NO_MATCH)11.948 E F0(,)A F1(ARG_ERR_BAD_ARG)209 108 Q F0(,)A F1
-(ARG_ERR_NO_ARG)6 E F0(on error)2.5 E 2.5(,z)-.4 G(ero otherwise.)-2.5 E
--.15(Fo)209 126 S 4.042(ry).15 G 1.542(our con)-4.042 F -.15(ve)-.4 G
-1.542(nience there is a function,).15 F/F2 10/Courier-Bold@0 SF
-(getarg_optarg)4.042 E F0 1.542(\(\), that returns the)B 1.251
-(traditional ar)209 138 R 1.251(gument string, and you pass it all ar)
--.18 F 1.251(guments, sans data, that where)-.18 F(gi)209 150 Q -.15(ve)
--.25 G 2.5(nt).15 G 2.5(ot)-2.5 G(he collection function.)-2.5 E(Don')
-209 168 Q 2.5(tu)-.18 G(se this more this unless you absolutely ha)-2.5
-E .3 -.15(ve t)-.2 H(o.).15 E .213(Option parsing is similar to what)102
-186 R F1(getopt)2.713 E F0 .214(uses. Short options without ar)2.714 F
-.214(guments can be compressed \()-.18 F F2(\255xyz)1.666 E F0 .207
-(is the same as)102 198 R F2 1.873<ad7820ad7920ad7a>4.373 F F0 .207
-(\), and short options with ar)B .207(guments tak)-.18 F 2.706(et)-.1 G
-.206(hese as either the rest of the ar)-2.706 F(gv-string)-.18 E
-(or as the ne)102 210 Q(xt option \()-.15 E F2<ad6f>1.666 E/F3 10
-/Courier-Oblique@0 SF(foo)A F0 2.5(,o)C(r)-2.5 E F2<ad6f>4.166 E F3(foo)
-6 E F0(\).)A .78(Long option names are pre\214x)102 228 R .781
-(ed with -- \(double dash\), and the v)-.15 F .781
-(alue with a = \(equal\),)-.25 F F2(\255-foo=)4.947 E F3(bar)A F0 3.281
-(.L)C(ong)-3.281 E 3.815
-(option \215ags can either be speci\214ed as the)102 240 R 6.315(ya)-.15
-G 3.815(re \()-6.315 F F2(\255-help)1.666 E F0 3.815
-(\), or with an \(boolean parsable\) option)B(\()102 252 Q F2
-(\255-help=)1.666 E F3(yes)A F0(,)A F2(\255-help=)5.659 E F3(true)A F0
-3.993(,o)C 3.993(rs)-3.993 G 1.493(imilar\), or the)-3.993 F 3.993(yc)
--.15 G 1.493(an also be ne)-3.993 F -.05(ga)-.15 G 1.493(ted \().05 F F2
-(\255-no-help)1.666 E F0 1.493(is the same as)3.993 F F2(\255-help=)
-103.666 264 Q F0 1.363(no\), and if you')B 1.362
-(re really confused you can do it multiple times \()-.5 F F2
-(\255-no-no-help=)1.666 E F3(false)A F0 3.862(,o)C(r)-3.862 E -2.15 -.25
-(ev e)102 276 T(n).25 E F2(\255-no-no-help=)4.166 E F3(maybe)A F0(\).)A
-/F4 10/Times-Bold@0 SF(EXAMPLE)72 300 Q F1(#include <stdio.h>)102 330 Q
-(#include <string.h>)102 342 Q(#include <getarg.h>)102 354 Q(char)102
-378 Q/F5 10/Symbol SF(*)6 E F1(source = "Ouagadougou";)A(char)102 390 Q
-F5(*)6 E F1(destination;)A(int weight;)102 402 Q
-(int include_catalog = 1;)102 414 Q(int help_flag;)102 426 Q
-(struct getargs args[] = {)102 450 Q 6({")126 462 S 30(source", 's',)-6
-F 6(arg_string, &source,)6 F("source of shippment", "city" },)138 474 Q
-6({")126 486 S(destination", 'd', arg_string,)-6 E(&destination,)12 E
-("destination of shippment", "city" },)138 498 Q 6({")126 510 S 30
-(weight", 'w',)-6 F(arg_integer, &weight,)6 E
-("weight of shippment", "tons" },)138 522 Q 6({")126 534 S 24
-(catalog", 'c',)-6 F(arg_negative_flag, &include_catalog,)6 E
-("include product catalog" },)138 546 Q 6({")126 558 S 42(help", 'h',)-6
-F(arg_flag, &help_flag })6 E(};)102 570 Q
-(int num_args = sizeof\(args\) / sizeof\(args[0]\); /)102 594 Q F5(*)A
-F1(number of elements in args)6 E F5(*)6 E F1(/)A(const char)102 618 Q
-F5(*)6 E F1(progname = "ship++";)A(int)102 642 Q(main\(int argc, char)
-102 654 Q F5(**)6 E F1(argv\))A({)102 666 Q(int optind = 0;)126 678 Q
-(if \(getarg\(args, num_args, argc, argv, &optind\)\) {)126 690 Q
-(arg_printusage\(args, num_args, progname, "stuff..."\);)147 702 Q F0
--.4(RO)77 750 S 152.325(KEN September).4 F(24, 1999)2.5 E(3)188.865 E EP
-%%Page: 4 4
-%%BeginPageSetup
-BP
-%%EndPageSetup
-/F0 10/Times-Roman@0 SF(GET)72 48 Q -.834(ARG \( 3 \))-.93 F
-(OpenBSD Programmer')111.062 E 2.5(sM)-.55 G 108.562(anual GET)-2.5 F
--.834(ARG \( 3 \))-.93 F/F1 10/Courier@0 SF(exit \(1\);)147 96 Q(})126
-108 Q(if \(help_flag\) {)126 120 Q
-(arg_printusage\(args, num_args, progname, "stuff..."\);)147 132 Q
-(exit \(0\);)147 144 Q(})126 156 Q(if \(destination == NULL\) {)126 168
-Q(fprintf\(stderr, "%s: must specify destination0, progname\);)147 180 Q
-(exit\(1\);)147 192 Q(})126 204 Q
-(if \(strcmp\(source, destination\) == 0\) {)126 216 Q
-(fprintf\(stderr, "%s: destination must be different from source0\);)147
-228 Q(exit\(1\);)147 240 Q(})126 252 Q(/)126 264 Q/F2 10/Symbol SF(*)A
-F1(include more stuff here ...)6 E F2(*)6 E F1(/)A(exit\(2\);)126 276 Q
-(})102 288 Q F0(The output help output from this program looks lik)102
-306 Q 2.5(et)-.1 G(his:)-2.5 E F1 6($s)102 324 S(hip++ --help)-6 E
-(Usage: ship++ [--source=city] [-s city] [--destination=city] [-d city])
-102 336 Q
-([--weight=tons] [-w tons] [--no-catalog] [-c] [--help] [-h] stuff...)
-120 348 Q(-s city, --source=city)102 360 Q(source of shippment)36 E
-(-d city, --destination=city destination of shippment)102 372 Q
-(-w tons, --weight=tons)102 384 Q(weight of shippment)36 E
-(-c, --no-catalog)102 396 Q(include product catalog)72 E/F3 10
-/Times-Bold@0 SF -.1(BU)72 432 S(GS).1 E F0 .9(It should be more \215e)
-102 444 R .9(xible, so it w)-.15 F .901
-(ould be possible to use other more complicated option syntax)-.1 F .901
-(es, such as)-.15 F(what)102 456 Q F1(ps)3.167 E F0 .667(\(1\), and)B F1
-(tar)3.167 E F0 .666(\(1\), uses, or the AFS model where you can skip t\
-he \215ag names as long as the options)B(come in the correct order)102
-468 Q(.)-.55 E(Options with multiple ar)102 486 Q
-(guments should be handled better)-.18 E(.)-.55 E(Should be inte)102 504
-Q(greated with SL.)-.15 E(It')102 522 Q 2.5(sv)-.55 G
-(ery confusing that the struct you pass in is called getar)-2.65 E(gS.)
--.18 E F3 1.666(SEE ALSO)72 546 R F1(getopt)102 558 Q F0(\(3\))A -.4(RO)
-77 750 S 152.325(KEN September).4 F(24, 1999)2.5 E(4)188.865 E EP
-%%Trailer
-end
-%%EOF
diff --git a/ndb/src/common/util/md5-rfc1321.txt b/ndb/src/common/util/md5-rfc1321.txt
deleted file mode 100644
index c9e09e00cce..00000000000
--- a/ndb/src/common/util/md5-rfc1321.txt
+++ /dev/null
@@ -1,1179 +0,0 @@
-
-
-
-
-
-
-Network Working Group R. Rivest
-Request for Comments: 1321 MIT Laboratory for Computer Science
- and RSA Data Security, Inc.
- April 1992
-
-
- The MD5 Message-Digest Algorithm
-
-Status of this Memo
-
- This memo provides information for the Internet community. It does
- not specify an Internet standard. Distribution of this memo is
- unlimited.
-
-Acknowlegements
-
- We would like to thank Don Coppersmith, Burt Kaliski, Ralph Merkle,
- David Chaum, and Noam Nisan for numerous helpful comments and
- suggestions.
-
-Table of Contents
-
- 1. Executive Summary 1
- 2. Terminology and Notation 2
- 3. MD5 Algorithm Description 3
- 4. Summary 6
- 5. Differences Between MD4 and MD5 6
- References 7
- APPENDIX A - Reference Implementation 7
- Security Considerations 21
- Author's Address 21
-
-1. Executive Summary
-
- This document describes the MD5 message-digest algorithm. The
- algorithm takes as input a message of arbitrary length and produces
- as output a 128-bit "fingerprint" or "message digest" of the input.
- It is conjectured that it is computationally infeasible to produce
- two messages having the same message digest, or to produce any
- message having a given prespecified target message digest. The MD5
- algorithm is intended for digital signature applications, where a
- large file must be "compressed" in a secure manner before being
- encrypted with a private (secret) key under a public-key cryptosystem
- such as RSA.
-
-
-
-
-
-
-
-Rivest [Page 1]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- The MD5 algorithm is designed to be quite fast on 32-bit machines. In
- addition, the MD5 algorithm does not require any large substitution
- tables; the algorithm can be coded quite compactly.
-
- The MD5 algorithm is an extension of the MD4 message-digest algorithm
- 1,2]. MD5 is slightly slower than MD4, but is more "conservative" in
- design. MD5 was designed because it was felt that MD4 was perhaps
- being adopted for use more quickly than justified by the existing
- critical review; because MD4 was designed to be exceptionally fast,
- it is "at the edge" in terms of risking successful cryptanalytic
- attack. MD5 backs off a bit, giving up a little in speed for a much
- greater likelihood of ultimate security. It incorporates some
- suggestions made by various reviewers, and contains additional
- optimizations. The MD5 algorithm is being placed in the public domain
- for review and possible adoption as a standard.
-
- For OSI-based applications, MD5's object identifier is
-
- md5 OBJECT IDENTIFIER ::=
- iso(1) member-body(2) US(840) rsadsi(113549) digestAlgorithm(2) 5}
-
- In the X.509 type AlgorithmIdentifier [3], the parameters for MD5
- should have type NULL.
-
-2. Terminology and Notation
-
- In this document a "word" is a 32-bit quantity and a "byte" is an
- eight-bit quantity. A sequence of bits can be interpreted in a
- natural manner as a sequence of bytes, where each consecutive group
- of eight bits is interpreted as a byte with the high-order (most
- significant) bit of each byte listed first. Similarly, a sequence of
- bytes can be interpreted as a sequence of 32-bit words, where each
- consecutive group of four bytes is interpreted as a word with the
- low-order (least significant) byte given first.
-
- Let x_i denote "x sub i". If the subscript is an expression, we
- surround it in braces, as in x_{i+1}. Similarly, we use ^ for
- superscripts (exponentiation), so that x^i denotes x to the i-th
- power.
-
- Let the symbol "+" denote addition of words (i.e., modulo-2^32
- addition). Let X <<< s denote the 32-bit value obtained by circularly
- shifting (rotating) X left by s bit positions. Let not(X) denote the
- bit-wise complement of X, and let X v Y denote the bit-wise OR of X
- and Y. Let X xor Y denote the bit-wise XOR of X and Y, and let XY
- denote the bit-wise AND of X and Y.
-
-
-
-
-
-Rivest [Page 2]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
-3. MD5 Algorithm Description
-
- We begin by supposing that we have a b-bit message as input, and that
- we wish to find its message digest. Here b is an arbitrary
- nonnegative integer; b may be zero, it need not be a multiple of
- eight, and it may be arbitrarily large. We imagine the bits of the
- message written down as follows:
-
- m_0 m_1 ... m_{b-1}
-
- The following five steps are performed to compute the message digest
- of the message.
-
-3.1 Step 1. Append Padding Bits
-
- The message is "padded" (extended) so that its length (in bits) is
- congruent to 448, modulo 512. That is, the message is extended so
- that it is just 64 bits shy of being a multiple of 512 bits long.
- Padding is always performed, even if the length of the message is
- already congruent to 448, modulo 512.
-
- Padding is performed as follows: a single "1" bit is appended to the
- message, and then "0" bits are appended so that the length in bits of
- the padded message becomes congruent to 448, modulo 512. In all, at
- least one bit and at most 512 bits are appended.
-
-3.2 Step 2. Append Length
-
- A 64-bit representation of b (the length of the message before the
- padding bits were added) is appended to the result of the previous
- step. In the unlikely event that b is greater than 2^64, then only
- the low-order 64 bits of b are used. (These bits are appended as two
- 32-bit words and appended low-order word first in accordance with the
- previous conventions.)
-
- At this point the resulting message (after padding with bits and with
- b) has a length that is an exact multiple of 512 bits. Equivalently,
- this message has a length that is an exact multiple of 16 (32-bit)
- words. Let M[0 ... N-1] denote the words of the resulting message,
- where N is a multiple of 16.
-
-3.3 Step 3. Initialize MD Buffer
-
- A four-word buffer (A,B,C,D) is used to compute the message digest.
- Here each of A, B, C, D is a 32-bit register. These registers are
- initialized to the following values in hexadecimal, low-order bytes
- first):
-
-
-
-
-Rivest [Page 3]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- word A: 01 23 45 67
- word B: 89 ab cd ef
- word C: fe dc ba 98
- word D: 76 54 32 10
-
-3.4 Step 4. Process Message in 16-Word Blocks
-
- We first define four auxiliary functions that each take as input
- three 32-bit words and produce as output one 32-bit word.
-
- F(X,Y,Z) = XY v not(X) Z
- G(X,Y,Z) = XZ v Y not(Z)
- H(X,Y,Z) = X xor Y xor Z
- I(X,Y,Z) = Y xor (X v not(Z))
-
- In each bit position F acts as a conditional: if X then Y else Z.
- The function F could have been defined using + instead of v since XY
- and not(X)Z will never have 1's in the same bit position.) It is
- interesting to note that if the bits of X, Y, and Z are independent
- and unbiased, the each bit of F(X,Y,Z) will be independent and
- unbiased.
-
- The functions G, H, and I are similar to the function F, in that they
- act in "bitwise parallel" to produce their output from the bits of X,
- Y, and Z, in such a manner that if the corresponding bits of X, Y,
- and Z are independent and unbiased, then each bit of G(X,Y,Z),
- H(X,Y,Z), and I(X,Y,Z) will be independent and unbiased. Note that
- the function H is the bit-wise "xor" or "parity" function of its
- inputs.
-
- This step uses a 64-element table T[1 ... 64] constructed from the
- sine function. Let T[i] denote the i-th element of the table, which
- is equal to the integer part of 4294967296 times abs(sin(i)), where i
- is in radians. The elements of the table are given in the appendix.
-
- Do the following:
-
- /* Process each 16-word block. */
- For i = 0 to N/16-1 do
-
- /* Copy block i into X. */
- For j = 0 to 15 do
- Set X[j] to M[i*16+j].
- end /* of loop on j */
-
- /* Save A as AA, B as BB, C as CC, and D as DD. */
- AA = A
- BB = B
-
-
-
-Rivest [Page 4]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- CC = C
- DD = D
-
- /* Round 1. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + F(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- [ABCD 0 7 1] [DABC 1 12 2] [CDAB 2 17 3] [BCDA 3 22 4]
- [ABCD 4 7 5] [DABC 5 12 6] [CDAB 6 17 7] [BCDA 7 22 8]
- [ABCD 8 7 9] [DABC 9 12 10] [CDAB 10 17 11] [BCDA 11 22 12]
- [ABCD 12 7 13] [DABC 13 12 14] [CDAB 14 17 15] [BCDA 15 22 16]
-
- /* Round 2. */
- /* Let [abcd k s i] denote the operation
- a = b + ((a + G(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- [ABCD 1 5 17] [DABC 6 9 18] [CDAB 11 14 19] [BCDA 0 20 20]
- [ABCD 5 5 21] [DABC 10 9 22] [CDAB 15 14 23] [BCDA 4 20 24]
- [ABCD 9 5 25] [DABC 14 9 26] [CDAB 3 14 27] [BCDA 8 20 28]
- [ABCD 13 5 29] [DABC 2 9 30] [CDAB 7 14 31] [BCDA 12 20 32]
-
- /* Round 3. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + H(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- [ABCD 5 4 33] [DABC 8 11 34] [CDAB 11 16 35] [BCDA 14 23 36]
- [ABCD 1 4 37] [DABC 4 11 38] [CDAB 7 16 39] [BCDA 10 23 40]
- [ABCD 13 4 41] [DABC 0 11 42] [CDAB 3 16 43] [BCDA 6 23 44]
- [ABCD 9 4 45] [DABC 12 11 46] [CDAB 15 16 47] [BCDA 2 23 48]
-
- /* Round 4. */
- /* Let [abcd k s t] denote the operation
- a = b + ((a + I(b,c,d) + X[k] + T[i]) <<< s). */
- /* Do the following 16 operations. */
- [ABCD 0 6 49] [DABC 7 10 50] [CDAB 14 15 51] [BCDA 5 21 52]
- [ABCD 12 6 53] [DABC 3 10 54] [CDAB 10 15 55] [BCDA 1 21 56]
- [ABCD 8 6 57] [DABC 15 10 58] [CDAB 6 15 59] [BCDA 13 21 60]
- [ABCD 4 6 61] [DABC 11 10 62] [CDAB 2 15 63] [BCDA 9 21 64]
-
- /* Then perform the following additions. (That is increment each
- of the four registers by the value it had before this block
- was started.) */
- A = A + AA
- B = B + BB
- C = C + CC
- D = D + DD
-
- end /* of loop on i */
-
-
-
-Rivest [Page 5]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
-3.5 Step 5. Output
-
- The message digest produced as output is A, B, C, D. That is, we
- begin with the low-order byte of A, and end with the high-order byte
- of D.
-
- This completes the description of MD5. A reference implementation in
- C is given in the appendix.
-
-4. Summary
-
- The MD5 message-digest algorithm is simple to implement, and provides
- a "fingerprint" or message digest of a message of arbitrary length.
- It is conjectured that the difficulty of coming up with two messages
- having the same message digest is on the order of 2^64 operations,
- and that the difficulty of coming up with any message having a given
- message digest is on the order of 2^128 operations. The MD5 algorithm
- has been carefully scrutinized for weaknesses. It is, however, a
- relatively new algorithm and further security analysis is of course
- justified, as is the case with any new proposal of this sort.
-
-5. Differences Between MD4 and MD5
-
- The following are the differences between MD4 and MD5:
-
- 1. A fourth round has been added.
-
- 2. Each step now has a unique additive constant.
-
- 3. The function g in round 2 was changed from (XY v XZ v YZ) to
- (XZ v Y not(Z)) to make g less symmetric.
-
- 4. Each step now adds in the result of the previous step. This
- promotes a faster "avalanche effect".
-
- 5. The order in which input words are accessed in rounds 2 and
- 3 is changed, to make these patterns less like each other.
-
- 6. The shift amounts in each round have been approximately
- optimized, to yield a faster "avalanche effect." The shifts in
- different rounds are distinct.
-
-
-
-
-
-
-
-
-
-
-Rivest [Page 6]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
-References
-
- [1] Rivest, R., "The MD4 Message Digest Algorithm", RFC 1320, MIT and
- RSA Data Security, Inc., April 1992.
-
- [2] Rivest, R., "The MD4 message digest algorithm", in A.J. Menezes
- and S.A. Vanstone, editors, Advances in Cryptology - CRYPTO '90
- Proceedings, pages 303-311, Springer-Verlag, 1991.
-
- [3] CCITT Recommendation X.509 (1988), "The Directory -
- Authentication Framework."
-
-APPENDIX A - Reference Implementation
-
- This appendix contains the following files taken from RSAREF: A
- Cryptographic Toolkit for Privacy-Enhanced Mail:
-
- global.h -- global header file
-
- md5.h -- header file for MD5
-
- md5c.c -- source code for MD5
-
- For more information on RSAREF, send email to <rsaref@rsa.com>.
-
- The appendix also includes the following file:
-
- mddriver.c -- test driver for MD2, MD4 and MD5
-
- The driver compiles for MD5 by default but can compile for MD2 or MD4
- if the symbol MD is defined on the C compiler command line as 2 or 4.
-
- The implementation is portable and should work on many different
- plaforms. However, it is not difficult to optimize the implementation
- on particular platforms, an exercise left to the reader. For example,
- on "little-endian" platforms where the lowest-addressed byte in a 32-
- bit word is the least significant and there are no alignment
- restrictions, the call to Decode in MD5Transform can be replaced with
- a typecast.
-
-A.1 global.h
-
-/* GLOBAL.H - RSAREF types and constants
- */
-
-/* PROTOTYPES should be set to one if and only if the compiler supports
- function argument prototyping.
-The following makes PROTOTYPES default to 0 if it has not already
-
-
-
-Rivest [Page 7]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- been defined with C compiler flags.
- */
-#ifndef PROTOTYPES
-#define PROTOTYPES 0
-#endif
-
-/* POINTER defines a generic pointer type */
-typedef unsigned char *POINTER;
-
-/* UINT2 defines a two byte word */
-typedef unsigned short int UINT2;
-
-/* UINT4 defines a four byte word */
-typedef unsigned long int UINT4;
-
-/* PROTO_LIST is defined depending on how PROTOTYPES is defined above.
-If using PROTOTYPES, then PROTO_LIST returns the list, otherwise it
- returns an empty list.
- */
-#if PROTOTYPES
-#define PROTO_LIST(list) list
-#else
-#define PROTO_LIST(list) ()
-#endif
-
-A.2 md5.h
-
-/* MD5.H - header file for MD5C.C
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-
-
-
-Rivest [Page 8]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-/* MD5 context. */
-typedef struct {
- UINT4 state[4]; /* state (ABCD) */
- UINT4 count[2]; /* number of bits, modulo 2^64 (lsb first) */
- unsigned char buffer[64]; /* input buffer */
-} MD5_CTX;
-
-void MD5Init PROTO_LIST ((MD5_CTX *));
-void MD5Update PROTO_LIST
- ((MD5_CTX *, unsigned char *, unsigned int));
-void MD5Final PROTO_LIST ((unsigned char [16], MD5_CTX *));
-
-A.3 md5c.c
-
-/* MD5C.C - RSA Data Security, Inc., MD5 message-digest algorithm
- */
-
-/* Copyright (C) 1991-2, RSA Data Security, Inc. Created 1991. All
-rights reserved.
-
-License to copy and use this software is granted provided that it
-is identified as the "RSA Data Security, Inc. MD5 Message-Digest
-Algorithm" in all material mentioning or referencing this software
-or this function.
-
-License is also granted to make and use derivative works provided
-that such works are identified as "derived from the RSA Data
-Security, Inc. MD5 Message-Digest Algorithm" in all material
-mentioning or referencing the derived work.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-#include "global.h"
-#include "md5.h"
-
-/* Constants for MD5Transform routine.
- */
-
-
-
-Rivest [Page 9]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
-#define S11 7
-#define S12 12
-#define S13 17
-#define S14 22
-#define S21 5
-#define S22 9
-#define S23 14
-#define S24 20
-#define S31 4
-#define S32 11
-#define S33 16
-#define S34 23
-#define S41 6
-#define S42 10
-#define S43 15
-#define S44 21
-
-static void MD5Transform PROTO_LIST ((UINT4 [4], unsigned char [64]));
-static void Encode PROTO_LIST
- ((unsigned char *, UINT4 *, unsigned int));
-static void Decode PROTO_LIST
- ((UINT4 *, unsigned char *, unsigned int));
-static void MD5_memcpy PROTO_LIST ((POINTER, POINTER, unsigned int));
-static void MD5_memset PROTO_LIST ((POINTER, int, unsigned int));
-
-static unsigned char PADDING[64] = {
- 0x80, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
- 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0
-};
-
-/* F, G, H and I are basic MD5 functions.
- */
-#define F(x, y, z) (((x) & (y)) | ((~x) & (z)))
-#define G(x, y, z) (((x) & (z)) | ((y) & (~z)))
-#define H(x, y, z) ((x) ^ (y) ^ (z))
-#define I(x, y, z) ((y) ^ ((x) | (~z)))
-
-/* ROTATE_LEFT rotates x left n bits.
- */
-#define ROTATE_LEFT(x, n) (((x) << (n)) | ((x) >> (32-(n))))
-
-/* FF, GG, HH, and II transformations for rounds 1, 2, 3, and 4.
-Rotation is separate from addition to prevent recomputation.
- */
-#define FF(a, b, c, d, x, s, ac) { \
- (a) += F ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
-
-
-
-Rivest [Page 10]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- (a) += (b); \
- }
-#define GG(a, b, c, d, x, s, ac) { \
- (a) += G ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define HH(a, b, c, d, x, s, ac) { \
- (a) += H ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-#define II(a, b, c, d, x, s, ac) { \
- (a) += I ((b), (c), (d)) + (x) + (UINT4)(ac); \
- (a) = ROTATE_LEFT ((a), (s)); \
- (a) += (b); \
- }
-
-/* MD5 initialization. Begins an MD5 operation, writing a new context.
- */
-void MD5Init (context)
-MD5_CTX *context; /* context */
-{
- context->count[0] = context->count[1] = 0;
- /* Load magic initialization constants.
-*/
- context->state[0] = 0x67452301;
- context->state[1] = 0xefcdab89;
- context->state[2] = 0x98badcfe;
- context->state[3] = 0x10325476;
-}
-
-/* MD5 block update operation. Continues an MD5 message-digest
- operation, processing another message block, and updating the
- context.
- */
-void MD5Update (context, input, inputLen)
-MD5_CTX *context; /* context */
-unsigned char *input; /* input block */
-unsigned int inputLen; /* length of input block */
-{
- unsigned int i, index, partLen;
-
- /* Compute number of bytes mod 64 */
- index = (unsigned int)((context->count[0] >> 3) & 0x3F);
-
- /* Update number of bits */
- if ((context->count[0] += ((UINT4)inputLen << 3))
-
-
-
-Rivest [Page 11]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- < ((UINT4)inputLen << 3))
- context->count[1]++;
- context->count[1] += ((UINT4)inputLen >> 29);
-
- partLen = 64 - index;
-
- /* Transform as many times as possible.
-*/
- if (inputLen >= partLen) {
- MD5_memcpy
- ((POINTER)&context->buffer[index], (POINTER)input, partLen);
- MD5Transform (context->state, context->buffer);
-
- for (i = partLen; i + 63 < inputLen; i += 64)
- MD5Transform (context->state, &input[i]);
-
- index = 0;
- }
- else
- i = 0;
-
- /* Buffer remaining input */
- MD5_memcpy
- ((POINTER)&context->buffer[index], (POINTER)&input[i],
- inputLen-i);
-}
-
-/* MD5 finalization. Ends an MD5 message-digest operation, writing the
- the message digest and zeroizing the context.
- */
-void MD5Final (digest, context)
-unsigned char digest[16]; /* message digest */
-MD5_CTX *context; /* context */
-{
- unsigned char bits[8];
- unsigned int index, padLen;
-
- /* Save number of bits */
- Encode (bits, context->count, 8);
-
- /* Pad out to 56 mod 64.
-*/
- index = (unsigned int)((context->count[0] >> 3) & 0x3f);
- padLen = (index < 56) ? (56 - index) : (120 - index);
- MD5Update (context, PADDING, padLen);
-
- /* Append length (before padding) */
- MD5Update (context, bits, 8);
-
-
-
-Rivest [Page 12]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- /* Store state in digest */
- Encode (digest, context->state, 16);
-
- /* Zeroize sensitive information.
-*/
- MD5_memset ((POINTER)context, 0, sizeof (*context));
-}
-
-/* MD5 basic transformation. Transforms state based on block.
- */
-static void MD5Transform (state, block)
-UINT4 state[4];
-unsigned char block[64];
-{
- UINT4 a = state[0], b = state[1], c = state[2], d = state[3], x[16];
-
- Decode (x, block, 64);
-
- /* Round 1 */
- FF (a, b, c, d, x[ 0], S11, 0xd76aa478); /* 1 */
- FF (d, a, b, c, x[ 1], S12, 0xe8c7b756); /* 2 */
- FF (c, d, a, b, x[ 2], S13, 0x242070db); /* 3 */
- FF (b, c, d, a, x[ 3], S14, 0xc1bdceee); /* 4 */
- FF (a, b, c, d, x[ 4], S11, 0xf57c0faf); /* 5 */
- FF (d, a, b, c, x[ 5], S12, 0x4787c62a); /* 6 */
- FF (c, d, a, b, x[ 6], S13, 0xa8304613); /* 7 */
- FF (b, c, d, a, x[ 7], S14, 0xfd469501); /* 8 */
- FF (a, b, c, d, x[ 8], S11, 0x698098d8); /* 9 */
- FF (d, a, b, c, x[ 9], S12, 0x8b44f7af); /* 10 */
- FF (c, d, a, b, x[10], S13, 0xffff5bb1); /* 11 */
- FF (b, c, d, a, x[11], S14, 0x895cd7be); /* 12 */
- FF (a, b, c, d, x[12], S11, 0x6b901122); /* 13 */
- FF (d, a, b, c, x[13], S12, 0xfd987193); /* 14 */
- FF (c, d, a, b, x[14], S13, 0xa679438e); /* 15 */
- FF (b, c, d, a, x[15], S14, 0x49b40821); /* 16 */
-
- /* Round 2 */
- GG (a, b, c, d, x[ 1], S21, 0xf61e2562); /* 17 */
- GG (d, a, b, c, x[ 6], S22, 0xc040b340); /* 18 */
- GG (c, d, a, b, x[11], S23, 0x265e5a51); /* 19 */
- GG (b, c, d, a, x[ 0], S24, 0xe9b6c7aa); /* 20 */
- GG (a, b, c, d, x[ 5], S21, 0xd62f105d); /* 21 */
- GG (d, a, b, c, x[10], S22, 0x2441453); /* 22 */
- GG (c, d, a, b, x[15], S23, 0xd8a1e681); /* 23 */
- GG (b, c, d, a, x[ 4], S24, 0xe7d3fbc8); /* 24 */
- GG (a, b, c, d, x[ 9], S21, 0x21e1cde6); /* 25 */
- GG (d, a, b, c, x[14], S22, 0xc33707d6); /* 26 */
- GG (c, d, a, b, x[ 3], S23, 0xf4d50d87); /* 27 */
-
-
-
-Rivest [Page 13]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- GG (b, c, d, a, x[ 8], S24, 0x455a14ed); /* 28 */
- GG (a, b, c, d, x[13], S21, 0xa9e3e905); /* 29 */
- GG (d, a, b, c, x[ 2], S22, 0xfcefa3f8); /* 30 */
- GG (c, d, a, b, x[ 7], S23, 0x676f02d9); /* 31 */
- GG (b, c, d, a, x[12], S24, 0x8d2a4c8a); /* 32 */
-
- /* Round 3 */
- HH (a, b, c, d, x[ 5], S31, 0xfffa3942); /* 33 */
- HH (d, a, b, c, x[ 8], S32, 0x8771f681); /* 34 */
- HH (c, d, a, b, x[11], S33, 0x6d9d6122); /* 35 */
- HH (b, c, d, a, x[14], S34, 0xfde5380c); /* 36 */
- HH (a, b, c, d, x[ 1], S31, 0xa4beea44); /* 37 */
- HH (d, a, b, c, x[ 4], S32, 0x4bdecfa9); /* 38 */
- HH (c, d, a, b, x[ 7], S33, 0xf6bb4b60); /* 39 */
- HH (b, c, d, a, x[10], S34, 0xbebfbc70); /* 40 */
- HH (a, b, c, d, x[13], S31, 0x289b7ec6); /* 41 */
- HH (d, a, b, c, x[ 0], S32, 0xeaa127fa); /* 42 */
- HH (c, d, a, b, x[ 3], S33, 0xd4ef3085); /* 43 */
- HH (b, c, d, a, x[ 6], S34, 0x4881d05); /* 44 */
- HH (a, b, c, d, x[ 9], S31, 0xd9d4d039); /* 45 */
- HH (d, a, b, c, x[12], S32, 0xe6db99e5); /* 46 */
- HH (c, d, a, b, x[15], S33, 0x1fa27cf8); /* 47 */
- HH (b, c, d, a, x[ 2], S34, 0xc4ac5665); /* 48 */
-
- /* Round 4 */
- II (a, b, c, d, x[ 0], S41, 0xf4292244); /* 49 */
- II (d, a, b, c, x[ 7], S42, 0x432aff97); /* 50 */
- II (c, d, a, b, x[14], S43, 0xab9423a7); /* 51 */
- II (b, c, d, a, x[ 5], S44, 0xfc93a039); /* 52 */
- II (a, b, c, d, x[12], S41, 0x655b59c3); /* 53 */
- II (d, a, b, c, x[ 3], S42, 0x8f0ccc92); /* 54 */
- II (c, d, a, b, x[10], S43, 0xffeff47d); /* 55 */
- II (b, c, d, a, x[ 1], S44, 0x85845dd1); /* 56 */
- II (a, b, c, d, x[ 8], S41, 0x6fa87e4f); /* 57 */
- II (d, a, b, c, x[15], S42, 0xfe2ce6e0); /* 58 */
- II (c, d, a, b, x[ 6], S43, 0xa3014314); /* 59 */
- II (b, c, d, a, x[13], S44, 0x4e0811a1); /* 60 */
- II (a, b, c, d, x[ 4], S41, 0xf7537e82); /* 61 */
- II (d, a, b, c, x[11], S42, 0xbd3af235); /* 62 */
- II (c, d, a, b, x[ 2], S43, 0x2ad7d2bb); /* 63 */
- II (b, c, d, a, x[ 9], S44, 0xeb86d391); /* 64 */
-
- state[0] += a;
- state[1] += b;
- state[2] += c;
- state[3] += d;
-
- /* Zeroize sensitive information.
-
-
-
-Rivest [Page 14]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
-*/
- MD5_memset ((POINTER)x, 0, sizeof (x));
-}
-
-/* Encodes input (UINT4) into output (unsigned char). Assumes len is
- a multiple of 4.
- */
-static void Encode (output, input, len)
-unsigned char *output;
-UINT4 *input;
-unsigned int len;
-{
- unsigned int i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4) {
- output[j] = (unsigned char)(input[i] & 0xff);
- output[j+1] = (unsigned char)((input[i] >> 8) & 0xff);
- output[j+2] = (unsigned char)((input[i] >> 16) & 0xff);
- output[j+3] = (unsigned char)((input[i] >> 24) & 0xff);
- }
-}
-
-/* Decodes input (unsigned char) into output (UINT4). Assumes len is
- a multiple of 4.
- */
-static void Decode (output, input, len)
-UINT4 *output;
-unsigned char *input;
-unsigned int len;
-{
- unsigned int i, j;
-
- for (i = 0, j = 0; j < len; i++, j += 4)
- output[i] = ((UINT4)input[j]) | (((UINT4)input[j+1]) << 8) |
- (((UINT4)input[j+2]) << 16) | (((UINT4)input[j+3]) << 24);
-}
-
-/* Note: Replace "for loop" with standard memcpy if possible.
- */
-
-static void MD5_memcpy (output, input, len)
-POINTER output;
-POINTER input;
-unsigned int len;
-{
- unsigned int i;
-
- for (i = 0; i < len; i++)
-
-
-
-Rivest [Page 15]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- output[i] = input[i];
-}
-
-/* Note: Replace "for loop" with standard memset if possible.
- */
-static void MD5_memset (output, value, len)
-POINTER output;
-int value;
-unsigned int len;
-{
- unsigned int i;
-
- for (i = 0; i < len; i++)
- ((char *)output)[i] = (char)value;
-}
-
-A.4 mddriver.c
-
-/* MDDRIVER.C - test driver for MD2, MD4 and MD5
- */
-
-/* Copyright (C) 1990-2, RSA Data Security, Inc. Created 1990. All
-rights reserved.
-
-RSA Data Security, Inc. makes no representations concerning either
-the merchantability of this software or the suitability of this
-software for any particular purpose. It is provided "as is"
-without express or implied warranty of any kind.
-
-These notices must be retained in any copies of any part of this
-documentation and/or software.
- */
-
-/* The following makes MD default to MD5 if it has not already been
- defined with C compiler flags.
- */
-#ifndef MD
-#define MD MD5
-#endif
-
-#include <stdio.h>
-#include <time.h>
-#include <string.h>
-#include "global.h"
-#if MD == 2
-#include "md2.h"
-#endif
-#if MD == 4
-
-
-
-Rivest [Page 16]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
-#include "md4.h"
-#endif
-#if MD == 5
-#include "md5.h"
-#endif
-
-/* Length of test block, number of test blocks.
- */
-#define TEST_BLOCK_LEN 1000
-#define TEST_BLOCK_COUNT 1000
-
-static void MDString PROTO_LIST ((char *));
-static void MDTimeTrial PROTO_LIST ((void));
-static void MDTestSuite PROTO_LIST ((void));
-static void MDFile PROTO_LIST ((char *));
-static void MDFilter PROTO_LIST ((void));
-static void MDPrint PROTO_LIST ((unsigned char [16]));
-
-#if MD == 2
-#define MD_CTX MD2_CTX
-#define MDInit MD2Init
-#define MDUpdate MD2Update
-#define MDFinal MD2Final
-#endif
-#if MD == 4
-#define MD_CTX MD4_CTX
-#define MDInit MD4Init
-#define MDUpdate MD4Update
-#define MDFinal MD4Final
-#endif
-#if MD == 5
-#define MD_CTX MD5_CTX
-#define MDInit MD5Init
-#define MDUpdate MD5Update
-#define MDFinal MD5Final
-#endif
-
-/* Main driver.
-
-Arguments (may be any combination):
- -sstring - digests string
- -t - runs time trial
- -x - runs test script
- filename - digests file
- (none) - digests standard input
- */
-int main (argc, argv)
-int argc;
-
-
-
-Rivest [Page 17]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
-char *argv[];
-{
- int i;
-
- if (argc > 1)
- for (i = 1; i < argc; i++)
- if (argv[i][0] == '-' && argv[i][1] == 's')
- MDString (argv[i] + 2);
- else if (strcmp (argv[i], "-t") == 0)
- MDTimeTrial ();
- else if (strcmp (argv[i], "-x") == 0)
- MDTestSuite ();
- else
- MDFile (argv[i]);
- else
- MDFilter ();
-
- return (0);
-}
-
-/* Digests a string and prints the result.
- */
-static void MDString (string)
-char *string;
-{
- MD_CTX context;
- unsigned char digest[16];
- unsigned int len = strlen (string);
-
- MDInit (&context);
- MDUpdate (&context, string, len);
- MDFinal (digest, &context);
-
- printf ("MD%d (\"%s\") = ", MD, string);
- MDPrint (digest);
- printf ("\n");
-}
-
-/* Measures the time to digest TEST_BLOCK_COUNT TEST_BLOCK_LEN-byte
- blocks.
- */
-static void MDTimeTrial ()
-{
- MD_CTX context;
- time_t endTime, startTime;
- unsigned char block[TEST_BLOCK_LEN], digest[16];
- unsigned int i;
-
-
-
-
-Rivest [Page 18]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- printf
- ("MD%d time trial. Digesting %d %d-byte blocks ...", MD,
- TEST_BLOCK_LEN, TEST_BLOCK_COUNT);
-
- /* Initialize block */
- for (i = 0; i < TEST_BLOCK_LEN; i++)
- block[i] = (unsigned char)(i & 0xff);
-
- /* Start timer */
- time (&startTime);
-
- /* Digest blocks */
- MDInit (&context);
- for (i = 0; i < TEST_BLOCK_COUNT; i++)
- MDUpdate (&context, block, TEST_BLOCK_LEN);
- MDFinal (digest, &context);
-
- /* Stop timer */
- time (&endTime);
-
- printf (" done\n");
- printf ("Digest = ");
- MDPrint (digest);
- printf ("\nTime = %ld seconds\n", (long)(endTime-startTime));
- printf
- ("Speed = %ld bytes/second\n",
- (long)TEST_BLOCK_LEN * (long)TEST_BLOCK_COUNT/(endTime-startTime));
-}
-
-/* Digests a reference suite of strings and prints the results.
- */
-static void MDTestSuite ()
-{
- printf ("MD%d test suite:\n", MD);
-
- MDString ("");
- MDString ("a");
- MDString ("abc");
- MDString ("message digest");
- MDString ("abcdefghijklmnopqrstuvwxyz");
- MDString
- ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789");
- MDString
- ("1234567890123456789012345678901234567890\
-1234567890123456789012345678901234567890");
-}
-
-/* Digests a file and prints the result.
-
-
-
-Rivest [Page 19]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- */
-static void MDFile (filename)
-char *filename;
-{
- FILE *file;
- MD_CTX context;
- int len;
- unsigned char buffer[1024], digest[16];
-
- if ((file = fopen (filename, "rb")) == NULL)
- printf ("%s can't be opened\n", filename);
-
- else {
- MDInit (&context);
- while (len = fread (buffer, 1, 1024, file))
- MDUpdate (&context, buffer, len);
- MDFinal (digest, &context);
-
- fclose (file);
-
- printf ("MD%d (%s) = ", MD, filename);
- MDPrint (digest);
- printf ("\n");
- }
-}
-
-/* Digests the standard input and prints the result.
- */
-static void MDFilter ()
-{
- MD_CTX context;
- int len;
- unsigned char buffer[16], digest[16];
-
- MDInit (&context);
- while (len = fread (buffer, 1, 16, stdin))
- MDUpdate (&context, buffer, len);
- MDFinal (digest, &context);
-
- MDPrint (digest);
- printf ("\n");
-}
-
-/* Prints a message digest in hexadecimal.
- */
-static void MDPrint (digest)
-unsigned char digest[16];
-{
-
-
-
-Rivest [Page 20]
-
-RFC 1321 MD5 Message-Digest Algorithm April 1992
-
-
- unsigned int i;
-
- for (i = 0; i < 16; i++)
- printf ("%02x", digest[i]);
-}
-
-A.5 Test suite
-
- The MD5 test suite (driver option "-x") should print the following
- results:
-
-MD5 test suite:
-MD5 ("") = d41d8cd98f00b204e9800998ecf8427e
-MD5 ("a") = 0cc175b9c0f1b6a831c399e269772661
-MD5 ("abc") = 900150983cd24fb0d6963f7d28e17f72
-MD5 ("message digest") = f96b697d7cb7938d525a2f31aaf161d0
-MD5 ("abcdefghijklmnopqrstuvwxyz") = c3fcd3d76192e4007dfb496cca67e13b
-MD5 ("ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789") =
-d174ab98d277d9f5a5611c2c9f419d9f
-MD5 ("123456789012345678901234567890123456789012345678901234567890123456
-78901234567890") = 57edf4a22be3c955ac49da2e2107b67a
-
-Security Considerations
-
- The level of security discussed in this memo is considered to be
- sufficient for implementing very high security hybrid digital-
- signature schemes based on MD5 and a public-key cryptosystem.
-
-Author's Address
-
- Ronald L. Rivest
- Massachusetts Institute of Technology
- Laboratory for Computer Science
- NE43-324
- 545 Technology Square
- Cambridge, MA 02139-1986
-
- Phone: (617) 253-5880
- EMail: rivest@theory.lcs.mit.edu
-
-
-
-
-
-
-
-
-
-
-
-
-Rivest [Page 21]
-
diff --git a/ndb/src/common/util/md5_hash.cpp b/ndb/src/common/util/md5_hash.cpp
index 068843183ac..d4eedbc40fb 100644
--- a/ndb/src/common/util/md5_hash.cpp
+++ b/ndb/src/common/util/md5_hash.cpp
@@ -75,7 +75,7 @@ void byteReverse(unsigned char *buf, unsigned longs)
* reflect the addition of 16 longwords of new data. MD5Update blocks
* the data and converts bytes into longwords for this routine.
*/
-void MD5Transform(Uint32 buf[4], Uint32 const in[16])
+static void MD5Transform(Uint32 buf[4], Uint32 const in[16])
{
register Uint32 a, b, c, d;
@@ -162,13 +162,13 @@ void MD5Transform(Uint32 buf[4], Uint32 const in[16])
* Start MD5 accumulation. Set bit count to 0 and buffer to mysterious
* initialization constants.
*/
-Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
+void md5_hash(Uint32 result[4], const Uint64* keybuf, Uint32 no_of_32_words)
{
-/*
- * This is the external interface of the module
- * It is assumed that keybuf is placed on 8 byte
- * alignment.
- */
+ /**
+ * This is the external interface of the module
+ * It is assumed that keybuf is placed on 8 byte
+ * alignment.
+ */
Uint32 i;
Uint32 buf[4];
Uint64 transform64_buf[8];
@@ -230,6 +230,10 @@ Uint32 md5_hash(const Uint64* keybuf, Uint32 no_of_32_words)
byteReverse((unsigned char *)transform32_buf, 16);
MD5Transform(buf, transform32_buf);
}
- return buf[0];
+
+ result[0] = buf[0];
+ result[1] = buf[1];
+ result[2] = buf[2];
+ result[3] = buf[3];
}
diff --git a/ndb/src/common/util/socket_io.cpp b/ndb/src/common/util/socket_io.cpp
index 6f4c7e63684..83a546de773 100644
--- a/ndb/src/common/util/socket_io.cpp
+++ b/ndb/src/common/util/socket_io.cpp
@@ -172,22 +172,21 @@ vprint_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
const char * fmt, va_list ap){
char buf[1000];
char *buf2 = buf;
- size_t size = sizeof(buf);
+ size_t size;
- if (fmt != 0) {
+ if (fmt != 0 && fmt[0] != 0) {
size = BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
/* Check if the output was truncated */
- if(size >= sizeof(buf)) {
- buf2 = (char *)malloc(size+1);
+ if(size > sizeof(buf)) {
+ buf2 = (char *)malloc(size);
if(buf2 == NULL)
return -1;
BaseString::vsnprintf(buf2, size, fmt, ap);
- } else
- size = sizeof(buf);
+ }
} else
- buf[0] = 0;
+ return 0;
- int ret = write_socket(socket, timeout_millis, buf2, strlen(buf2));
+ int ret = write_socket(socket, timeout_millis, buf2, size);
if(buf2 != buf)
free(buf2);
return ret;
@@ -199,23 +198,23 @@ vprintln_socket(NDB_SOCKET_TYPE socket, int timeout_millis,
const char * fmt, va_list ap){
char buf[1000];
char *buf2 = buf;
- size_t size = sizeof(buf);
+ size_t size;
- if (fmt != 0) {
- size = BaseString::vsnprintf(buf, sizeof(buf), fmt, ap);
+ if (fmt != 0 && fmt[0] != 0) {
+ size = BaseString::vsnprintf(buf, sizeof(buf), fmt, ap)+1;// extra byte for '/n'
/* Check if the output was truncated */
- if(size >= sizeof(buf)-1) {
- buf2 = (char *)malloc(size+2);
+ if(size > sizeof(buf)) {
+ buf2 = (char *)malloc(size);
if(buf2 == NULL)
return -1;
- BaseString::vsnprintf(buf2, size+1, fmt, ap);
- } else
- size = sizeof(buf);
- } else
- buf[0] = 0;
- strlcat(buf2, "\n", size+2);
+ BaseString::vsnprintf(buf2, size, fmt, ap);
+ }
+ } else {
+ size = 1;
+ }
+ buf2[size-1]='\n';
- int ret = write_socket(socket, timeout_millis, buf2, strlen(buf2));
+ int ret = write_socket(socket, timeout_millis, buf2, size);
if(buf2 != buf)
free(buf2);
return ret;
diff --git a/ndb/src/common/util/strlcat.c b/ndb/src/common/util/strlcat.c
deleted file mode 100644
index aa282abe48d..00000000000
--- a/ndb/src/common/util/strlcat.c
+++ /dev/null
@@ -1,48 +0,0 @@
-/*
- * Copyright (c) 1995 - 1999 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <ndb_global.h>
-
-/* RCSID("$KTH: strlcat.c,v 1.1 2000/08/16 01:23:47 lha Exp $"); */
-
-
-#ifndef HAVE_STRLCAT
-
-size_t
-strlcat (char *dst, const char *src, size_t dst_sz)
-{
- size_t len = strlen(dst);
-
- return len + strlcpy (dst + len, src, dst_sz - len);
-}
-#endif
diff --git a/ndb/src/common/util/strlcpy.c b/ndb/src/common/util/strlcpy.c
deleted file mode 100644
index 97cff177d48..00000000000
--- a/ndb/src/common/util/strlcpy.c
+++ /dev/null
@@ -1,57 +0,0 @@
-/*
- * Copyright (c) 1995 - 1999 Kungliga Tekniska Högskolan
- * (Royal Institute of Technology, Stockholm, Sweden).
- * All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *
- * 1. Redistributions of source code must retain the above copyright
- * notice, this list of conditions and the following disclaimer.
- *
- * 2. Redistributions in binary form must reproduce the above copyright
- * notice, this list of conditions and the following disclaimer in the
- * documentation and/or other materials provided with the distribution.
- *
- * 3. Neither the name of the Institute nor the names of its contributors
- * may be used to endorse or promote products derived from this software
- * without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
- * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
- * ARE DISCLAIMED. IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
- * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
- * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
- * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
- * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
- * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
- * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
- * SUCH DAMAGE.
- */
-
-#include <ndb_global.h>
-
-/* RCSID("$KTH: strlcpy.c,v 1.1 2000/08/16 01:23:48 lha Exp $"); */
-
-#ifndef HAVE_STRLCPY
-
-size_t
-strlcpy (char *dst, const char *src, size_t dst_sz)
-{
- size_t n;
- char *p;
-
- for (p = dst, n = 0;
- n + 1 < dst_sz && *src != '\0';
- ++p, ++src, ++n)
- *p = *src;
- *p = '\0';
- if (*src == '\0')
- return n;
- else
- return n + strlen (src);
-}
-
-#endif
diff --git a/ndb/src/common/util/version.c b/ndb/src/common/util/version.c
index 965d0a735e1..7a537297861 100644
--- a/ndb/src/common/util/version.c
+++ b/ndb/src/common/util/version.c
@@ -70,7 +70,6 @@ struct NdbUpGradeCompatible {
#ifndef TEST_VERSION
struct NdbUpGradeCompatible ndbCompatibleTable_full[] = {
{ MAKE_VERSION(3,5,2), MAKE_VERSION(3,5,1), UG_Exact },
- { MAKE_VERSION(4,1,8), MAKE_VERSION(3,5,4), UG_Exact }, /* Aligned version with MySQL */
{ 0, 0, UG_Null }
};
diff --git a/ndb/src/cw/Makefile_old b/ndb/src/cw/Makefile_old
deleted file mode 100644
index e710c1e244d..00000000000
--- a/ndb/src/cw/Makefile_old
+++ /dev/null
@@ -1,6 +0,0 @@
-include .defs.mk
-
-DIRS := cpcd
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/src/cw/cpcc-win32/csharp/AssemblyInfo.cs b/ndb/src/cw/cpcc-win32/csharp/AssemblyInfo.cs
deleted file mode 100644
index 9f89a3282c5..00000000000
--- a/ndb/src/cw/cpcc-win32/csharp/AssemblyInfo.cs
+++ /dev/null
@@ -1,58 +0,0 @@
-using System.Reflection;
-using System.Runtime.CompilerServices;
-
-//
-// General Information about an assembly is controlled through the following
-// set of attributes. Change these attribute values to modify the information
-// associated with an assembly.
-//
-[assembly: AssemblyTitle("")]
-[assembly: AssemblyDescription("")]
-[assembly: AssemblyConfiguration("")]
-[assembly: AssemblyCompany("")]
-[assembly: AssemblyProduct("")]
-[assembly: AssemblyCopyright("")]
-[assembly: AssemblyTrademark("")]
-[assembly: AssemblyCulture("")]
-
-//
-// Version information for an assembly consists of the following four values:
-//
-// Major Version
-// Minor Version
-// Build Number
-// Revision
-//
-// You can specify all the values or you can default the Revision and Build Numbers
-// by using the '*' as shown below:
-
-[assembly: AssemblyVersion("1.0.*")]
-
-//
-// In order to sign your assembly you must specify a key to use. Refer to the
-// Microsoft .NET Framework documentation for more information on assembly signing.
-//
-// Use the attributes below to control which key is used for signing.
-//
-// Notes:
-// (*) If no key is specified, the assembly is not signed.
-// (*) KeyName refers to a key that has been installed in the Crypto Service
-// Provider (CSP) on your machine. KeyFile refers to a file which contains
-// a key.
-// (*) If the KeyFile and the KeyName values are both specified, the
-// following processing occurs:
-// (1) If the KeyName can be found in the CSP, that key is used.
-// (2) If the KeyName does not exist and the KeyFile does exist, the key
-// in the KeyFile is installed into the CSP and used.
-// (*) In order to create a KeyFile, you can use the sn.exe (Strong Name) utility.
-// When specifying the KeyFile, the location of the KeyFile should be
-// relative to the project output directory which is
-// %Project Directory%\obj\<configuration>. For example, if your KeyFile is
-// located in the project directory, you would specify the AssemblyKeyFile
-// attribute as [assembly: AssemblyKeyFile("..\\..\\mykey.snk")]
-// (*) Delay Signing is an advanced option - see the Microsoft .NET Framework
-// documentation for more information on this.
-//
-[assembly: AssemblyDelaySign(false)]
-[assembly: AssemblyKeyFile("")]
-[assembly: AssemblyKeyName("")]
diff --git a/ndb/src/cw/cpcc-win32/vb6/frmSplash.frm b/ndb/src/cw/cpcc-win32/vb6/frmSplash.frm
deleted file mode 100644
index 56ccbd79876..00000000000
--- a/ndb/src/cw/cpcc-win32/vb6/frmSplash.frm
+++ /dev/null
@@ -1,159 +0,0 @@
-VERSION 5.00
-Begin VB.Form frmSplash
- BorderStyle = 3 'Fixed Dialog
- ClientHeight = 4710
- ClientLeft = 45
- ClientTop = 45
- ClientWidth = 7455
- ControlBox = 0 'False
- LinkTopic = "Form1"
- MaxButton = 0 'False
- MinButton = 0 'False
- ScaleHeight = 4710
- ScaleWidth = 7455
- ShowInTaskbar = 0 'False
- StartUpPosition = 2 'CenterScreen
- Visible = 0 'False
- Begin VB.Frame fraMainFrame
- Height = 4590
- Left = 45
- TabIndex = 0
- Top = -15
- Width = 7380
- Begin VB.PictureBox picLogo
- Height = 2385
- Left = 510
- Picture = "frmSplash.frx":0000
- ScaleHeight = 2325
- ScaleWidth = 1755
- TabIndex = 2
- Top = 855
- Width = 1815
- End
- Begin VB.Label lblLicenseTo
- Alignment = 1 'Right Justify
- Caption = "LicenseTo"
- Height = 255
- Left = 270
- TabIndex = 1
- Tag = "LicenseTo"
- Top = 300
- Width = 6855
- End
- Begin VB.Label lblProductName
- AutoSize = -1 'True
- Caption = "Product"
- BeginProperty Font
- Name = "MS Sans Serif"
- Size = 29.25
- Charset = 0
- Weight = 700
- Underline = 0 'False
- Italic = 0 'False
- Strikethrough = 0 'False
- EndProperty
- Height = 720
- Left = 2670
- TabIndex = 9
- Tag = "Product"
- Top = 1200
- Width = 2190
- End
- Begin VB.Label lblCompanyProduct
- AutoSize = -1 'True
- Caption = "CompanyProduct"
- BeginProperty Font
- Name = "MS Sans Serif"
- Size = 18
- Charset = 0
- Weight = 700
- Underline = 0 'False
- Italic = 0 'False
- Strikethrough = 0 'False
- EndProperty
- Height = 435
- Left = 2505
- TabIndex = 8
- Tag = "CompanyProduct"
- Top = 765
- Width = 3000
- End
- Begin VB.Label lblPlatform
- Alignment = 1 'Right Justify
- AutoSize = -1 'True
- Caption = "Platform"
- BeginProperty Font
- Name = "MS Sans Serif"
- Size = 13.5
- Charset = 0
- Weight = 700
- Underline = 0 'False
- Italic = 0 'False
- Strikethrough = 0 'False
- EndProperty
- Height = 360
- Left = 5865
- TabIndex = 7
- Tag = "Platform"
- Top = 2400
- Width = 1140
- End
- Begin VB.Label lblVersion
- Alignment = 1 'Right Justify
- AutoSize = -1 'True
- Caption = "Version"
- BeginProperty Font
- Name = "MS Sans Serif"
- Size = 12
- Charset = 0
- Weight = 700
- Underline = 0 'False
- Italic = 0 'False
- Strikethrough = 0 'False
- EndProperty
- Height = 300
- Left = 6075
- TabIndex = 6
- Tag = "Version"
- Top = 2760
- Width = 930
- End
- Begin VB.Label lblWarning
- Caption = "Warning"
- Height = 195
- Left = 300
- TabIndex = 3
- Tag = "Warning"
- Top = 3720
- Width = 6855
- End
- Begin VB.Label lblCompany
- Caption = "Company"
- Height = 255
- Left = 4710
- TabIndex = 5
- Tag = "Company"
- Top = 3330
- Width = 2415
- End
- Begin VB.Label lblCopyright
- Caption = "Copyright"
- Height = 255
- Left = 4710
- TabIndex = 4
- Tag = "Copyright"
- Top = 3120
- Width = 2415
- End
- End
-End
-Attribute VB_Name = "frmSplash"
-Attribute VB_GlobalNameSpace = False
-Attribute VB_Creatable = False
-Attribute VB_PredeclaredId = True
-Attribute VB_Exposed = False
-Private Sub Form_Load()
- lblVersion.Caption = "Version " & App.Major & "." & App.Minor & "." & App.Revision
- lblProductName.Caption = App.Title
-End Sub
-
diff --git a/ndb/src/cw/cpcd/Makefile_old b/ndb/src/cw/cpcd/Makefile_old
deleted file mode 100644
index f214fb087d2..00000000000
--- a/ndb/src/cw/cpcd/Makefile_old
+++ /dev/null
@@ -1,11 +0,0 @@
-include .defs.mk
-
-TYPE := util
-BIN_TARGET := ndb_cpcd
-
-# Source files of non-templated classes (.cpp files)
-SOURCES = main.cpp CPCD.cpp Process.cpp APIService.cpp Monitor.cpp common.cpp
-
-BIN_TARGET_LIBS += logger
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/cw/cpcd/common.cpp b/ndb/src/cw/cpcd/common.cpp
index cb1c0c37183..53c0e4d5a64 100644
--- a/ndb/src/cw/cpcd/common.cpp
+++ b/ndb/src/cw/cpcd/common.cpp
@@ -96,66 +96,3 @@ insert_file(const char * filename, class Properties& p){
if(f) fclose(f);
return res;
}
-
-int
-parse_config_file(struct getargs args[], int num_arg, const Properties& p){
- Properties::Iterator it(&p);
- for(const char * name = it.first(); name != 0; name = it.next()){
- bool found = false;
- for(int i = 0; i<num_arg; i++){
- if(strcmp(name, args[i].long_name) != 0)
- continue;
-
- found = true;
-
- const char * tmp;
- p.get(name, &tmp);
-
- int t = 1;
-
- switch(args[i].type){
- case arg_integer:{
- int val = atoi(tmp);
- if(args[i].value){
- *((int*)args[i].value) = val;
- }
- }
- break;
- case arg_string:
- if(args[i].value){
- *((const char**)args[i].value) = tmp;
- }
- break;
- case arg_negative_flag:
- t = 0;
- case arg_flag:
- if(args[i].value){
- if(!strcasecmp(tmp, "y") ||
- !strcasecmp(tmp, "on") ||
- !strcasecmp(tmp, "true") ||
- !strcasecmp(tmp, "1")){
- *((int*)args[i].value) = t;
- }
- if(!strcasecmp(tmp, "n") ||
- !strcasecmp(tmp, "off") ||
- !strcasecmp(tmp, "false") ||
- !strcasecmp(tmp, "0")){
- *((int*)args[i].value) = t;
- }
- }
- t = 1;
- break;
- case arg_strings:
- case arg_double:
- case arg_collect:
- case arg_counter:
- break;
- }
- }
- if(!found) {
- printf("Unknown parameter: %s\n", name);
- return 1;
- }
- }
- return 0;
-}
diff --git a/ndb/src/cw/cpcd/common.hpp b/ndb/src/cw/cpcd/common.hpp
index c3d87b8b9f5..4f5f702762f 100644
--- a/ndb/src/cw/cpcd/common.hpp
+++ b/ndb/src/cw/cpcd/common.hpp
@@ -19,7 +19,9 @@
#include <ndb_global.h>
#include <logger/Logger.hpp>
+#if 0
#include <getarg.h>
+#endif
extern int debug;
@@ -30,6 +32,5 @@ int insert(const char * pair, class Properties & p);
int insert_file(const char * filename, class Properties&);
int insert_file(FILE *, class Properties&, bool break_on_empty = false);
-int parse_config_file(struct getargs args[], int num_arg, const Properties& p);
#endif /* ! __CPCD_COMMON_HPP_INCLUDED__ */
diff --git a/ndb/src/cw/cpcd/main.cpp b/ndb/src/cw/cpcd/main.cpp
index 207b81bfa89..300b51d7b5a 100644
--- a/ndb/src/cw/cpcd/main.cpp
+++ b/ndb/src/cw/cpcd/main.cpp
@@ -15,13 +15,13 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h> /* Needed for mkdir(2) */
+#include <ndb_opts.h>
#include "CPCD.hpp"
#include "APIService.hpp"
#include <NdbMain.h>
#include <NdbSleep.h>
#include <BaseString.hpp>
-#include <getarg.h>
#include <logger/Logger.hpp>
#include <logger/FileLogHandler.hpp>
#include <logger/SysLogHandler.hpp>
@@ -29,28 +29,44 @@
#include "common.hpp"
static const char *work_dir = CPCD_DEFAULT_WORK_DIR;
-static int port = CPCD_DEFAULT_TCP_PORT;
-static int use_syslog = 0;
+static int port;
+static int use_syslog;
static const char *logfile = NULL;
static const char *config_file = CPCD_DEFAULT_CONFIG_FILE;
static const char *user = 0;
-static struct getargs args[] = {
- { "work-dir", 'w', arg_string, &work_dir,
- "Work directory", "directory" },
- { "port", 'p', arg_integer, &port,
- "TCP port to listen on", "port" },
- { "syslog", 'S', arg_flag, &use_syslog,
- "Log events to syslog", NULL},
- { "logfile", 'L', arg_string, &logfile,
- "File to log events to", "file"},
- { "debug", 'D', arg_flag, &debug,
- "Enable debug mode", NULL},
- { "config", 'c', arg_string, &config_file, "Config file", NULL },
- { "user", 'u', arg_string, &user, "Run as user", NULL }
+static struct my_option my_long_options[] =
+{
+ { "work-dir", 'w', "Work directory",
+ (gptr*) &work_dir, (gptr*) &work_dir, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "port", 'p', "TCP port to listen on",
+ (gptr*) &port, (gptr*) &port, 0,
+ GET_INT, REQUIRED_ARG, CPCD_DEFAULT_TCP_PORT, 0, 0, 0, 0, 0 },
+ { "syslog", 'S', "Log events to syslog",
+ (gptr*) &use_syslog, (gptr*) &use_syslog, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "logfile", 'L', "File to log events to",
+ (gptr*) &logfile, (gptr*) &logfile, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "debug", 'D', "Enable debug mode",
+ (gptr*) &debug, (gptr*) &debug, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "config", 'c', "Config file",
+ (gptr*) &config_file, (gptr*) &config_file, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "user", 'u', "Run as user",
+ (gptr*) &user, (gptr*) &user, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-static const int num_args = sizeof(args) / sizeof(args[0]);
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ return 0;
+}
static CPCD * g_cpcd = 0;
#if 0
@@ -59,23 +75,16 @@ extern "C" static void sig_child(int signo, siginfo_t*, void*);
const char *progname = "ndb_cpcd";
-NDB_MAIN(ndb_cpcd){
- int optind = 0;
-
- if(getarg(args, num_args, argc, argv, &optind)) {
- arg_printusage(args, num_args, progname, "");
- exit(1);
- }
-
- Properties p;
- insert_file(config_file, p);
- if(parse_config_file(args, num_args, p)){
- ndbout_c("Invalid config file: %s", config_file);
- exit(1);
- }
+int main(int argc, char** argv){
+ int save_argc= argc;
+ char** save_argv= argv;
+ const char *load_default_groups[]= { "ndb_cpcd",0 };
+ MY_INIT(argv[0]);
- if(getarg(args, num_args, argc, argv, &optind)) {
- arg_printusage(args, num_args, progname, "");
+ load_defaults("ndb_cpcd",load_default_groups,&argc,&argv);
+ if (handle_options(&argc, &argv, my_long_options, get_one_option)) {
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
exit(1);
}
diff --git a/ndb/src/external/LINUX.x86/sci/include/list.h b/ndb/src/external/LINUX.x86/sci/include/list.h
deleted file mode 100644
index 81c467a461b..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/list.h
+++ /dev/null
@@ -1,56 +0,0 @@
-/* $Id: list.h,v 1.1 2002/12/13 12:17:20 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-
-#ifndef _LIST_H
-#define _LIST_H
-#include "sci_types.h"
-
-
-typedef struct ListElement *ListElement_t;
-typedef struct List *List_t;
-
-struct ListElement {
- void *element;
- u_vkaddr_t key;
- ListElement_t prev,next;
-};
-
-void *Get_Element(ListElement_t el);
-void Set_Element(ListElement_t el,void *elptr,u_vkaddr_t key);
-void Create_Element(ListElement_t *el);
-void Destroy_Element(ListElement_t *el);
-void Create_List(List_t *list);
-void Destroy_List(List_t *list);
-void Add_Element(List_t list,ListElement_t el);
-void Remove_Element(List_t list,ListElement_t el);
-ListElement_t Find_Element(List_t list,u_vkaddr_t key);
-scibool List_Empty(List_t);
-scibool List_Elements(List_t);
-ListElement_t First_Element(List_t list);
-ListElement_t Last_Element(List_t list);
-ListElement_t Next_Element(ListElement_t el);
-
-#endif /* _LIST_H */
diff --git a/ndb/src/external/LINUX.x86/sci/include/os/inttypes.h b/ndb/src/external/LINUX.x86/sci/include/os/inttypes.h
deleted file mode 100644
index b9e5a6cb19f..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/os/inttypes.h
+++ /dev/null
@@ -1,53 +0,0 @@
-/* $Id: inttypes.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-#ifndef _SCI_OS_INTTYPES_H_
-#define _SCI_OS_INTTYPES_H_
-
-/*
- * --------------------------------------------------------------------------------------
- * Basic types of various sizes.
- * --------------------------------------------------------------------------------------
- */
-typedef unsigned char unsigned8;
-typedef unsigned short unsigned16;
-typedef unsigned int unsigned32;
-typedef unsigned long long unsigned64;
-
-typedef signed char signed8;
-typedef signed short signed16;
-typedef signed int signed32;
-typedef signed long long signed64;
-
-
-#ifdef CPU_WORD_IS_64_BIT
-typedef unsigned64 uptr_t;
-typedef signed64 iptr_t;
-#else
-typedef unsigned32 uptr_t;
-typedef signed32 iptr_t;
-#endif
-
-#endif /* _SCI_OS_INTTYPES_H_ */
diff --git a/ndb/src/external/LINUX.x86/sci/include/rmlib.h b/ndb/src/external/LINUX.x86/sci/include/rmlib.h
deleted file mode 100644
index 9d2722e9798..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/rmlib.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* $Id: rmlib.h,v 1.1 2002/12/13 12:17:20 hin Exp $ */
-
-/*********************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Lesser General Public License as published by *
- * the Free Software Foundation; either version 2.1 of the License, *
- * or (at your option) any later version. *
- * *
- * 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 Lesser General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *********************************************************************************/
-
-/********************************************************************************/
-/* This header file contains the declarations of the SCI Reflective Memory */
-/* library rmlib. The implementation of the library functions is in rmlib.c. */
-/* The library contains all the functions that operate on the reflective */
-/* memory. */
-/* */
-/* NB! */
-/* */
-/* DOLPHIN'S SCI REFLECTIVE MEMORY FILES ARE UNDER DEVELOPMENT AND MAY CHANGE. */
-/* PLEASE CONTACT DOLPHIN FOR FURTHER INFORMATION. */
-/* */
-/* */
-/********************************************************************************/
-
-#include "sisci_error.h"
-#include "sisci_api.h"
-#include "sisci_demolib.h"
-#include "sisci_types.h"
-
-unsigned int seqerr, syncseqerr;
-
-#ifndef _RMLIB_H
-#define _RMLIB_H
-
-
-#if defined(_REENTRANT)
-
-#define _RMLIB_EXPAND_NAME(name) _RMLIB_MT_ ## name
-
-#else
-
-#define _RMLIB_EXPAND_NAME(name) _RMLIB_ST_ ## name
-
-#endif
-
-#ifdef __sparc
-#define CACHE_SIZE 2097152
-#else
-#define CACHE_SIZE 8192
-#endif
-
-/*********************************************************************************/
-/* FLAG VALUES */
-/*********************************************************************************/
-
-#define REFLECT_ERRCHECK 0x2
-
-struct ReflectiveMemorySpace {
- unsigned int localAdapterNo;
- unsigned int localNodeId;
- unsigned int remoteNodeId;
- sci_desc_t sd;
- sci_desc_t syncsd;
- sci_map_t localMap;
- sci_map_t remoteMap;
- unsigned int localSegmentId;
- unsigned int remoteSegmentId;
- unsigned int syncSegmentId;
- unsigned int sync_rSegmentId;
- unsigned int segmentSize;
- unsigned int *localMapAddr;
- volatile unsigned int *remoteMapAddr;
- sci_local_segment_t localSegment;
- sci_remote_segment_t remoteSegment;
- sci_local_segment_t syncSegment;
- sci_remote_segment_t sync_rSegment;
- sci_map_t syncMap;
- sci_map_t sync_rMap;
- sci_sequence_t syncsequence;
- sci_sequence_t sequence;
- unsigned int protection;
- unsigned int retry_value;
- sci_sequence_status_t sequenceStatus, syncsequenceStatus;
- volatile unsigned int *syncMapAddr;
- volatile unsigned int *sync_rMapAddr;
-};
-
-/*********************************************************************************/
-/* P R I N T R E F L E C T I V E M E M O R Y S P A C E */
-/* */
-/*********************************************************************************/
-#define ReflectPrintParameters _RMLIB_EXPAND_NAME(ReflectPrintParameters)
-void ReflectPrintParameters(FILE *stream, struct ReflectiveMemorySpace RM_space);
-
-/*********************************************************************************/
-/* R E F L E C T D M A S E T U P */
-/* */
-/*********************************************************************************/
-#define ReflectDmaSetup _RMLIB_EXPAND_NAME(ReflectDmaSetup)
-sci_error_t ReflectDmaSetup(struct ReflectiveMemorySpace RM_space, sci_dma_queue_t *dmaQueue);
-
-/*********************************************************************************/
-/* R E F L E C T D M A R E M O V E */
-/* */
-/*********************************************************************************/
-#define ReflectDmaRemove _RMLIB_EXPAND_NAME(ReflectDmaRemove)
-sci_error_t ReflectDmaRemove(sci_dma_queue_t dmaQueue);
-
-/*********************************************************************************/
-/* R E F L E C T D M A R U N */
-/* */
-/*********************************************************************************/
-#define ReflectDmaRun _RMLIB_EXPAND_NAME(ReflectDmaRun)
-sci_error_t ReflectDmaRun(struct ReflectiveMemorySpace RM_space,
- unsigned int* privateSrc,
- unsigned int size,
- unsigned int offset,
- sci_dma_queue_t dmaQueue);
-/*********************************************************************************/
-/* C L O S E R E F L E C T I V E M E M O R Y S P A C E */
-/* */
-/*********************************************************************************/
-#define ReflectClose _RMLIB_EXPAND_NAME(ReflectClose)
-sci_error_t ReflectClose(struct ReflectiveMemorySpace RM_space, unsigned int segment_no);
-
-/*********************************************************************************/
-/* O P E N R E F L E C T I V E M E M O R Y S P A C E */
-/* */
-/*********************************************************************************/
-#define ReflectOpen _RMLIB_EXPAND_NAME(ReflectOpen)
-sci_error_t ReflectOpen(struct ReflectiveMemorySpace *RM_space,
- unsigned int size,
- unsigned int segment_no,
- unsigned int localAdapterNo,
- unsigned int remoteNodeId,
- unsigned int protection,
- unsigned int retry_value);
-
-/*********************************************************************************/
-/* R E F L E C T G E T A C C E S S */
-/* */
-/*********************************************************************************/
-#define ReflectGetAccess _RMLIB_EXPAND_NAME(ReflectGetAccess)
-sci_error_t ReflectGetAccess(struct ReflectiveMemorySpace *RM_space);
-
-/*********************************************************************************/
-/* R E F L E C T R E L E A S E A C C E S S */
-/* */
-/*********************************************************************************/
-#define ReflectReleaseAccess _RMLIB_EXPAND_NAME(ReflectReleaseAccess)
-sci_error_t ReflectReleaseAccess(struct ReflectiveMemorySpace *RM_space);
-
-/*********************************************************************************/
-/* R E F L E C T D M A */
-/* */
-/*********************************************************************************/
-#define ReflectDma _RMLIB_EXPAND_NAME(ReflectDma)
-sci_error_t ReflectDma(struct ReflectiveMemorySpace RM_space,
- unsigned int* privateSrc,
- unsigned int size,
- unsigned int offset);
-
-/*********************************************************************************/
-/* R E F L E C T M E M C O P Y */
-/* */
-/*********************************************************************************/
-#define ReflectMemCopy _RMLIB_EXPAND_NAME(ReflectMemCopy)
-sci_error_t ReflectMemCopy(struct ReflectiveMemorySpace RM_space,
- unsigned int* privateSrc,
- unsigned int size,
- unsigned int offset,
- unsigned int flags);
-
-/*********************************************************************************/
-/* R E F L E C T S E T */
-/* */
-/*********************************************************************************/
-#define ReflectSet _RMLIB_EXPAND_NAME(ReflectSet)
-sci_error_t ReflectSet(struct ReflectiveMemorySpace RM_space,
- unsigned int value,
- unsigned int size,
- unsigned int offset,
- unsigned int flags
- );
-
-/*********************************************************************************/
-/* R E F L E C T P R I N T */
-/* */
-/*********************************************************************************/
-#define ReflectPrint _RMLIB_EXPAND_NAME(ReflectPrint)
-sci_error_t ReflectPrint(FILE *stream,
- struct ReflectiveMemorySpace RM_space,
- unsigned int size,
- unsigned int offset
- );
-
-
-#endif
diff --git a/ndb/src/external/LINUX.x86/sci/include/sci_errno.h b/ndb/src/external/LINUX.x86/sci/include/sci_errno.h
deleted file mode 100644
index 03f3256a86f..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/sci_errno.h
+++ /dev/null
@@ -1,216 +0,0 @@
-/* $Id: sci_errno.h,v 1.1 2002/12/13 12:17:20 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-
-#ifndef _SCI_ERRNO_H_
-#define _SCI_ERRNO_H_
-
-
-/*
- * SCI Error return values always have 30 bit set
- * Remote errors should have bit 0 set
- */
-#define SCI_ERR_MASK 0x40000000
-#define ESCI_REMOTE_MASK 0x01000000
-
-#define SCI_ERR(u) ((unsigned32)(u)&0x7FFFFFFF )
-#define _SCI_ERROR(x) ((x) | SCI_ERR_MASK)
-#define _SCI_REMOTE_ERROR(x) ( _SCI_ERROR(x) | ESCI_REMOTE_MASK )
-
-/*
- * Error codes
- */
-typedef enum {
- ESCI_OK = 0x000,
- ESCI_STILL_EXPORTED = _SCI_ERROR(0x800),
-
- ESCI_BUS_ERR = _SCI_ERROR(0x900),
- ESCI_PEND_SCIERR = _SCI_ERROR(0x901),
- ESCI_SCI_ERR = _SCI_ERROR(0x902),
-
- /*
- * Specific SCI error responses:
- */
- ESCI_SCI_ERR_DATA = _SCI_ERROR(0x9021),
- ESCI_SCI_ERR_TYPE = _SCI_ERROR(0x9022),
- ESCI_SCI_ERR_ADDR = _SCI_ERROR(0x9023),
-
- ESCI_LINK_TIMEOUT = _SCI_ERROR(0x903),
- ESCI_EXDEV_TIMEOUT = _SCI_ERROR(0x904),
- ESCI_REMOTE_ERR = _SCI_ERROR(0x905),
- ESCI_MBX_BUSY = _SCI_ERROR(0x906),
- ESCI_DMAERR = _SCI_ERROR(0x907),
- ESCI_DMA_DISABLED = _SCI_ERROR(0x908),
- ESCI_SW_MBX_SEND_FAILED = _SCI_ERROR(0x909),
- ESCI_HW_MBX_SEND_FAILED = _SCI_ERROR(0x90A),
- ESCI_HAS_NO_SESSION = _SCI_ERROR(0xA00),
- ESCI_CONNREFUSED_SESSION = _SCI_ERROR(0xA01),
- ESCI_SESSION_NOT_ESTABLISHED = _SCI_ERROR(0xA11),
- ESCI_REMOTE_NO_VALID_SESSION = _SCI_ERROR(0xA02),
- ESCI_SESSION_DISABLED = _SCI_ERROR(0xA03),
- ESCI_NODE_CLOSED = _SCI_ERROR(0xA04),
- ESCI_NODE_DISABLED = _SCI_ERROR(0xA05),
-
- ESCI_LOCAL_MASTER_ERR = _SCI_ERROR(0xA06),
- ESCI_REMOTE_MASTER_ERR = _SCI_REMOTE_ERROR(0xA06),
-
- ESCI_ILLEGAL_CMD_RECEIVED = _SCI_ERROR(0xA08),
- ESCI_ILLEGAL_CMD_SENT = _SCI_ERROR(0xA09),
-
- /* used above: ESCI_SESSION_NOT_ESTABLISHED = _SCI_ERROR(0xA11), */
-
- /*
- * Remote error codes
- */
- ESCI_CONNREFUSED = _SCI_ERROR(0xB00),
- ESCI_NODE_NOT_RESPONDING = _SCI_ERROR(0xB01),
- ESCI_ISCONN = _SCI_ERROR(0xB02),
- ESCI_HOSTUNREACH = _SCI_ERROR(0xB03),
- ESCI_NO_SUCH_USER_ID = _SCI_ERROR(0xB04),
- ESCI_REMOTE_NO_SUCH_USER_ID = _SCI_REMOTE_ERROR(0xB04), /* ESCI_NO_SUCH_USER_ID */
- ESCI_NO_SUCH_KEY = _SCI_ERROR(0xB04), /* ESCI_NO_SUCH_USER_ID */
- ESCI_REMOTE_NO_SUCH_KEY = _SCI_REMOTE_ERROR(0xB04), /* ESCI_REMOTE_NO_SUCH_USER_ID */
- ESCI_NODE_ERR = _SCI_ERROR(0xB06),
- ESCI_REMOTE_NODE_ERR = _SCI_REMOTE_ERROR(0xB06), /* ESCI_NODE_ERR */
- ESCI_NOSPC = _SCI_ERROR(0xB08),
- ESCI_REMOTE_NOSPC = _SCI_REMOTE_ERROR(0xB08), /* ESCI_NOSPC */
- ESCI_NODMASPC = _SCI_ERROR(0xB0A),
- ESCI_REMOTE_NODMASPC = _SCI_REMOTE_ERROR(0xB0A), /* ESCI_NODMASPC */
- ESCI_NOTMAP = _SCI_ERROR(0xC00),
- ESCI_ISMAP = _SCI_ERROR(0xC01),
- ESCI_NOT_INITIALIZED = _SCI_ERROR(0xD00),
- ESCI_REMOTE_NOT_INITIALIZED = _SCI_REMOTE_ERROR(ESCI_NOT_INITIALIZED),
- /*
- * ???
- */
- ESCI_PARAM_ERR = _SCI_ERROR(0xD01),
- ESCI_NO_FREE_VC = _SCI_ERROR(0xD02),
- ESCI_REMOTE_NO_FREE_VC = _SCI_REMOTE_ERROR(0xD02), /* ESCI_NO_FREE_VC */
-
- /*
- * Adapter state related error codes:
- */
- ESCI_SUSPENDED = _SCI_ERROR(0xD03),
- ESCI_NOT_SUSPENDED = _SCI_ERROR(0xD04),
- ESCI_NOT_READY = _SCI_ERROR(0xD05),
- ESCI_NOT_CONFIGURED = _SCI_ERROR(0xD06),
- ESCI_INVALID_ADAPTERID = _SCI_ERROR(0xD07), /* if an adapter-id is out of range */
- ESCI_NONEXIST_ADAPTERID = _SCI_ERROR(0xD08), /* if adapter-id is valid but no adapter matches */
- ESCI_ADAPTERID_INUSE = _SCI_ERROR(0xD09),
-
- ESCI_INVALID_INSTANCE = _SCI_ERROR(0xD0A),
- ESCI_NONEXIST_INSTANCE = _SCI_ERROR(0xD0B),
-
- ESCI_ADAPTER_INIT_FAILURE = _SCI_ERROR(0xD0C),
-
- ESCI_PAUSED = _SCI_ERROR(0xD0D),
- ESCI_NOT_PAUSED = _SCI_ERROR(0xD0E),
- ESCI_ADAPTER_NEED_RESET = _SCI_ERROR(0xD0F),
-
- ESCI_NONEXIST_SERIAL_NUMBER = _SCI_ERROR(0xD10),
- ESCI_NOT_AVAILABLE = _SCI_ERROR(0xD11),
-
- ESCI_EACCESS = _SCI_ERROR(0xD12),
-
- /*
- * Local error codes
- */
- ESCI_NO_LOCAL_ACCESS = _SCI_ERROR(0xE00),
- ESCI_LRESOURCE_BUSY = _SCI_ERROR(0xE01),
- ESCI_LRESOURCE_EXIST = _SCI_ERROR(0xE02),
- ESCI_NO_LRESOURCE = _SCI_ERROR(0xE03),
- ESCI_NOTCONN = _SCI_ERROR(0xE04),
- ESCI_LOCAL_ERR = _SCI_ERROR(0xE05),
- ESCI_NOVAL_NODEID = _SCI_ERROR(0xE06),
- ESCI_NOT_SUPPORTED = _SCI_ERROR(0xE07),
- ESCI_TIMEOUT = _SCI_ERROR(0xE08),
- ESCI_NO_LOCAL_LC_ACCESS = _SCI_ERROR(0xE0A),
- ESCI_INVALID_ATT = _SCI_ERROR(0xE0B),
- ESCI_BAD_CHECKSUM = _SCI_ERROR(0xE0C),
- ESCI_INTERRUPT_FLAG_DISABLED = _SCI_ERROR(0xE0D),
- ESCI_COND_INT_RACE_PROBLEM = _SCI_ERROR(0xE0E),
- ESCI_OVERFLOW = _SCI_ERROR(0xE0F),
- ESCI_BLINK_PARITY_ERROR = _SCI_ERROR(0xE10),
- ESCI_FIRMWARE_VERSION_MISMATCH = _SCI_ERROR(0xE11),
-
- /*
- * Link error codes
- */
- ESCI_NO_LINK_ACCESS = _SCI_ERROR(0xF00),
- ESCI_NO_REMOTE_LINK_ACCESS = _SCI_REMOTE_ERROR(0xF00), /* ESCI_NO_LINK_ACCESS */
-
- ESCI_NO_SUCH_NODE = _SCI_ERROR(0xF02),
- ESCI_USR_ACCESS_DISABLED = _SCI_ERROR(0xF03),
- ESCI_HW_AVOID_DEADLOCK = _SCI_ERROR(0xF04),
- ESCI_POTENTIAL_ERROR = _SCI_ERROR(0xF05),
-
- ESCI_FENCED = _SCI_ERROR(0xF06),
- ESCI_SWITCH_HW_FAILURE = _SCI_ERROR(0xF07),
- ESCI_SWITCH_WRONG_BLINK_ID = _SCI_ERROR(0xF08),
- ESCI_SWITCH_WRONG_PORT_NUMB = _SCI_ERROR(0xF09),
- ESCI_SWITCH_WRONG_INIT_TYPE = _SCI_ERROR(0xF0A), /* It is determined that the swith initialization
- * do not match the local adapter initialization
- */
- ESCI_SWITCH_WRONG_SWITCH_NUMB = _SCI_ERROR(0xF0B), /* It is determined that we are operationg on the
- * wrong switch port
- */
- ESCI_SWITCH_NOT_CONNECTED = _SCI_ERROR(0xF0C),
- ESCI_SWITCH_NOT_RECOGNIZED = _SCI_ERROR(0xF0D),
- ESCI_SWITCH_INIT_IN_PROGRESS = _SCI_ERROR(0xF0E), /* Switch TINI initialization in progress */
-
-
- ESCI_NO_BACKBONE_LINK_ACCESS = _SCI_ERROR(0xF20),
- ESCI_BACKBONE_FENCED = _SCI_ERROR(0xF21),
- ESCI_NO_BACKBONE_ACCESS = _SCI_ERROR(0xF22),
- ESCI_BACKBONE_CABLE_PROBLEM = _SCI_ERROR(0xF23),
- ESCI_BACKBONE_BLINK_PROBLEM = _SCI_ERROR(0xF24),
- ESCI_BACKBONE_HWINIT_PROBLEM = _SCI_ERROR(0xF25),
- ESCI_BACKBONE_ID_PROBLEM = _SCI_ERROR(0xF26),
- ESCI_BACKBONE_STATE_PROBLEM = _SCI_ERROR(0xF27),
- ESCI_BACKBONE_REQ_LINK_PROBLEM = _SCI_ERROR(0xF28),
- ESCI_BACKBONE_UNFENCING = _SCI_ERROR(0xF29), /* Unfencing in progress */
-
- /*
- * added for pci port
- */
- ESCI_AGAIN = _SCI_ERROR(0xF15),
- ESCI_ORANGE = _SCI_ERROR(0xF16), /* Out of range */
- ESCI_NOSYS = _SCI_ERROR(0xF17), /* Used instead of ENOSYS. Means function not implemented */
- ESCI_REMOTE_NOSYS = _SCI_REMOTE_ERROR(ESCI_NOSYS),
- ESCI_INTR = _SCI_ERROR(0xF18), /* Used instead of EINTR from sys/errno.h */
- ESCI_IO = _SCI_ERROR(0xF19), /* Used instead of EIO from sys/errno.h */
- ESCI_FAULT = _SCI_ERROR(0xF1A), /* Used instead of EFAULT from sys/errno.h */
- ESCI_BUSY = _SCI_ERROR(0xF1B), /* Used instead of EBUST from sys/errno.h */
- ESCI_INVAL = _SCI_ERROR(0xF1C), /* Used instead of EINVAL from sys/errno.h */
- ESCI_NXIO = _SCI_ERROR(0xF1D), /* Used instead of ENXIO from sys/errno.h */
- ESCI_EXIST = _SCI_ERROR(0xF1E) /* Used instead of EEXIST from sys/errno.h */
-
-} scierror_t;
-
-#endif /* _SCI_ERRNO_H_ */
-
-
-
-
diff --git a/ndb/src/external/LINUX.x86/sci/include/sci_types.h b/ndb/src/external/LINUX.x86/sci/include/sci_types.h
deleted file mode 100644
index 740b3a45cfd..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/sci_types.h
+++ /dev/null
@@ -1,300 +0,0 @@
-/* $Id: sci_types.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-#ifndef _SCI_TYPES_H_
-#define _SCI_TYPES_H_
-
-/*
- * Remains for the time being for backward compatibility ....
- */
-
-/* #define UNIQUE(type) struct { type x; } * */
-#ifndef UNIQUE
-#define UNIQUE(type) type
-#endif
-#include "os/inttypes.h"
-
-#if defined(WIN32)
-#if defined(_KERNEL)
-#include <ntddk.h>
-#else
-#include <WTYPES.H>
-#endif /* _KERNEL */
-#else
-#if defined(Linux)
-#if defined(__KERNEL__)
-#include <linux/types.h>
-#else
-#include <sys/types.h>
-#endif
-#else
-#include <sys/types.h>
-#endif
-#ifdef SUNOS5
-#include <sys/ddi.h>
-#include <sys/sunddi.h>
-#endif
-#ifdef OS_IS_TRU64
-#include <io/common/devdriver.h>
-#endif
-#ifdef OS_IS_HP_UX11
-#if defined(_KERNEL)
-#include <../wsio/wsio.h>
-#else
-#include <sys/wsio.h>
-#endif
-#endif
-#endif
-
-/* See comments about "UNCONFIGURED_ADAPTERS" in config.h */
-#define UNCONFIGURED_ADAPTERS 100
-
-#ifndef FALSE
-#define FALSE 0
-#endif
-
-#ifndef TRUE
-#define TRUE 1
-#endif
-
-#ifndef NULL
-#define NULL 0
-#endif
-
-#ifndef IN
-#define IN
-#endif
-
-#ifndef NOT
-#define NOT !
-#endif
-
-/*
- * --------------------------------------------------------------------------------------
- * Basic types of various sizes.
- * --------------------------------------------------------------------------------------
- */
-
-typedef signed32 scibool;
-#ifndef OS_IS_VXWORKS
-typedef signed32 BOOL;
-#else
-/* VXWORKS has already defined BOOL */
-#endif
-typedef unsigned32 node_t; /* This is the logical nodeid */
-typedef unsigned32 sciNodeId_t; /* This is the physical 16 bit SCI nodeid */
-
-/*
- * --------------------------------------------------------------------------------------
- * Various register types.
- * --------------------------------------------------------------------------------------
- */
-typedef volatile unsigned32 register32;
-
-
-/*
-Temporary for Windows NT, until we use only the above types.
-*/
-
-#ifdef WIN32
-
-typedef unsigned char u_char;
-typedef unsigned short u_short;
-typedef unsigned long u_long;
-typedef unsigned int u_int;
-typedef char * caddr_t;
-
-typedef long off_t;
-typedef unsigned int size_t;
-
-#endif
-#ifdef OS_IS_VXWORKS
-#include <vxWorks.h>
-#endif
-
-/*
- * --------------------------------------------------------------------------------------
- * Various address types.
- *
- * We are using a struct * instead of unsigned long (int) inorder to enforce strong
- * type checking
- *
- * --------------------------------------------------------------------------------------
- */
-typedef UNIQUE(void *) vkaddr_t; /* Virtual kernel address */
-typedef UNIQUE(uptr_t) vuaddr_t; /* Virtual user address */
-
-typedef UNIQUE(unsigned32) remaddr_t; /* Remote IO address (physical address on PCs) */
-typedef UNIQUE(unsigned32) sciofs_lo_t; /* Lower 32 bits of an SCI offset. */
-typedef UNIQUE(unsigned32) sciofs_hi_t; /* The upper 16 bits of an SCI offset. */
-
-typedef UNIQUE(unsigned32) ioaddr_t; /* Local IO address (physical address on PCs) */
-typedef unsigned32 u_ioaddr_t;
-typedef unsigned32 iooffset_t;
-typedef unsigned32 iosize_t;
-
-typedef uptr_t vkoffset_t;
-typedef uptr_t u_vkaddr_t;
-typedef uptr_t u_vuaddr_t;
-typedef unsigned32 u_sciofs_lo_t;
-typedef unsigned32 u_sciofs_hi_t;
-typedef unsigned32 u_remaddr_t;
-typedef unsigned32 attOffset_t; /* Address displacement from start of ATT entry */
-
-typedef unsigned32 adapterNo_t;
-
-typedef enum {
- NO_NODE = 0,
- AD_MEM_NODE = 1,
- AD_ALT_NODE = 2,
- AD_MBX_NODE = 3,
- AD_LC_NODE = 4,
- AD_LC_PORT_0 = 5,
- AD_LC_PORT_1 = 6,
- AD_LC_PORT_2 = 7,
- PHYS_NODE = 8
-} node_type_t;
-
-
-/*
- * Currently we don't support more than 32 bit sizes.
- */
-#define SIZEOF(x) ((unsigned32)sizeof(x))
-
-#if defined(_KERNEL)
-
-/*
- * --------------------------------------------------------------------------------------
- * Some small macros intended to ease the transition to more strongly typed address
- * types. The intention is that they in the long run shall be removed ...
- * --------------------------------------------------------------------------------------
- */
-#define P2SIZE_T(x) ((size_t)((uptr_t)(x))) /* Pointer to size_t */
-#define P2U32(x) ((unsigned32)((uptr_t)(x))) /* Pointer to Unsigned 32-bit int */
-#ifdef WIN32
-#define PHADDR(x) ((ioaddr_t)(x))
-#define HASV(x) (x)
-#endif
-#if 0
-static vkaddr_t VKPTR (void * ptr) { return (vkaddr_t)ptr; }
-static vkaddr_t VKADDR(volatile void * ptr) { return (vkaddr_t)ptr; }
-#else
-#define VKPTR(ptr) (vkaddr_t)ptr
-#define VKADDR(ptr) (vkaddr_t)ptr
-#endif
-
-#ifdef KLOG
-#define KLOG_LOG(n,m,v) ts_log((n),(m),(v))
-#else
-#define KLOG_LOG(n,m,v)
-#endif /* KLOG */
-
-
-/*
- * --------------------------------------------------------------------------------------
- *
- * M E M A R E A T
- *
- * Memory area descriptor.
- *
- * paddr -- Physical address (aligned) of memory area
- * ual_vaddr -- (Kernel )Virtual address of the unaligned memory area
- * vaddr -- (Kernel) Virtual address of memory area
- * rsize -- Real (Physical) Size of memory area
- * msize -- Mapped (Virtual) Size of memory area (Size of area mapped
- * into virtual) memory
- *
- * --------------------------------------
- * | | <----- msize ----->| |
- * |<------|------- rsize ------|------>|
- * --------------------------------------
- * /|\ /|\
- * | |
- * ual_vaddr vaddr/paddr
- *
- * --------------------------------------------------------------------------------------
- */
-struct _memarea_ {
- ioaddr_t ioaddr;
- vkaddr_t vaddr;
- vkaddr_t ual_vaddr;
- size_t rsize;
- size_t msize;
- char *id;
- unsigned32 cookie;
-
-
-#ifdef SUNOS5
-#ifdef _USE_NEW_SOLARIS_DDI_INTERFACE
- ddi_acc_handle_t mem_handle;
- ddi_dma_handle_t dma_handle;
-#else
- ddi_dma_handle_t handle;
-#endif
-#endif
-#ifdef OS_IS_TRU64
- dma_handle_t dma_handle;
-#endif
-
-#if OS_IS_LINUX
- unsigned long ph_base_addr;
-#endif
-
-#ifdef OS_IS_HP_UX11
- struct isc_table_type * isc;
- wsio_shmem_attr_t type;
-#endif
-};
-
-typedef struct _memarea_ memarea_t;
-
-#ifdef SCI_MALLOC_DEBUG
-struct _maddr_ {
- char *id;
- size_t size;
- struct _maddr_ *next;
- struct _maddr_ **prev;
- unsigned32 cookie;
-};
-
-typedef struct _maddr_ maddr_t;
-
-#define MALLOC_COOKIE 0xc3c3c3c3
-
-#else
-
-typedef struct { void *p; } *maddr_t;
-
-#endif /* SCI_MALLOC_DEBUG */
-
-
-typedef struct {
- scibool disabled;
- unsigned32 disable_cnt;
-} disable_info_t;
-
-#endif /* _KERNEL */
-
-#endif /* _SCI_TYPES_H_ */
diff --git a/ndb/src/external/LINUX.x86/sci/include/sisci_api.h b/ndb/src/external/LINUX.x86/sci/include/sisci_api.h
deleted file mode 100644
index 38fdf54125f..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/sisci_api.h
+++ /dev/null
@@ -1,2170 +0,0 @@
-/* $Id: sisci_api.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2001 *
- * Dolphin Interconnect Solutions AS *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Lesser General Public License as published by *
- * the Free Software Foundation; either version 2.1 of the License, *
- * or (at your option) any later version. *
- * *
- * 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 Lesser General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-#ifndef _SISCI_API_H
-#define _SISCI_API_H
-
-#include "sisci_types.h"
-#include "sisci_error.h"
-
-
-#ifdef WIN32
-#ifdef API_DLL
-#define DLL __declspec(dllexport)
-#elif CLIENT_DLL
-#define DLL __declspec(dllimport)
-#endif
-#endif /* WIN32 */
-
-
-#ifndef DLL
-#define DLL
-#endif
-
-#if defined(_REENTRANT)
-#define _SISCI_EXPANDE_FUNCTION_NAME(name) _SISCI_PUBLIC_FUNC_MT_ ## name
-#define _SISCI_EXPANDE_VARIABLE_NAME(name) _SISCI_PUBLIC_VAR_MT_ ## name
-#else
-#define _SISCI_EXPANDE_FUNCTION_NAME(name) _SISCI_PUBLIC_FUNC_ST_ ## name
-#define _SISCI_EXPANDE_VARIABLE_NAME(name) _SISCI_PUBLIC_VAR_ST_ ## name
-#endif
-#define _SISCI_EXPANDE_CONSTANT_NAME(name) _SISCI_PUBLIC_CONST_ ## name
-
-#if defined(CPLUSPLUS) || defined(__cplusplus)
-extern "C" {
-#endif
-
-
-/*********************************************************************************/
-/* FLAG VALUES */
-/*********************************************************************************/
-
-#define SCI_FLAG_FIXED_INTNO _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FIXED_INTNO)
-extern const unsigned int SCI_FLAG_FIXED_INTNO;
-
-#define SCI_FLAG_SHARED_INT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_SHARED_INT)
-extern const unsigned int SCI_FLAG_SHARED_INT;
-
-#define SCI_FLAG_FIXED_MAP_ADDR _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FIXED_MAP_ADDR)
-extern const unsigned int SCI_FLAG_FIXED_MAP_ADDR;
-
-#define SCI_FLAG_READONLY_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_READONLY_MAP)
-extern const unsigned int SCI_FLAG_READONLY_MAP;
-
-#define SCI_FLAG_USE_CALLBACK _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_USE_CALLBACK)
-extern const unsigned int SCI_FLAG_USE_CALLBACK;
-
-#define SCI_FLAG_BLOCK_READ _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_BLOCK_READ)
-extern const unsigned int SCI_FLAG_BLOCK_READ;
-
-#define SCI_FLAG_THREAD_SAFE _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_THREAD_SAFE)
-extern const unsigned int SCI_FLAG_THREAD_SAFE;
-
-#define SCI_FLAG_ASYNCHRONOUS_CONNECT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_ASYNCHRONOUS_CONNECT)
-extern const unsigned int SCI_FLAG_ASYNCHRONOUS_CONNECT;
-
-#define SCI_FLAG_EMPTY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_EMPTY)
-extern const unsigned int SCI_FLAG_EMPTY;
-
-#define SCI_FLAG_PRIVATE _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_PRIVATE)
-extern const unsigned int SCI_FLAG_PRIVATE;
-
-#define SCI_FLAG_FORCE_DISCONNECT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FORCE_DISCONNECT)
-extern const unsigned int SCI_FLAG_FORCE_DISCONNECT;
-
-#define SCI_FLAG_NOTIFY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NOTIFY)
-extern const unsigned int SCI_FLAG_NOTIFY;
-
-#define SCI_FLAG_DMA_READ _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_READ)
-extern const unsigned int SCI_FLAG_DMA_READ;
-
-#define SCI_FLAG_DMA_POST _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_POST)
-extern const unsigned int SCI_FLAG_DMA_POST;
-
-#define SCI_FLAG_DMA_WAIT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_WAIT)
-extern const unsigned int SCI_FLAG_DMA_WAIT;
-
-#define SCI_FLAG_DMA_RESET _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_RESET)
-extern const unsigned int SCI_FLAG_DMA_RESET;
-
-#define SCI_FLAG_NO_FLUSH _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NO_FLUSH)
-extern const unsigned int SCI_FLAG_NO_FLUSH;
-
-#define SCI_FLAG_NO_STORE_BARRIER _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NO_STORE_BARRIER)
-extern const unsigned int SCI_FLAG_NO_STORE_BARRIER;
-
-#define SCI_FLAG_FAST_BARRIER _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FAST_BARRIER)
-extern const unsigned int SCI_FLAG_FAST_BARRIER;
-
-#define SCI_FLAG_ERROR_CHECK _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_ERROR_CHECK)
-extern const unsigned int SCI_FLAG_ERROR_CHECK;
-
-#define SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY)
-extern const unsigned int SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY;
-
-/* the FLUSH_CPU_BUFFERS_ONLY flag is for backwards compabillity only and should never be used */
-#define FLUSH_CPU_BUFFERS_ONLY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY)
-
-#define SCI_FLAG_LOCK_OPERATION _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_LOCK_OPERATION)
-extern const unsigned int SCI_FLAG_LOCK_OPERATION;
-
-#define SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP)
-extern const unsigned int SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP;
-
-#define SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP)
-extern const unsigned int SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP;
-
-#define SCI_FLAG_IO_MAP_IOSPACE _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_IO_MAP_IOSPACE)
-extern const unsigned int SCI_FLAG_IO_MAP_IOSPACE;
-
-#define SCI_FLAG_DMOVE_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMOVE_MAP)
-extern const unsigned int SCI_FLAG_DMOVE_MAP;
-
-#define SCI_FLAG_WRITES_DISABLE_GATHER_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_WRITES_DISABLE_GATHER_MAP)
-extern const unsigned int SCI_FLAG_WRITES_DISABLE_GATHER_MAP;
-
-#define SCI_FLAG_DISABLE_128_BYTES_PACKETS _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DISABLE_128_BYTES_PACKETS)
-extern const unsigned int SCI_FLAG_DISABLE_128_BYTES_PACKETS;
-
-#define SCI_FLAG_SHARED_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_SHARED_MAP)
-extern const unsigned int SCI_FLAG_SHARED_MAP;
-
-#define SCI_FLAG_DMA_SOURCE_ONLY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_SOURCE_ONLY)
-extern const unsigned int SCI_FLAG_DMA_SOURCE_ONLY;
-
-#define SCI_FLAG_CONDITIONAL_INTERRUPT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_CONDITIONAL_INTERRUPT)
-extern const unsigned int SCI_FLAG_CONDITIONAL_INTERRUPT;
-
-#define SCI_FLAG_CONDITIONAL_INTERRUPT_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_CONDITIONAL_INTERRUPT_MAP)
-extern const unsigned int SCI_FLAG_CONDITIONAL_INTERRUPT_MAP;
-
-#define SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP)
-extern const unsigned int SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP;
-
-#define SCI_FLAG_NO_MEMORY_LOOPBACK_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NO_MEMORY_LOOPBACK_MAP)
-extern const unsigned int SCI_FLAG_NO_MEMORY_LOOPBACK_MAP;
-
-#if defined(OS_IS_LYNXOS) || defined(OS_IS_VXWORKS)
-#define SCI_FLAG_WRITE_BACK_CACHE_MAP _SISCI_EXPANDE_CONSTANT_NAME(WRITE_BACK_CACHE_MAP)
-extern const unsigned int SCI_FLAG_WRITE_BACK_CACHE_MAP;
-#endif
-
-#define SCI_FLAG_DMA_PHDMA _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_PHDMA)
-extern const unsigned int SCI_FLAG_DMA_PHDMA;
-
-/*********************************************************************************/
-/* GENERAL VALUES */
-/*********************************************************************************/
-#define SCI_LOCAL_HOST _SISCI_EXPANDE_CONSTANT_NAME(SCI_LOCAL_HOST)
-extern const unsigned int SCI_LOCAL_HOST;
-
-#define SCI_INFINITE_TIMEOUT _SISCI_EXPANDE_CONSTANT_NAME(SCI_INFINITE_TIMEOUT)
-extern const unsigned int SCI_INFINITE_TIMEOUT;
-
-/*********************************************************************************/
-/* GENERAL ERROR CODES */
-/* */
-/* SCI_ERR_ILLEGAL_FLAG - Illegal flag value. */
-/* SCI_ERR_FLAG_NOT_IMPLEMENTED - Flag legal but flag feature not implemented. */
-/* SCI_ERR_NOT_IMPLEMENTED - Function not implemented. */
-/* SCI_ERR_SYSTEM - A system error. Check errno. */
-/* SCI_ERR_NOSPC - Unable to allocate OS resources. */
-/* SCI_ERR_API_NOSPC - Unable to allocate API resources. */
-/* SCI_ERR_HW_NOSPC - Unable to allocate HW resources (Hardware) */
-/* */
-/*********************************************************************************/
-
-
-/*********************************************************************************/
-/* GENERAL "ADAPTER" ERROR CODES */
-/* */
-/* SCI_ERR_NO_SUCH_ADAPTERNO - Adapter number is legal but does not exist. */
-/* SCI_ERR_ILLEGAL_ADAPTERNO - Illegal local adapter number (i.e. outside */
-/* legal range). */
-/* */
-/*********************************************************************************/
-
-
-/*********************************************************************************/
-/* GENERAL "NODEID" ERROR CODES */
-/* */
-/* SCI_ERR_NO_SUCH_NODEID - The remote adapter identified by nodeId does */
-/* not respond, but the intermediate link(s) */
-/* seem(s) to be operational. */
-/* SCI_ERR_ILLEGAL_NODEID - Illegal NodeId. */
-/* */
-/*********************************************************************************/
-
-
-
-/*********************************************************************************
- * *
- * S C I I N I T I A L I Z E *
- * *
- * This function initializes the SISCI library. *
- * The function must be called before SCIOpen(). *
- * *
- * Flags: *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * None *
- * *
- *********************************************************************************/
-#define SCIInitialize _SISCI_EXPANDE_FUNCTION_NAME(SCIInitialize)
-DLL void SCIInitialize(unsigned int flags,
- sci_error_t *error);
-#if 0
-unsigned int __Internal_SISCI_version_var;
-#endif
-
-/*********************************************************************************
- * *
- * S C I T E R M I N A T E *
- * *
- * This function terminates the SISCI library. *
- * The function must be called after SCIClose(). *
- * *
- * *
- *********************************************************************************/
-#define SCITerminate _SISCI_EXPANDE_FUNCTION_NAME(SCITerminate)
-DLL void SCITerminate(void);
-
-/*********************************************************************************
- * *
- * S C I O P E N *
- * *
- * *
- * Opens a SCI virtual device. *
- * Caller must supply a pointer to a variable of type sci_desc_t to be *
- * initialized. *
- * *
- * Flags *
- * SCI_FLAG_THREAD_SAFE - Operations on resources associated with this *
- * descriptor will be performed in a multithread-safe *
- * manner. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_INCONSISTENT_VERSIONS - Inconsistency between the SISCI library *
- * and the SISCI driver versions. *
- * *
- * *
- *********************************************************************************/
-#define SCIOpen _SISCI_EXPANDE_FUNCTION_NAME(SCIOpen)
-DLL void SCIOpen(sci_desc_t *sd,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C L O S E *
- * *
- * This function closes an open SCI virtual device. *
- * *
- * Flags: *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - All resources are not deallocated. *
- * *
- *********************************************************************************/
-#define SCIClose _SISCI_EXPANDE_FUNCTION_NAME(SCIClose)
-DLL void SCIClose(sci_desc_t sd,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C O N N E C T S E G M E N T *
- * *
- * Connects to a remote shared memory segment located at <nodeId> with the *
- * identifier <segmentId>. *
- * The user may then call SCIMapRemoteSegment() to map shared memory *
- * into user space. *
- * *
- * Flags *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_ASYNCHRONOUS_CONNECT *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_SUCH_SEGMENT - Could not find the remote segment with the *
- * given segmentId. *
- * SCI_ERR_CONNECTION_REFUSED - Connection attempt refused by remote node. *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCIConnectSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIConnectSegment)
-DLL void SCIConnectSegment(sci_desc_t sd,
- sci_remote_segment_t *segment,
- unsigned int nodeId,
- unsigned int segmentId,
- unsigned int localAdapterNo,
- sci_cb_remote_segment_t callback,
- void *callbackArg,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I D I S C O N N E C T S E G M E N T *
- * *
- * Disconnects from the give mapped shared memory segment *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - The segment is currently mapped or in use. *
- * *
- *********************************************************************************/
-#define SCIDisconnectSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIDisconnectSegment)
-DLL void SCIDisconnectSegment(sci_remote_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I G E T R E M O T E S E G M E N T S I Z E *
- * *
- *********************************************************************************/
-#define SCIGetRemoteSegmentSize _SISCI_EXPANDE_FUNCTION_NAME(SCIGetRemoteSegmentSize)
-DLL unsigned int SCIGetRemoteSegmentSize(sci_remote_segment_t segment);
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R R E M O T E S E G M E N T E V E N T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation. *
- * SCI_ERR_CANCELLED - The wait operation has been cancelled du *
- * to a SCIDisconnectSegment() on the same *
- * handle. The handle is invalid when this *
- * error is returned. *
- * *
- *********************************************************************************/
-#define SCIWaitForRemoteSegmentEvent _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForRemoteSegmentEvent)
-DLL sci_segment_cb_reason_t SCIWaitForRemoteSegmentEvent(
- sci_remote_segment_t segment,
- sci_error_t *status,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I M A P R E M O T E S E G M E N T *
- * *
- * This function is used to include a shared memory segment in the virtual *
- * address space of the application. *
- * *
- * Flags: *
- * *
- * SCI_FLAG_SHARED_MAP - The low level physical map may be shared by *
- * other applications. *
- * *
- * SCI_FLAG_FIXED_MAP_ADDR - Map at the suggested virtual address *
- * SCI_FLAG_READONLY_MAP - The segment is mapped in read-only mode *
- * SCI_FLAG_LOCK_OPERATION - Enable Lock operations (fetch and add) *
- * SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP *
- * - Enable aggressive prefetch with speculative *
- * hold. *
- * *
- * SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP *
- * - The PSB66 will prefetch 64 bytes. As soon *
- * as the PCI read retry has been accepted, *
- * the stream will change state to FREE, even *
- * if less than 64 bytes were actually read. *
- * *
- * SCI_FLAG_IO_MAP_IOSPACE - Enable No Prefetch, no speculative hold. *
- * *
- * SCI_FLAG_DMOVE_MAP - Enable DMOVE packet type. The stream will be *
- * set into FREE state immediately. *
- * *
- * SCI_FLAG_WRITES_DISABLE_GATHER_MAP *
- * - Disable use of gather. *
- * *
- * SCI_FLAG_DISABLE_128_BYTES_PACKETS *
- * - Disable use of 128-Byte packets *
- * *
- * SCI_FLAG_CONDITIONAL_INTERRUPT_MAP *
- * - Write operations through this map will cause *
- * an atomic "fetch-and-add-one" operation on *
- * remote memory, but in addition an interrupt *
- * will be generated if the target memory *
- * location contained a "null value" before the *
- * add operation was carried out. *
- * The conditional interrupt flag must also be *
- * specified in the SCIRegisterInterruptFlag() *
- * function. *
- * *
- * SCI_FLAG_UNCONDITIONAL_INTERRUPT_MAP *
- * - Write operations through this map will cause *
- * an interrupt for the remote adapter *
- * "in addition to" updating the corresponding *
- * remote memory location with the data being *
- * written. *
- * The unconditional interrupt flag must also *
- * be specified in the *
- * SCIRegisterInterruptFlag() function. *
- * *
- * SCI_FLAG_WRITE_BACK_CACHE_MAP *
- * - Enable cacheing of the mapped region. *
- * Writes through this map will be written to a *
- * write back cache, hence no remote SCI updates*
- * until the cache line is flushed. The *
- * application is responsible for the cache *
- * flush operation. *
- * The SCImemCopy() function will handle this *
- * correctly by doing cache flushes internally. *
- * This feature is architechture dependent and *
- * not be available on all plattforms. *
- * *
- * SCI_FLAG_NO_MEMORY_LOOPBACK_MAP *
- * - Forces a map to a remote segment located *
- * in the local machine to be mapped using *
- * SCI loopback. This is useful i.e. if you *
- * want to use a regular map access to be *
- * serialized with lock operations. *
- * The default behaviour is to access a remte *
- * segment located in the local machine as a *
- * local MMU operation. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the offset and size is *
- * larger than the segment size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as *
- * required by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as *
- * required by the implementation. *
- * *
- *********************************************************************************/
-#define SCIMapRemoteSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIMapRemoteSegment)
-DLL volatile void *SCIMapRemoteSegment(
- sci_remote_segment_t segment,
- sci_map_t *map,
- unsigned int offset,
- unsigned int size,
- void *addr,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I M A P L O C A L S E G M E N T *
- * *
- * Flags *
- * *
- * SCI_FLAG_FIXED_MAP_ADDR *
- * SCI_FLAG_READONLY_MAP *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the offset and size is *
- * larger than the segment size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as *
- * required by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as *
- * required by the implementation. *
- * *
- *********************************************************************************/
-#define SCIMapLocalSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIMapLocalSegment)
-DLL void *SCIMapLocalSegment(sci_local_segment_t segment,
- sci_map_t *map,
- unsigned int offset,
- unsigned int size,
- void *addr,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I U N M A P S E G M E N T *
- * *
- * This function unmaps pages of shared memory from the callers virtual *
- * address space. *
- * *
- * Flags *
- * None. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - The map is currently in use. *
- * *
- *********************************************************************************/
-#define SCIUnmapSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIUnmapSegment)
-DLL void SCIUnmapSegment(sci_map_t map,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C R E A T E S E G M E N T *
- * *
- * Make the specified segment available for connections via the specified *
- * adapter. If successful, the segment can be accessed from remote nodes *
- * via the specified adapter. *
- * *
- * Flags: *
- * *
- * SCI_FLAG_USE_CALLBACK - The callback function will be invoked for events *
- * on this segment. *
- * SCI_FLAG_EMPTY - No memory will be allocated for the segment. *
- * SCI_FLAG_PRIVATE - The segment will be private meaning it will never *
- * be any connections to it. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_SEGMENTID_USED - The segment with this segmentId is already used *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * *
- *********************************************************************************/
-#define SCICreateSegment _SISCI_EXPANDE_FUNCTION_NAME(SCICreateSegment)
-DLL void SCICreateSegment(sci_desc_t sd,
- sci_local_segment_t *segment,
- unsigned int segmentId,
- unsigned int size,
- sci_cb_local_segment_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R L O C A L S E G M E N T E V E N T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_TIMEOUT - The function timed out after specified timeout value. *
- * SCI_ERR_CANCELLED - The wait operation has been cancelled du to a *
- * SCIRemoveSegment() on the same handle. *
- * The handle is invalid when this error is returned. *
- * *
- *********************************************************************************/
-#define SCIWaitForLocalSegmentEvent _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForLocalSegmentEvent)
-DLL sci_segment_cb_reason_t SCIWaitForLocalSegmentEvent(
- sci_local_segment_t segment,
- unsigned int *sourcenodeId,
- unsigned int *localAdapterNo,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I P R E P A R E S E G M E N T *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_SOURCE_ONLY - The segment will be used as a source segment *
- * for DMA operations. On some system types this *
- * will enable the SISCI driver to use performance *
- * improving features. *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIPrepareSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIPrepareSegment)
-DLL void SCIPrepareSegment(sci_local_segment_t segment,
- unsigned int localAdapterNo,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E S E G M E N T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - Unable to remove the segment. The segment is currently *
- * in use. *
- * *
- *********************************************************************************/
-#define SCIRemoveSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveSegment)
-DLL void SCIRemoveSegment(sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T S E G M E N T A V A I L A B L E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * SCI_ERR_SEGMENT_NOT_PREPARED - The segment has not been prepared for access *
- * from this adapter. *
- * SCI_ERR_ILLEGAL_OPERATION - The segment is created with the *
- * SCI_FLAG_PRIVATE flag specified and *
- * therefore has no segmentId. *
- * *
- *********************************************************************************/
-#define SCISetSegmentAvailable _SISCI_EXPANDE_FUNCTION_NAME(SCISetSegmentAvailable)
-DLL void SCISetSegmentAvailable(sci_local_segment_t segment,
- unsigned int localAdapterNo,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T S E G M E N T U N A V A I L A B L E *
- * *
- * Flags *
- * *
- * SCI_FLAG_FORCE_DISCONNECT *
- * SCI_FLAG_NOTIFY *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation. *
- * *
- *********************************************************************************/
-#define SCISetSegmentUnavailable _SISCI_EXPANDE_FUNCTION_NAME(SCISetSegmentUnavailable)
-DLL void SCISetSegmentUnavailable(sci_local_segment_t segment,
- unsigned int localAdapterNo,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C R E A T E M A P S E Q U E N C E *
- * *
- * Flags: *
- * *
- * SCI_FLAG_FAST_BARRIER *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCICreateMapSequence _SISCI_EXPANDE_FUNCTION_NAME(SCICreateMapSequence)
-DLL void SCICreateMapSequence(sci_map_t map,
- sci_sequence_t *sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E S E Q U E N C E *
- * *
- * Flags: *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIRemoveSequence _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveSequence)
-DLL void SCIRemoveSequence(sci_sequence_t sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S T A R T S E Q U E N C E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIStartSequence _SISCI_EXPANDE_FUNCTION_NAME(SCIStartSequence)
-DLL sci_sequence_status_t SCIStartSequence(sci_sequence_t sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I C H E C K S E Q U E N CE *
- * *
- * Flags *
- * *
- * SCI_FLAG_NO_FLUSH *
- * SCI_FLAG_NO_STORE_BARRIER *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCICheckSequence _SISCI_EXPANDE_FUNCTION_NAME(SCICheckSequence)
-DLL sci_sequence_status_t SCICheckSequence(sci_sequence_t sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S T O R E B A R R I E R *
- * *
- * Flags *
- * None. *
- * *
- * *
- * *
- *********************************************************************************/
-#define SCIStoreBarrier _SISCI_EXPANDE_FUNCTION_NAME(SCIStoreBarrier)
-DLL void SCIStoreBarrier(sci_sequence_t sequence,
- unsigned int flags);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I F L U S H R E A D B U F F E R S *
- * *
- *********************************************************************************/
-#define SCIFlushReadBuffers _SISCI_EXPANDE_FUNCTION_NAME(SCIFlushReadBuffers)
-DLL void SCIFlushReadBuffers(sci_sequence_t sequence);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I P R O B E N O D E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCIProbeNode _SISCI_EXPANDE_FUNCTION_NAME(SCIProbeNode)
-DLL int SCIProbeNode(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int nodeId,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I G E T C S R R E G I S T E R *
- * *
- * SISCI Priveleged function *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCIGetCSRRegister _SISCI_EXPANDE_FUNCTION_NAME(SCIGetCSRRegister)
-DLL unsigned int SCIGetCSRRegister(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int SCINodeId,
- unsigned int CSROffset,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T C S R R E G I S T E R *
- * *
- * SISCI Priveleged function *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCISetCSRRegister _SISCI_EXPANDE_FUNCTION_NAME(SCISetCSRRegister)
-DLL void SCISetCSRRegister(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int SCINodeId,
- unsigned int CSROffset,
- unsigned int CSRValue,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I G E T L O C A L C S R *
- * *
- * SISCI Priveleged function *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIGetLocalCSR _SISCI_EXPANDE_FUNCTION_NAME(SCIGetLocalCSR)
-DLL unsigned int SCIGetLocalCSR(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int CSROffset,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T L O C A L C S R *
- * *
- * SISCI Priveleged function
- *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCISetLocalCSR _SISCI_EXPANDE_FUNCTION_NAME(SCISetLocalCSR)
-DLL void SCISetLocalCSR(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int CSROffset,
- unsigned int CSRValue,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I A T T A C H P H Y S I C A L M E M O R Y *
- * *
- * SISCI Priveleged function *
- * *
- * Description: *
- * *
- * This function enables usage of physical devices and memory regions where the *
- * Physical PCI bus address ( and mapped CPU address ) are already known. *
- * The function will register the physical memory as a SISCI segment which can *
- * be connected and mapped as a regular SISCI segment. *
- * *
- * Requirements: *
- * *
- * SCICreateSegment() with flag SCI_FLAG_EMPTY must have been called in advance *
- * *
- * Parameter description: *
- * sci_ioaddr_t ioaddress : This is the address on the PCI bus that a PCI bus *
- * master has to use to write to the specified memory *
- * void * address : This is the (mapped) virtual address that the *
- * application has to use to access the device. *
- * This means that the device has to be mapped in *
- * advance bye the devices own driver. *
- * If the device is not to be accessed by the local *
- * CPU, the address pointer shold be set to NULL *
- * Flags *
- * *
- * None *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIAttachPhysicalMemory _SISCI_EXPANDE_FUNCTION_NAME(SCIAttachPhysicalMemory)
-DLL void SCIAttachPhysicalMemory(sci_ioaddr_t ioaddress,
- void *address,
- unsigned int busNo,
- unsigned int size,
- sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I Q U E R Y *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_QUERY - Unrecognized command. *
- * *
- *********************************************************************************/
-#define SCIQuery _SISCI_EXPANDE_FUNCTION_NAME(SCIQuery)
-DLL void SCIQuery(unsigned int command,
- void *data,
- unsigned int flags,
- sci_error_t *error);
-
-
-/* MAJOR QUERY COMMANDS */
-
-/* This command requires a pointer to a structure of type */
-/* "sci_query_string". The string will be filled in by the query. */
-#define SCI_Q_VENDORID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_VENDORID)
-extern const unsigned int SCI_Q_VENDORID;
-
-
-/* Same as for SCI_VENDOR_ID */
-#define SCI_Q_API _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_API)
-extern const unsigned int SCI_Q_API;
-
-
-/* User passes a pointer to an allocated object of the */
-/* "sci_query_adapter" struct. */
-#define SCI_Q_ADAPTER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER)
-extern const unsigned int SCI_Q_ADAPTER;
-
-
-/* User passes a pointer to an allocated object of the */
-/* "sci_query_system" struct. */
-#define SCI_Q_SYSTEM _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM)
-extern const unsigned int SCI_Q_SYSTEM;
-
-#define SCI_Q_LOCAL_SEGMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_LOCAL_SEGMENT)
-extern const unsigned int SCI_Q_LOCAL_SEGMENT;
-
-#define SCI_Q_REMOTE_SEGMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_REMOTE_SEGMENT)
-extern const unsigned int SCI_Q_REMOTE_SEGMENT;
-
-#define SCI_Q_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_MAP)
-extern const unsigned int SCI_Q_MAP;
-
-typedef struct {
- char *str; /* Pointer to a string of minimum "length" characters */
- unsigned int length;
-} sci_query_string_t;
-
-
-typedef struct {
- unsigned int localAdapterNo; /* The adapter no. that the query concern. */
- unsigned int portNo; /* The SCI Link port number that the query concern. */
- unsigned int subcommand; /* A subcommand as specified below. */
- void *data; /* A pointer to an unsigned int that will return */
- /* the response to the query. */
-} sci_query_adapter_t;
-
-
-typedef struct {
- unsigned int subcommand; /* A subcommand as specified below. */
- void *data; /* A pointer to an unsigned int that will return */
- /* the response to the query. */
-} sci_query_system_t;
-
-typedef struct {
- sci_local_segment_t segment;
- unsigned int subcommand;
- union {
- sci_ioaddr_t ioaddr;
- } data;
-} sci_query_local_segment_t;
-
-typedef struct {
- sci_remote_segment_t segment;
- unsigned int subcommand;
- union {
- sci_ioaddr_t ioaddr;
- } data;
-} sci_query_remote_segment_t;
-
-typedef struct {
- sci_map_t map;
- unsigned int subcommand;
- unsigned int data;
-} sci_query_map_t;
-
-/* Minor query commands (sub-commands) for adapter specific information SCI_ADAPTER */
-#define SCI_Q_ADAPTER_DMA_SIZE_ALIGNMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_DMA_SIZE_ALIGNMENT)
-extern const unsigned int SCI_Q_ADAPTER_DMA_SIZE_ALIGNMENT;
-
-#define SCI_Q_ADAPTER_DMA_OFFSET_ALIGNMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_DMA_OFFSET_ALIGNMENT)
-extern const unsigned int SCI_Q_ADAPTER_DMA_OFFSET_ALIGNMENT;
-
-#define SCI_Q_ADAPTER_DMA_MTU _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_DMA_MTU)
-extern const unsigned int SCI_Q_ADAPTER_DMA_MTU;
-
-#define SCI_Q_ADAPTER_SUGGESTED_MIN_DMA_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SUGGESTED_MIN_DMA_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_SUGGESTED_MIN_DMA_SIZE;
-
-#define SCI_Q_ADAPTER_SUGGESTED_MIN_BLOCK_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SUGGESTED_MIN_BLOCK_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_SUGGESTED_MIN_BLOCK_SIZE;
-
-#define SCI_Q_ADAPTER_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_NODEID;
-
-#define SCI_Q_ADAPTER_SERIAL_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SERIAL_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_SERIAL_NUMBER;
-
-#define SCI_Q_ADAPTER_CARD_TYPE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CARD_TYPE)
-extern const unsigned int SCI_Q_ADAPTER_CARD_TYPE;
-
-#define SCI_Q_ADAPTER_NUMBER_OF_STREAMS _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_NUMBER_OF_STREAMS)
-extern const unsigned int SCI_Q_ADAPTER_NUMBER_OF_STREAMS;
-
-#define SCI_Q_ADAPTER_STREAM_BUFFER_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_STREAM_BUFFER_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_STREAM_BUFFER_SIZE;
-
-#define SCI_Q_ADAPTER_CONFIGURED _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CONFIGURED)
-extern const unsigned int SCI_Q_ADAPTER_CONFIGURED;
-
-#define SCI_Q_ADAPTER_LINK_OPERATIONAL _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_LINK_OPERATIONAL)
-extern const unsigned int SCI_Q_ADAPTER_LINK_OPERATIONAL;
-
-#define SCI_Q_ADAPTER_HW_LINK_STATUS_IS_OK _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_HW_LINK_STATUS_IS_OK)
-extern const unsigned int SCI_Q_ADAPTER_HW_LINK_STATUS_IS_OK;
-
-#define SCI_Q_ADAPTER_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_NUMBER;
-
-#define SCI_Q_ADAPTER_INSTANCE_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_INSTANCE_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_INSTANCE_NUMBER;
-
-#define SCI_Q_ADAPTER_FIRMWARE_OK _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_FIRMWARE_OK)
-extern const unsigned int SCI_Q_ADAPTER_FIRMWARE_OK;
-
-#define SCI_Q_ADAPTER_CONNECTED_TO_SWITCH _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CONNECTED_TO_SWITCH)
-extern const unsigned int SCI_Q_ADAPTER_CONNECTED_TO_SWITCH;
-
-#define SCI_Q_ADAPTER_LOCAL_SWITCH_TYPE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_LOCAL_SWITCH_TYPE)
-extern const unsigned int SCI_Q_ADAPTER_LOCAL_SWITCH_TYPE;
-
-#define SCI_Q_ADAPTER_LOCAL_SWITCH_PORT_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_LOCAL_SWITCH_PORT_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_LOCAL_SWITCH_PORT_NUMBER;
-
-#define SCI_Q_ADAPTER_CONNECTED_TO_EXPECTED_SWITCH_PORT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CONNECTED_TO_EXPECTED_SWITCH_PORT)
-extern const unsigned int SCI_Q_ADAPTER_CONNECTED_TO_EXPECTED_SWITCH_PORT;
-
-#define SCI_Q_ADAPTER_ATT_PAGE_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_ATT_PAGE_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_ATT_PAGE_SIZE;
-
-#define SCI_Q_ADAPTER_ATT_NUMBER_OF_ENTRIES _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_ATT_NUMBER_OF_ENTRIES)
-extern const unsigned int SCI_Q_ADAPTER_ATT_NUMBER_OF_ENTRIES;
-
-#define SCI_Q_ADAPTER_ATT_AVAILABLE_ENTRIES _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_ATT_AVAILABLE_ENTRIES)
-extern const unsigned int SCI_Q_ADAPTER_ATT_AVAILABLE_ENTRIES;
-
-#define SCI_Q_ADAPTER_PHYS_MEM_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SCI_Q_ADAPTER_PHYS_MEM_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_PHYS_MEM_NODEID;
-
-#define SCI_Q_ADAPTER_PHYS_MBX_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SCI_Q_ADAPTER_PHYS_MBX_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_PHYS_MBX_NODEID;
-
-#define SCI_Q_ADAPTER_PHYS_LINK_PORT_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_PHYS_LINK_PORT_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_PHYS_LINK_PORT_NODEID;
-
-#define SCI_Q_ADAPTER_SCI_LINK_FREQUENCY _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SCI_LINK_FREQUENCY)
-extern const unsigned int SCI_Q_ADAPTER_SCI_LINK_FREQUENCY;
-
-#define SCI_Q_ADAPTER_B_LINK_FREQUENCY _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_B_LINK_FREQUENCY)
-extern const unsigned int SCI_Q_ADAPTER_B_LINK_FREQUENCY;
-
-#define SCI_Q_ADAPTER_IO_BUS_FREQUENCY _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_IO_BUS_FREQUENCY)
-extern const unsigned int SCI_Q_ADAPTER_IO_BUS_FREQUENCY;
-
-/* Minor query commands (sub-commands) for adapter specific information SCI_SYSTEM */
-#define SCI_Q_SYSTEM_HOSTBRIDGE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM_HOSTBRIDGE)
-extern const unsigned int SCI_Q_SYSTEM_HOSTBRIDGE;
-
-#define SCI_Q_SYSTEM_WRITE_POSTING_ENABLED _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM_WRITE_POSTING_ENABLED)
-extern const unsigned int SCI_Q_SYSTEM_WRITE_POSTING_ENABLED;
-
-#define SCI_Q_SYSTEM_WRITE_COMBINING_ENABLED _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM_WRITE_COMBINING_ENABLED)
-extern const unsigned int SCI_Q_SYSTEM_WRITE_COMBINING_ENABLED;
-
-#define SCI_Q_LOCAL_SEGMENT_IOADDR _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_LOCAL_SEGMENT_IOADDR)
-extern const unsigned int SCI_Q_LOCAL_SEGMENT_IOADDR;
-
-#define SCI_Q_REMOTE_SEGMENT_IOADDR _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_REMOTE_SEGMENT_IOADDR)
-extern const unsigned int SCI_Q_REMOTE_SEGMENT_IOADDR;
-
-#define SCI_Q_MAP_MAPPED_TO_LOCAL_TARGET _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_MAP_MAPPED_TO_LOCAL_TARGET)
-extern const unsigned int SCI_Q_MAP_MAPPED_TO_LOCAL_TARGET;
-
-#define SCI_Q_MAP_QUERY_REMOTE_MAPPED_TO_LOCAL_TARGET _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_MAP_QUERY_REMOTE_MAPPED_TO_LOCAL_TARGET)
-extern const unsigned int SCI_Q_MAP_QUERY_REMOTE_MAPPED_TO_LOCAL_TARGET;
-
-#define HOSTBRIDGE_NOT_AVAILABLE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_NOT_AVAILABLE)
-extern const unsigned int HOSTBRIDGE_NOT_AVAILABLE;
-
-#define HOSTBRIDGE_UNKNOWN _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_UNKNOWN)
-extern const unsigned int HOSTBRIDGE_UNKNOWN;
-
-#define HOSTBRIDGE_440FX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440FX)
-extern const unsigned int HOSTBRIDGE_440FX;
-
-#define HOSTBRIDGE_440LX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440LX)
-extern const unsigned int HOSTBRIDGE_440LX;
-
-#define HOSTBRIDGE_440BX_A _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440BX_A)
-extern const unsigned int HOSTBRIDGE_440BX_A;
-
-#define HOSTBRIDGE_440BX_B _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440BX_B)
-extern const unsigned int HOSTBRIDGE_440BX_B;
-
-#define HOSTBRIDGE_440GX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440GX)
-extern const unsigned int HOSTBRIDGE_440GX;
-
-#define HOSTBRIDGE_450KX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450KX)
-extern const unsigned int HOSTBRIDGE_450KX;
-
-#define HOSTBRIDGE_430NX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_430NX)
-extern const unsigned int HOSTBRIDGE_430NX;
-
-#define HOSTBRIDGE_450NX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450NX)
-extern const unsigned int HOSTBRIDGE_450NX;
-
-#define HOSTBRIDGE_450NX_MICO _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450NX_MICO)
-extern const unsigned int HOSTBRIDGE_450NX_MICO;
-
-#define HOSTBRIDGE_450NX_PXB _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450NX_PXB)
-extern const unsigned int HOSTBRIDGE_450NX_PXB;
-
-#define HOSTBRIDGE_I810 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I810)
-extern const unsigned int HOSTBRIDGE_I810;
-
-#define HOSTBRIDGE_I810_DC100 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I810_DC100)
-extern const unsigned int HOSTBRIDGE_I810_DC100;
-
-#define HOSTBRIDGE_I810E _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I810E)
-extern const unsigned int HOSTBRIDGE_I810E;
-
-#define HOSTBRIDGE_I815 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I815)
-extern const unsigned int HOSTBRIDGE_I815;
-
-#define HOSTBRIDGE_I840 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I840)
-extern const unsigned int HOSTBRIDGE_I840;
-
-#define HOSTBRIDGE_I850 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I850)
-extern const unsigned int HOSTBRIDGE_I850;
-
-#define HOSTBRIDGE_I860 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I860)
-extern const unsigned int HOSTBRIDGE_I860;
-
-#define HOSTBRIDGE_INTEL_E7500 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_INTEL_E7500)
-extern const unsigned int HOSTBRIDGE_INTEL_E7500;
-
-#define HOSTBRIDGE_VIA_KT133 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_KT133)
-extern const unsigned int HOSTBRIDGE_VIA_KT133;
-
-#define HOSTBRIDGE_VIA_KX133 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_KX133)
-extern const unsigned int HOSTBRIDGE_VIA_KX133;
-
-#define HOSTBRIDGE_VIA_APOLLO_PRO_133A _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_APOLLO_PRO_133A)
-extern const unsigned int HOSTBRIDGE_VIA_APOLLO_PRO_133A;
-
-#define HOSTBRIDGE_VIA_APOLLO_PRO_266 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_APOLLO_PRO_266)
-extern const unsigned int HOSTBRIDGE_VIA_APOLLO_PRO_266;
-
-#define HOSTBRIDGE_AMD_760_MP _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_AMD_760_MP)
-extern const unsigned int HOSTBRIDGE_AMD_760_MP;
-
-#define HOSTBRIDGE_AMD_HAMMER _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_AMD_HAMMER)
-extern const unsigned int HOSTBRIDGE_AMD_HAMMER;
-
-#define HOSTBRIDGE_SERVERWORKS_HE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_HE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_HE;
-
-#define HOSTBRIDGE_SERVERWORKS_HE_B _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_HE_B)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_HE_B;
-
-#define HOSTBRIDGE_SERVERWORKS_LE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_LE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_LE;
-
-#define HOSTBRIDGE_SERVERWORKS_GC_HE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_GC_HE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_GC_HE;
-
-#define HOSTBRIDGE_SERVERWORKS_GC_LE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_GC_LE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_GC_LE;
-
-#define HOSTBRIDGE_SERVERWORKS_GC_WS _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_GC_WS)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_GC_WS;
-
-#define HOSTBRIDGE_SERVERWORKS_GC_SL _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_GC_SL)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_GC_SL;
-
-
-#define HOSTBRIDGE_WRITE_POSTING_DISABLED _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_WRITE_POSTING_DISABLED)
-extern const unsigned int HOSTBRIDGE_WRITE_POSTING_DISABLED;
-
-#define HOSTBRIDGE_WRITE_POSTING_ENABLED _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_WRITE_POSTING_ENABLED)
-extern const unsigned int HOSTBRIDGE_WRITE_POSTING_ENABLED;
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C R E A T E D M A Q U E U E *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_PHDMA : Create physical DMA queue. Please note that this is an *
- * priveleged operation. *
- * *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCICreateDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCICreateDMAQueue)
-DLL void SCICreateDMAQueue(sci_desc_t sd,
- sci_dma_queue_t *dq,
- unsigned int localAdapterNo,
- unsigned int maxEntries,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E D M A Q U E U E *
- * *
- * Flags *
- * None. * *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Not allowed in this queue state. *
- * *
- *********************************************************************************/
-#define SCIRemoveDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveDMAQueue)
-DLL void SCIRemoveDMAQueue(sci_dma_queue_t dq,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I E N Q U E U E D M A T R A N S F E R *
- * *
- * Flags: *
- * *
- * SCI_FLAG_DMA_READ - The DMA will be remote --> local *
- * (default is local --> remote) *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the offset and size is larger *
- * than the segment size or larger than max *
- * DMA size. *
- * SCI_ERR_MAX_ENTRIES - The DMA queue is full *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_SEGMENT_NOT_PREPARED - The local segment has not been prepared for *
- * access from the adapter associated with the *
- * queue. *
- * SCI_ERR_SEGMENT_NOT_CONNECTED - The remote segment is not connected through *
- * the adapter associated with the queue. *
- *********************************************************************************/
-#define SCIEnqueueDMATransfer _SISCI_EXPANDE_FUNCTION_NAME(SCIEnqueueDMATransfer)
-DLL sci_dma_queue_state_t SCIEnqueueDMATransfer(sci_dma_queue_t dq,
- sci_local_segment_t localSegment,
- sci_remote_segment_t remoteSegment,
- unsigned int localOffset,
- unsigned int remoteOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I P O S T D M A Q U E U E *
- * *
- * Flags: *
- * *
- * SCI_FLAG_USE_CALLBACK - The end of the transfer will cause the callback *
- * function to be invoked. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * *
- *********************************************************************************/
-#define SCIPostDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIPostDMAQueue)
-DLL void SCIPostDMAQueue(sci_dma_queue_t dq,
- sci_cb_dma_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I A B O R T D M A Q U E U E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * *
- *********************************************************************************/
-#define SCIAbortDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIAbortDMAQueue)
-DLL void SCIAbortDMAQueue(sci_dma_queue_t dq,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I R E S E T D M A Q U E U E *
- * *
- * Flags *
- * None. * *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIResetDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIResetDMAQueue)
-DLL void SCIResetDMAQueue(sci_dma_queue_t dq,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I D M A Q U E U E S T A T E *
- * *
- *********************************************************************************/
-#define SCIDMAQueueState _SISCI_EXPANDE_FUNCTION_NAME(SCIDMAQueueState)
-DLL sci_dma_queue_state_t SCIDMAQueueState(sci_dma_queue_t dq);
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R D M A Q U E U E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * *
- *********************************************************************************/
-#define SCIWaitForDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForDMAQueue)
-DLL sci_dma_queue_state_t SCIWaitForDMAQueue(sci_dma_queue_t dq,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I P H D M A E N Q U E U E *
- * *
- * SISCI Priveleged function *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_READ *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIphDmaEnqueue _SISCI_EXPANDE_FUNCTION_NAME(SCIphDmaEnqueue)
-DLL void SCIphDmaEnqueue(sci_dma_queue_t dmaqueue,
- unsigned int size,
- sci_ioaddr_t localBusAddr,
- unsigned int remote_nodeid,
- unsigned int remote_highaddr,
- unsigned int remote_lowaddr,
- unsigned int flags,
- sci_error_t *error);
-
-/*********************************************************************************
- * *
- * S C I P H D M A S T A R T *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_WAIT *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_DMA_RESET *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIphDmaStart _SISCI_EXPANDE_FUNCTION_NAME(SCIphDmaStart)
-DLL sci_dma_queue_state_t SCIphDmaStart(sci_dma_queue_t dmaqueue,
- sci_cb_dma_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-/*********************************************************************************
- * *
- * S C I C R E A T E I N T E R R U P T *
- * *
- * Flags *
- * *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_FIXED_INTNO *
- * SCI_FLAG_SHARED_INT *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_INTNO_USED - This interrupt number is already used. *
- * *
- *********************************************************************************/
-#define SCICreateInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCICreateInterrupt)
-DLL void SCICreateInterrupt(sci_desc_t sd,
- sci_local_interrupt_t *interrupt,
- unsigned int localAdapterNo,
- unsigned int *interruptNo,
- sci_cb_interrupt_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIRemoveInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveInterrupt)
-DLL void SCIRemoveInterrupt(sci_local_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_TIMEOUT - The function timed out after specified timeout value. *
- * SCI_ERR_CANCELLED - The wait was interrupted by a call to *
- * SCIRemoveInterrupt. *
- * The handle is invalid when this error code is returned.*
- * *
- *********************************************************************************/
-#define SCIWaitForInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForInterrupt)
-DLL void SCIWaitForInterrupt(sci_local_interrupt_t interrupt,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C O N N E C T I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_SUCH_INTNO - No such interrupt number. *
- * SCI_ERR_CONNECTION_REFUSED - Connection attempt refused by remote node. *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * *
- *********************************************************************************/
-#define SCIConnectInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIConnectInterrupt)
-DLL void SCIConnectInterrupt(sci_desc_t sd,
- sci_remote_interrupt_t *interrupt,
- unsigned int nodeId,
- unsigned int localAdapterNo,
- unsigned int interruptNo,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I D I S C O N N E C T I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIDisconnectInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIDisconnectInterrupt)
-DLL void SCIDisconnectInterrupt(sci_remote_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I T R I G G E R I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCITriggerInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCITriggerInterrupt)
-DLL void SCITriggerInterrupt(sci_remote_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I R E G I S T E R I N T E R R U P T F L A G *
- * *
- * *
- * This function register an "interrupt flag" that is identified as an unique *
- * location within a local segment. If successful, the resulting interrupt *
- * handle will have been associated with the specified local segment. *
- * *
- * It is up to the (remote) client(s) to set up an "interrupt mapping" for the *
- * corresponding segment offset using either the *
- * *
- * - SCI_FLAG_CONDITIONAL_INTERRUPT_MAP *
- * *
- * or the *
- * *
- * - SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP *
- * *
- * option to "SCIMapRemoteSegment()". - I.e. after having established a *
- * connection to the corresponding segment. A trigger operation can then *
- * be implemented using a store operation via the relevant "interrupt map". *
- * *
- * *
- * *
- * *
- * *
- * Flags: *
- * *
- * SCI_FLAG_CONDITIONAL_INTERRUPT - Triggering is to take place using *
- * "conditional interrupts". *
- * *
- * *
- * *
- * Specific error codes for this function: *
- * None. *
- * *
- *********************************************************************************/
-#define SCIRegisterInterruptFlag _SISCI_EXPANDE_FUNCTION_NAME(SCIRegisterInterruptFlag)
-DLL void SCIRegisterInterruptFlag(
- unsigned int localAdapterNo,
- sci_local_interrupt_t *interrupt,
- sci_local_segment_t segment,
- unsigned int offset,
- sci_cb_interrupt_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I E N A B L E C O N D I T I O N A L I N T E R R U P T *
- * *
- * *
- * This function make sure that another HW interrupt will take place the next *
- * time the corresponding interrupt flag is triggered by a *
- * "conditional interrupt" operation. *
- * *
- * Default semantics: *
- * *
- * When successful, the client can rely on that the first subsequent trigger *
- * operation will cause a HW interrupt and subsequently cause the client *
- * handler function to be invoked. *
- * *
- * If an interrupt was triggered in parallell with the enable operation, then *
- * the operation will fail (SCI_ERR_COND_INT_RACE_PROBLEM), and the client can *
- * not rely on another trigger operation will lead to handler invocation. *
- * Hence, any state checking normally associated with handling the *
- * corresponding interrupt should take place before attempting to enable *
- * again. *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_COND_INT_RACE_PROBLEM - The enable operation failed because an *
- * incomming trigger operation happened *
- * concurrently. *
- * *
- *********************************************************************************/
-#define SCIEnableConditionalInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIEnableConditionalInterrupt)
-DLL void SCIEnableConditionalInterrupt(
- sci_local_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I D I S A B L E C O N D I T I O N A L I N T E R R U P T *
- * *
- * *
- * Prevent subsequent "conditional interrupt"trigger operations for *
- * the specified interupt flag from causing HW interrupt and handler *
- * invocations. *
- * *
- * *
- * Default semantics: *
- * *
- * If successful, no subsequent HW interrupts will take place, but handler *
- * invocations that have already been scheduled may still take place. *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIDisableConditionalInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIDisableConditionalInterrupt)
-DLL void SCIDisableConditionalInterrupt(
- sci_local_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I G E T C O N D I T I O N A L I N T E R R U P T C O U N T E R *
- * *
- * *
- * Returns a value that indicates the number of times this flag has *
- * been trigged since the last time it was enabled or disabled. *
- * Calling the SCIEnableConditionalInterrupt / SCIDisableConditionalInterrupt *
- * functions will reset the counter value. *
- * *
- * Default semantics: *
- * *
- * If successful, the current trig count is returned in the *
- * interruptTrigCounter parameter. *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OVERFLOW - The number of trig operations have exceeded the range *
- * that can be counted. *
- *********************************************************************************/
-#define SCIGetConditionalInterruptTrigCounter _SISCI_EXPANDE_FUNCTION_NAME(SCIGetConditionalInterruptTrigCounter)
-DLL void SCIGetConditionalInterruptTrigCounter(
- sci_local_interrupt_t interrupt,
- unsigned int *interruptTrigCounter,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I T R A N S F E R B L O C K *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger *
- * than the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-#define SCITransferBlock _SISCI_EXPANDE_FUNCTION_NAME(SCITransferBlock)
-DLL void SCITransferBlock(sci_map_t sourceMap,
- unsigned int sourceOffset,
- sci_map_t destinationMap,
- unsigned int destinationOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I T R A N S F E R B L O C K A S Y N C *
- * *
- * Flags *
- * *
- * SCI_FLAG_BLOCK_READ *
- * SCI_FLAG_USE_CALLBACK *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger than *
- * the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required by *
- * the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-#define SCITransferBlockAsync _SISCI_EXPANDE_FUNCTION_NAME(SCITransferBlockAsync)
-DLL void SCITransferBlockAsync(sci_map_t sourceMap,
- unsigned int sourceOffset,
- sci_map_t destinationMap,
- unsigned int destinationOffset,
- unsigned int size,
- sci_block_transfer_t *block,
- sci_cb_block_transfer_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R B L O C K T R A N S F E R *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * *
- *********************************************************************************/
-#define SCIWaitForBlockTransfer _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForBlockTransfer)
-DLL void SCIWaitForBlockTransfer(sci_block_transfer_t block,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I A B O R T B L O C K T R A N S F E R *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * *
- *********************************************************************************/
-#define SCIAbortBlockTransfer _SISCI_EXPANDE_FUNCTION_NAME(SCIAbortBlockTransfer)
-DLL void SCIAbortBlockTransfer(sci_block_transfer_t block,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I M E M C P Y *
- * *
- * Flags: *
- * SCI_FLAG_BLOCK_READ *
- * SCI_FLAG_ERROR_CHECK *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger *
- * than the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-
-#define SCIMemCpy _SISCI_EXPANDE_FUNCTION_NAME(SCIMemCpy)
-DLL void SCIMemCpy(sci_sequence_t sequence,
- void *memAddr,
- sci_map_t remoteMap,
- unsigned int remoteOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I M E M C O P Y *
- * *
- * Flags: *
- * SCI_FLAG_BLOCK_READ *
- * SCI_FLAG_ERROR_CHECK *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger *
- * than the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-
-
-#define SCIMemCopy _SISCI_EXPANDE_FUNCTION_NAME(SCIMemCopy)
-DLL void SCIMemCopy(void *memAddr,
- sci_map_t remoteMap,
- unsigned int remoteOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E G I S T E R S E G M E N T M E M O R Y *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required by *
- * the implementation. *
- * SCI_ERR_ILLEGAL_ADDRESS - Illegal address. *
- * SCI_ERR_OUT_OF_RANGE - Size is larger than the maximum size for the *
- * local segment. *
- * *
- *********************************************************************************/
-#define SCIRegisterSegmentMemory _SISCI_EXPANDE_FUNCTION_NAME(SCIRegisterSegmentMemory)
-DLL void SCIRegisterSegmentMemory(void *address,
- unsigned int size,
- sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C O N N E C T S C I S P A C E *
- * *
- * SISCI Priveleged function *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_CONNECTION_REFUSED - Connection attempt refused by remote node. *
- * *
- *********************************************************************************/
-#define SCIConnectSCISpace _SISCI_EXPANDE_FUNCTION_NAME(SCIConnectSCISpace)
-DLL void SCIConnectSCISpace(sci_desc_t sd,
- unsigned int localAdapterNo,
- sci_remote_segment_t *segment,
- sci_address_t address,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*
- * =====================================================================================
- *
- * S C I A T T A C H L O C A L S E G M E N T
- * Description:
- *
- * SCIAttachLocalSegment() permits an application to "attach" to an already existing
- * local segment, implying that two or more application want
- * share the same local segment. The prerequest, is that the
- * application which originally created the segment ("owner") has
- * preformed a SCIShareSegment() in order to mark the segment
- * "shareable".
- *
- *
- * Flags:
- *
- * SCI_FLAG_USE_CALLBACK - The callback function will be invoked for events
- * on this segment.
- *
- *
- * Specific error codes for this function:
- *
- * SCI_ERR_ACCESS - No such shared segment
- * SCI_ERR_NO_SUCH_SEGMENT - No such segment
- * Note: Current implenentation will return SCI_ERR_ACCESS for both cases. This will
- * change from next release. Application should handle both cases.
- *
- * =====================================================================================
- */
-#define SCIAttachLocalSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIAttachLocalSegment)
-
-DLL void
-SCIAttachLocalSegment(sci_desc_t sd,
- sci_local_segment_t *segment,
- unsigned int segmentId,
- unsigned int *size,
- sci_cb_local_segment_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-/*
- * =====================================================================================
- *
- * S C I S H A R E S E G M E N T
- *
- * Description:
- *
- * SCIShareSegment() permits other application to "attach" to an already existing
- * local segment, implying that two or more application want
- * share the same local segment. The prerequest, is that the
- * application which originally created the segment ("owner") has
- * preformed a SCIShareSegment() in order to mark the segment
- * "shareable".
- *
- *
- * Flags:
- * none
- *
- * Specific error codes for this function:
- *
- *
- *
- * =====================================================================================
- */
-#define SCIShareSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIShareSegment)
-
-DLL void
-SCIShareSegment(sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I F L U S H *
- * *
- * This function will flush the CPU buffers and the PSB buffers. *
- * *
- * Flags *
- * SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY : *
- * Only flush CPU buffers ( Write combining *
- * etc buffers). *
- * *
- *********************************************************************************/
-
-#define SCIFlush _SISCI_EXPANDE_FUNCTION_NAME(SCIFlush)
-DLL void SCIFlush(sci_sequence_t sequence,
- unsigned int flags);
-
-#if defined(CPLUSPLUS) || defined(__cplusplus)
-}
-#endif
-
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ndb/src/external/LINUX.x86/sci/include/sisci_demolib.h b/ndb/src/external/LINUX.x86/sci/include/sisci_demolib.h
deleted file mode 100644
index 4284fc5585c..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/sisci_demolib.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/* $Id: sisci_demolib.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-#ifndef _SISCI_DEMOLIB_H
-#define _SISCI_DEMOLIB_H
-
-
-#if defined(_REENTRANT)
-
-#define _SISCI_DEMOLIB_EXPAND_NAME(name) _SISCI_DEMOLIB_MT_ ## name
-
-#else
-
-#define _SISCI_DEMOLIB_EXPAND_NAME(name) _SISCI_DEMOLIB_ST_ ## name
-
-#endif
-
-/*********************************************************************************/
-/* Q U E R Y A D A P T E R */
-/* */
-/*********************************************************************************/
-
-#define QueryAdapter _SISCI_DEMOLIB_EXPAND_NAME(QueryAdapter)
-
-sci_error_t QueryAdapter(
- unsigned int subcommand,
- unsigned int localAdapterNo,
- unsigned int portNo,
- unsigned int *data);
-
-
-/*********************************************************************************/
-/* Q U E R Y S Y S T E M */
-/* */
-/*********************************************************************************/
-
-#define QuerySystem _SISCI_DEMOLIB_EXPAND_NAME(QuerySystem)
-
-sci_error_t QuerySystem(
- unsigned int subcommand,
- unsigned int *data);
-
-
-/*********************************************************************************/
-/* D E T E C T F I R S T A D A P T E R C A R D */
-/* */
-/*********************************************************************************/
-
-#define DetectFirstAdapterCard _SISCI_DEMOLIB_EXPAND_NAME(DetectFirstAdapterCard)
-
-sci_error_t DetectFirstAdapterCard(
- unsigned int *localAdapterNo,
- unsigned int *localNodeId);
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R T Y P E */
-/* */
-/*********************************************************************************/
-
-#define GetAdapterType _SISCI_DEMOLIB_EXPAND_NAME(GetAdapterType)
-
-sci_error_t GetAdapterType(unsigned int localAdapterNo,
- unsigned int *adapterType);
-
-
-/*********************************************************************************/
-/* G E T L O C A L N O D E I D */
-/* */
-/*********************************************************************************/
-
-#define GetLocalNodeId _SISCI_DEMOLIB_EXPAND_NAME(GetLocalNodeId)
-
-sci_error_t GetLocalNodeId(
- unsigned int localAdapterNo,
- unsigned int *localNodeId);
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R S E R I A L N U M B E R */
-/* */
-/*********************************************************************************/
-
-#define GetAdapterSerialNumber _SISCI_DEMOLIB_EXPAND_NAME(GetAdapterSerialNumber)
-
-sci_error_t GetAdapterSerialNumber(
- unsigned int localAdapterNo,
- unsigned int *serialNo);
-
-
-
-/*********************************************************************************/
-/* G E T H O S T B R I D G E T Y P E */
-/* */
-/*********************************************************************************/
-
-#define GetHostbridgeType _SISCI_DEMOLIB_EXPAND_NAME(GetHostbridgeType)
-
-sci_error_t GetHostbridgeType(unsigned int *hostbridgeType);
-
-
-
-/*********************************************************************************/
-/* P R I N T H O S T B R I D G E T Y P E */
-/* */
-/*********************************************************************************/
-
-#define PrintHostbridgeType _SISCI_DEMOLIB_EXPAND_NAME(PrintHostbridgeType)
-
-void PrintHostbridgeType(unsigned int hostbridge);
-
-
-
-/*********************************************************************************/
-/* G E T A P I V E R S I O N S T R I N G */
-/* */
-/*********************************************************************************/
-
-#define GetAPIVersionString _SISCI_DEMOLIB_EXPAND_NAME(GetAPIVersionString)
-
-sci_error_t GetAPIVersionString(char str[], unsigned int strLength);
-
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R I O B U S F R E Q U E N C Y */
-/* */
-/*********************************************************************************/
-
-sci_error_t GetAdapterIoBusFrequency(unsigned int localAdapterNo,
- unsigned int *ioBusFrequency);
-
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R S C I L I N K F R E Q U E N C Y */
-/* */
-/*********************************************************************************/
-
-sci_error_t GetAdapterSciLinkFrequency(unsigned int localAdapterNo,
- unsigned int *sciLinkFrequency);
-
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R B L I N K F R E Q U E N C Y */
-/* */
-/*********************************************************************************/
-
-sci_error_t GetAdapterBlinkFrequency(unsigned int localAdapterNo,
- unsigned int *bLinkFrequency);
-
-
-/*********************************************************************************/
-/* S E N D I N T E R R U P T */
-/* */
-/*********************************************************************************/
-
-#define SendInterrupt _SISCI_DEMOLIB_EXPAND_NAME(SendInterrupt)
-
-sci_error_t SendInterrupt(
- sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int localNodeId,
- unsigned int remoteNodeId,
- unsigned int interruptNo);
-
-
-/*********************************************************************************/
-/* R E C E I V E I N T E R R U P T */
-/* */
-/*********************************************************************************/
-
-#define ReceiveInterrupt _SISCI_DEMOLIB_EXPAND_NAME(ReceiveInterrupt)
-
-sci_error_t ReceiveInterrupt(
- sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int localNodeId,
- unsigned int interruptNo);
-
-
-/*********************************************************************************/
-/* E N D I A N S W A P */
-/* */
-/*********************************************************************************/
-
-#define EndianSwap _SISCI_DEMOLIB_EXPAND_NAME(EndianSwap)
-
-unsigned int EndianSwap (unsigned int value);
-
-
-/*********************************************************************************/
-/* S L E E P M I L L I S E C O N D S */
-/* */
-/*********************************************************************************/
-
-#define SleepMilliseconds _SISCI_DEMOLIB_EXPAND_NAME(SleepMilliseconds)
-
-void SleepMilliseconds(int milliseconds);
-
-
-
-
-#endif
diff --git a/ndb/src/external/LINUX.x86/sci/include/sisci_error.h b/ndb/src/external/LINUX.x86/sci/include/sisci_error.h
deleted file mode 100644
index c53fe8ad5d9..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/sisci_error.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* $Id: sisci_error.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-
-
-#ifndef _SISCI_ERROR_H_
-#define _SISCI_ERROR_H_
-
-
-/* SCI Error return values always have 30 bit set */
-#define SCI_ERR_MASK 0x40000000
-#define SCI_ERR_REMOTE_MASK 0x01 /* Remote errors should have bit 0 set */
-
-#define SCI_ERR(u) ((unsigned32)(u)&0x7FFFFFFF )
-
-/* Error codes */
-typedef enum {
- SCI_ERR_OK = 0x000,
-
-
- SCI_ERR_BUSY = (0x900 | SCI_ERR_MASK),
- SCI_ERR_FLAG_NOT_IMPLEMENTED = (0x901 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_FLAG = (0x902 | SCI_ERR_MASK),
- SCI_ERR_NOSPC = (0x904 | SCI_ERR_MASK),
- SCI_ERR_API_NOSPC = (0x905 | SCI_ERR_MASK),
- SCI_ERR_HW_NOSPC = (0x906 | SCI_ERR_MASK),
- SCI_ERR_NOT_IMPLEMENTED = (0x907 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_ADAPTERNO = (0x908 | SCI_ERR_MASK),
- SCI_ERR_NO_SUCH_ADAPTERNO = (0x909 | SCI_ERR_MASK),
- SCI_ERR_TIMEOUT = (0x90A | SCI_ERR_MASK),
- SCI_ERR_OUT_OF_RANGE = (0x90B | SCI_ERR_MASK),
- SCI_ERR_NO_SUCH_SEGMENT = (0x90C | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_NODEID = (0x90D | SCI_ERR_MASK),
- SCI_ERR_CONNECTION_REFUSED = (0x90E | SCI_ERR_MASK),
- SCI_ERR_SEGMENT_NOT_CONNECTED = (0x90F | SCI_ERR_MASK),
- SCI_ERR_SIZE_ALIGNMENT = (0x910 | SCI_ERR_MASK),
- SCI_ERR_OFFSET_ALIGNMENT = (0x911 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_PARAMETER = (0x912 | SCI_ERR_MASK),
- SCI_ERR_MAX_ENTRIES = (0x913 | SCI_ERR_MASK),
- SCI_ERR_SEGMENT_NOT_PREPARED = (0x914 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_ADDRESS = (0x915 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_OPERATION = (0x916 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_QUERY = (0x917 | SCI_ERR_MASK),
- SCI_ERR_SEGMENTID_USED = (0x918 | SCI_ERR_MASK),
- SCI_ERR_SYSTEM = (0x919 | SCI_ERR_MASK),
- SCI_ERR_CANCELLED = (0x91A | SCI_ERR_MASK),
- SCI_ERR_NOT_CONNECTED = (0x91B | SCI_ERR_MASK),
- SCI_ERR_NOT_AVAILABLE = (0x91C | SCI_ERR_MASK),
- SCI_ERR_INCONSISTENT_VERSIONS = (0x91D | SCI_ERR_MASK),
- SCI_ERR_COND_INT_RACE_PROBLEM = (0x91E | SCI_ERR_MASK),
- SCI_ERR_OVERFLOW = (0x91F | SCI_ERR_MASK),
- SCI_ERR_NOT_INITIALIZED = (0x920 | SCI_ERR_MASK),
-
- SCI_ERR_ACCESS = (0x921 | SCI_ERR_MASK),
-
- SCI_ERR_NO_SUCH_NODEID = (0xA00 | SCI_ERR_MASK),
- SCI_ERR_NODE_NOT_RESPONDING = (0xA02 | SCI_ERR_MASK),
- SCI_ERR_NO_REMOTE_LINK_ACCESS = (0xA04 | SCI_ERR_MASK),
- SCI_ERR_NO_LINK_ACCESS = (0xA05 | SCI_ERR_MASK),
- SCI_ERR_TRANSFER_FAILED = (0xA06 | SCI_ERR_MASK)
-} sci_error_t;
-
-
-#endif /* _SCI_ERROR_H_ */
-
-
-
diff --git a/ndb/src/external/LINUX.x86/sci/include/sisci_types.h b/ndb/src/external/LINUX.x86/sci/include/sisci_types.h
deleted file mode 100644
index f4125fdec69..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/sisci_types.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $Id: sisci_types.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-#ifndef _SISCI_TYPES_H
-#define _SISCI_TYPES_H
-
-#include "sisci_error.h"
-
-#ifndef IN
-#define IN
-#endif
-
-#ifndef OUT
-#define OUT
-#endif
-
-#ifndef IN_OUT
-#define IN_OUT
-#endif
-
-/* Opaque data types for descriptors/handles */
-typedef struct sci_desc *sci_desc_t;
-typedef struct sci_local_segment *sci_local_segment_t;
-typedef struct sci_remote_segment *sci_remote_segment_t;
-
-typedef struct sci_map *sci_map_t;
-typedef struct sci_sequence *sci_sequence_t;
-#ifndef KERNEL
-typedef struct sci_dma_queue *sci_dma_queue_t;
-#endif
-typedef struct sci_remote_interrupt *sci_remote_interrupt_t;
-typedef struct sci_local_interrupt *sci_local_interrupt_t;
-typedef struct sci_block_transfer *sci_block_transfer_t;
-
-/*
- * Constants defining reasons for segment callbacks:
- */
-
-typedef enum {
- SCI_CB_CONNECT = 1,
- SCI_CB_DISCONNECT,
- SCI_CB_NOT_OPERATIONAL,
- SCI_CB_OPERATIONAL,
- SCI_CB_LOST
-} sci_segment_cb_reason_t;
-
-#define MAX_CB_REASON SCI_CB_LOST
-
-/* dma_queue_states is identical to the dma_queue_state_t in genif.h, they must be consistent.*/
-typedef enum {
- SCI_DMAQUEUE_IDLE,
- SCI_DMAQUEUE_GATHER,
- SCI_DMAQUEUE_POSTED,
- SCI_DMAQUEUE_DONE,
- SCI_DMAQUEUE_ABORTED,
- SCI_DMAQUEUE_ERROR
-} sci_dma_queue_state_t;
-
-
-typedef enum {
- SCI_SEQ_OK,
- SCI_SEQ_RETRIABLE,
- SCI_SEQ_NOT_RETRIABLE,
- SCI_SEQ_PENDING
-} sci_sequence_status_t;
-
-
-typedef struct {
- unsigned short nodeId; /* SCI Address bit 63 - 48 */
- unsigned short offsHi; /* SCI Address bit 47 - 32 */
- unsigned int offsLo; /* SCI Address bit 31 - 0 */
-} sci_address_t;
-
-
-typedef unsigned int sci_ioaddr_t;
-
-typedef enum {
- SCI_CALLBACK_CANCEL = 1,
- SCI_CALLBACK_CONTINUE
-} sci_callback_action_t;
-
-#ifndef KERNEL
-typedef sci_callback_action_t (*sci_cb_local_segment_t)(void *arg,
- sci_local_segment_t segment,
- sci_segment_cb_reason_t reason,
- unsigned int nodeId,
- unsigned int localAdapterNo,
- sci_error_t error);
-
-typedef sci_callback_action_t (*sci_cb_remote_segment_t)(void *arg,
- sci_remote_segment_t segment,
- sci_segment_cb_reason_t reason,
- sci_error_t status);
-
-
-typedef sci_callback_action_t (*sci_cb_dma_t)(void IN *arg,
- sci_dma_queue_t queue,
- sci_error_t status);
-
-
-typedef int (*sci_cb_block_transfer_t)(void *arg,
- sci_block_transfer_t block,
- sci_error_t status);
-
-
-typedef sci_callback_action_t (*sci_cb_interrupt_t)(void *arg,
- sci_local_interrupt_t interrupt,
- sci_error_t status);
-
-#endif /* KERNEL */
-#endif
diff --git a/ndb/src/external/LINUX.x86/sci/include/sisci_version.h b/ndb/src/external/LINUX.x86/sci/include/sisci_version.h
deleted file mode 100644
index f1807c33aa5..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/sisci_version.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* $Id: sisci_version.h,v 1.1 2002/12/13 12:17:21 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Lesser General Public License as published by *
- * the Free Software Foundation; either version 2.1 of the License, *
- * or (at your option) any later version. *
- * *
- * 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 Lesser General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-#ifndef SISCI_VERSION_H
-#define SISCI_VERSION_H
-
-
-#define SISCI_API_VER_MAJOR 0x01
-#define SISCI_API_VER_MAJORC "1"
-
-#define SISCI_API_VER_MINOR 0x010
-#define SISCI_API_VER_MINORC "10"
-#define SISCI_API_VER_MICRO 0x005
-#define SISCI_API_VER_MICROC "5"
-
-#define SISCI_SIGN_VERSION_MASK 0xfffff000 /* used to mask off API_VER_MICRO */
-
-#define SISCI_API_VERSION (SISCI_API_VER_MAJOR << 24 | SISCI_API_VER_MINOR << 12 | SISCI_API_VER_MICRO)
-
-/* the rules are:
- *
- * Changes in API_VER_MICRO should be binary compatible, New flags, functions added. No changes to user code
- * required if new features is not needed.
- *
- * Changes in API_VER_MINOR requires recompilation of user code.
- *
- * Changes in the API_VER_MAJOR will most likely require changes to user code. This should not happen very
- * often...
- *
- */
-
-#ifndef BUILD_DATE
-#define BUILD_DATE __DATE__
-#endif
-
-#ifndef BUILD_NAME
-#define BUILD_NAME ""
-#endif
-
-#define API_VERSION "SISCI API version " SISCI_API_VER_MAJORC "." SISCI_API_VER_MINORC "."SISCI_API_VER_MICROC " ( "BUILD_NAME" "BUILD_DATE" )"
-
-#endif
-
-
-/* Version info: */
-/* */
-/* 1.5.2 First SISCI version */
-/* 1.5.3 Some bug fixes */
-/* 1.5.4 Some bug fixes */
-/* 1.5.5 No release */
-/* 1.5.6 Lock flag implemented in function SCIConnectSegment */
-/* 1.5.7 Expanded query functionality */
-/* 1.5.8 Updated error checking (sequence) functionality for D320 */
-/* 1.6.0 Updated error checking (sequence) D320 and IRM 1.9 support */
-/* 1.9.0 Ported to Solaris_sparc, Solaris_x86 and Linux. IRM 1.9. */
-/* 1.9.1 Some bug fixes */
-/* 1.9.2 Added more adapter queries */
-/* 1.9.3 Bug fix in SCIMapLocalSegment and SCIMapRemoteSegment */
-/* 1.9.4 NT Release Developers Kit 2.40 */
-/* 1.9.5 Added flush after data transfer in SCIMemCopy() */
-/* 1.9.5 NT Release Developers Kit 2.44 */
-/* 1.10.0:
- * New SCIInitialize(), SCITerminate() functions.
- * Support for D330
- *
- *
- */
-
-
diff --git a/ndb/src/external/LINUX.x86/sci/include/version.h b/ndb/src/external/LINUX.x86/sci/include/version.h
deleted file mode 100644
index a0e1fa6c5cd..00000000000
--- a/ndb/src/external/LINUX.x86/sci/include/version.h
+++ /dev/null
@@ -1,25 +0,0 @@
-#ifndef _VERSION_H
-#define _VERSION_H
-
-
-/*
-#define DEMO_VER_MAJOR "1"
-#define DEMO_VER_MINOR "5"
-#define DEMO_VER_MICRO "0"
-*/
-
-#ifndef BUILD_DATE
-#define BUILD_DATE __DATE__
-#endif
-
-#ifndef BUILD_NAME
-#define BUILD_NAME ""
-#endif
-
-/*
-#define DEMO_VERSION "version " DEMO_VER_MAJOR "." DEMO_VER_MINOR "."DEMO_VER_MICRO " ("BUILD_NAME" "BUILD_DATE" )"
-*/
-#define DEMO_VERSION " ("BUILD_NAME" "BUILD_DATE" )"
-
-
-#endif
diff --git a/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_api.h b/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_api.h
deleted file mode 100644
index d02d3aafe7f..00000000000
--- a/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_api.h
+++ /dev/null
@@ -1,2148 +0,0 @@
-/* $Id: sisci_api.h,v 1.1 2002/12/13 12:17:22 hin Exp $ */
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2001 *
- * Dolphin Interconnect Solutions AS *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Lesser General Public License as published by *
- * the Free Software Foundation; either version 2.1 of the License, *
- * or (at your option) any later version. *
- * *
- * 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 Lesser General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-#ifndef _SISCI_API_H
-#define _SISCI_API_H
-
-#include "sisci_types.h"
-#include "sisci_error.h"
-
-
-#ifdef WIN32
-#ifdef API_DLL
-#define DLL __declspec(dllexport)
-#elif CLIENT_DLL
-#define DLL __declspec(dllimport)
-#endif
-#endif /* WIN32 */
-
-
-#ifndef DLL
-#define DLL
-#endif
-
-#if defined(_REENTRANT)
-#define _SISCI_EXPANDE_FUNCTION_NAME(name) _SISCI_PUBLIC_FUNC_MT_ ## name
-#define _SISCI_EXPANDE_VARIABLE_NAME(name) _SISCI_PUBLIC_VAR_MT_ ## name
-#else
-#define _SISCI_EXPANDE_FUNCTION_NAME(name) _SISCI_PUBLIC_FUNC_ST_ ## name
-#define _SISCI_EXPANDE_VARIABLE_NAME(name) _SISCI_PUBLIC_VAR_ST_ ## name
-#endif
-#define _SISCI_EXPANDE_CONSTANT_NAME(name) _SISCI_PUBLIC_CONST_ ## name
-
-#if defined(CPLUSPLUS) || defined(__cplusplus)
-extern "C" {
-#endif
-
-
-/*********************************************************************************/
-/* FLAG VALUES */
-/*********************************************************************************/
-
-#define SCI_FLAG_FIXED_INTNO _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FIXED_INTNO)
-extern const unsigned int SCI_FLAG_FIXED_INTNO;
-
-#define SCI_FLAG_SHARED_INT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_SHARED_INT)
-extern const unsigned int SCI_FLAG_SHARED_INT;
-
-#define SCI_FLAG_FIXED_MAP_ADDR _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FIXED_MAP_ADDR)
-extern const unsigned int SCI_FLAG_FIXED_MAP_ADDR;
-
-#define SCI_FLAG_READONLY_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_READONLY_MAP)
-extern const unsigned int SCI_FLAG_READONLY_MAP;
-
-#define SCI_FLAG_USE_CALLBACK _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_USE_CALLBACK)
-extern const unsigned int SCI_FLAG_USE_CALLBACK;
-
-#define SCI_FLAG_BLOCK_READ _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_BLOCK_READ)
-extern const unsigned int SCI_FLAG_BLOCK_READ;
-
-#define SCI_FLAG_THREAD_SAFE _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_THREAD_SAFE)
-extern const unsigned int SCI_FLAG_THREAD_SAFE;
-
-#define SCI_FLAG_ASYNCHRONOUS_CONNECT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_ASYNCHRONOUS_CONNECT)
-extern const unsigned int SCI_FLAG_ASYNCHRONOUS_CONNECT;
-
-#define SCI_FLAG_EMPTY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_EMPTY)
-extern const unsigned int SCI_FLAG_EMPTY;
-
-#define SCI_FLAG_PRIVATE _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_PRIVATE)
-extern const unsigned int SCI_FLAG_PRIVATE;
-
-#define SCI_FLAG_FORCE_DISCONNECT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FORCE_DISCONNECT)
-extern const unsigned int SCI_FLAG_FORCE_DISCONNECT;
-
-#define SCI_FLAG_NOTIFY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NOTIFY)
-extern const unsigned int SCI_FLAG_NOTIFY;
-
-#define SCI_FLAG_DMA_READ _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_READ)
-extern const unsigned int SCI_FLAG_DMA_READ;
-
-#define SCI_FLAG_DMA_POST _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_POST)
-extern const unsigned int SCI_FLAG_DMA_POST;
-
-#define SCI_FLAG_DMA_WAIT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_WAIT)
-extern const unsigned int SCI_FLAG_DMA_WAIT;
-
-#define SCI_FLAG_DMA_RESET _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_RESET)
-extern const unsigned int SCI_FLAG_DMA_RESET;
-
-#define SCI_FLAG_NO_FLUSH _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NO_FLUSH)
-extern const unsigned int SCI_FLAG_NO_FLUSH;
-
-#define SCI_FLAG_NO_STORE_BARRIER _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NO_STORE_BARRIER)
-extern const unsigned int SCI_FLAG_NO_STORE_BARRIER;
-
-#define SCI_FLAG_FAST_BARRIER _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FAST_BARRIER)
-extern const unsigned int SCI_FLAG_FAST_BARRIER;
-
-#define SCI_FLAG_ERROR_CHECK _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_ERROR_CHECK)
-extern const unsigned int SCI_FLAG_ERROR_CHECK;
-
-#define SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY)
-extern const unsigned int SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY;
-
-/* the FLUSH_CPU_BUFFERS_ONLY flag is for backwards compabillity only and should never be used */
-#define FLUSH_CPU_BUFFERS_ONLY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY)
-
-#define SCI_FLAG_LOCK_OPERATION _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_LOCK_OPERATION)
-extern const unsigned int SCI_FLAG_LOCK_OPERATION;
-
-#define SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP)
-extern const unsigned int SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP;
-
-#define SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP)
-extern const unsigned int SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP;
-
-#define SCI_FLAG_IO_MAP_IOSPACE _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_IO_MAP_IOSPACE)
-extern const unsigned int SCI_FLAG_IO_MAP_IOSPACE;
-
-#define SCI_FLAG_DMOVE_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMOVE_MAP)
-extern const unsigned int SCI_FLAG_DMOVE_MAP;
-
-#define SCI_FLAG_WRITES_DISABLE_GATHER_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_WRITES_DISABLE_GATHER_MAP)
-extern const unsigned int SCI_FLAG_WRITES_DISABLE_GATHER_MAP;
-
-#define SCI_FLAG_DISABLE_128_BYTES_PACKETS _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DISABLE_128_BYTES_PACKETS)
-extern const unsigned int SCI_FLAG_DISABLE_128_BYTES_PACKETS;
-
-#define SCI_FLAG_DMA_SOURCE_ONLY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_SOURCE_ONLY)
-extern const unsigned int SCI_FLAG_DMA_SOURCE_ONLY;
-
-#define SCI_FLAG_CONDITIONAL_INTERRUPT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_CONDITIONAL_INTERRUPT)
-extern const unsigned int SCI_FLAG_CONDITIONAL_INTERRUPT;
-
-#define SCI_FLAG_CONDITIONAL_INTERRUPT_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_CONDITIONAL_INTERRUPT_MAP)
-extern const unsigned int SCI_FLAG_CONDITIONAL_INTERRUPT_MAP;
-
-#define SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP)
-extern const unsigned int SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP;
-
-#define SCI_FLAG_NO_MEMORY_LOOPBACK_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NO_MEMORY_LOOPBACK_MAP)
-extern const unsigned int SCI_FLAG_NO_MEMORY_LOOPBACK_MAP;
-
-#if defined(OS_IS_LYNXOS) || defined(OS_IS_VXWORKS)
-#define SCI_FLAG_WRITE_BACK_CACHE_MAP _SISCI_EXPANDE_CONSTANT_NAME(WRITE_BACK_CACHE_MAP)
-extern const unsigned int SCI_FLAG_WRITE_BACK_CACHE_MAP;
-#endif
-
-#define SCI_FLAG_DMA_PHDMA _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_PHDMA)
-extern const unsigned int SCI_FLAG_DMA_PHDMA;
-
-/*********************************************************************************/
-/* GENERAL VALUES */
-/*********************************************************************************/
-#define SCI_LOCAL_HOST _SISCI_EXPANDE_CONSTANT_NAME(SCI_LOCAL_HOST)
-extern const unsigned int SCI_LOCAL_HOST;
-
-#define SCI_INFINITE_TIMEOUT _SISCI_EXPANDE_CONSTANT_NAME(SCI_INFINITE_TIMEOUT)
-extern const unsigned int SCI_INFINITE_TIMEOUT;
-
-/*********************************************************************************/
-/* GENERAL ERROR CODES */
-/* */
-/* SCI_ERR_ILLEGAL_FLAG - Illegal flag value. */
-/* SCI_ERR_FLAG_NOT_IMPLEMENTED - Flag legal but flag feature not implemented. */
-/* SCI_ERR_NOT_IMPLEMENTED - Function not implemented. */
-/* SCI_ERR_SYSTEM - A system error. Check errno. */
-/* SCI_ERR_NOSPC - Unable to allocate OS resources. */
-/* SCI_ERR_API_NOSPC - Unable to allocate API resources. */
-/* SCI_ERR_HW_NOSPC - Unable to allocate HW resources (Hardware) */
-/* */
-/*********************************************************************************/
-
-
-/*********************************************************************************/
-/* GENERAL "ADAPTER" ERROR CODES */
-/* */
-/* SCI_ERR_NO_SUCH_ADAPTERNO - Adapter number is legal but does not exist. */
-/* SCI_ERR_ILLEGAL_ADAPTERNO - Illegal local adapter number (i.e. outside */
-/* legal range). */
-/* */
-/*********************************************************************************/
-
-
-/*********************************************************************************/
-/* GENERAL "NODEID" ERROR CODES */
-/* */
-/* SCI_ERR_NO_SUCH_NODEID - The remote adapter identified by nodeId does */
-/* not respond, but the intermediate link(s) */
-/* seem(s) to be operational. */
-/* SCI_ERR_ILLEGAL_NODEID - Illegal NodeId. */
-/* */
-/*********************************************************************************/
-
-
-
-/*********************************************************************************
- * *
- * S C I I N I T I A L I Z E *
- * *
- * This function initializes the SISCI library. *
- * The function must be called before SCIOpen(). *
- * *
- * Flags: *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * None *
- * *
- *********************************************************************************/
-#define SCIInitialize _SISCI_EXPANDE_FUNCTION_NAME(SCIInitialize)
-DLL void SCIInitialize(unsigned int flags,
- sci_error_t *error);
-#if 0
-unsigned int __Internal_SISCI_version_var;
-#endif
-
-/*********************************************************************************
- * *
- * S C I T E R M I N A T E *
- * *
- * This function terminates the SISCI library. *
- * The function must be called after SCIClose(). *
- * *
- * *
- *********************************************************************************/
-#define SCITerminate _SISCI_EXPANDE_FUNCTION_NAME(SCITerminate)
-DLL void SCITerminate(void);
-
-/*********************************************************************************
- * *
- * S C I O P E N *
- * *
- * *
- * Opens a SCI virtual device. *
- * Caller must supply a pointer to a variable of type sci_desc_t to be *
- * initialized. *
- * *
- * Flags *
- * SCI_FLAG_THREAD_SAFE - Operations on resources associated with this *
- * descriptor will be performed in a multithread-safe *
- * manner. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_INCONSISTENT_VERSIONS - Inconsistency between the SISCI library *
- * and the SISCI driver versions. *
- * *
- * *
- *********************************************************************************/
-#define SCIOpen _SISCI_EXPANDE_FUNCTION_NAME(SCIOpen)
-DLL void SCIOpen(sci_desc_t *sd,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C L O S E *
- * *
- * This function closes an open SCI virtual device. *
- * *
- * Flags: *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - All resources are not deallocated. *
- * *
- *********************************************************************************/
-#define SCIClose _SISCI_EXPANDE_FUNCTION_NAME(SCIClose)
-DLL void SCIClose(sci_desc_t sd,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C O N N E C T S E G M E N T *
- * *
- * Connects to a remote shared memory segment located at <nodeId> with the *
- * identifier <segmentId>. *
- * The user may then call SCIMapRemoteSegment() to map shared memory *
- * into user space. *
- * *
- * Flags *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_ASYNCHRONOUS_CONNECT *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_SUCH_SEGMENT - Could not find the remote segment with the *
- * given segmentId. *
- * SCI_ERR_CONNECTION_REFUSED - Connection attempt refused by remote node. *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCIConnectSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIConnectSegment)
-DLL void SCIConnectSegment(sci_desc_t sd,
- sci_remote_segment_t *segment,
- unsigned int nodeId,
- unsigned int segmentId,
- unsigned int localAdapterNo,
- sci_cb_remote_segment_t callback,
- void *callbackArg,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I D I S C O N N E C T S E G M E N T *
- * *
- * Disconnects from the give mapped shared memory segment *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - The segment is currently mapped or in use. *
- * *
- *********************************************************************************/
-#define SCIDisconnectSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIDisconnectSegment)
-DLL void SCIDisconnectSegment(sci_remote_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I G E T R E M O T E S E G M E N T S I Z E *
- * *
- *********************************************************************************/
-#define SCIGetRemoteSegmentSize _SISCI_EXPANDE_FUNCTION_NAME(SCIGetRemoteSegmentSize)
-DLL unsigned int SCIGetRemoteSegmentSize(sci_remote_segment_t segment);
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R R E M O T E S E G M E N T E V E N T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation. *
- * SCI_ERR_CANCELLED - The wait operation has been cancelled du *
- * to a SCIDisconnectSegment() on the same *
- * handle. The handle is invalid when this *
- * error is returned. *
- * *
- *********************************************************************************/
-#define SCIWaitForRemoteSegmentEvent _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForRemoteSegmentEvent)
-DLL sci_segment_cb_reason_t SCIWaitForRemoteSegmentEvent(
- sci_remote_segment_t segment,
- sci_error_t *status,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I M A P R E M O T E S E G M E N T *
- * *
- * This function is used to include a shared memory segment in the virtual *
- * address space of the application. *
- * *
- * Flags: *
- * *
- * SCI_FLAG_FIXED_MAP_ADDR - Map at the suggested virtual address *
- * SCI_FLAG_READONLY_MAP - The segment is mapped in read-only mode *
- * SCI_FLAG_LOCK_OPERATION - Enable Lock operations (fetch and add) *
- * SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP *
- * - Enable aggressive prefetch with speculative *
- * hold. *
- * *
- * SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP *
- * - The PSB66 will prefetch 64 bytes. As soon *
- * as the PCI read retry has been accepted, *
- * the stream will change state to FREE, even *
- * if less than 64 bytes were actually read. *
- * *
- * SCI_FLAG_IO_MAP_IOSPACE - Enable No Prefetch, no speculative hold. *
- * *
- * SCI_FLAG_DMOVE_MAP - Enable DMOVE packet type. The stream will be *
- * set into FREE state immediately. *
- * *
- * SCI_FLAG_WRITES_DISABLE_GATHER_MAP *
- * - Disable use of gather. *
- * *
- * SCI_FLAG_DISABLE_128_BYTES_PACKETS *
- * - Disable use of 128-Byte packets *
- * *
- * SCI_FLAG_CONDITIONAL_INTERRUPT_MAP *
- * - Write operations through this map will cause *
- * an atomic "fetch-and-add-one" operation on *
- * remote memory, but in addition an interrupt *
- * will be generated if the target memory *
- * location contained a "null value" before the *
- * add operation was carried out. *
- * The conditional interrupt flag must also be *
- * specified in the SCIRegisterInterruptFlag() *
- * function. *
- * *
- * SCI_FLAG_UNCONDITIONAL_INTERRUPT_MAP *
- * - Write operations through this map will cause *
- * an interrupt for the remote adapter *
- * "in addition to" updating the corresponding *
- * remote memory location with the data being *
- * written. *
- * The unconditional interrupt flag must also *
- * be specified in the *
- * SCIRegisterInterruptFlag() function. *
- * *
- * SCI_FLAG_WRITE_BACK_CACHE_MAP *
- * - Enable cacheing of the mapped region. *
- * Writes through this map will be written to a *
- * write back cache, hence no remote SCI updates*
- * until the cache line is flushed. The *
- * application is responsible for the cache *
- * flush operation. *
- * The SCImemCopy() function will handle this *
- * correctly by doing cache flushes internally. *
- * This feature is architechture dependent and *
- * not be available on all plattforms. *
- * *
- * SCI_FLAG_NO_MEMORY_LOOPBACK_MAP *
- * - Forces a map to a remote segment located *
- * in the local machine to be mapped using *
- * SCI loopback. This is useful i.e. if you *
- * want to use a regular map access to be *
- * serialized with lock operations. *
- * The default behaviour is to access a remte *
- * segment located in the local machine as a *
- * local MMU operation. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the offset and size is *
- * larger than the segment size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as *
- * required by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as *
- * required by the implementation. *
- * *
- *********************************************************************************/
-#define SCIMapRemoteSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIMapRemoteSegment)
-DLL volatile void *SCIMapRemoteSegment(
- sci_remote_segment_t segment,
- sci_map_t *map,
- unsigned int offset,
- unsigned int size,
- void *addr,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I M A P L O C A L S E G M E N T *
- * *
- * Flags *
- * *
- * SCI_FLAG_FIXED_MAP_ADDR *
- * SCI_FLAG_READONLY_MAP *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the offset and size is *
- * larger than the segment size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as *
- * required by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as *
- * required by the implementation. *
- * *
- *********************************************************************************/
-#define SCIMapLocalSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIMapLocalSegment)
-DLL void *SCIMapLocalSegment(sci_local_segment_t segment,
- sci_map_t *map,
- unsigned int offset,
- unsigned int size,
- void *addr,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I U N M A P S E G M E N T *
- * *
- * This function unmaps pages of shared memory from the callers virtual *
- * address space. *
- * *
- * Flags *
- * None. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - The map is currently in use. *
- * *
- *********************************************************************************/
-#define SCIUnmapSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIUnmapSegment)
-DLL void SCIUnmapSegment(sci_map_t map,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C R E A T E S E G M E N T *
- * *
- * Make the specified segment available for connections via the specified *
- * adapter. If successful, the segment can be accessed from remote nodes *
- * via the specified adapter. *
- * *
- * Flags: *
- * *
- * SCI_FLAG_USE_CALLBACK - The callback function will be invoked for events *
- * on this segment. *
- * SCI_FLAG_EMPTY - No memory will be allocated for the segment. *
- * SCI_FLAG_PRIVATE - The segment will be private meaning it will never *
- * be any connections to it. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_SEGMENTID_USED - The segment with this segmentId is already used *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * *
- *********************************************************************************/
-#define SCICreateSegment _SISCI_EXPANDE_FUNCTION_NAME(SCICreateSegment)
-DLL void SCICreateSegment(sci_desc_t sd,
- sci_local_segment_t *segment,
- unsigned int segmentId,
- unsigned int size,
- sci_cb_local_segment_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R L O C A L S E G M E N T E V E N T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_TIMEOUT - The function timed out after specified timeout value. *
- * SCI_ERR_CANCELLED - The wait operation has been cancelled du to a *
- * SCIRemoveSegment() on the same handle. *
- * The handle is invalid when this error is returned. *
- * *
- *********************************************************************************/
-#define SCIWaitForLocalSegmentEvent _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForLocalSegmentEvent)
-DLL sci_segment_cb_reason_t SCIWaitForLocalSegmentEvent(
- sci_local_segment_t segment,
- unsigned int *sourcenodeId,
- unsigned int *localAdapterNo,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I P R E P A R E S E G M E N T *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_SOURCE_ONLY - The segment will be used as a source segment *
- * for DMA operations. On some system types this *
- * will enable the SISCI driver to use performance *
- * improving features. *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIPrepareSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIPrepareSegment)
-DLL void SCIPrepareSegment(sci_local_segment_t segment,
- unsigned int localAdapterNo,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E S E G M E N T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - Unable to remove the segment. The segment is currently *
- * in use. *
- * *
- *********************************************************************************/
-#define SCIRemoveSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveSegment)
-DLL void SCIRemoveSegment(sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T S E G M E N T A V A I L A B L E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * SCI_ERR_SEGMENT_NOT_PREPARED - The segment has not been prepared for access *
- * from this adapter. *
- * SCI_ERR_ILLEGAL_OPERATION - The segment is created with the *
- * SCI_FLAG_PRIVATE flag specified and *
- * therefore has no segmentId. *
- * *
- *********************************************************************************/
-#define SCISetSegmentAvailable _SISCI_EXPANDE_FUNCTION_NAME(SCISetSegmentAvailable)
-DLL void SCISetSegmentAvailable(sci_local_segment_t segment,
- unsigned int localAdapterNo,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T S E G M E N T U N A V A I L A B L E *
- * *
- * Flags *
- * *
- * SCI_FLAG_FORCE_DISCONNECT *
- * SCI_FLAG_NOTIFY *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation. *
- * *
- *********************************************************************************/
-#define SCISetSegmentUnavailable _SISCI_EXPANDE_FUNCTION_NAME(SCISetSegmentUnavailable)
-DLL void SCISetSegmentUnavailable(sci_local_segment_t segment,
- unsigned int localAdapterNo,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C R E A T E M A P S E Q U E N C E *
- * *
- * Flags: *
- * *
- * SCI_FLAG_FAST_BARRIER *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCICreateMapSequence _SISCI_EXPANDE_FUNCTION_NAME(SCICreateMapSequence)
-DLL void SCICreateMapSequence(sci_map_t map,
- sci_sequence_t *sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E S E Q U E N C E *
- * *
- * Flags: *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIRemoveSequence _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveSequence)
-DLL void SCIRemoveSequence(sci_sequence_t sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S T A R T S E Q U E N C E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIStartSequence _SISCI_EXPANDE_FUNCTION_NAME(SCIStartSequence)
-DLL sci_sequence_status_t SCIStartSequence(sci_sequence_t sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I C H E C K S E Q U E N CE *
- * *
- * Flags *
- * *
- * SCI_FLAG_NO_FLUSH *
- * SCI_FLAG_NO_STORE_BARRIER *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCICheckSequence _SISCI_EXPANDE_FUNCTION_NAME(SCICheckSequence)
-DLL sci_sequence_status_t SCICheckSequence(sci_sequence_t sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S T O R E B A R R I E R *
- * *
- * Flags *
- * None. *
- * *
- * *
- * *
- *********************************************************************************/
-#define SCIStoreBarrier _SISCI_EXPANDE_FUNCTION_NAME(SCIStoreBarrier)
-DLL void SCIStoreBarrier(sci_sequence_t sequence,
- unsigned int flags);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I F L U S H R E A D B U F F E R S *
- * *
- *********************************************************************************/
-#define SCIFlushReadBuffers _SISCI_EXPANDE_FUNCTION_NAME(SCIFlushReadBuffers)
-DLL void SCIFlushReadBuffers(sci_sequence_t sequence);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I P R O B E N O D E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCIProbeNode _SISCI_EXPANDE_FUNCTION_NAME(SCIProbeNode)
-DLL int SCIProbeNode(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int nodeId,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I G E T C S R R E G I S T E R *
- * *
- * SISCI Priveleged function *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCIGetCSRRegister _SISCI_EXPANDE_FUNCTION_NAME(SCIGetCSRRegister)
-DLL unsigned int SCIGetCSRRegister(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int SCINodeId,
- unsigned int CSROffset,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T C S R R E G I S T E R *
- * *
- * SISCI Priveleged function *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCISetCSRRegister _SISCI_EXPANDE_FUNCTION_NAME(SCISetCSRRegister)
-DLL void SCISetCSRRegister(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int SCINodeId,
- unsigned int CSROffset,
- unsigned int CSRValue,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I G E T L O C A L C S R *
- * *
- * SISCI Priveleged function *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIGetLocalCSR _SISCI_EXPANDE_FUNCTION_NAME(SCIGetLocalCSR)
-DLL unsigned int SCIGetLocalCSR(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int CSROffset,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T L O C A L C S R *
- * *
- * SISCI Priveleged function
- *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCISetLocalCSR _SISCI_EXPANDE_FUNCTION_NAME(SCISetLocalCSR)
-DLL void SCISetLocalCSR(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int CSROffset,
- unsigned int CSRValue,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I A T T A C H P H Y S I C A L M E M O R Y *
- * *
- * SISCI Priveleged function *
- * *
- * Description: *
- * *
- * This function enables usage of physical devices and memory regions where the *
- * Physical PCI bus address ( and mapped CPU address ) are already known. *
- * The function will register the physical memory as a SISCI segment which can *
- * be connected and mapped as a regular SISCI segment. *
- * *
- * Requirements: *
- * *
- * SCICreateSegment() with flag SCI_FLAG_EMPTY must have been called in advance *
- * *
- * Parameter description: *
- * sci_ioaddr_t ioaddress : This is the address on the PCI bus that a PCI bus *
- * master has to use to write to the specified memory *
- * void * address : This is the (mapped) virtual address that the *
- * application has to use to access the device. *
- * This means that the device has to be mapped in *
- * advance bye the devices own driver. *
- * If the device is not to be accessed by the local *
- * CPU, the address pointer shold be set to NULL *
- * Flags *
- * *
- * None *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIAttachPhysicalMemory _SISCI_EXPANDE_FUNCTION_NAME(SCIAttachPhysicalMemory)
-DLL void SCIAttachPhysicalMemory(sci_ioaddr_t ioaddress,
- void *address,
- unsigned int busNo,
- unsigned int size,
- sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I Q U E R Y *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_QUERY - Unrecognized command. *
- * *
- *********************************************************************************/
-#define SCIQuery _SISCI_EXPANDE_FUNCTION_NAME(SCIQuery)
-DLL void SCIQuery(unsigned int command,
- void *data,
- unsigned int flags,
- sci_error_t *error);
-
-
-/* MAJOR QUERY COMMANDS */
-
-/* This command requires a pointer to a structure of type */
-/* "sci_query_string". The string will be filled in by the query. */
-#define SCI_Q_VENDORID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_VENDORID)
-extern const unsigned int SCI_Q_VENDORID;
-
-
-/* Same as for SCI_VENDOR_ID */
-#define SCI_Q_API _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_API)
-extern const unsigned int SCI_Q_API;
-
-
-/* User passes a pointer to an allocated object of the */
-/* "sci_query_adapter" struct. */
-#define SCI_Q_ADAPTER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER)
-extern const unsigned int SCI_Q_ADAPTER;
-
-
-/* User passes a pointer to an allocated object of the */
-/* "sci_query_system" struct. */
-#define SCI_Q_SYSTEM _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM)
-extern const unsigned int SCI_Q_SYSTEM;
-
-#define SCI_Q_LOCAL_SEGMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_LOCAL_SEGMENT)
-extern const unsigned int SCI_Q_LOCAL_SEGMENT;
-
-#define SCI_Q_REMOTE_SEGMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_REMOTE_SEGMENT)
-extern const unsigned int SCI_Q_REMOTE_SEGMENT;
-
-#define SCI_Q_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_MAP)
-extern const unsigned int SCI_Q_MAP;
-
-typedef struct {
- char *str; /* Pointer to a string of minimum "length" characters */
- unsigned int length;
-} sci_query_string_t;
-
-
-typedef struct {
- unsigned int localAdapterNo; /* The adapter no. that the query concern. */
- unsigned int portNo; /* The SCI Link port number that the query concern. */
- unsigned int subcommand; /* A subcommand as specified below. */
- void *data; /* A pointer to an unsigned int that will return */
- /* the response to the query. */
-} sci_query_adapter_t;
-
-
-typedef struct {
- unsigned int subcommand; /* A subcommand as specified below. */
- void *data; /* A pointer to an unsigned int that will return */
- /* the response to the query. */
-} sci_query_system_t;
-
-typedef struct {
- sci_local_segment_t segment;
- unsigned int subcommand;
- union {
- sci_ioaddr_t ioaddr;
- } data;
-} sci_query_local_segment_t;
-
-typedef struct {
- sci_remote_segment_t segment;
- unsigned int subcommand;
- union {
- sci_ioaddr_t ioaddr;
- } data;
-} sci_query_remote_segment_t;
-
-typedef struct {
- sci_map_t map;
- unsigned int subcommand;
- unsigned int data;
-} sci_query_map_t;
-
-/* Minor query commands (sub-commands) for adapter specific information SCI_ADAPTER */
-#define SCI_Q_ADAPTER_DMA_SIZE_ALIGNMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_DMA_SIZE_ALIGNMENT)
-extern const unsigned int SCI_Q_ADAPTER_DMA_SIZE_ALIGNMENT;
-
-#define SCI_Q_ADAPTER_DMA_OFFSET_ALIGNMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_DMA_OFFSET_ALIGNMENT)
-extern const unsigned int SCI_Q_ADAPTER_DMA_OFFSET_ALIGNMENT;
-
-#define SCI_Q_ADAPTER_DMA_MTU _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_DMA_MTU)
-extern const unsigned int SCI_Q_ADAPTER_DMA_MTU;
-
-#define SCI_Q_ADAPTER_SUGGESTED_MIN_DMA_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SUGGESTED_MIN_DMA_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_SUGGESTED_MIN_DMA_SIZE;
-
-#define SCI_Q_ADAPTER_SUGGESTED_MIN_BLOCK_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SUGGESTED_MIN_BLOCK_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_SUGGESTED_MIN_BLOCK_SIZE;
-
-#define SCI_Q_ADAPTER_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_NODEID;
-
-#define SCI_Q_ADAPTER_SERIAL_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SERIAL_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_SERIAL_NUMBER;
-
-#define SCI_Q_ADAPTER_CARD_TYPE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CARD_TYPE)
-extern const unsigned int SCI_Q_ADAPTER_CARD_TYPE;
-
-#define SCI_Q_ADAPTER_NUMBER_OF_STREAMS _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_NUMBER_OF_STREAMS)
-extern const unsigned int SCI_Q_ADAPTER_NUMBER_OF_STREAMS;
-
-#define SCI_Q_ADAPTER_STREAM_BUFFER_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_STREAM_BUFFER_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_STREAM_BUFFER_SIZE;
-
-#define SCI_Q_ADAPTER_CONFIGURED _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CONFIGURED)
-extern const unsigned int SCI_Q_ADAPTER_CONFIGURED;
-
-#define SCI_Q_ADAPTER_LINK_OPERATIONAL _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_LINK_OPERATIONAL)
-extern const unsigned int SCI_Q_ADAPTER_LINK_OPERATIONAL;
-
-#define SCI_Q_ADAPTER_HW_LINK_STATUS_IS_OK _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_HW_LINK_STATUS_IS_OK)
-extern const unsigned int SCI_Q_ADAPTER_HW_LINK_STATUS_IS_OK;
-
-#define SCI_Q_ADAPTER_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_NUMBER;
-
-#define SCI_Q_ADAPTER_INSTANCE_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_INSTANCE_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_INSTANCE_NUMBER;
-
-#define SCI_Q_ADAPTER_FIRMWARE_OK _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_FIRMWARE_OK)
-extern const unsigned int SCI_Q_ADAPTER_FIRMWARE_OK;
-
-#define SCI_Q_ADAPTER_CONNECTED_TO_SWITCH _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CONNECTED_TO_SWITCH)
-extern const unsigned int SCI_Q_ADAPTER_CONNECTED_TO_SWITCH;
-
-#define SCI_Q_ADAPTER_LOCAL_SWITCH_TYPE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_LOCAL_SWITCH_TYPE)
-extern const unsigned int SCI_Q_ADAPTER_LOCAL_SWITCH_TYPE;
-
-#define SCI_Q_ADAPTER_LOCAL_SWITCH_PORT_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_LOCAL_SWITCH_PORT_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_LOCAL_SWITCH_PORT_NUMBER;
-
-#define SCI_Q_ADAPTER_CONNECTED_TO_EXPECTED_SWITCH_PORT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CONNECTED_TO_EXPECTED_SWITCH_PORT)
-extern const unsigned int SCI_Q_ADAPTER_CONNECTED_TO_EXPECTED_SWITCH_PORT;
-
-#define SCI_Q_ADAPTER_ATT_PAGE_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_ATT_PAGE_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_ATT_PAGE_SIZE;
-
-#define SCI_Q_ADAPTER_ATT_NUMBER_OF_ENTRIES _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_ATT_NUMBER_OF_ENTRIES)
-extern const unsigned int SCI_Q_ADAPTER_ATT_NUMBER_OF_ENTRIES;
-
-#define SCI_Q_ADAPTER_ATT_AVAILABLE_ENTRIES _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_ATT_AVAILABLE_ENTRIES)
-extern const unsigned int SCI_Q_ADAPTER_ATT_AVAILABLE_ENTRIES;
-
-#define SCI_Q_ADAPTER_PHYS_MEM_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SCI_Q_ADAPTER_PHYS_MEM_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_PHYS_MEM_NODEID;
-
-#define SCI_Q_ADAPTER_PHYS_MBX_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SCI_Q_ADAPTER_PHYS_MBX_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_PHYS_MBX_NODEID;
-
-#define SCI_Q_ADAPTER_PHYS_LINK_PORT_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_PHYS_LINK_PORT_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_PHYS_LINK_PORT_NODEID;
-
-#define SCI_Q_ADAPTER_SCI_LINK_FREQUENCY _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SCI_LINK_FREQUENCY)
-extern const unsigned int SCI_Q_ADAPTER_SCI_LINK_FREQUENCY;
-
-#define SCI_Q_ADAPTER_B_LINK_FREQUENCY _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_B_LINK_FREQUENCY)
-extern const unsigned int SCI_Q_ADAPTER_B_LINK_FREQUENCY;
-
-#define SCI_Q_ADAPTER_IO_BUS_FREQUENCY _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_IO_BUS_FREQUENCY)
-extern const unsigned int SCI_Q_ADAPTER_IO_BUS_FREQUENCY;
-
-/* Minor query commands (sub-commands) for adapter specific information SCI_SYSTEM */
-#define SCI_Q_SYSTEM_HOSTBRIDGE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM_HOSTBRIDGE)
-extern const unsigned int SCI_Q_SYSTEM_HOSTBRIDGE;
-
-#define SCI_Q_SYSTEM_WRITE_POSTING_ENABLED _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM_WRITE_POSTING_ENABLED)
-extern const unsigned int SCI_Q_SYSTEM_WRITE_POSTING_ENABLED;
-
-#define SCI_Q_SYSTEM_WRITE_COMBINING_ENABLED _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM_WRITE_COMBINING_ENABLED)
-extern const unsigned int SCI_Q_SYSTEM_WRITE_COMBINING_ENABLED;
-
-#define SCI_Q_LOCAL_SEGMENT_IOADDR _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_LOCAL_SEGMENT_IOADDR)
-extern const unsigned int SCI_Q_LOCAL_SEGMENT_IOADDR;
-
-#define SCI_Q_REMOTE_SEGMENT_IOADDR _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_REMOTE_SEGMENT_IOADDR)
-extern const unsigned int SCI_Q_REMOTE_SEGMENT_IOADDR;
-
-#define SCI_Q_MAP_MAPPED_TO_LOCAL_TARGET _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_MAP_MAPPED_TO_LOCAL_TARGET)
-extern const unsigned int SCI_Q_MAP_MAPPED_TO_LOCAL_TARGET;
-
-#define SCI_Q_MAP_QUERY_REMOTE_MAPPED_TO_LOCAL_TARGET _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_MAP_QUERY_REMOTE_MAPPED_TO_LOCAL_TARGET)
-extern const unsigned int SCI_Q_MAP_QUERY_REMOTE_MAPPED_TO_LOCAL_TARGET;
-
-#define HOSTBRIDGE_NOT_AVAILABLE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_NOT_AVAILABLE)
-extern const unsigned int HOSTBRIDGE_NOT_AVAILABLE;
-
-#define HOSTBRIDGE_UNKNOWN _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_UNKNOWN)
-extern const unsigned int HOSTBRIDGE_UNKNOWN;
-
-#define HOSTBRIDGE_440FX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440FX)
-extern const unsigned int HOSTBRIDGE_440FX;
-
-#define HOSTBRIDGE_440LX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440LX)
-extern const unsigned int HOSTBRIDGE_440LX;
-
-#define HOSTBRIDGE_440BX_A _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440BX_A)
-extern const unsigned int HOSTBRIDGE_440BX_A;
-
-#define HOSTBRIDGE_440BX_B _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440BX_B)
-extern const unsigned int HOSTBRIDGE_440BX_B;
-
-#define HOSTBRIDGE_440GX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440GX)
-extern const unsigned int HOSTBRIDGE_440GX;
-
-#define HOSTBRIDGE_450KX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450KX)
-extern const unsigned int HOSTBRIDGE_450KX;
-
-#define HOSTBRIDGE_430NX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_430NX)
-extern const unsigned int HOSTBRIDGE_430NX;
-
-#define HOSTBRIDGE_450NX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450NX)
-extern const unsigned int HOSTBRIDGE_450NX;
-
-#define HOSTBRIDGE_450NX_MICO _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450NX_MICO)
-extern const unsigned int HOSTBRIDGE_450NX_MICO;
-
-#define HOSTBRIDGE_450NX_PXB _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450NX_PXB)
-extern const unsigned int HOSTBRIDGE_450NX_PXB;
-
-#define HOSTBRIDGE_I810 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I810)
-extern const unsigned int HOSTBRIDGE_I810;
-
-#define HOSTBRIDGE_I810_DC100 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I810_DC100)
-extern const unsigned int HOSTBRIDGE_I810_DC100;
-
-#define HOSTBRIDGE_I810E _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I810E)
-extern const unsigned int HOSTBRIDGE_I810E;
-
-#define HOSTBRIDGE_I815 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I815)
-extern const unsigned int HOSTBRIDGE_I815;
-
-#define HOSTBRIDGE_I840 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I840)
-extern const unsigned int HOSTBRIDGE_I840;
-
-#define HOSTBRIDGE_I850 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I850)
-extern const unsigned int HOSTBRIDGE_I850;
-
-#define HOSTBRIDGE_I860 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I860)
-extern const unsigned int HOSTBRIDGE_I860;
-
-#define HOSTBRIDGE_VIA_KT133 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_KT133)
-extern const unsigned int HOSTBRIDGE_VIA_KT133;
-
-#define HOSTBRIDGE_VIA_KX133 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_KX133)
-extern const unsigned int HOSTBRIDGE_VIA_KX133;
-
-#define HOSTBRIDGE_VIA_APOLLO_PRO_133A _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_APOLLO_PRO_133A)
-extern const unsigned int HOSTBRIDGE_VIA_APOLLO_PRO_133A;
-
-#define HOSTBRIDGE_VIA_APOLLO_PRO_266 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_APOLLO_PRO_266)
-extern const unsigned int HOSTBRIDGE_VIA_APOLLO_PRO_266;
-
-#define HOSTBRIDGE_AMD_760_MP _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_AMD_760_MP)
-extern const unsigned int HOSTBRIDGE_AMD_760_MP;
-
-#define HOSTBRIDGE_SERVERWORKS_HE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_HE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_HE;
-
-#define HOSTBRIDGE_SERVERWORKS_HE_B _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_HE_B)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_HE_B;
-
-#define HOSTBRIDGE_SERVERWORKS_LE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_LE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_LE;
-
-
-
-#define HOSTBRIDGE_WRITE_POSTING_DISABLED _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_WRITE_POSTING_DISABLED)
-extern const unsigned int HOSTBRIDGE_WRITE_POSTING_DISABLED;
-
-#define HOSTBRIDGE_WRITE_POSTING_ENABLED _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_WRITE_POSTING_ENABLED)
-extern const unsigned int HOSTBRIDGE_WRITE_POSTING_ENABLED;
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C R E A T E D M A Q U E U E *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_PHDMA : Create physical DMA queue. Please note that this is an *
- * priveleged operation. *
- * *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCICreateDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCICreateDMAQueue)
-DLL void SCICreateDMAQueue(sci_desc_t sd,
- sci_dma_queue_t *dq,
- unsigned int localAdapterNo,
- unsigned int maxEntries,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E D M A Q U E U E *
- * *
- * Flags *
- * None. * *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Not allowed in this queue state. *
- * *
- *********************************************************************************/
-#define SCIRemoveDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveDMAQueue)
-DLL void SCIRemoveDMAQueue(sci_dma_queue_t dq,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I E N Q U E U E D M A T R A N S F E R *
- * *
- * Flags: *
- * *
- * SCI_FLAG_DMA_READ - The DMA will be remote --> local *
- * (default is local --> remote) *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the offset and size is larger *
- * than the segment size or larger than max *
- * DMA size. *
- * SCI_ERR_MAX_ENTRIES - The DMA queue is full *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_SEGMENT_NOT_PREPARED - The local segment has not been prepared for *
- * access from the adapter associated with the *
- * queue. *
- * SCI_ERR_SEGMENT_NOT_CONNECTED - The remote segment is not connected through *
- * the adapter associated with the queue. *
- *********************************************************************************/
-#define SCIEnqueueDMATransfer _SISCI_EXPANDE_FUNCTION_NAME(SCIEnqueueDMATransfer)
-DLL sci_dma_queue_state_t SCIEnqueueDMATransfer(sci_dma_queue_t dq,
- sci_local_segment_t localSegment,
- sci_remote_segment_t remoteSegment,
- unsigned int localOffset,
- unsigned int remoteOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I P O S T D M A Q U E U E *
- * *
- * Flags: *
- * *
- * SCI_FLAG_USE_CALLBACK - The end of the transfer will cause the callback *
- * function to be invoked. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * *
- *********************************************************************************/
-#define SCIPostDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIPostDMAQueue)
-DLL void SCIPostDMAQueue(sci_dma_queue_t dq,
- sci_cb_dma_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I A B O R T D M A Q U E U E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * *
- *********************************************************************************/
-#define SCIAbortDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIAbortDMAQueue)
-DLL void SCIAbortDMAQueue(sci_dma_queue_t dq,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I R E S E T D M A Q U E U E *
- * *
- * Flags *
- * None. * *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIResetDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIResetDMAQueue)
-DLL void SCIResetDMAQueue(sci_dma_queue_t dq,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I D M A Q U E U E S T A T E *
- * *
- *********************************************************************************/
-#define SCIDMAQueueState _SISCI_EXPANDE_FUNCTION_NAME(SCIDMAQueueState)
-DLL sci_dma_queue_state_t SCIDMAQueueState(sci_dma_queue_t dq);
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R D M A Q U E U E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * *
- *********************************************************************************/
-#define SCIWaitForDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForDMAQueue)
-DLL sci_dma_queue_state_t SCIWaitForDMAQueue(sci_dma_queue_t dq,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I P H D M A E N Q U E U E *
- * *
- * SISCI Priveleged function *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_READ *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIphDmaEnqueue _SISCI_EXPANDE_FUNCTION_NAME(SCIphDmaEnqueue)
-DLL void SCIphDmaEnqueue(sci_dma_queue_t dmaqueue,
- unsigned int size,
- sci_ioaddr_t localBusAddr,
- unsigned int remote_nodeid,
- unsigned int remote_highaddr,
- unsigned int remote_lowaddr,
- unsigned int flags,
- sci_error_t *error);
-
-/*********************************************************************************
- * *
- * S C I P H D M A S T A R T *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_WAIT *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_DMA_RESET *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIphDmaStart _SISCI_EXPANDE_FUNCTION_NAME(SCIphDmaStart)
-DLL sci_dma_queue_state_t SCIphDmaStart(sci_dma_queue_t dmaqueue,
- sci_cb_dma_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-/*********************************************************************************
- * *
- * S C I C R E A T E I N T E R R U P T *
- * *
- * Flags *
- * *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_FIXED_INTNO *
- * SCI_FLAG_SHARED_INT *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_INTNO_USED - This interrupt number is already used. *
- * *
- *********************************************************************************/
-#define SCICreateInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCICreateInterrupt)
-DLL void SCICreateInterrupt(sci_desc_t sd,
- sci_local_interrupt_t *interrupt,
- unsigned int localAdapterNo,
- unsigned int *interruptNo,
- sci_cb_interrupt_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIRemoveInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveInterrupt)
-DLL void SCIRemoveInterrupt(sci_local_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_TIMEOUT - The function timed out after specified timeout value. *
- * SCI_ERR_CANCELLED - The wait was interrupted by a call to *
- * SCIRemoveInterrupt. *
- * The handle is invalid when this error code is returned.*
- * *
- *********************************************************************************/
-#define SCIWaitForInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForInterrupt)
-DLL void SCIWaitForInterrupt(sci_local_interrupt_t interrupt,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C O N N E C T I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_SUCH_INTNO - No such interrupt number. *
- * SCI_ERR_CONNECTION_REFUSED - Connection attempt refused by remote node. *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * *
- *********************************************************************************/
-#define SCIConnectInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIConnectInterrupt)
-DLL void SCIConnectInterrupt(sci_desc_t sd,
- sci_remote_interrupt_t *interrupt,
- unsigned int nodeId,
- unsigned int localAdapterNo,
- unsigned int interruptNo,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I D I S C O N N E C T I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIDisconnectInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIDisconnectInterrupt)
-DLL void SCIDisconnectInterrupt(sci_remote_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I T R I G G E R I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCITriggerInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCITriggerInterrupt)
-DLL void SCITriggerInterrupt(sci_remote_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I R E G I S T E R I N T E R R U P T F L A G *
- * *
- * *
- * This function register an "interrupt flag" that is identified as an unique *
- * location within a local segment. If successful, the resulting interrupt *
- * handle will have been associated with the specified local segment. *
- * *
- * It is up to the (remote) client(s) to set up an "interrupt mapping" for the *
- * corresponding segment offset using either the *
- * *
- * - SCI_FLAG_CONDITIONAL_INTERRUPT_MAP *
- * *
- * or the *
- * *
- * - SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP *
- * *
- * option to "SCIMapRemoteSegment()". - I.e. after having established a *
- * connection to the corresponding segment. A trigger operation can then *
- * be implemented using a store operation via the relevant "interrupt map". *
- * *
- * *
- * *
- * *
- * *
- * Flags: *
- * *
- * SCI_FLAG_CONDITIONAL_INTERRUPT - Triggering is to take place using *
- * "conditional interrupts". *
- * *
- * *
- * *
- * Specific error codes for this function: *
- * None. *
- * *
- *********************************************************************************/
-#define SCIRegisterInterruptFlag _SISCI_EXPANDE_FUNCTION_NAME(SCIRegisterInterruptFlag)
-DLL void SCIRegisterInterruptFlag(
- unsigned int localAdapterNo,
- sci_local_interrupt_t *interrupt,
- sci_local_segment_t segment,
- unsigned int offset,
- sci_cb_interrupt_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I E N A B L E C O N D I T I O N A L I N T E R R U P T *
- * *
- * *
- * This function make sure that another HW interrupt will take place the next *
- * time the corresponding interrupt flag is triggered by a *
- * "conditional interrupt" operation. *
- * *
- * Default semantics: *
- * *
- * When successful, the client can rely on that the first subsequent trigger *
- * operation will cause a HW interrupt and subsequently cause the client *
- * handler function to be invoked. *
- * *
- * If an interrupt was triggered in parallell with the enable operation, then *
- * the operation will fail (SCI_ERR_COND_INT_RACE_PROBLEM), and the client can *
- * not rely on another trigger operation will lead to handler invocation. *
- * Hence, any state checking normally associated with handling the *
- * corresponding interrupt should take place before attempting to enable *
- * again. *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_COND_INT_RACE_PROBLEM - The enable operation failed because an *
- * incomming trigger operation happened *
- * concurrently. *
- * *
- *********************************************************************************/
-#define SCIEnableConditionalInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIEnableConditionalInterrupt)
-DLL void SCIEnableConditionalInterrupt(
- sci_local_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I D I S A B L E C O N D I T I O N A L I N T E R R U P T *
- * *
- * *
- * Prevent subsequent "conditional interrupt"trigger operations for *
- * the specified interupt flag from causing HW interrupt and handler *
- * invocations. *
- * *
- * *
- * Default semantics: *
- * *
- * If successful, no subsequent HW interrupts will take place, but handler *
- * invocations that have already been scheduled may still take place. *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIDisableConditionalInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIDisableConditionalInterrupt)
-DLL void SCIDisableConditionalInterrupt(
- sci_local_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I G E T C O N D I T I O N A L I N T E R R U P T C O U N T E R *
- * *
- * *
- * Returns a value that indicates the number of times this flag has *
- * been trigged since the last time it was enabled or disabled. *
- * Calling the SCIEnableConditionalInterrupt / SCIDisableConditionalInterrupt *
- * functions will reset the counter value. *
- * *
- * Default semantics: *
- * *
- * If successful, the current trig count is returned in the *
- * interruptTrigCounter parameter. *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OVERFLOW - The number of trig operations have exceeded the range *
- * that can be counted. *
- *********************************************************************************/
-#define SCIGetConditionalInterruptTrigCounter _SISCI_EXPANDE_FUNCTION_NAME(SCIGetConditionalInterruptTrigCounter)
-DLL void SCIGetConditionalInterruptTrigCounter(
- sci_local_interrupt_t interrupt,
- unsigned int *interruptTrigCounter,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I T R A N S F E R B L O C K *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger *
- * than the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-#define SCITransferBlock _SISCI_EXPANDE_FUNCTION_NAME(SCITransferBlock)
-DLL void SCITransferBlock(sci_map_t sourceMap,
- unsigned int sourceOffset,
- sci_map_t destinationMap,
- unsigned int destinationOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I T R A N S F E R B L O C K A S Y N C *
- * *
- * Flags *
- * *
- * SCI_FLAG_BLOCK_READ *
- * SCI_FLAG_USE_CALLBACK *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger than *
- * the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required by *
- * the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-#define SCITransferBlockAsync _SISCI_EXPANDE_FUNCTION_NAME(SCITransferBlockAsync)
-DLL void SCITransferBlockAsync(sci_map_t sourceMap,
- unsigned int sourceOffset,
- sci_map_t destinationMap,
- unsigned int destinationOffset,
- unsigned int size,
- sci_block_transfer_t *block,
- sci_cb_block_transfer_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R B L O C K T R A N S F E R *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * *
- *********************************************************************************/
-#define SCIWaitForBlockTransfer _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForBlockTransfer)
-DLL void SCIWaitForBlockTransfer(sci_block_transfer_t block,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I A B O R T B L O C K T R A N S F E R *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * *
- *********************************************************************************/
-#define SCIAbortBlockTransfer _SISCI_EXPANDE_FUNCTION_NAME(SCIAbortBlockTransfer)
-DLL void SCIAbortBlockTransfer(sci_block_transfer_t block,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I M E M C P Y *
- * *
- * Flags: *
- * SCI_FLAG_BLOCK_READ *
- * SCI_FLAG_ERROR_CHECK *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger *
- * than the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-
-#define SCIMemCpy _SISCI_EXPANDE_FUNCTION_NAME(SCIMemCpy)
-DLL void SCIMemCpy(sci_sequence_t sequence,
- void *memAddr,
- sci_map_t remoteMap,
- unsigned int remoteOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I M E M C O P Y *
- * *
- * Flags: *
- * SCI_FLAG_BLOCK_READ *
- * SCI_FLAG_ERROR_CHECK *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger *
- * than the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-
-
-#define SCIMemCopy _SISCI_EXPANDE_FUNCTION_NAME(SCIMemCopy)
-DLL void SCIMemCopy(void *memAddr,
- sci_map_t remoteMap,
- unsigned int remoteOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E G I S T E R S E G M E N T M E M O R Y *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required by *
- * the implementation. *
- * SCI_ERR_ILLEGAL_ADDRESS - Illegal address. *
- * SCI_ERR_OUT_OF_RANGE - Size is larger than the maximum size for the *
- * local segment. *
- * *
- *********************************************************************************/
-#define SCIRegisterSegmentMemory _SISCI_EXPANDE_FUNCTION_NAME(SCIRegisterSegmentMemory)
-DLL void SCIRegisterSegmentMemory(void *address,
- unsigned int size,
- sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C O N N E C T S C I S P A C E *
- * *
- * SISCI Priveleged function *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_CONNECTION_REFUSED - Connection attempt refused by remote node. *
- * *
- *********************************************************************************/
-#define SCIConnectSCISpace _SISCI_EXPANDE_FUNCTION_NAME(SCIConnectSCISpace)
-DLL void SCIConnectSCISpace(sci_desc_t sd,
- unsigned int localAdapterNo,
- sci_remote_segment_t *segment,
- sci_address_t address,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*
- * =====================================================================================
- *
- * S C I A T T A C H L O C A L S E G M E N T
- * Description:
- *
- * SCIAttachLocalSegment() permits an application to "attach" to an already existing
- * local segment, implying that two or more application want
- * share the same local segment. The prerequest, is that the
- * application which originally created the segment ("owner") has
- * preformed a SCIShareSegment() in order to mark the segment
- * "shareable".
- *
- *
- * Flags:
- *
- * SCI_FLAG_USE_CALLBACK - The callback function will be invoked for events
- * on this segment.
- *
- *
- * Specific error codes for this function:
- *
- * SCI_ERR_ACCESS - No such shared segment
- * SCI_ERR_NO_SUCH_SEGMENT - No such segment
- * Note: Current implenentation will return SCI_ERR_ACCESS for both cases. This will
- * change from next release. Application should handle both cases.
- *
- * =====================================================================================
- */
-#define SCIAttachLocalSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIAttachLocalSegment)
-
-DLL void
-SCIAttachLocalSegment(sci_desc_t sd,
- sci_local_segment_t *segment,
- unsigned int segmentId,
- unsigned int *size,
- sci_cb_local_segment_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-/*
- * =====================================================================================
- *
- * S C I S H A R E S E G M E N T
- *
- * Description:
- *
- * SCIShareSegment() permits other application to "attach" to an already existing
- * local segment, implying that two or more application want
- * share the same local segment. The prerequest, is that the
- * application which originally created the segment ("owner") has
- * preformed a SCIShareSegment() in order to mark the segment
- * "shareable".
- *
- *
- * Flags:
- * none
- *
- * Specific error codes for this function:
- *
- *
- *
- * =====================================================================================
- */
-#define SCIShareSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIShareSegment)
-
-DLL void
-SCIShareSegment(sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I F L U S H *
- * *
- * This function will flush the CPU buffers and the PSB buffers. *
- * *
- * Flags *
- * SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY : *
- * Only flush CPU buffers ( Write combining *
- * etc buffers). *
- * *
- *********************************************************************************/
-
-#define SCIFlush _SISCI_EXPANDE_FUNCTION_NAME(SCIFlush)
-DLL void SCIFlush(sci_sequence_t sequence,
- unsigned int flags);
-
-#if defined(CPLUSPLUS) || defined(__cplusplus)
-}
-#endif
-
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_error.h b/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_error.h
deleted file mode 100644
index aab7c136d3a..00000000000
--- a/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_error.h
+++ /dev/null
@@ -1,89 +0,0 @@
-/* $Id: sisci_error.h,v 1.1 2002/12/13 12:17:22 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-
-
-#ifndef _SISCI_ERROR_H_
-#define _SISCI_ERROR_H_
-
-
-/* SCI Error return values always have 30 bit set */
-#define SCI_ERR_MASK 0x40000000
-#define SCI_ERR_REMOTE_MASK 0x01 /* Remote errors should have bit 0 set */
-
-#define SCI_ERR(u) ((unsigned32)(u)&0x7FFFFFFF )
-
-/* Error codes */
-typedef enum {
- SCI_ERR_OK = 0x000,
-
-
- SCI_ERR_BUSY = (0x900 | SCI_ERR_MASK),
- SCI_ERR_FLAG_NOT_IMPLEMENTED = (0x901 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_FLAG = (0x902 | SCI_ERR_MASK),
- SCI_ERR_NOSPC = (0x904 | SCI_ERR_MASK),
- SCI_ERR_API_NOSPC = (0x905 | SCI_ERR_MASK),
- SCI_ERR_HW_NOSPC = (0x906 | SCI_ERR_MASK),
- SCI_ERR_NOT_IMPLEMENTED = (0x907 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_ADAPTERNO = (0x908 | SCI_ERR_MASK),
- SCI_ERR_NO_SUCH_ADAPTERNO = (0x909 | SCI_ERR_MASK),
- SCI_ERR_TIMEOUT = (0x90A | SCI_ERR_MASK),
- SCI_ERR_OUT_OF_RANGE = (0x90B | SCI_ERR_MASK),
- SCI_ERR_NO_SUCH_SEGMENT = (0x90C | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_NODEID = (0x90D | SCI_ERR_MASK),
- SCI_ERR_CONNECTION_REFUSED = (0x90E | SCI_ERR_MASK),
- SCI_ERR_SEGMENT_NOT_CONNECTED = (0x90F | SCI_ERR_MASK),
- SCI_ERR_SIZE_ALIGNMENT = (0x910 | SCI_ERR_MASK),
- SCI_ERR_OFFSET_ALIGNMENT = (0x911 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_PARAMETER = (0x912 | SCI_ERR_MASK),
- SCI_ERR_MAX_ENTRIES = (0x913 | SCI_ERR_MASK),
- SCI_ERR_SEGMENT_NOT_PREPARED = (0x914 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_ADDRESS = (0x915 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_OPERATION = (0x916 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_QUERY = (0x917 | SCI_ERR_MASK),
- SCI_ERR_SEGMENTID_USED = (0x918 | SCI_ERR_MASK),
- SCI_ERR_SYSTEM = (0x919 | SCI_ERR_MASK),
- SCI_ERR_CANCELLED = (0x91A | SCI_ERR_MASK),
- SCI_ERR_NOT_CONNECTED = (0x91B | SCI_ERR_MASK),
- SCI_ERR_NOT_AVAILABLE = (0x91C | SCI_ERR_MASK),
- SCI_ERR_INCONSISTENT_VERSIONS = (0x91D | SCI_ERR_MASK),
- SCI_ERR_COND_INT_RACE_PROBLEM = (0x91E | SCI_ERR_MASK),
- SCI_ERR_OVERFLOW = (0x91F | SCI_ERR_MASK),
- SCI_ERR_NOT_INITIALIZED = (0x920 | SCI_ERR_MASK),
-
- SCI_ERR_ACCESS = (0x921 | SCI_ERR_MASK),
-
- SCI_ERR_NO_SUCH_NODEID = (0xA00 | SCI_ERR_MASK),
- SCI_ERR_NODE_NOT_RESPONDING = (0xA02 | SCI_ERR_MASK),
- SCI_ERR_NO_REMOTE_LINK_ACCESS = (0xA04 | SCI_ERR_MASK),
- SCI_ERR_NO_LINK_ACCESS = (0xA05 | SCI_ERR_MASK),
- SCI_ERR_TRANSFER_FAILED = (0xA06 | SCI_ERR_MASK)
-} sci_error_t;
-
-
-#endif /* _SCI_ERROR_H_ */
-
-
-
diff --git a/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_types.h b/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_types.h
deleted file mode 100644
index 77989ffca59..00000000000
--- a/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_types.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $Id: sisci_types.h,v 1.1 2002/12/13 12:17:22 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-#ifndef _SISCI_TYPES_H
-#define _SISCI_TYPES_H
-
-#include "sisci_error.h"
-
-#ifndef IN
-#define IN
-#endif
-
-#ifndef OUT
-#define OUT
-#endif
-
-#ifndef IN_OUT
-#define IN_OUT
-#endif
-
-/* Opaque data types for descriptors/handles */
-typedef struct sci_desc *sci_desc_t;
-typedef struct sci_local_segment *sci_local_segment_t;
-typedef struct sci_remote_segment *sci_remote_segment_t;
-
-typedef struct sci_map *sci_map_t;
-typedef struct sci_sequence *sci_sequence_t;
-#ifndef KERNEL
-typedef struct sci_dma_queue *sci_dma_queue_t;
-#endif
-typedef struct sci_remote_interrupt *sci_remote_interrupt_t;
-typedef struct sci_local_interrupt *sci_local_interrupt_t;
-typedef struct sci_block_transfer *sci_block_transfer_t;
-
-/*
- * Constants defining reasons for segment callbacks:
- */
-
-typedef enum {
- SCI_CB_CONNECT = 1,
- SCI_CB_DISCONNECT,
- SCI_CB_NOT_OPERATIONAL,
- SCI_CB_OPERATIONAL,
- SCI_CB_LOST
-} sci_segment_cb_reason_t;
-
-#define MAX_CB_REASON SCI_CB_LOST
-
-/* dma_queue_states is identical to the dma_queue_state_t in genif.h, they must be consistent.*/
-typedef enum {
- SCI_DMAQUEUE_IDLE,
- SCI_DMAQUEUE_GATHER,
- SCI_DMAQUEUE_POSTED,
- SCI_DMAQUEUE_DONE,
- SCI_DMAQUEUE_ABORTED,
- SCI_DMAQUEUE_ERROR
-} sci_dma_queue_state_t;
-
-
-typedef enum {
- SCI_SEQ_OK,
- SCI_SEQ_RETRIABLE,
- SCI_SEQ_NOT_RETRIABLE,
- SCI_SEQ_PENDING
-} sci_sequence_status_t;
-
-
-typedef struct {
- unsigned short nodeId; /* SCI Address bit 63 - 48 */
- unsigned short offsHi; /* SCI Address bit 47 - 32 */
- unsigned int offsLo; /* SCI Address bit 31 - 0 */
-} sci_address_t;
-
-
-typedef unsigned int sci_ioaddr_t;
-
-typedef enum {
- SCI_CALLBACK_CANCEL = 1,
- SCI_CALLBACK_CONTINUE
-} sci_callback_action_t;
-
-#ifndef KERNEL
-typedef sci_callback_action_t (*sci_cb_local_segment_t)(void *arg,
- sci_local_segment_t segment,
- sci_segment_cb_reason_t reason,
- unsigned int nodeId,
- unsigned int localAdapterNo,
- sci_error_t error);
-
-typedef sci_callback_action_t (*sci_cb_remote_segment_t)(void *arg,
- sci_remote_segment_t segment,
- sci_segment_cb_reason_t reason,
- sci_error_t status);
-
-
-typedef sci_callback_action_t (*sci_cb_dma_t)(void IN *arg,
- sci_dma_queue_t queue,
- sci_error_t status);
-
-
-typedef int (*sci_cb_block_transfer_t)(void *arg,
- sci_block_transfer_t block,
- sci_error_t status);
-
-
-typedef sci_callback_action_t (*sci_cb_interrupt_t)(void *arg,
- sci_local_interrupt_t interrupt,
- sci_error_t status);
-
-#endif /* KERNEL */
-#endif
diff --git a/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_version.h b/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_version.h
deleted file mode 100644
index c2fccb9ec33..00000000000
--- a/ndb/src/external/SOLARIS.SPARC/sci/include/sisci_version.h
+++ /dev/null
@@ -1,91 +0,0 @@
-/* $Id: sisci_version.h,v 1.1 2002/12/13 12:17:22 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Lesser General Public License as published by *
- * the Free Software Foundation; either version 2.1 of the License, *
- * or (at your option) any later version. *
- * *
- * 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 Lesser General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-#ifndef SISCI_VERSION_H
-#define SISCI_VERSION_H
-
-
-#define SISCI_API_VER_MAJOR 1
-#define SISCI_API_VER_MAJORC "1"
-
-#define SISCI_API_VER_MINOR 10
-#define SISCI_API_VER_MINORC "10"
-#define SISCI_API_VER_MICRO 4
-#define SISCI_API_VER_MICROC "4"
-
-#define SISCI_SIGN_VERSION_MASK 0xfffff000 /* used to mask off API_VER_MICRO */
-
-#define SISCI_API_VERSION (SISCI_API_VER_MAJOR << 24 | SISCI_API_VER_MINOR << 12 | SISCI_API_VER_MICRO)
-
-/* the rules are:
- *
- * Changes in API_VER_MICRO should be binary compatible, New flags, functions added. No changes to user code
- * required if new features is not needed.
- *
- * Changes in API_VER_MINOR requires recompilation of user code.
- *
- * Changes in the API_VER_MAJOR will most likely require changes to user code. This should not happen very
- * often...
- *
- */
-
-#ifndef BUILD_DATE
-#define BUILD_DATE __DATE__
-#endif
-
-#ifndef BUILD_NAME
-#define BUILD_NAME ""
-#endif
-
-#define API_VERSION "SISCI API version " SISCI_API_VER_MAJORC "." SISCI_API_VER_MINORC "."SISCI_API_VER_MICROC " ( "BUILD_NAME" "BUILD_DATE" )"
-
-#endif
-
-
-/* Version info: */
-/* */
-/* 1.5.2 First SISCI version */
-/* 1.5.3 Some bug fixes */
-/* 1.5.4 Some bug fixes */
-/* 1.5.5 No release */
-/* 1.5.6 Lock flag implemented in function SCIConnectSegment */
-/* 1.5.7 Expanded query functionality */
-/* 1.5.8 Updated error checking (sequence) functionality for D320 */
-/* 1.6.0 Updated error checking (sequence) D320 and IRM 1.9 support */
-/* 1.9.0 Ported to Solaris_sparc, Solaris_x86 and Linux. IRM 1.9. */
-/* 1.9.1 Some bug fixes */
-/* 1.9.2 Added more adapter queries */
-/* 1.9.3 Bug fix in SCIMapLocalSegment and SCIMapRemoteSegment */
-/* 1.9.4 NT Release Developers Kit 2.40 */
-/* 1.9.5 Added flush after data transfer in SCIMemCopy() */
-/* 1.9.5 NT Release Developers Kit 2.44 */
-/* 1.10.0:
- * New SCIInitialize(), SCITerminate() functions.
- * Support for D330
- *
- *
- */
-
-
diff --git a/ndb/src/external/WIN32.x86/sci/include/rmlib.h b/ndb/src/external/WIN32.x86/sci/include/rmlib.h
deleted file mode 100644
index 87ba20db99f..00000000000
--- a/ndb/src/external/WIN32.x86/sci/include/rmlib.h
+++ /dev/null
@@ -1,212 +0,0 @@
-/* $Id: rmlib.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
-
-/*********************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Lesser General Public License as published by *
- * the Free Software Foundation; either version 2.1 of the License, *
- * or (at your option) any later version. *
- * *
- * 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 Lesser General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *********************************************************************************/
-
-/********************************************************************************/
-/* This header file contains the declarations of the SCI Reflective Memory */
-/* library rmlib. The implementation of the library functions is in rmlib.c. */
-/* The library contains all the functions that operate on the reflective */
-/* memory. */
-/* */
-/* NB! */
-/* */
-/* DOLPHIN'S SCI REFLECTIVE MEMORY FILES ARE UNDER DEVELOPMENT AND MAY CHANGE. */
-/* PLEASE CONTACT DOLPHIN FOR FURTHER INFORMATION. */
-/* */
-/* */
-/********************************************************************************/
-
-#include "sisci_error.h"
-#include "sisci_api.h"
-#include "sisci_demolib.h"
-#include "sisci_types.h"
-
-unsigned int seqerr, syncseqerr;
-
-#ifndef _RMLIB_H
-#define _RMLIB_H
-
-
-#if defined(_REENTRANT)
-
-#define _RMLIB_EXPAND_NAME(name) _RMLIB_MT_ ## name
-
-#else
-
-#define _RMLIB_EXPAND_NAME(name) _RMLIB_ST_ ## name
-
-#endif
-
-#ifdef __sparc
-#define CACHE_SIZE 2097152
-#else
-#define CACHE_SIZE 8192
-#endif
-
-/*********************************************************************************/
-/* FLAG VALUES */
-/*********************************************************************************/
-
-#define REFLECT_ERRCHECK 0x2
-
-struct ReflectiveMemorySpace {
- unsigned int localAdapterNo;
- unsigned int localNodeId;
- unsigned int remoteNodeId;
- sci_desc_t sd;
- sci_desc_t syncsd;
- sci_map_t localMap;
- sci_map_t remoteMap;
- unsigned int localSegmentId;
- unsigned int remoteSegmentId;
- unsigned int syncSegmentId;
- unsigned int sync_rSegmentId;
- unsigned int segmentSize;
- unsigned int *localMapAddr;
- volatile unsigned int *remoteMapAddr;
- sci_local_segment_t localSegment;
- sci_remote_segment_t remoteSegment;
- sci_local_segment_t syncSegment;
- sci_remote_segment_t sync_rSegment;
- sci_map_t syncMap;
- sci_map_t sync_rMap;
- sci_sequence_t syncsequence;
- sci_sequence_t sequence;
- unsigned int protection;
- unsigned int retry_value;
- sci_sequence_status_t sequenceStatus, syncsequenceStatus;
- volatile unsigned int *syncMapAddr;
- volatile unsigned int *sync_rMapAddr;
-};
-
-/*********************************************************************************/
-/* P R I N T R E F L E C T I V E M E M O R Y S P A C E */
-/* */
-/*********************************************************************************/
-#define ReflectPrintParameters _RMLIB_EXPAND_NAME(ReflectPrintParameters)
-void ReflectPrintParameters(FILE *stream, struct ReflectiveMemorySpace RM_space);
-
-/*********************************************************************************/
-/* R E F L E C T D M A S E T U P */
-/* */
-/*********************************************************************************/
-#define ReflectDmaSetup _RMLIB_EXPAND_NAME(ReflectDmaSetup)
-sci_error_t ReflectDmaSetup(struct ReflectiveMemorySpace RM_space, sci_dma_queue_t *dmaQueue);
-
-/*********************************************************************************/
-/* R E F L E C T D M A R E M O V E */
-/* */
-/*********************************************************************************/
-#define ReflectDmaRemove _RMLIB_EXPAND_NAME(ReflectDmaRemove)
-sci_error_t ReflectDmaRemove(sci_dma_queue_t dmaQueue);
-
-/*********************************************************************************/
-/* R E F L E C T D M A R U N */
-/* */
-/*********************************************************************************/
-#define ReflectDmaRun _RMLIB_EXPAND_NAME(ReflectDmaRun)
-sci_error_t ReflectDmaRun(struct ReflectiveMemorySpace RM_space,
- unsigned int* privateSrc,
- unsigned int size,
- unsigned int offset,
- sci_dma_queue_t dmaQueue);
-/*********************************************************************************/
-/* C L O S E R E F L E C T I V E M E M O R Y S P A C E */
-/* */
-/*********************************************************************************/
-#define ReflectClose _RMLIB_EXPAND_NAME(ReflectClose)
-sci_error_t ReflectClose(struct ReflectiveMemorySpace RM_space, unsigned int segment_no);
-
-/*********************************************************************************/
-/* O P E N R E F L E C T I V E M E M O R Y S P A C E */
-/* */
-/*********************************************************************************/
-#define ReflectOpen _RMLIB_EXPAND_NAME(ReflectOpen)
-sci_error_t ReflectOpen(struct ReflectiveMemorySpace *RM_space,
- unsigned int size,
- unsigned int segment_no,
- unsigned int localAdapterNo,
- unsigned int remoteNodeId,
- unsigned int protection,
- unsigned int retry_value);
-
-/*********************************************************************************/
-/* R E F L E C T G E T A C C E S S */
-/* */
-/*********************************************************************************/
-#define ReflectGetAccess _RMLIB_EXPAND_NAME(ReflectGetAccess)
-sci_error_t ReflectGetAccess(struct ReflectiveMemorySpace *RM_space);
-
-/*********************************************************************************/
-/* R E F L E C T R E L E A S E A C C E S S */
-/* */
-/*********************************************************************************/
-#define ReflectReleaseAccess _RMLIB_EXPAND_NAME(ReflectReleaseAccess)
-sci_error_t ReflectReleaseAccess(struct ReflectiveMemorySpace *RM_space);
-
-/*********************************************************************************/
-/* R E F L E C T D M A */
-/* */
-/*********************************************************************************/
-#define ReflectDma _RMLIB_EXPAND_NAME(ReflectDma)
-sci_error_t ReflectDma(struct ReflectiveMemorySpace RM_space,
- unsigned int* privateSrc,
- unsigned int size,
- unsigned int offset);
-
-/*********************************************************************************/
-/* R E F L E C T M E M C O P Y */
-/* */
-/*********************************************************************************/
-#define ReflectMemCopy _RMLIB_EXPAND_NAME(ReflectMemCopy)
-sci_error_t ReflectMemCopy(struct ReflectiveMemorySpace RM_space,
- unsigned int* privateSrc,
- unsigned int size,
- unsigned int offset,
- unsigned int flags);
-
-/*********************************************************************************/
-/* R E F L E C T S E T */
-/* */
-/*********************************************************************************/
-#define ReflectSet _RMLIB_EXPAND_NAME(ReflectSet)
-sci_error_t ReflectSet(struct ReflectiveMemorySpace RM_space,
- unsigned int value,
- unsigned int size,
- unsigned int offset,
- unsigned int flags
- );
-
-/*********************************************************************************/
-/* R E F L E C T P R I N T */
-/* */
-/*********************************************************************************/
-#define ReflectPrint _RMLIB_EXPAND_NAME(ReflectPrint)
-sci_error_t ReflectPrint(FILE *stream,
- struct ReflectiveMemorySpace RM_space,
- unsigned int size,
- unsigned int offset
- );
-
-
-#endif
diff --git a/ndb/src/external/WIN32.x86/sci/include/scilib.h b/ndb/src/external/WIN32.x86/sci/include/scilib.h
deleted file mode 100644
index d1501082bab..00000000000
--- a/ndb/src/external/WIN32.x86/sci/include/scilib.h
+++ /dev/null
@@ -1,330 +0,0 @@
-/* $Id: scilib.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 2002 *
- * Dolphin Interconnect Solutions AS *
- * *
- *******************************************************************************/
-
-
-#if defined(_REENTRANT)
-#define _SCIL_EXPANDE_FUNCTION_NAME(name) _SCIL_PUBLIC_FUNC_MT_ ## name
-#define _SCIL_EXPANDE_VARIABLE_NAME(name) _SCIL_PUBLIC_VAR_MT_ ## name
-#else
-#define _SCIL_EXPANDE_FUNCTION_NAME(name) _SCIL_PUBLIC_FUNC_ST_ ## name
-#define _SCIL_EXPANDE_VARIABLE_NAME(name) _SCIL_PUBLIC_VAR_ST_ ## name
-#endif
-#define _SCIL_EXPANDE_CONSTANT_NAME(name) _SCIL_PUBLIC_CONST_ ## name
-
-#include "sisci_api.h"
-
-#if defined(CPLUSPLUS) || defined(__cplusplus)
-extern "C" {
-#endif
-
-
-/*
- * SISCI segment id pollution:
- * ===========================
- * The SISCI library uses regular SISCI segmens internally.
- * The MSG_QUEUE_LIB_IDENTIFIER_MASK is a mask which is used by the SISCI
- * library to identify internal SISCI segments ids, from segments used directly
- * by the user.
- *
- * Future versions of the library may have its own namespace.
- *
- */
-
-#define MSG_QUEUE_LIB_IDENTIFIER_MASK 0x10000000
-
-
-/*********************************************************************************/
-/* FLAG VALUES */
-/*********************************************************************************/
-
-#define SCIL_FLAG_ERROR_CHECK_DATA _SCIL_EXPANDE_CONSTANT_NAME(SCIL_FLAG_ERROR_CHECK_DATA)
-extern const unsigned int SCIL_FLAG_ERROR_CHECK_DATA;
-
-#define SCIL_FLAG_ERROR_CHECK_PROT _SCIL_EXPANDE_CONSTANT_NAME(SCIL_FLAG_ERROR_CHECK_PROT)
-extern const unsigned int SCIL_FLAG_ERROR_CHECK_PROT;
-
-#define SCIL_FLAG_FULL_ERROR_CHECK _SCIL_EXPANDE_CONSTANT_NAME(SCIL_FLAG_FULL_ERROR_CHECK)
-extern const unsigned int SCIL_FLAG_FULL_ERROR_CHECK;
-
-
-
-
-
-typedef struct sci_msq_queue *sci_msq_queue_t;
-
-
-/*********************************************************************************
- * *
- * S C I L C r e a t e M s g Q u e u e *
- * *
- * Parameters: *
- * *
- * Creates a message queue. The message queue identifier object will be allocated*
- * if the sci_msq_queue_t * msg pointer is NULL. The function will create a *
- * remote connection. If this connection times out, the function shoud be *
- * repeated until connection is established. SCILRemoveMsgQueue() must be called *
- * to remove the connection and deallocate the message queue identifier. *
- * *
- * sci_msq_queue_t *msq : Message queue identifier *
- * The function must be called with a null pointer *
- * the first time. *
- * unsigned int localAdapterNo: Local Adapter Number *
- * unsigned int remoteNodeId : Remote nodeId *
- * unsigned int msqId : Message queue number *
- * unsigned int maxMsgCount : The maximum count of messages in queue *
- * unsigned int maxMsgSize, : The maximum size of each messages in queue *
- * unsigned int timeout : Time to wait for successful connection *
- * unsigned int flags : Flags. *
- * *
- * Flags *
- * *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * None. Normal SISIC error codes. *
- * *
- *********************************************************************************/
-#define SCILCreateMsgQueue _SCIL_EXPANDE_FUNCTION_NAME(SCILCreateMsgQueue)
-DLL sci_error_t SCILCreateMsgQueue(sci_msq_queue_t *msq,
- unsigned int localAdapterNo,
- unsigned int remoteNodeId,
- unsigned int msqId,
- unsigned int maxMsgCount,
- unsigned int maxMsgSize,
- unsigned int timeout,
- unsigned int flags);
-
-
-/*********************************************************************************
- * *
- * S C I L R e c e i v e M s g *
- * *
- * *
- * Receives a message from the queue. *
- * *
- * Paremeters *
- * *
- * sci_msq_queue_t msq : message queue identifier *
- * void *msg : Location to store received data *
- * unsigned int size : Size of message to read *
- * unsigned int *sizeLeft: Bytes left in buffer, after current receive. This is *
- * just a hint. There may be more. *
- * *
- * Flags *
- * *
- * SCIL_FLAG_ERROR_CHECK_PROT: The internal buffer management is done using full*
- * error checking.
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_EWOULD_BLOCK : There is not enough data in the message buffer *
- * to read the specified number of bytes. *
- * . *
- * SCI_ERR_NOT_CONNECTED : The connection is not established. *
- * *
- *********************************************************************************/
-#define SCILReceiveMsg _SCIL_EXPANDE_FUNCTION_NAME(SCILReceiveMsg)
-DLL sci_error_t SCILReceiveMsg(
- sci_msq_queue_t msq,
- void *msg,
- unsigned int size,
- unsigned int *sizeLeft,
- unsigned int flags);
-
-
-
-/*********************************************************************************
- * *
- * S C I L S e n d M s g *
- * *
- * *
- * Sends a message to the queue. *
- * *
- * Paremeters *
- * *
- * sci_msq_queue_t msq : Message queue identifier *
- * void *msg : Send data *
- * unsigned int size : Size of message to send *
- * unsigned int *sizeFree: Bytes free in buffer, after current send. This is *
- * just a hint. There may be more. *
- * *
- * Flags *
- * *
- * SCIL_FLAG_ERROR_CHECK_DATA: The data is transmitted using full error checking*
- * SCIL_FLAG_ERROR_CHECK_PROT: The internal buffer management is done using full*
- * error checking. *
- * SCIL_FLSG_FULL_ERROR_CHECK: This flag is an combination of both above. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_EWOULD_BLOCK : There is not enough data in the message buffer *
- * to send the specified number of bytes. *
- * . *
- * SCI_ERR_NOT_CONNECTED : The connection is not established. *
- * *
- *********************************************************************************/
-#define SCILSendMsg _SCIL_EXPANDE_FUNCTION_NAME(SCILSendMsg)
-DLL sci_error_t SCILSendMsg(
- sci_msq_queue_t msq,
- void *msg,
- unsigned int size,
- unsigned int *sizeFree,
- unsigned int flags);
-
-
-/*********************************************************************************
- * *
- * S C I L R e m o v e M s g Q u e ue *
- * *
- * *
- * Removes a message queue. *
- * *
- * sci_msq_queue_t msq : Message queue identifier *
- * *
- * Flags *
- * *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * None *
- * *
- *********************************************************************************/
-#define SCILRemoveMsgQueue _SCIL_EXPANDE_FUNCTION_NAME(SCILRemoveMsgQueue)
-DLL sci_error_t SCILRemoveMsgQueue(
- sci_msq_queue_t *msq,
- unsigned int flags);
-
-
-
-/*********************************************************************************
- * *
- * S C I L I n i t *
- * *
- * *
- * Initializes the SCI library. This function must be called before any other *
- * function in the library. *
- * *
- * Flags *
- * *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * None *
- * . *
- *********************************************************************************/
-#define SCILInit _SCIL_EXPANDE_FUNCTION_NAME(SCILInit)
-DLL sci_error_t SCILInit(unsigned int flags);
-
-
-
-/*********************************************************************************
- * *
- * S C I L D e s t r o y *
- * *
- * *
- * Removes internal resources allocated by the SCI Library. No other library *
- * function should be called after this function. *
- * *
- * Flags *
- * *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * None *
- * *
- *********************************************************************************/
-#define SCILDestroy _SCIL_EXPANDE_FUNCTION_NAME(SCILDestroy)
-DLL sci_error_t SCILDestroy(unsigned int flags);
-
-
-
-/*********************************************************************************
- * *
- * S C I L C o n n e c t M s g Q u e u e *
- * *
- * *
- * Makes a connection to a remote message queue. This must be done before *
- * SCILSendMsg() is called. *
- * *
- * Parameters: *
- * *
- * sci_msq_queue_t *msq : Message queue identifier *
- * unsigned int localAdapterNo: Local Adapter Number *
- * unsigned int remoteNodeId : Remote nodeId *
- * unsigned int msqId : Message queue number *
- * unsigned int maxMsgCount : The maximum count of messages in queue *
- * unsigned int maxMsgSize, : The maximum size of each messages in queue *
- * unsigned int timeout : Time to wait for successful connection *
- * unsigned int flags : Flags. *
- * *
- * Flags *
- * *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * None. Normal SISIC error codes. *
- * *
- *********************************************************************************/
-#define SCILConnectMsgQueue _SCIL_EXPANDE_FUNCTION_NAME(SCILConnectMsgQueue)
-DLL sci_error_t SCILConnectMsgQueue(sci_msq_queue_t *msq,
- unsigned int localAdapterNo,
- unsigned int remoteNodeId,
- unsigned int rmsgId,
- unsigned int maxMsgCount,
- unsigned int maxMsgSize,
- unsigned int timeout,
- unsigned int flags);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I L D i s c o n n e c t M s g Q u e u e *
- * *
- * *
- * Disconnects from a remote message queue. *
- * *
- * Parameters: *
- * *
- * sci_msq_queue_t *msq : Message queue identifier *
- * *
- * Flags *
- * *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * None *
- * *
- *********************************************************************************/
-#define SCILDisconnectMsgQueue _SCIL_EXPANDE_FUNCTION_NAME(SCILDisconnectMsgQueue)
-DLL sci_error_t SCILDisconnectMsgQueue(sci_msq_queue_t *msq,
- unsigned int flags);
-
-
-
-#if defined(CPLUSPLUS) || defined(__cplusplus)
-}
-#endif
-
-
-
-
-
-
-
-
-
-
diff --git a/ndb/src/external/WIN32.x86/sci/include/sisci_api.h b/ndb/src/external/WIN32.x86/sci/include/sisci_api.h
deleted file mode 100644
index 9f4a1ddffb3..00000000000
--- a/ndb/src/external/WIN32.x86/sci/include/sisci_api.h
+++ /dev/null
@@ -1,2217 +0,0 @@
-/* $Id: sisci_api.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2001 *
- * Dolphin Interconnect Solutions AS *
- * *
- * This program is free software; you can redistribute it and/or modify *
- * it under the terms of the GNU Lesser General Public License as published by *
- * the Free Software Foundation; either version 2.1 of the License, *
- * or (at your option) any later version. *
- * *
- * 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 Lesser General Public License *
- * along with this program; if not, write to the Free Software *
- * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-#ifndef _SISCI_API_H
-#define _SISCI_API_H
-
-#include "sisci_types.h"
-#include "sisci_error.h"
-
-
-#ifdef WIN32
-#ifdef API_DLL
-#define DLL __declspec(dllexport)
-#elif CLIENT_DLL
-#define DLL __declspec(dllimport)
-#endif
-#endif /* WIN32 */
-
-
-#ifndef DLL
-#define DLL
-#endif
-
-#if defined(_REENTRANT)
-#define _SISCI_EXPANDE_FUNCTION_NAME(name) _SISCI_PUBLIC_FUNC_MT_ ## name
-#define _SISCI_EXPANDE_VARIABLE_NAME(name) _SISCI_PUBLIC_VAR_MT_ ## name
-#else
-#define _SISCI_EXPANDE_FUNCTION_NAME(name) _SISCI_PUBLIC_FUNC_ST_ ## name
-#define _SISCI_EXPANDE_VARIABLE_NAME(name) _SISCI_PUBLIC_VAR_ST_ ## name
-#endif
-#define _SISCI_EXPANDE_CONSTANT_NAME(name) _SISCI_PUBLIC_CONST_ ## name
-
-#if defined(CPLUSPLUS) || defined(__cplusplus)
-extern "C" {
-#endif
-
-
-/*********************************************************************************/
-/* FLAG VALUES */
-/*********************************************************************************/
-
-#define SCI_FLAG_FIXED_INTNO _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FIXED_INTNO)
-extern const unsigned int SCI_FLAG_FIXED_INTNO;
-
-#define SCI_FLAG_SHARED_INT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_SHARED_INT)
-extern const unsigned int SCI_FLAG_SHARED_INT;
-
-#define SCI_FLAG_COUNTING_INT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_COUNTING_INT)
-extern const unsigned int SCI_FLAG_COUNTING_INT;
-
-#define SCI_FLAG_FIXED_MAP_ADDR _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FIXED_MAP_ADDR)
-extern const unsigned int SCI_FLAG_FIXED_MAP_ADDR;
-
-#define SCI_FLAG_READONLY_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_READONLY_MAP)
-extern const unsigned int SCI_FLAG_READONLY_MAP;
-
-#define SCI_FLAG_USE_CALLBACK _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_USE_CALLBACK)
-extern const unsigned int SCI_FLAG_USE_CALLBACK;
-
-#define SCI_FLAG_BLOCK_READ _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_BLOCK_READ)
-extern const unsigned int SCI_FLAG_BLOCK_READ;
-
-#define SCI_FLAG_THREAD_SAFE _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_THREAD_SAFE)
-extern const unsigned int SCI_FLAG_THREAD_SAFE;
-
-#define SCI_FLAG_ASYNCHRONOUS_CONNECT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_ASYNCHRONOUS_CONNECT)
-extern const unsigned int SCI_FLAG_ASYNCHRONOUS_CONNECT;
-
-#define SCI_FLAG_EMPTY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_EMPTY)
-extern const unsigned int SCI_FLAG_EMPTY;
-
-#define SCI_FLAG_PRIVATE _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_PRIVATE)
-extern const unsigned int SCI_FLAG_PRIVATE;
-
-#define SCI_FLAG_FORCE_DISCONNECT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FORCE_DISCONNECT)
-extern const unsigned int SCI_FLAG_FORCE_DISCONNECT;
-
-#define SCI_FLAG_NOTIFY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NOTIFY)
-extern const unsigned int SCI_FLAG_NOTIFY;
-
-#define SCI_FLAG_DMA_READ _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_READ)
-extern const unsigned int SCI_FLAG_DMA_READ;
-
-#define SCI_FLAG_DMA_POST _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_POST)
-extern const unsigned int SCI_FLAG_DMA_POST;
-
-#define SCI_FLAG_DMA_WAIT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_WAIT)
-extern const unsigned int SCI_FLAG_DMA_WAIT;
-
-#define SCI_FLAG_DMA_RESET _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_RESET)
-extern const unsigned int SCI_FLAG_DMA_RESET;
-
-#define SCI_FLAG_NO_FLUSH _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NO_FLUSH)
-extern const unsigned int SCI_FLAG_NO_FLUSH;
-
-#define SCI_FLAG_NO_STORE_BARRIER _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NO_STORE_BARRIER)
-extern const unsigned int SCI_FLAG_NO_STORE_BARRIER;
-
-#define SCI_FLAG_FAST_BARRIER _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FAST_BARRIER)
-extern const unsigned int SCI_FLAG_FAST_BARRIER;
-
-#define SCI_FLAG_ERROR_CHECK _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_ERROR_CHECK)
-extern const unsigned int SCI_FLAG_ERROR_CHECK;
-
-#define SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY)
-extern const unsigned int SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY;
-
-/* the FLUSH_CPU_BUFFERS_ONLY flag is for backwards compabillity only and should never be used */
-#define FLUSH_CPU_BUFFERS_ONLY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY)
-
-#define SCI_FLAG_LOCK_OPERATION _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_LOCK_OPERATION)
-extern const unsigned int SCI_FLAG_LOCK_OPERATION;
-
-#define SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP)
-extern const unsigned int SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP;
-
-#define SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP)
-extern const unsigned int SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP;
-
-#define SCI_FLAG_IO_MAP_IOSPACE _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_IO_MAP_IOSPACE)
-extern const unsigned int SCI_FLAG_IO_MAP_IOSPACE;
-
-#define SCI_FLAG_DMOVE_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMOVE_MAP)
-extern const unsigned int SCI_FLAG_DMOVE_MAP;
-
-#define SCI_FLAG_WRITES_DISABLE_GATHER_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_WRITES_DISABLE_GATHER_MAP)
-extern const unsigned int SCI_FLAG_WRITES_DISABLE_GATHER_MAP;
-
-#define SCI_FLAG_DISABLE_128_BYTES_PACKETS _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DISABLE_128_BYTES_PACKETS)
-extern const unsigned int SCI_FLAG_DISABLE_128_BYTES_PACKETS;
-
-#define SCI_FLAG_SHARED_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_SHARED_MAP)
-extern const unsigned int SCI_FLAG_SHARED_MAP;
-
-#define SCI_FLAG_DMA_SOURCE_ONLY _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_SOURCE_ONLY)
-extern const unsigned int SCI_FLAG_DMA_SOURCE_ONLY;
-
-#define SCI_FLAG_CONDITIONAL_INTERRUPT _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_CONDITIONAL_INTERRUPT)
-extern const unsigned int SCI_FLAG_CONDITIONAL_INTERRUPT;
-
-#define SCI_FLAG_CONDITIONAL_INTERRUPT_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_CONDITIONAL_INTERRUPT_MAP)
-extern const unsigned int SCI_FLAG_CONDITIONAL_INTERRUPT_MAP;
-
-#define SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP)
-extern const unsigned int SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP;
-
-#define SCI_FLAG_NO_MEMORY_LOOPBACK_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_NO_MEMORY_LOOPBACK_MAP)
-extern const unsigned int SCI_FLAG_NO_MEMORY_LOOPBACK_MAP;
-
-#if defined(OS_IS_LYNXOS) || defined(OS_IS_VXWORKS)
-#define SCI_FLAG_WRITE_BACK_CACHE_MAP _SISCI_EXPANDE_CONSTANT_NAME(WRITE_BACK_CACHE_MAP)
-extern const unsigned int SCI_FLAG_WRITE_BACK_CACHE_MAP;
-#endif
-
-#define SCI_FLAG_DMA_PHDMA _SISCI_EXPANDE_CONSTANT_NAME(SCI_FLAG_DMA_PHDMA)
-extern const unsigned int SCI_FLAG_DMA_PHDMA;
-
-/*********************************************************************************/
-/* GENERAL VALUES */
-/*********************************************************************************/
-#define SCI_LOCAL_HOST _SISCI_EXPANDE_CONSTANT_NAME(SCI_LOCAL_HOST)
-extern const unsigned int SCI_LOCAL_HOST;
-
-#define SCI_INFINITE_TIMEOUT _SISCI_EXPANDE_CONSTANT_NAME(SCI_INFINITE_TIMEOUT)
-extern const unsigned int SCI_INFINITE_TIMEOUT;
-
-/*********************************************************************************/
-/* GENERAL ERROR CODES */
-/* */
-/* SCI_ERR_ILLEGAL_FLAG - Illegal flag value. */
-/* SCI_ERR_FLAG_NOT_IMPLEMENTED - Flag legal but flag feature not implemented. */
-/* SCI_ERR_NOT_IMPLEMENTED - Function not implemented. */
-/* SCI_ERR_SYSTEM - A system error. Check errno. */
-/* SCI_ERR_NOSPC - Unable to allocate OS resources. */
-/* SCI_ERR_API_NOSPC - Unable to allocate API resources. */
-/* SCI_ERR_HW_NOSPC - Unable to allocate HW resources (Hardware) */
-/* */
-/*********************************************************************************/
-
-
-/*********************************************************************************/
-/* GENERAL "ADAPTER" ERROR CODES */
-/* */
-/* SCI_ERR_NO_SUCH_ADAPTERNO - Adapter number is legal but does not exist. */
-/* SCI_ERR_ILLEGAL_ADAPTERNO - Illegal local adapter number (i.e. outside */
-/* legal range). */
-/* */
-/*********************************************************************************/
-
-
-/*********************************************************************************/
-/* GENERAL "NODEID" ERROR CODES */
-/* */
-/* SCI_ERR_NO_SUCH_NODEID - The remote adapter identified by nodeId does */
-/* not respond, but the intermediate link(s) */
-/* seem(s) to be operational. */
-/* SCI_ERR_ILLEGAL_NODEID - Illegal NodeId. */
-/* */
-/*********************************************************************************/
-
-
-
-/*********************************************************************************
- * *
- * S C I I N I T I A L I Z E *
- * *
- * This function initializes the SISCI library. *
- * The function must be called before SCIOpen(). *
- * *
- * Flags: *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * None *
- * *
- *********************************************************************************/
-#define SCIInitialize _SISCI_EXPANDE_FUNCTION_NAME(SCIInitialize)
-DLL void SCIInitialize(unsigned int flags,
- sci_error_t *error);
-#if 0
-unsigned int __Internal_SISCI_version_var;
-#endif
-
-/*********************************************************************************
- * *
- * S C I T E R M I N A T E *
- * *
- * This function terminates the SISCI library. *
- * The function must be called after SCIClose(). *
- * *
- * *
- *********************************************************************************/
-#define SCITerminate _SISCI_EXPANDE_FUNCTION_NAME(SCITerminate)
-DLL void SCITerminate(void);
-
-/*********************************************************************************
- * *
- * S C I O P E N *
- * *
- * *
- * Opens a SCI virtual device. *
- * Caller must supply a pointer to a variable of type sci_desc_t to be *
- * initialized. *
- * *
- * Flags *
- * SCI_FLAG_THREAD_SAFE - Operations on resources associated with this *
- * descriptor will be performed in a multithread-safe *
- * manner. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_INCONSISTENT_VERSIONS - Inconsistency between the SISCI library *
- * and the SISCI driver versions. *
- * *
- * *
- *********************************************************************************/
-#define SCIOpen _SISCI_EXPANDE_FUNCTION_NAME(SCIOpen)
-DLL void SCIOpen(sci_desc_t *sd,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C L O S E *
- * *
- * This function closes an open SCI virtual device. *
- * *
- * Flags: *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - All resources are not deallocated. *
- * *
- *********************************************************************************/
-#define SCIClose _SISCI_EXPANDE_FUNCTION_NAME(SCIClose)
-DLL void SCIClose(sci_desc_t sd,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C O N N E C T S E G M E N T *
- * *
- * Connects to a remote shared memory segment located at <nodeId> with the *
- * identifier <segmentId>. *
- * The user may then call SCIMapRemoteSegment() to map shared memory *
- * into user space. *
- * *
- * Flags *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_ASYNCHRONOUS_CONNECT *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_SUCH_SEGMENT - Could not find the remote segment with the *
- * given segmentId. *
- * SCI_ERR_CONNECTION_REFUSED - Connection attempt refused by remote node. *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCIConnectSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIConnectSegment)
-DLL void SCIConnectSegment(sci_desc_t sd,
- sci_remote_segment_t *segment,
- unsigned int nodeId,
- unsigned int segmentId,
- unsigned int localAdapterNo,
- sci_cb_remote_segment_t callback,
- void *callbackArg,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I D I S C O N N E C T S E G M E N T *
- * *
- * Disconnects from the give mapped shared memory segment *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - The segment is currently mapped or in use. *
- * *
- *********************************************************************************/
-#define SCIDisconnectSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIDisconnectSegment)
-DLL void SCIDisconnectSegment(sci_remote_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I G E T R E M O T E S E G M E N T S I Z E *
- * *
- *********************************************************************************/
-#define SCIGetRemoteSegmentSize _SISCI_EXPANDE_FUNCTION_NAME(SCIGetRemoteSegmentSize)
-DLL unsigned int SCIGetRemoteSegmentSize(sci_remote_segment_t segment);
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R R E M O T E S E G M E N T E V E N T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation. *
- * SCI_ERR_CANCELLED - The wait operation has been cancelled du *
- * to a SCIDisconnectSegment() on the same *
- * handle. The handle is invalid when this *
- * error is returned. *
- * *
- *********************************************************************************/
-#define SCIWaitForRemoteSegmentEvent _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForRemoteSegmentEvent)
-DLL sci_segment_cb_reason_t SCIWaitForRemoteSegmentEvent(
- sci_remote_segment_t segment,
- sci_error_t *status,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I M A P R E M O T E S E G M E N T *
- * *
- * This function is used to include a shared memory segment in the virtual *
- * address space of the application. *
- * *
- * Flags: *
- * *
- * SCI_FLAG_SHARED_MAP - The low level physical map may be shared by *
- * other applications. *
- * *
- * SCI_FLAG_FIXED_MAP_ADDR - Map at the suggested virtual address *
- * SCI_FLAG_READONLY_MAP - The segment is mapped in read-only mode *
- * SCI_FLAG_LOCK_OPERATION - Enable Lock operations (fetch and add) *
- * SCI_FLAG_READ_PREFETCH_AGGR_HOLD_MAP *
- * - Enable aggressive prefetch with speculative *
- * hold. *
- * *
- * SCI_FLAG_READ_PREFETCH_NO_HOLD_MAP *
- * - The PSB66 will prefetch 64 bytes. As soon *
- * as the PCI read retry has been accepted, *
- * the stream will change state to FREE, even *
- * if less than 64 bytes were actually read. *
- * *
- * SCI_FLAG_IO_MAP_IOSPACE - Enable No Prefetch, no speculative hold. *
- * *
- * SCI_FLAG_DMOVE_MAP - Enable DMOVE packet type. The stream will be *
- * set into FREE state immediately. *
- * *
- * SCI_FLAG_WRITES_DISABLE_GATHER_MAP *
- * - Disable use of gather. *
- * *
- * SCI_FLAG_DISABLE_128_BYTES_PACKETS *
- * - Disable use of 128-Byte packets *
- * *
- * SCI_FLAG_CONDITIONAL_INTERRUPT_MAP *
- * - Write operations through this map will cause *
- * an atomic "fetch-and-add-one" operation on *
- * remote memory, but in addition an interrupt *
- * will be generated if the target memory *
- * location contained a "null value" before the *
- * add operation was carried out. *
- * The conditional interrupt flag must also be *
- * specified in the SCIRegisterInterruptFlag() *
- * function. *
- * *
- * SCI_FLAG_UNCONDITIONAL_INTERRUPT_MAP *
- * - Write operations through this map will cause *
- * an interrupt for the remote adapter *
- * "in addition to" updating the corresponding *
- * remote memory location with the data being *
- * written. *
- * The unconditional interrupt flag must also *
- * be specified in the *
- * SCIRegisterInterruptFlag() function. *
- * *
- * SCI_FLAG_WRITE_BACK_CACHE_MAP *
- * - Enable cacheing of the mapped region. *
- * Writes through this map will be written to a *
- * write back cache, hence no remote SCI updates*
- * until the cache line is flushed. The *
- * application is responsible for the cache *
- * flush operation. *
- * The SCImemCopy() function will handle this *
- * correctly by doing cache flushes internally. *
- * This feature is architechture dependent and *
- * not be available on all plattforms. *
- * *
- * SCI_FLAG_NO_MEMORY_LOOPBACK_MAP *
- * - Forces a map to a remote segment located *
- * in the local machine to be mapped using *
- * SCI loopback. This is useful i.e. if you *
- * want to use a regular map access to be *
- * serialized with lock operations. *
- * The default behaviour is to access a remte *
- * segment located in the local machine as a *
- * local MMU operation. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the offset and size is *
- * larger than the segment size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as *
- * required by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as *
- * required by the implementation. *
- * *
- *********************************************************************************/
-#define SCIMapRemoteSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIMapRemoteSegment)
-DLL volatile void *SCIMapRemoteSegment(
- sci_remote_segment_t segment,
- sci_map_t *map,
- unsigned int offset,
- unsigned int size,
- void *addr,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I M A P L O C A L S E G M E N T *
- * *
- * Flags *
- * *
- * SCI_FLAG_FIXED_MAP_ADDR *
- * SCI_FLAG_READONLY_MAP *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the offset and size is *
- * larger than the segment size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as *
- * required by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as *
- * required by the implementation. *
- * *
- *********************************************************************************/
-#define SCIMapLocalSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIMapLocalSegment)
-DLL void *SCIMapLocalSegment(sci_local_segment_t segment,
- sci_map_t *map,
- unsigned int offset,
- unsigned int size,
- void *addr,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I U N M A P S E G M E N T *
- * *
- * This function unmaps pages of shared memory from the callers virtual *
- * address space. *
- * *
- * Flags *
- * None. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - The map is currently in use. *
- * *
- *********************************************************************************/
-#define SCIUnmapSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIUnmapSegment)
-DLL void SCIUnmapSegment(sci_map_t map,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C R E A T E S E G M E N T *
- * *
- * Make the specified segment available for connections via the specified *
- * adapter. If successful, the segment can be accessed from remote nodes *
- * via the specified adapter. *
- * *
- * Flags: *
- * *
- * SCI_FLAG_USE_CALLBACK - The callback function will be invoked for events *
- * on this segment. *
- * SCI_FLAG_EMPTY - No memory will be allocated for the segment. *
- * SCI_FLAG_PRIVATE - The segment will be private meaning it will never *
- * be any connections to it. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_SEGMENTID_USED - The segment with this segmentId is already used *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * *
- *********************************************************************************/
-#define SCICreateSegment _SISCI_EXPANDE_FUNCTION_NAME(SCICreateSegment)
-DLL void SCICreateSegment(sci_desc_t sd,
- sci_local_segment_t *segment,
- unsigned int segmentId,
- unsigned int size,
- sci_cb_local_segment_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R L O C A L S E G M E N T E V E N T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_TIMEOUT - The function timed out after specified timeout value. *
- * SCI_ERR_CANCELLED - The wait operation has been cancelled du to a *
- * SCIRemoveSegment() on the same handle. *
- * The handle is invalid when this error is returned. *
- * *
- *********************************************************************************/
-#define SCIWaitForLocalSegmentEvent _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForLocalSegmentEvent)
-DLL sci_segment_cb_reason_t SCIWaitForLocalSegmentEvent(
- sci_local_segment_t segment,
- unsigned int *sourcenodeId,
- unsigned int *localAdapterNo,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I P R E P A R E S E G M E N T *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_SOURCE_ONLY - The segment will be used as a source segment *
- * for DMA operations. On some system types this *
- * will enable the SISCI driver to use performance *
- * improving features. *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIPrepareSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIPrepareSegment)
-DLL void SCIPrepareSegment(sci_local_segment_t segment,
- unsigned int localAdapterNo,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E S E G M E N T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_BUSY - Unable to remove the segment. The segment is currently *
- * in use. *
- * *
- *********************************************************************************/
-#define SCIRemoveSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveSegment)
-DLL void SCIRemoveSegment(sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T S E G M E N T A V A I L A B L E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * SCI_ERR_SEGMENT_NOT_PREPARED - The segment has not been prepared for access *
- * from this adapter. *
- * SCI_ERR_ILLEGAL_OPERATION - The segment is created with the *
- * SCI_FLAG_PRIVATE flag specified and *
- * therefore has no segmentId. *
- * *
- *********************************************************************************/
-#define SCISetSegmentAvailable _SISCI_EXPANDE_FUNCTION_NAME(SCISetSegmentAvailable)
-DLL void SCISetSegmentAvailable(sci_local_segment_t segment,
- unsigned int localAdapterNo,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T S E G M E N T U N A V A I L A B L E *
- * *
- * Flags *
- * *
- * SCI_FLAG_FORCE_DISCONNECT *
- * SCI_FLAG_NOTIFY *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation. *
- * *
- *********************************************************************************/
-#define SCISetSegmentUnavailable _SISCI_EXPANDE_FUNCTION_NAME(SCISetSegmentUnavailable)
-DLL void SCISetSegmentUnavailable(sci_local_segment_t segment,
- unsigned int localAdapterNo,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C R E A T E M A P S E Q U E N C E *
- * *
- * Flags: *
- * *
- * SCI_FLAG_FAST_BARRIER *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCICreateMapSequence _SISCI_EXPANDE_FUNCTION_NAME(SCICreateMapSequence)
-DLL void SCICreateMapSequence(sci_map_t map,
- sci_sequence_t *sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E S E Q U E N C E *
- * *
- * Flags: *
- * None *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIRemoveSequence _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveSequence)
-DLL void SCIRemoveSequence(sci_sequence_t sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S T A R T S E Q U E N C E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIStartSequence _SISCI_EXPANDE_FUNCTION_NAME(SCIStartSequence)
-DLL sci_sequence_status_t SCIStartSequence(sci_sequence_t sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I C H E C K S E Q U E N CE *
- * *
- * Flags *
- * *
- * SCI_FLAG_NO_FLUSH *
- * SCI_FLAG_NO_STORE_BARRIER *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCICheckSequence _SISCI_EXPANDE_FUNCTION_NAME(SCICheckSequence)
-DLL sci_sequence_status_t SCICheckSequence(sci_sequence_t sequence,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S T O R E B A R R I E R *
- * *
- * Flags *
- * None. *
- * *
- * *
- * *
- *********************************************************************************/
-#define SCIStoreBarrier _SISCI_EXPANDE_FUNCTION_NAME(SCIStoreBarrier)
-DLL void SCIStoreBarrier(sci_sequence_t sequence,
- unsigned int flags);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I F L U S H R E A D B U F F E R S *
- * *
- *********************************************************************************/
-#define SCIFlushReadBuffers _SISCI_EXPANDE_FUNCTION_NAME(SCIFlushReadBuffers)
-DLL void SCIFlushReadBuffers(sci_sequence_t sequence);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I P R O B E N O D E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCIProbeNode _SISCI_EXPANDE_FUNCTION_NAME(SCIProbeNode)
-DLL int SCIProbeNode(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int nodeId,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I G E T C S R R E G I S T E R *
- * *
- * SISCI Priveleged function *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCIGetCSRRegister _SISCI_EXPANDE_FUNCTION_NAME(SCIGetCSRRegister)
-DLL unsigned int SCIGetCSRRegister(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int SCINodeId,
- unsigned int CSROffset,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T C S R R E G I S T E R *
- * *
- * SISCI Priveleged function *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_LINK_ACCESS - It was not possible to communicate via the *
- * local adapter. *
- * SCI_ERR_NO_REMOTE_LINK_ACCESS - It was not possible to communicate via a *
- * remote switch port. *
- * *
- *********************************************************************************/
-#define SCISetCSRRegister _SISCI_EXPANDE_FUNCTION_NAME(SCISetCSRRegister)
-DLL void SCISetCSRRegister(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int SCINodeId,
- unsigned int CSROffset,
- unsigned int CSRValue,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I G E T L O C A L C S R *
- * *
- * SISCI Priveleged function *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIGetLocalCSR _SISCI_EXPANDE_FUNCTION_NAME(SCIGetLocalCSR)
-DLL unsigned int SCIGetLocalCSR(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int CSROffset,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I S E T L O C A L C S R *
- * *
- * SISCI Priveleged function
- *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCISetLocalCSR _SISCI_EXPANDE_FUNCTION_NAME(SCISetLocalCSR)
-DLL void SCISetLocalCSR(sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int CSROffset,
- unsigned int CSRValue,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I A T T A C H P H Y S I C A L M E M O R Y *
- * *
- * SISCI Priveleged function *
- * *
- * Description: *
- * *
- * This function enables usage of physical devices and memory regions where the *
- * Physical PCI bus address ( and mapped CPU address ) are already known. *
- * The function will register the physical memory as a SISCI segment which can *
- * be connected and mapped as a regular SISCI segment. *
- * *
- * Requirements: *
- * *
- * SCICreateSegment() with flag SCI_FLAG_EMPTY must have been called in advance *
- * *
- * Parameter description: *
- * sci_ioaddr_t ioaddress : This is the address on the PCI bus that a PCI bus *
- * master has to use to write to the specified memory *
- * void * address : This is the (mapped) virtual address that the *
- * application has to use to access the device. *
- * This means that the device has to be mapped in *
- * advance bye the devices own driver. *
- * If the device is not to be accessed by the local *
- * CPU, the address pointer shold be set to NULL *
- * Flags *
- * *
- * None *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIAttachPhysicalMemory _SISCI_EXPANDE_FUNCTION_NAME(SCIAttachPhysicalMemory)
-DLL void SCIAttachPhysicalMemory(sci_ioaddr_t ioaddress,
- void *address,
- unsigned int busNo,
- unsigned int size,
- sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I Q U E R Y *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_QUERY - Unrecognized command. *
- * *
- *********************************************************************************/
-#define SCIQuery _SISCI_EXPANDE_FUNCTION_NAME(SCIQuery)
-DLL void SCIQuery(unsigned int command,
- void *data,
- unsigned int flags,
- sci_error_t *error);
-
-
-/* MAJOR QUERY COMMANDS */
-
-/* This command requires a pointer to a structure of type */
-/* "sci_query_string". The string will be filled in by the query. */
-#define SCI_Q_VENDORID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_VENDORID)
-extern const unsigned int SCI_Q_VENDORID;
-
-
-/* Same as for SCI_VENDOR_ID */
-#define SCI_Q_API _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_API)
-extern const unsigned int SCI_Q_API;
-
-
-/* User passes a pointer to an allocated object of the */
-/* "sci_query_adapter" struct. */
-#define SCI_Q_ADAPTER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER)
-extern const unsigned int SCI_Q_ADAPTER;
-
-
-/* User passes a pointer to an allocated object of the */
-/* "sci_query_system" struct. */
-#define SCI_Q_SYSTEM _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM)
-extern const unsigned int SCI_Q_SYSTEM;
-
-#define SCI_Q_LOCAL_SEGMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_LOCAL_SEGMENT)
-extern const unsigned int SCI_Q_LOCAL_SEGMENT;
-
-#define SCI_Q_REMOTE_SEGMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_REMOTE_SEGMENT)
-extern const unsigned int SCI_Q_REMOTE_SEGMENT;
-
-#define SCI_Q_MAP _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_MAP)
-extern const unsigned int SCI_Q_MAP;
-
-typedef char* sci_semaphoreId_t;
-
-#ifdef WIN32
-struct _semaphoreid {
- char *semaphoreName;
-};
-#endif /*WIN32*/
-
-typedef struct {
- char *str; /* Pointer to a string of minimum "length" characters */
- unsigned int length;
-} sci_query_string_t;
-
-
-typedef struct {
- unsigned int localAdapterNo; /* The adapter no. that the query concern. */
- unsigned int portNo; /* The SCI Link port number that the query concern. */
- unsigned int subcommand; /* A subcommand as specified below. */
- void *data; /* A pointer to an unsigned int that will return */
- /* the response to the query. */
-} sci_query_adapter_t;
-
-
-typedef struct {
- unsigned int subcommand; /* A subcommand as specified below. */
- void *data; /* A pointer to an unsigned int that will return */
- /* the response to the query. */
-} sci_query_system_t;
-
-typedef struct {
- sci_local_segment_t segment;
- unsigned int subcommand;
- union {
- sci_ioaddr_t ioaddr;
- } data;
-} sci_query_local_segment_t;
-
-typedef struct {
- sci_remote_segment_t segment;
- unsigned int subcommand;
- union {
- sci_ioaddr_t ioaddr;
- } data;
-} sci_query_remote_segment_t;
-
-typedef struct {
- sci_map_t map;
- unsigned int subcommand;
- unsigned int data;
-} sci_query_map_t;
-
-/* Minor query commands (sub-commands) for adapter specific information SCI_ADAPTER */
-#define SCI_Q_ADAPTER_DMA_SIZE_ALIGNMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_DMA_SIZE_ALIGNMENT)
-extern const unsigned int SCI_Q_ADAPTER_DMA_SIZE_ALIGNMENT;
-
-#define SCI_Q_ADAPTER_DMA_OFFSET_ALIGNMENT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_DMA_OFFSET_ALIGNMENT)
-extern const unsigned int SCI_Q_ADAPTER_DMA_OFFSET_ALIGNMENT;
-
-#define SCI_Q_ADAPTER_DMA_MTU _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_DMA_MTU)
-extern const unsigned int SCI_Q_ADAPTER_DMA_MTU;
-
-#define SCI_Q_ADAPTER_SUGGESTED_MIN_DMA_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SUGGESTED_MIN_DMA_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_SUGGESTED_MIN_DMA_SIZE;
-
-#define SCI_Q_ADAPTER_SUGGESTED_MIN_BLOCK_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SUGGESTED_MIN_BLOCK_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_SUGGESTED_MIN_BLOCK_SIZE;
-
-#define SCI_Q_ADAPTER_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_NODEID;
-
-#define SCI_Q_ADAPTER_SERIAL_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SERIAL_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_SERIAL_NUMBER;
-
-#define SCI_Q_ADAPTER_CARD_TYPE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CARD_TYPE)
-extern const unsigned int SCI_Q_ADAPTER_CARD_TYPE;
-
-#define SCI_Q_ADAPTER_NUMBER_OF_STREAMS _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_NUMBER_OF_STREAMS)
-extern const unsigned int SCI_Q_ADAPTER_NUMBER_OF_STREAMS;
-
-#define SCI_Q_ADAPTER_STREAM_BUFFER_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_STREAM_BUFFER_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_STREAM_BUFFER_SIZE;
-
-#define SCI_Q_ADAPTER_CONFIGURED _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CONFIGURED)
-extern const unsigned int SCI_Q_ADAPTER_CONFIGURED;
-
-#define SCI_Q_ADAPTER_LINK_OPERATIONAL _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_LINK_OPERATIONAL)
-extern const unsigned int SCI_Q_ADAPTER_LINK_OPERATIONAL;
-
-#define SCI_Q_ADAPTER_HW_LINK_STATUS_IS_OK _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_HW_LINK_STATUS_IS_OK)
-extern const unsigned int SCI_Q_ADAPTER_HW_LINK_STATUS_IS_OK;
-
-#define SCI_Q_ADAPTER_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_NUMBER;
-
-#define SCI_Q_ADAPTER_INSTANCE_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_INSTANCE_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_INSTANCE_NUMBER;
-
-#define SCI_Q_ADAPTER_FIRMWARE_OK _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_FIRMWARE_OK)
-extern const unsigned int SCI_Q_ADAPTER_FIRMWARE_OK;
-
-#define SCI_Q_ADAPTER_CONNECTED_TO_SWITCH _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CONNECTED_TO_SWITCH)
-extern const unsigned int SCI_Q_ADAPTER_CONNECTED_TO_SWITCH;
-
-#define SCI_Q_ADAPTER_LOCAL_SWITCH_TYPE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_LOCAL_SWITCH_TYPE)
-extern const unsigned int SCI_Q_ADAPTER_LOCAL_SWITCH_TYPE;
-
-#define SCI_Q_ADAPTER_LOCAL_SWITCH_PORT_NUMBER _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_LOCAL_SWITCH_PORT_NUMBER)
-extern const unsigned int SCI_Q_ADAPTER_LOCAL_SWITCH_PORT_NUMBER;
-
-#define SCI_Q_ADAPTER_CONNECTED_TO_EXPECTED_SWITCH_PORT _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_CONNECTED_TO_EXPECTED_SWITCH_PORT)
-extern const unsigned int SCI_Q_ADAPTER_CONNECTED_TO_EXPECTED_SWITCH_PORT;
-
-#define SCI_Q_ADAPTER_ATT_PAGE_SIZE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_ATT_PAGE_SIZE)
-extern const unsigned int SCI_Q_ADAPTER_ATT_PAGE_SIZE;
-
-#define SCI_Q_ADAPTER_ATT_NUMBER_OF_ENTRIES _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_ATT_NUMBER_OF_ENTRIES)
-extern const unsigned int SCI_Q_ADAPTER_ATT_NUMBER_OF_ENTRIES;
-
-#define SCI_Q_ADAPTER_ATT_AVAILABLE_ENTRIES _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_ATT_AVAILABLE_ENTRIES)
-extern const unsigned int SCI_Q_ADAPTER_ATT_AVAILABLE_ENTRIES;
-
-#define SCI_Q_ADAPTER_PHYS_MEM_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SCI_Q_ADAPTER_PHYS_MEM_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_PHYS_MEM_NODEID;
-
-#define SCI_Q_ADAPTER_PHYS_MBX_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SCI_Q_ADAPTER_PHYS_MBX_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_PHYS_MBX_NODEID;
-
-#define SCI_Q_ADAPTER_PHYS_LINK_PORT_NODEID _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_PHYS_LINK_PORT_NODEID)
-extern const unsigned int SCI_Q_ADAPTER_PHYS_LINK_PORT_NODEID;
-
-#define SCI_Q_ADAPTER_SCI_LINK_FREQUENCY _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_SCI_LINK_FREQUENCY)
-extern const unsigned int SCI_Q_ADAPTER_SCI_LINK_FREQUENCY;
-
-#define SCI_Q_ADAPTER_B_LINK_FREQUENCY _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_B_LINK_FREQUENCY)
-extern const unsigned int SCI_Q_ADAPTER_B_LINK_FREQUENCY;
-
-#define SCI_Q_ADAPTER_IO_BUS_FREQUENCY _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_ADAPTER_IO_BUS_FREQUENCY)
-extern const unsigned int SCI_Q_ADAPTER_IO_BUS_FREQUENCY;
-
-/* Minor query commands (sub-commands) for adapter specific information SCI_SYSTEM */
-#define SCI_Q_SYSTEM_HOSTBRIDGE _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM_HOSTBRIDGE)
-extern const unsigned int SCI_Q_SYSTEM_HOSTBRIDGE;
-
-#define SCI_Q_SYSTEM_WRITE_POSTING_ENABLED _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM_WRITE_POSTING_ENABLED)
-extern const unsigned int SCI_Q_SYSTEM_WRITE_POSTING_ENABLED;
-
-#define SCI_Q_SYSTEM_WRITE_COMBINING_ENABLED _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_SYSTEM_WRITE_COMBINING_ENABLED)
-extern const unsigned int SCI_Q_SYSTEM_WRITE_COMBINING_ENABLED;
-
-#define SCI_Q_LOCAL_SEGMENT_IOADDR _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_LOCAL_SEGMENT_IOADDR)
-extern const unsigned int SCI_Q_LOCAL_SEGMENT_IOADDR;
-
-#define SCI_Q_REMOTE_SEGMENT_IOADDR _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_REMOTE_SEGMENT_IOADDR)
-extern const unsigned int SCI_Q_REMOTE_SEGMENT_IOADDR;
-
-#define SCI_Q_MAP_MAPPED_TO_LOCAL_TARGET _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_MAP_MAPPED_TO_LOCAL_TARGET)
-extern const unsigned int SCI_Q_MAP_MAPPED_TO_LOCAL_TARGET;
-
-#define SCI_Q_MAP_QUERY_REMOTE_MAPPED_TO_LOCAL_TARGET _SISCI_EXPANDE_CONSTANT_NAME(SCI_Q_MAP_QUERY_REMOTE_MAPPED_TO_LOCAL_TARGET)
-extern const unsigned int SCI_Q_MAP_QUERY_REMOTE_MAPPED_TO_LOCAL_TARGET;
-
-#define HOSTBRIDGE_NOT_AVAILABLE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_NOT_AVAILABLE)
-extern const unsigned int HOSTBRIDGE_NOT_AVAILABLE;
-
-#define HOSTBRIDGE_UNKNOWN _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_UNKNOWN)
-extern const unsigned int HOSTBRIDGE_UNKNOWN;
-
-#define HOSTBRIDGE_440FX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440FX)
-extern const unsigned int HOSTBRIDGE_440FX;
-
-#define HOSTBRIDGE_440LX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440LX)
-extern const unsigned int HOSTBRIDGE_440LX;
-
-#define HOSTBRIDGE_440BX_A _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440BX_A)
-extern const unsigned int HOSTBRIDGE_440BX_A;
-
-#define HOSTBRIDGE_440BX_B _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440BX_B)
-extern const unsigned int HOSTBRIDGE_440BX_B;
-
-#define HOSTBRIDGE_440GX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_440GX)
-extern const unsigned int HOSTBRIDGE_440GX;
-
-#define HOSTBRIDGE_450KX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450KX)
-extern const unsigned int HOSTBRIDGE_450KX;
-
-#define HOSTBRIDGE_430NX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_430NX)
-extern const unsigned int HOSTBRIDGE_430NX;
-
-#define HOSTBRIDGE_450NX _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450NX)
-extern const unsigned int HOSTBRIDGE_450NX;
-
-#define HOSTBRIDGE_450NX_MICO _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450NX_MICO)
-extern const unsigned int HOSTBRIDGE_450NX_MICO;
-
-#define HOSTBRIDGE_450NX_PXB _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_450NX_PXB)
-extern const unsigned int HOSTBRIDGE_450NX_PXB;
-
-#define HOSTBRIDGE_I810 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I810)
-extern const unsigned int HOSTBRIDGE_I810;
-
-#define HOSTBRIDGE_I810_DC100 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I810_DC100)
-extern const unsigned int HOSTBRIDGE_I810_DC100;
-
-#define HOSTBRIDGE_I810E _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I810E)
-extern const unsigned int HOSTBRIDGE_I810E;
-
-#define HOSTBRIDGE_I815 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I815)
-extern const unsigned int HOSTBRIDGE_I815;
-
-#define HOSTBRIDGE_I840 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I840)
-extern const unsigned int HOSTBRIDGE_I840;
-
-#define HOSTBRIDGE_I850 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I850)
-extern const unsigned int HOSTBRIDGE_I850;
-
-#define HOSTBRIDGE_I860 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_I860)
-extern const unsigned int HOSTBRIDGE_I860;
-
-#define HOSTBRIDGE_INTEL_E7500 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_INTEL_E7500)
-extern const unsigned int HOSTBRIDGE_INTEL_E7500;
-
-#define HOSTBRIDGE_VIA_KT133 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_KT133)
-extern const unsigned int HOSTBRIDGE_VIA_KT133;
-
-#define HOSTBRIDGE_VIA_KX133 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_KX133)
-extern const unsigned int HOSTBRIDGE_VIA_KX133;
-
-#define HOSTBRIDGE_VIA_APOLLO_PRO_133A _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_APOLLO_PRO_133A)
-extern const unsigned int HOSTBRIDGE_VIA_APOLLO_PRO_133A;
-
-#define HOSTBRIDGE_VIA_APOLLO_PRO_266 _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_VIA_APOLLO_PRO_266)
-extern const unsigned int HOSTBRIDGE_VIA_APOLLO_PRO_266;
-
-#define HOSTBRIDGE_AMD_760_MP _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_AMD_760_MP)
-extern const unsigned int HOSTBRIDGE_AMD_760_MP;
-
-#define HOSTBRIDGE_AMD_HAMMER _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_AMD_HAMMER)
-extern const unsigned int HOSTBRIDGE_AMD_HAMMER;
-
-#define HOSTBRIDGE_SERVERWORKS_HE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_HE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_HE;
-
-#define HOSTBRIDGE_SERVERWORKS_HE_B _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_HE_B)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_HE_B;
-
-#define HOSTBRIDGE_SERVERWORKS_LE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_LE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_LE;
-
-#define HOSTBRIDGE_SERVERWORKS_GC_HE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_GC_HE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_GC_HE;
-
-#define HOSTBRIDGE_SERVERWORKS_GC_LE _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_GC_LE)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_GC_LE;
-
-#define HOSTBRIDGE_SERVERWORKS_GC_WS _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_GC_WS)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_GC_WS;
-
-#define HOSTBRIDGE_SERVERWORKS_GC_SL _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_SERVERWORKS_GC_SL)
-extern const unsigned int HOSTBRIDGE_SERVERWORKS_GC_SL;
-
-
-#define HOSTBRIDGE_WRITE_POSTING_DISABLED _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_WRITE_POSTING_DISABLED)
-extern const unsigned int HOSTBRIDGE_WRITE_POSTING_DISABLED;
-
-#define HOSTBRIDGE_WRITE_POSTING_ENABLED _SISCI_EXPANDE_CONSTANT_NAME(HOSTBRIDGE_WRITE_POSTING_ENABLED)
-extern const unsigned int HOSTBRIDGE_WRITE_POSTING_ENABLED;
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C R E A T E D M A Q U E U E *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_PHDMA : Create physical DMA queue. Please note that this is an *
- * priveleged operation. *
- * *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCICreateDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCICreateDMAQueue)
-DLL void SCICreateDMAQueue(sci_desc_t sd,
- sci_dma_queue_t *dq,
- unsigned int localAdapterNo,
- unsigned int maxEntries,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E D M A Q U E U E *
- * *
- * Flags *
- * None. * *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Not allowed in this queue state. *
- * *
- *********************************************************************************/
-#define SCIRemoveDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveDMAQueue)
-DLL void SCIRemoveDMAQueue(sci_dma_queue_t dq,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I E N Q U E U E D M A T R A N S F E R *
- * *
- * Flags: *
- * *
- * SCI_FLAG_DMA_READ - The DMA will be remote --> local *
- * (default is local --> remote) *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the offset and size is larger *
- * than the segment size or larger than max *
- * DMA size. *
- * SCI_ERR_MAX_ENTRIES - The DMA queue is full *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_SEGMENT_NOT_PREPARED - The local segment has not been prepared for *
- * access from the adapter associated with the *
- * queue. *
- * SCI_ERR_SEGMENT_NOT_CONNECTED - The remote segment is not connected through *
- * the adapter associated with the queue. *
- *********************************************************************************/
-#define SCIEnqueueDMATransfer _SISCI_EXPANDE_FUNCTION_NAME(SCIEnqueueDMATransfer)
-DLL sci_dma_queue_state_t SCIEnqueueDMATransfer(sci_dma_queue_t dq,
- sci_local_segment_t localSegment,
- sci_remote_segment_t remoteSegment,
- unsigned int localOffset,
- unsigned int remoteOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I P O S T D M A Q U E U E *
- * *
- * Flags: *
- * *
- * SCI_FLAG_USE_CALLBACK - The end of the transfer will cause the callback *
- * function to be invoked. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * *
- *********************************************************************************/
-#define SCIPostDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIPostDMAQueue)
-DLL void SCIPostDMAQueue(sci_dma_queue_t dq,
- sci_cb_dma_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I A B O R T D M A Q U E U E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * *
- *********************************************************************************/
-#define SCIAbortDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIAbortDMAQueue)
-DLL void SCIAbortDMAQueue(sci_dma_queue_t dq,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I R E S E T D M A Q U E U E *
- * *
- * Flags *
- * None. * *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIResetDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIResetDMAQueue)
-DLL void SCIResetDMAQueue(sci_dma_queue_t dq,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I D M A Q U E U E S T A T E *
- * *
- *********************************************************************************/
-#define SCIDMAQueueState _SISCI_EXPANDE_FUNCTION_NAME(SCIDMAQueueState)
-DLL sci_dma_queue_state_t SCIDMAQueueState(sci_dma_queue_t dq);
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R D M A Q U E U E *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * *
- *********************************************************************************/
-#define SCIWaitForDMAQueue _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForDMAQueue)
-DLL sci_dma_queue_state_t SCIWaitForDMAQueue(sci_dma_queue_t dq,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I P H D M A E N Q U E U E *
- * *
- * SISCI Priveleged function *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_READ *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIphDmaEnqueue _SISCI_EXPANDE_FUNCTION_NAME(SCIphDmaEnqueue)
-DLL void SCIphDmaEnqueue(sci_dma_queue_t dmaqueue,
- unsigned int size,
- sci_ioaddr_t localBusAddr,
- unsigned int remote_nodeid,
- unsigned int remote_highaddr,
- unsigned int remote_lowaddr,
- unsigned int flags,
- sci_error_t *error);
-
-/*********************************************************************************
- * *
- * S C I P H D M A S T A R T *
- * *
- * Flags *
- * *
- * SCI_FLAG_DMA_WAIT *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_DMA_RESET *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIphDmaStart _SISCI_EXPANDE_FUNCTION_NAME(SCIphDmaStart)
-DLL sci_dma_queue_state_t SCIphDmaStart(sci_dma_queue_t dmaqueue,
- sci_cb_dma_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-#ifdef WIN32
-/*********************************************************************************
- * *
- * S C I C R E A T E N A M E D I N T E R R U P T *
- * *
- * Flags *
- * *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_FIXED_INTNO *
- * SCI_FLAG_SHARED_INT *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_INTNO_USED - This interrupt number is already used. *
- * *
- *********************************************************************************/
-#define SCICreateNamedInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCICreateNamedInterrupt)
-DLL void SCICreateNamedInterrupt(sci_desc_t sd,
- sci_local_interrupt_t *interrupt,
- unsigned int localAdapterNo,
- unsigned int *interruptNo,
- sci_cb_interrupt_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_semaphoreId_t semId,
- sci_error_t *error);
-#endif /*WIN32*/
-
-/*********************************************************************************
- * *
- * S C I C R E A T E I N T E R R U P T *
- * *
- * Flags *
- * *
- * SCI_FLAG_USE_CALLBACK *
- * SCI_FLAG_FIXED_INTNO *
- * SCI_FLAG_SHARED_INT *
- * SCI_FLAG_COUNTING_INT: This flag will enable counting interrupts. This means *
- * that the number of trigged interrupts is equal to the *
- * number of received interrupts. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_INTNO_USED - This interrupt number is already used. *
- * *
- *********************************************************************************/
-#define SCICreateInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCICreateInterrupt)
-DLL void SCICreateInterrupt(sci_desc_t sd,
- sci_local_interrupt_t *interrupt,
- unsigned int localAdapterNo,
- unsigned int *interruptNo,
- sci_cb_interrupt_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E M O V E I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- *********************************************************************************/
-#define SCIRemoveInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIRemoveInterrupt)
-DLL void SCIRemoveInterrupt(sci_local_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_TIMEOUT - The function timed out after specified timeout value. *
- * SCI_ERR_CANCELLED - The wait was interrupted by a call to *
- * SCIRemoveInterrupt. *
- * The handle is invalid when this error code is returned.*
- * *
- *********************************************************************************/
-#define SCIWaitForInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForInterrupt)
-DLL void SCIWaitForInterrupt(sci_local_interrupt_t interrupt,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C O N N E C T I N T E R R U P T *
- * *
- * Flags *
- * *
- * SCI_FLAG_COUNTING_INT: This flag will enable counting interrupts. This means *
- * that the number of trigged interrupts is equal to the *
- * number of received interrupts. *
- * if SCI_FLAG_COUNTING_INT is not used, the interface *
- * guarentees that there always will be an remote *
- * interrupt generated after the first and after the last*
- * trigger. If interupts is triggered faster than the *
- * remote interrupt handler can handle, interrupts may be*
- * lost. *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_NO_SUCH_INTNO - No such interrupt number. *
- * SCI_ERR_CONNECTION_REFUSED - Connection attempt refused by remote node. *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * *
- *********************************************************************************/
-#define SCIConnectInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIConnectInterrupt)
-DLL void SCIConnectInterrupt(sci_desc_t sd,
- sci_remote_interrupt_t *interrupt,
- unsigned int nodeId,
- unsigned int localAdapterNo,
- unsigned int interruptNo,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I D I S C O N N E C T I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIDisconnectInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIDisconnectInterrupt)
-DLL void SCIDisconnectInterrupt(sci_remote_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I T R I G G E R I N T E R R U P T *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCITriggerInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCITriggerInterrupt)
-DLL void SCITriggerInterrupt(sci_remote_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I R E G I S T E R I N T E R R U P T F L A G *
- * *
- * *
- * This function register an "interrupt flag" that is identified as an unique *
- * location within a local segment. If successful, the resulting interrupt *
- * handle will have been associated with the specified local segment. *
- * *
- * It is up to the (remote) client(s) to set up an "interrupt mapping" for the *
- * corresponding segment offset using either the *
- * *
- * - SCI_FLAG_CONDITIONAL_INTERRUPT_MAP *
- * *
- * or the *
- * *
- * - SCI_FLAG_UNCONDITIONAL_DATA_INTERRUPT_MAP *
- * *
- * option to "SCIMapRemoteSegment()". - I.e. after having established a *
- * connection to the corresponding segment. A trigger operation can then *
- * be implemented using a store operation via the relevant "interrupt map". *
- * *
- * *
- * *
- * *
- * *
- * Flags: *
- * *
- * SCI_FLAG_CONDITIONAL_INTERRUPT - Triggering is to take place using *
- * "conditional interrupts". *
- * *
- * *
- * *
- * Specific error codes for this function: *
- * None. *
- * *
- *********************************************************************************/
-#define SCIRegisterInterruptFlag _SISCI_EXPANDE_FUNCTION_NAME(SCIRegisterInterruptFlag)
-DLL void SCIRegisterInterruptFlag(
- unsigned int localAdapterNo,
- sci_local_interrupt_t *interrupt,
- sci_local_segment_t segment,
- unsigned int offset,
- sci_cb_interrupt_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I E N A B L E C O N D I T I O N A L I N T E R R U P T *
- * *
- * *
- * This function make sure that another HW interrupt will take place the next *
- * time the corresponding interrupt flag is triggered by a *
- * "conditional interrupt" operation. *
- * *
- * Default semantics: *
- * *
- * When successful, the client can rely on that the first subsequent trigger *
- * operation will cause a HW interrupt and subsequently cause the client *
- * handler function to be invoked. *
- * *
- * If an interrupt was triggered in parallell with the enable operation, then *
- * the operation will fail (SCI_ERR_COND_INT_RACE_PROBLEM), and the client can *
- * not rely on another trigger operation will lead to handler invocation. *
- * Hence, any state checking normally associated with handling the *
- * corresponding interrupt should take place before attempting to enable *
- * again. *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_COND_INT_RACE_PROBLEM - The enable operation failed because an *
- * incomming trigger operation happened *
- * concurrently. *
- * *
- *********************************************************************************/
-#define SCIEnableConditionalInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIEnableConditionalInterrupt)
-DLL void SCIEnableConditionalInterrupt(
- sci_local_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I D I S A B L E C O N D I T I O N A L I N T E R R U P T *
- * *
- * *
- * Prevent subsequent "conditional interrupt"trigger operations for *
- * the specified interupt flag from causing HW interrupt and handler *
- * invocations. *
- * *
- * *
- * Default semantics: *
- * *
- * If successful, no subsequent HW interrupts will take place, but handler *
- * invocations that have already been scheduled may still take place. *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * *
- *********************************************************************************/
-#define SCIDisableConditionalInterrupt _SISCI_EXPANDE_FUNCTION_NAME(SCIDisableConditionalInterrupt)
-DLL void SCIDisableConditionalInterrupt(
- sci_local_interrupt_t interrupt,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I G E T C O N D I T I O N A L I N T E R R U P T C O U N T E R *
- * *
- * *
- * Returns a value that indicates the number of times this flag has *
- * been trigged since the last time it was enabled or disabled. *
- * Calling the SCIEnableConditionalInterrupt / SCIDisableConditionalInterrupt *
- * functions will reset the counter value. *
- * *
- * Default semantics: *
- * *
- * If successful, the current trig count is returned in the *
- * interruptTrigCounter parameter. *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OVERFLOW - The number of trig operations have exceeded the range *
- * that can be counted. *
- *********************************************************************************/
-#define SCIGetConditionalInterruptTrigCounter _SISCI_EXPANDE_FUNCTION_NAME(SCIGetConditionalInterruptTrigCounter)
-DLL void SCIGetConditionalInterruptTrigCounter(
- sci_local_interrupt_t interrupt,
- unsigned int *interruptTrigCounter,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I T R A N S F E R B L O C K *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger *
- * than the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-#define SCITransferBlock _SISCI_EXPANDE_FUNCTION_NAME(SCITransferBlock)
-DLL void SCITransferBlock(sci_map_t sourceMap,
- unsigned int sourceOffset,
- sci_map_t destinationMap,
- unsigned int destinationOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I T R A N S F E R B L O C K A S Y N C *
- * *
- * Flags *
- * *
- * SCI_FLAG_BLOCK_READ *
- * SCI_FLAG_USE_CALLBACK *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger than *
- * the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required by *
- * the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-#define SCITransferBlockAsync _SISCI_EXPANDE_FUNCTION_NAME(SCITransferBlockAsync)
-DLL void SCITransferBlockAsync(sci_map_t sourceMap,
- unsigned int sourceOffset,
- sci_map_t destinationMap,
- unsigned int destinationOffset,
- unsigned int size,
- sci_block_transfer_t *block,
- sci_cb_block_transfer_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I W A I T F O R B L O C K T R A N S F E R *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * SCI_ERR_TIMEOUT - The function timed out after specified *
- * timeout value. *
- * *
- *********************************************************************************/
-#define SCIWaitForBlockTransfer _SISCI_EXPANDE_FUNCTION_NAME(SCIWaitForBlockTransfer)
-DLL void SCIWaitForBlockTransfer(sci_block_transfer_t block,
- unsigned int timeout,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I A B O R T B L O C K T R A N S F E R *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_ILLEGAL_OPERATION - Illegal operation *
- * *
- *********************************************************************************/
-#define SCIAbortBlockTransfer _SISCI_EXPANDE_FUNCTION_NAME(SCIAbortBlockTransfer)
-DLL void SCIAbortBlockTransfer(sci_block_transfer_t block,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-/*********************************************************************************
- * *
- * S C I M E M C P Y *
- * *
- * Flags: *
- * SCI_FLAG_BLOCK_READ *
- * SCI_FLAG_ERROR_CHECK *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger *
- * than the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-
-#define SCIMemCpy _SISCI_EXPANDE_FUNCTION_NAME(SCIMemCpy)
-DLL void SCIMemCpy(sci_sequence_t sequence,
- void *memAddr,
- sci_map_t remoteMap,
- unsigned int remoteOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I M E M C O P Y *
- * *
- * Flags: *
- * SCI_FLAG_BLOCK_READ *
- * SCI_FLAG_ERROR_CHECK *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_OUT_OF_RANGE - The sum of the size and offset is larger *
- * than the corresponding map size. *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_OFFSET_ALIGNMENT - Offset is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_TRANSFER_FAILED - The data transfer failed. *
- * *
- *********************************************************************************/
-
-
-#define SCIMemCopy _SISCI_EXPANDE_FUNCTION_NAME(SCIMemCopy)
-DLL void SCIMemCopy(void *memAddr,
- sci_map_t remoteMap,
- unsigned int remoteOffset,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*********************************************************************************
- * *
- * S C I R E G I S T E R S E G M E N T M E M O R Y *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required by *
- * the implementation. *
- * SCI_ERR_ILLEGAL_ADDRESS - Illegal address. *
- * SCI_ERR_OUT_OF_RANGE - Size is larger than the maximum size for the *
- * local segment. *
- * *
- *********************************************************************************/
-#define SCIRegisterSegmentMemory _SISCI_EXPANDE_FUNCTION_NAME(SCIRegisterSegmentMemory)
-DLL void SCIRegisterSegmentMemory(void *address,
- unsigned int size,
- sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-
-
-/*********************************************************************************
- * *
- * S C I C O N N E C T S C I S P A C E *
- * *
- * SISCI Priveleged function *
- * *
- * *
- * Flags *
- * None. *
- * *
- * *
- * Specific error codes for this function: *
- * *
- * SCI_ERR_SIZE_ALIGNMENT - Size is not correctly aligned as required *
- * by the implementation. *
- * SCI_ERR_CONNECTION_REFUSED - Connection attempt refused by remote node. *
- * *
- *********************************************************************************/
-#define SCIConnectSCISpace _SISCI_EXPANDE_FUNCTION_NAME(SCIConnectSCISpace)
-DLL void SCIConnectSCISpace(sci_desc_t sd,
- unsigned int localAdapterNo,
- sci_remote_segment_t *segment,
- sci_address_t address,
- unsigned int size,
- unsigned int flags,
- sci_error_t *error);
-
-
-
-/*
- * =====================================================================================
- *
- * S C I A T T A C H L O C A L S E G M E N T
- * Description:
- *
- * SCIAttachLocalSegment() permits an application to "attach" to an already existing
- * local segment, implying that two or more application want
- * share the same local segment. The prerequest, is that the
- * application which originally created the segment ("owner") has
- * preformed a SCIShareSegment() in order to mark the segment
- * "shareable".
- *
- *
- * Flags:
- *
- * SCI_FLAG_USE_CALLBACK - The callback function will be invoked for events
- * on this segment.
- *
- *
- * Specific error codes for this function:
- *
- * SCI_ERR_ACCESS - No such shared segment
- * SCI_ERR_NO_SUCH_SEGMENT - No such segment
- * Note: Current implenentation will return SCI_ERR_ACCESS for both cases. This will
- * change from next release. Application should handle both cases.
- *
- * =====================================================================================
- */
-#define SCIAttachLocalSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIAttachLocalSegment)
-
-DLL void
-SCIAttachLocalSegment(sci_desc_t sd,
- sci_local_segment_t *segment,
- unsigned int segmentId,
- unsigned int *size,
- sci_cb_local_segment_t callback,
- void *callbackArg,
- unsigned int flags,
- sci_error_t *error);
-/*
- * =====================================================================================
- *
- * S C I S H A R E S E G M E N T
- *
- * Description:
- *
- * SCIShareSegment() permits other application to "attach" to an already existing
- * local segment, implying that two or more application want
- * share the same local segment. The prerequest, is that the
- * application which originally created the segment ("owner") has
- * preformed a SCIShareSegment() in order to mark the segment
- * "shareable".
- *
- *
- * Flags:
- * none
- *
- * Specific error codes for this function:
- *
- *
- *
- * =====================================================================================
- */
-#define SCIShareSegment _SISCI_EXPANDE_FUNCTION_NAME(SCIShareSegment)
-
-DLL void
-SCIShareSegment(sci_local_segment_t segment,
- unsigned int flags,
- sci_error_t *error);
-
-
-/*********************************************************************************
- * *
- * S C I F L U S H *
- * *
- * This function will flush the CPU buffers and the PSB buffers. *
- * *
- * Flags *
- * SCI_FLAG_FLUSH_CPU_BUFFERS_ONLY : *
- * Only flush CPU buffers ( Write combining *
- * etc buffers). *
- * *
- *********************************************************************************/
-
-#define SCIFlush _SISCI_EXPANDE_FUNCTION_NAME(SCIFlush)
-DLL void SCIFlush(sci_sequence_t sequence,
- unsigned int flags);
-
-#if defined(CPLUSPLUS) || defined(__cplusplus)
-}
-#endif
-
-
-#endif
-
-
-
-
-
-
-
-
-
-
-
diff --git a/ndb/src/external/WIN32.x86/sci/include/sisci_demolib.h b/ndb/src/external/WIN32.x86/sci/include/sisci_demolib.h
deleted file mode 100644
index ce5bb2aec8e..00000000000
--- a/ndb/src/external/WIN32.x86/sci/include/sisci_demolib.h
+++ /dev/null
@@ -1,226 +0,0 @@
-/* $Id: sisci_demolib.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-#ifndef _SISCI_DEMOLIB_H
-#define _SISCI_DEMOLIB_H
-
-
-#if defined(_REENTRANT)
-
-#define _SISCI_DEMOLIB_EXPAND_NAME(name) _SISCI_DEMOLIB_MT_ ## name
-
-#else
-
-#define _SISCI_DEMOLIB_EXPAND_NAME(name) _SISCI_DEMOLIB_ST_ ## name
-
-#endif
-
-/*********************************************************************************/
-/* Q U E R Y A D A P T E R */
-/* */
-/*********************************************************************************/
-
-#define QueryAdapter _SISCI_DEMOLIB_EXPAND_NAME(QueryAdapter)
-
-sci_error_t QueryAdapter(
- unsigned int subcommand,
- unsigned int localAdapterNo,
- unsigned int portNo,
- unsigned int *data);
-
-
-/*********************************************************************************/
-/* Q U E R Y S Y S T E M */
-/* */
-/*********************************************************************************/
-
-#define QuerySystem _SISCI_DEMOLIB_EXPAND_NAME(QuerySystem)
-
-sci_error_t QuerySystem(
- unsigned int subcommand,
- unsigned int *data);
-
-
-/*********************************************************************************/
-/* D E T E C T F I R S T A D A P T E R C A R D */
-/* */
-/*********************************************************************************/
-
-#define DetectFirstAdapterCard _SISCI_DEMOLIB_EXPAND_NAME(DetectFirstAdapterCard)
-
-sci_error_t DetectFirstAdapterCard(
- unsigned int *localAdapterNo,
- unsigned int *localNodeId);
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R T Y P E */
-/* */
-/*********************************************************************************/
-
-#define GetAdapterType _SISCI_DEMOLIB_EXPAND_NAME(GetAdapterType)
-
-sci_error_t GetAdapterType(unsigned int localAdapterNo,
- unsigned int *adapterType);
-
-
-/*********************************************************************************/
-/* G E T L O C A L N O D E I D */
-/* */
-/*********************************************************************************/
-
-#define GetLocalNodeId _SISCI_DEMOLIB_EXPAND_NAME(GetLocalNodeId)
-
-sci_error_t GetLocalNodeId(
- unsigned int localAdapterNo,
- unsigned int *localNodeId);
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R S E R I A L N U M B E R */
-/* */
-/*********************************************************************************/
-
-#define GetAdapterSerialNumber _SISCI_DEMOLIB_EXPAND_NAME(GetAdapterSerialNumber)
-
-sci_error_t GetAdapterSerialNumber(
- unsigned int localAdapterNo,
- unsigned int *serialNo);
-
-
-
-/*********************************************************************************/
-/* G E T H O S T B R I D G E T Y P E */
-/* */
-/*********************************************************************************/
-
-#define GetHostbridgeType _SISCI_DEMOLIB_EXPAND_NAME(GetHostbridgeType)
-
-sci_error_t GetHostbridgeType(unsigned int *hostbridgeType);
-
-
-
-/*********************************************************************************/
-/* P R I N T H O S T B R I D G E T Y P E */
-/* */
-/*********************************************************************************/
-
-#define PrintHostbridgeType _SISCI_DEMOLIB_EXPAND_NAME(PrintHostbridgeType)
-
-void PrintHostbridgeType(unsigned int hostbridge);
-
-
-
-/*********************************************************************************/
-/* G E T A P I V E R S I O N S T R I N G */
-/* */
-/*********************************************************************************/
-
-#define GetAPIVersionString _SISCI_DEMOLIB_EXPAND_NAME(GetAPIVersionString)
-
-sci_error_t GetAPIVersionString(char str[], unsigned int strLength);
-
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R I O B U S F R E Q U E N C Y */
-/* */
-/*********************************************************************************/
-
-sci_error_t GetAdapterIoBusFrequency(unsigned int localAdapterNo,
- unsigned int *ioBusFrequency);
-
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R S C I L I N K F R E Q U E N C Y */
-/* */
-/*********************************************************************************/
-
-sci_error_t GetAdapterSciLinkFrequency(unsigned int localAdapterNo,
- unsigned int *sciLinkFrequency);
-
-
-
-/*********************************************************************************/
-/* G E T A D A P T E R B L I N K F R E Q U E N C Y */
-/* */
-/*********************************************************************************/
-
-sci_error_t GetAdapterBlinkFrequency(unsigned int localAdapterNo,
- unsigned int *bLinkFrequency);
-
-
-/*********************************************************************************/
-/* S E N D I N T E R R U P T */
-/* */
-/*********************************************************************************/
-
-#define SendInterrupt _SISCI_DEMOLIB_EXPAND_NAME(SendInterrupt)
-
-sci_error_t SendInterrupt(
- sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int localNodeId,
- unsigned int remoteNodeId,
- unsigned int interruptNo);
-
-
-/*********************************************************************************/
-/* R E C E I V E I N T E R R U P T */
-/* */
-/*********************************************************************************/
-
-#define ReceiveInterrupt _SISCI_DEMOLIB_EXPAND_NAME(ReceiveInterrupt)
-
-sci_error_t ReceiveInterrupt(
- sci_desc_t sd,
- unsigned int localAdapterNo,
- unsigned int localNodeId,
- unsigned int interruptNo);
-
-
-/*********************************************************************************/
-/* E N D I A N S W A P */
-/* */
-/*********************************************************************************/
-
-#define EndianSwap _SISCI_DEMOLIB_EXPAND_NAME(EndianSwap)
-
-unsigned int EndianSwap (unsigned int value);
-
-
-/*********************************************************************************/
-/* S L E E P M I L L I S E C O N D S */
-/* */
-/*********************************************************************************/
-
-#define SleepMilliseconds _SISCI_DEMOLIB_EXPAND_NAME(SleepMilliseconds)
-
-void SleepMilliseconds(int milliseconds);
-
-
-
-
-#endif
diff --git a/ndb/src/external/WIN32.x86/sci/include/sisci_error.h b/ndb/src/external/WIN32.x86/sci/include/sisci_error.h
deleted file mode 100644
index 56fa0d18b3a..00000000000
--- a/ndb/src/external/WIN32.x86/sci/include/sisci_error.h
+++ /dev/null
@@ -1,94 +0,0 @@
-/* $Id: sisci_error.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-
-
-#ifndef _SISCI_ERROR_H_
-#define _SISCI_ERROR_H_
-
-
-/* SCI Error return values always have 30 bit set */
-#define SCI_ERR_MASK 0x40000000
-#define SCI_ERR_REMOTE_MASK 0x01 /* Remote errors should have bit 0 set */
-
-#define SCI_ERR(u) ((unsigned32)(u)&0x7FFFFFFF )
-
-/* Error codes */
-typedef enum {
- SCI_ERR_OK = 0x000,
-
-
- SCI_ERR_BUSY = (0x900 | SCI_ERR_MASK),
- SCI_ERR_FLAG_NOT_IMPLEMENTED = (0x901 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_FLAG = (0x902 | SCI_ERR_MASK),
- SCI_ERR_NOSPC = (0x904 | SCI_ERR_MASK),
- SCI_ERR_API_NOSPC = (0x905 | SCI_ERR_MASK),
- SCI_ERR_HW_NOSPC = (0x906 | SCI_ERR_MASK),
- SCI_ERR_NOT_IMPLEMENTED = (0x907 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_ADAPTERNO = (0x908 | SCI_ERR_MASK),
- SCI_ERR_NO_SUCH_ADAPTERNO = (0x909 | SCI_ERR_MASK),
- SCI_ERR_TIMEOUT = (0x90A | SCI_ERR_MASK),
- SCI_ERR_OUT_OF_RANGE = (0x90B | SCI_ERR_MASK),
- SCI_ERR_NO_SUCH_SEGMENT = (0x90C | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_NODEID = (0x90D | SCI_ERR_MASK),
- SCI_ERR_CONNECTION_REFUSED = (0x90E | SCI_ERR_MASK),
- SCI_ERR_SEGMENT_NOT_CONNECTED = (0x90F | SCI_ERR_MASK),
- SCI_ERR_SIZE_ALIGNMENT = (0x910 | SCI_ERR_MASK),
- SCI_ERR_OFFSET_ALIGNMENT = (0x911 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_PARAMETER = (0x912 | SCI_ERR_MASK),
- SCI_ERR_MAX_ENTRIES = (0x913 | SCI_ERR_MASK),
- SCI_ERR_SEGMENT_NOT_PREPARED = (0x914 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_ADDRESS = (0x915 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_OPERATION = (0x916 | SCI_ERR_MASK),
- SCI_ERR_ILLEGAL_QUERY = (0x917 | SCI_ERR_MASK),
- SCI_ERR_SEGMENTID_USED = (0x918 | SCI_ERR_MASK),
- SCI_ERR_SYSTEM = (0x919 | SCI_ERR_MASK),
- SCI_ERR_CANCELLED = (0x91A | SCI_ERR_MASK),
- SCI_ERR_NOT_CONNECTED = (0x91B | SCI_ERR_MASK),
- SCI_ERR_NOT_AVAILABLE = (0x91C | SCI_ERR_MASK),
- SCI_ERR_INCONSISTENT_VERSIONS = (0x91D | SCI_ERR_MASK),
- SCI_ERR_COND_INT_RACE_PROBLEM = (0x91E | SCI_ERR_MASK),
- SCI_ERR_OVERFLOW = (0x91F | SCI_ERR_MASK),
- SCI_ERR_NOT_INITIALIZED = (0x920 | SCI_ERR_MASK),
-
- SCI_ERR_ACCESS = (0x921 | SCI_ERR_MASK),
-
- SCI_ERR_NO_SUCH_NODEID = (0xA00 | SCI_ERR_MASK),
- SCI_ERR_NODE_NOT_RESPONDING = (0xA02 | SCI_ERR_MASK),
- SCI_ERR_NO_REMOTE_LINK_ACCESS = (0xA04 | SCI_ERR_MASK),
- SCI_ERR_NO_LINK_ACCESS = (0xA05 | SCI_ERR_MASK),
- SCI_ERR_TRANSFER_FAILED = (0xA06 | SCI_ERR_MASK),
-
- SCI_ERR_EWOULD_BLOCK = ( 0xB00 | SCI_ERR_MASK),
- SCI_ERR_SEMAPHORE_COUNT_EXCEEDED = ( 0xB01 | SCI_ERR_MASK),
- SCI_ERR_IRQL_ILLEGAL = ( 0xB02 | SCI_ERR_MASK)
-
-} sci_error_t;
-
-
-#endif /* _SCI_ERROR_H_ */
-
-
-
diff --git a/ndb/src/external/WIN32.x86/sci/include/sisci_types.h b/ndb/src/external/WIN32.x86/sci/include/sisci_types.h
deleted file mode 100644
index 03e7957c3f2..00000000000
--- a/ndb/src/external/WIN32.x86/sci/include/sisci_types.h
+++ /dev/null
@@ -1,133 +0,0 @@
-/* $Id: sisci_types.h,v 1.1 2002/12/13 12:17:23 hin Exp $ */
-
-/*******************************************************************************
- * *
- * Copyright (C) 1993 - 2000 *
- * Dolphin Interconnect Solutions AS *
- * *
- * 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; either version 2 of the License, *
- * or (at your option) any later version. *
- * *
- * 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., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. *
- * *
- * *
- *******************************************************************************/
-
-
-#ifndef _SISCI_TYPES_H
-#define _SISCI_TYPES_H
-
-#include "sisci_error.h"
-
-#ifndef IN
-#define IN
-#endif
-
-#ifndef OUT
-#define OUT
-#endif
-
-#ifndef IN_OUT
-#define IN_OUT
-#endif
-
-/* Opaque data types for descriptors/handles */
-typedef struct sci_desc *sci_desc_t;
-typedef struct sci_local_segment *sci_local_segment_t;
-typedef struct sci_remote_segment *sci_remote_segment_t;
-
-typedef struct sci_map *sci_map_t;
-typedef struct sci_sequence *sci_sequence_t;
-#ifndef KERNEL
-typedef struct sci_dma_queue *sci_dma_queue_t;
-#endif
-typedef struct sci_remote_interrupt *sci_remote_interrupt_t;
-typedef struct sci_local_interrupt *sci_local_interrupt_t;
-typedef struct sci_block_transfer *sci_block_transfer_t;
-
-/*
- * Constants defining reasons for segment callbacks:
- */
-
-typedef enum {
- SCI_CB_CONNECT = 1,
- SCI_CB_DISCONNECT,
- SCI_CB_NOT_OPERATIONAL,
- SCI_CB_OPERATIONAL,
- SCI_CB_LOST
-} sci_segment_cb_reason_t;
-
-#define MAX_CB_REASON SCI_CB_LOST
-
-/* dma_queue_states is identical to the dma_queue_state_t in genif.h, they must be consistent.*/
-typedef enum {
- SCI_DMAQUEUE_IDLE,
- SCI_DMAQUEUE_GATHER,
- SCI_DMAQUEUE_POSTED,
- SCI_DMAQUEUE_DONE,
- SCI_DMAQUEUE_ABORTED,
- SCI_DMAQUEUE_ERROR
-} sci_dma_queue_state_t;
-
-
-typedef enum {
- SCI_SEQ_OK,
- SCI_SEQ_RETRIABLE,
- SCI_SEQ_NOT_RETRIABLE,
- SCI_SEQ_PENDING
-} sci_sequence_status_t;
-
-
-typedef struct {
- unsigned short nodeId; /* SCI Address bit 63 - 48 */
- unsigned short offsHi; /* SCI Address bit 47 - 32 */
- unsigned int offsLo; /* SCI Address bit 31 - 0 */
-} sci_address_t;
-
-
-typedef unsigned int sci_ioaddr_t;
-
-typedef enum {
- SCI_CALLBACK_CANCEL = 1,
- SCI_CALLBACK_CONTINUE
-} sci_callback_action_t;
-
-#ifndef KERNEL
-typedef sci_callback_action_t (*sci_cb_local_segment_t)(void *arg,
- sci_local_segment_t segment,
- sci_segment_cb_reason_t reason,
- unsigned int nodeId,
- unsigned int localAdapterNo,
- sci_error_t error);
-
-typedef sci_callback_action_t (*sci_cb_remote_segment_t)(void *arg,
- sci_remote_segment_t segment,
- sci_segment_cb_reason_t reason,
- sci_error_t status);
-
-
-typedef sci_callback_action_t (*sci_cb_dma_t)(void IN *arg,
- sci_dma_queue_t queue,
- sci_error_t status);
-
-
-typedef int (*sci_cb_block_transfer_t)(void *arg,
- sci_block_transfer_t block,
- sci_error_t status);
-
-
-typedef sci_callback_action_t (*sci_cb_interrupt_t)(void *arg,
- sci_local_interrupt_t interrupt,
- sci_error_t status);
-
-#endif /* KERNEL */
-#endif
diff --git a/ndb/src/kernel/Makefile_old b/ndb/src/kernel/Makefile_old
deleted file mode 100644
index d1f1741aca4..00000000000
--- a/ndb/src/kernel/Makefile_old
+++ /dev/null
@@ -1,5 +0,0 @@
-include .defs.mk
-
-DIRS := error vm ndb-main blocks
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/ERROR_codes.txt b/ndb/src/kernel/blocks/ERROR_codes.txt
index 70f11c33cd7..5193d3eae9d 100644
--- a/ndb/src/kernel/blocks/ERROR_codes.txt
+++ b/ndb/src/kernel/blocks/ERROR_codes.txt
@@ -1,8 +1,8 @@
Next QMGR 1
Next NDBCNTR 1000
Next NDBFS 2000
-Next DBACC 3001
-Next DBTUP 4007
+Next DBACC 3002
+Next DBTUP 4013
Next DBLQH 5042
Next DBDICT 6006
Next DBDIH 7174
@@ -10,7 +10,7 @@ Next DBTC 8035
Next CMVMI 9000
Next BACKUP 10022
Next DBUTIL 11002
-Next DBTUX 12001
+Next DBTUX 12007
Next SUMA 13001
TESTING NODE FAILURE, ARBITRATION
@@ -393,6 +393,13 @@ Failed Create Table:
--------------------
7173: Create table failed due to not sufficient number of fragment or
replica records.
+3001: Fail create 1st fragment
+4007 12001: Fail create 1st fragment
+4008 12002: Fail create 2nd fragment
+4009 12003: Fail create 1st attribute in 1st fragment
+4010 12004: Fail create last attribute in 1st fragment
+4011 12005: Fail create 1st attribute in 2nd fragment
+4012 12006: Fail create last attribute in 2nd fragment
Drop Table/Index:
-----------------
diff --git a/ndb/src/kernel/blocks/Makefile_old b/ndb/src/kernel/blocks/Makefile_old
deleted file mode 100644
index ce554dfc3b8..00000000000
--- a/ndb/src/kernel/blocks/Makefile_old
+++ /dev/null
@@ -1,28 +0,0 @@
-#--------------------------------------------------------------------------
-#
-# Name Makefile
-#
-#
-#
-# List subdirectories to be travered
-include .defs.mk
-
-DIRS := \
- cmvmi \
- dbacc \
- dbdict \
- dbdih \
- dblqh \
- dbtc \
- dbtup \
- ndbfs \
- ndbcntr \
- qmgr \
- trix \
- backup \
- dbutil \
- suma \
- grep \
- dbtux
-
-include ${NDB_TOP}/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/backup/Backup.cpp b/ndb/src/kernel/blocks/backup/Backup.cpp
index e6fe63d9014..9fc00883792 100644
--- a/ndb/src/kernel/blocks/backup/Backup.cpp
+++ b/ndb/src/kernel/blocks/backup/Backup.cpp
@@ -863,6 +863,13 @@ Backup::execBACKUP_REQ(Signal* signal)
sendBackupRef(senderRef, signal, senderData, BackupRef::IAmNotMaster);
return;
}//if
+
+ if (m_diskless)
+ {
+ sendBackupRef(senderRef, signal, senderData,
+ BackupRef::CannotBackupDiskless);
+ return;
+ }
if(dataLen32 != 0) {
jam();
diff --git a/ndb/src/kernel/blocks/backup/Backup.hpp b/ndb/src/kernel/blocks/backup/Backup.hpp
index 4dc2cd13ae0..fb29cb03b96 100644
--- a/ndb/src/kernel/blocks/backup/Backup.hpp
+++ b/ndb/src/kernel/blocks/backup/Backup.hpp
@@ -526,6 +526,7 @@ public:
NdbNodeBitmask c_aliveNodes;
DLList<BackupRecord> c_backups;
Config c_defaults;
+ Uint32 m_diskless;
STATIC_CONST(NO_OF_PAGES_META_FILE = 2);
diff --git a/ndb/src/kernel/blocks/backup/BackupInit.cpp b/ndb/src/kernel/blocks/backup/BackupInit.cpp
index 8daad05558b..d98541f2ea8 100644
--- a/ndb/src/kernel/blocks/backup/BackupInit.cpp
+++ b/ndb/src/kernel/blocks/backup/BackupInit.cpp
@@ -42,6 +42,7 @@ Backup::Backup(const Configuration & conf) :
ndbrequire(p != 0);
Uint32 noBackups = 0, noTables = 0, noAttribs = 0;
+ ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_DISCLESS, &m_diskless));
ndb_mgm_get_int_parameter(p, CFG_DB_PARALLEL_BACKUPS, &noBackups);
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_TABLES, &noTables));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_DB_NO_ATTRIBUTES, &noAttribs));
diff --git a/ndb/src/kernel/blocks/backup/Makefile.am b/ndb/src/kernel/blocks/backup/Makefile.am
index 85bf5b12415..e669febdc0d 100644
--- a/ndb/src/kernel/blocks/backup/Makefile.am
+++ b/ndb/src/kernel/blocks/backup/Makefile.am
@@ -1,6 +1,4 @@
-SUBDIRS = restore
-
noinst_LIBRARIES = libbackup.a
libbackup_a_SOURCES = Backup.cpp BackupInit.cpp
diff --git a/ndb/src/kernel/blocks/backup/Makefile_old b/ndb/src/kernel/blocks/backup/Makefile_old
deleted file mode 100644
index 989199cbe02..00000000000
--- a/ndb/src/kernel/blocks/backup/Makefile_old
+++ /dev/null
@@ -1,18 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-#ifneq ($(MYSQLCLUSTER_TOP),)
-DIRS := restore
-#endif
-
-ARCHIVE_TARGET := backup
-
-SOURCES = Backup.cpp BackupInit.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
-$(NDB_TOP)/bin/readBackupFile: read.o
- $(C++) -o $@ read.o \
- $(NDB_TOP)/lib/libportlib.a $(NDB_TOP)/lib/libgeneral.a
-
diff --git a/ndb/src/kernel/blocks/backup/restore/Makefile.am b/ndb/src/kernel/blocks/backup/restore/Makefile.am
deleted file mode 100644
index 16550f13546..00000000000
--- a/ndb/src/kernel/blocks/backup/restore/Makefile.am
+++ /dev/null
@@ -1,16 +0,0 @@
-
-ndbtools_PROGRAMS = ndb_restore
-
-ndb_restore_SOURCES = main.cpp consumer.cpp consumer_restore.cpp consumer_printer.cpp Restore.cpp
-
-LDADD_LOC = \
- $(top_builddir)/ndb/src/libndbclient.la \
- $(top_builddir)/dbug/libdbug.a \
- $(top_builddir)/mysys/libmysys.a \
- $(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@
-
-include $(top_srcdir)/ndb/config/common.mk.am
-
-INCLUDES += -I.. -I$(top_srcdir)/include -I$(top_srcdir)/ndb/include -I$(top_srcdir)/ndb/src/ndbapi -I$(top_srcdir)/ndb/include/ndbapi -I$(top_srcdir)/ndb/include/util -I$(top_srcdir)/ndb/include/portlib -I$(top_srcdir)/ndb/include/kernel
-
-ndb_restore_LDFLAGS = @ndb_bin_am_ldflags@
diff --git a/ndb/src/kernel/blocks/cmvmi/Makefile_old b/ndb/src/kernel/blocks/cmvmi/Makefile_old
deleted file mode 100644
index d75e5dbf08b..00000000000
--- a/ndb/src/kernel/blocks/cmvmi/Makefile_old
+++ /dev/null
@@ -1,9 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := cmvmi
-
-SOURCES = Cmvmi.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
index 169b77c0d85..af8ee136934 100644
--- a/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
+++ b/ndb/src/kernel/blocks/dbacc/Dbacc.hpp
@@ -22,6 +22,9 @@
#include <pc.hpp>
#include <SimulatedBlock.hpp>
+// primary key is stored in TUP
+#include <Dbtup.hpp>
+
#ifdef DBACC_C
// Debug Macros
#define dbgWord32(ptr, ind, val)
@@ -98,7 +101,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZPOS_PREV_PAGE 11
#define ZNORMAL_PAGE_TYPE 0
#define ZOVERFLOW_PAGE_TYPE 1
-#define ZLONG_PAGE_TYPE 2
#define ZDEFAULT_LIST 3
#define ZWORDS_IN_PAGE 2048
/* --------------------------------------------------------------------------------- */
@@ -132,16 +134,6 @@ ndbout << "Ptr: " << ptr.p->word32 << " \tIndex: " << tmp_string << " \tValue: "
#define ZPAGEZERO_NODETYPE 33
#define ZPAGEZERO_SLACK_CHECK 34
/* --------------------------------------------------------------------------------- */
-/* CONSTANTS FOR THE LONG KEY PAGES */
-/* --------------------------------------------------------------------------------- */
-/* --------------------------------------------------------------------------------- */
-// Maximum number of elements in long key page = (ZWORDS_IN_PAGE - ZHEAD_SIZE) /
-// (MinKeySize + IndexSize) = (2048 - 32) / (8 + 1) = 224. MinKeySize is actually 9
-// because 8 is the largest normal key size.
-#define ZMAX_NO_OF_LONGKEYS_IN_PAGE 225
-#define ZMAX_LONG_KEY_ARRAY_INDEX 3
-#define ZACTIVE_LONG_KEY_LEN 1
-/* --------------------------------------------------------------------------------- */
/* CONSTANTS IN ALPHABETICAL ORDER */
/* --------------------------------------------------------------------------------- */
#define ZADDFRAG 0
@@ -392,49 +384,6 @@ enum State {
// Records
-
-//----------------------------------------------------------------------------------
-// LONGKEY PAGE RECORD
-//
-// A long key page consist of a header part, a key data part and an index part. The
-// page starts with a header of size HEAD_SIZE. As you can see below, not every word
-// in the header is used. After the header comes the data part, where the actual
-// keys are stored. A key is always inserted after the existing keys in the data
-// part. If we have a fragmented data part and a new key doesn't fit after the
-// existing keys we reorganize the keys. The index part starts at the end of the
-// page and grows towards the end of the data part. This means that the limit
-// between the data part and the index part is floating. Each inserted key have a
-// word in the index part that describes size and position of the key in the data
-// part. The free indexes in the index part are single linked.
-//----------------------------------------------------------------------------------
- union LongKeyPage {
- struct {
- Uint32 pageId; // ZPOS_PAGE_ID 0
- Uint32 b;
- // The number of keys in page.
- Uint32 noOfElements; // ZPOS_NO_ELEM_IN_PAGE 2
- Uint32 d;
- Uint32 e;
- // The free area in the data part of page.
- Uint32 freeArea; // ZPOS_FREE_AREA_IN_PAGE 5
- // The index position, which defines the limit between the data and the index part.
- Uint32 highestIndex; // ZPOS_LAST_INDEX 6
- // The position where to insert the actual key in the data part.
- Uint32 insertPos; // ZPOS_INSERT_INDEX 7
- // Position in a page array where the pages are stored in a double linked list.
- // Based on the free area in the page. Values 0 to 3.
- Uint32 pageArrayPos; // ZPOS_ARRAY_POS 8
- // Next free position in the index part.
- Uint32 nextFreeIndex; // ZPOS_NEXT_FREE_INDEX 9
- // Next page in the double linked list.
- Uint32 nextPage; // ZPOS_NEXT_PAGE 10
- // Previous page in the double linked list.
- Uint32 prevPage; // ZPOS_PREV_PAGE 11
- } header;
- // This is kept to keep the logic and to make changes to a minimum.
- Uint32 word32[2048];
- };
-
/* --------------------------------------------------------------------------------- */
/* UNDO HEADER RECORD */
/* --------------------------------------------------------------------------------- */
@@ -444,9 +393,7 @@ enum State {
ZPAGE_INFO = 0,
ZOVER_PAGE_INFO = 1,
ZOP_INFO = 2,
- ZUNDO_INSERT_LONG_KEY = 3,
- ZUNDO_DELETE_LONG_KEY = 4,
- ZNO_UNDORECORD_TYPES = 5
+ ZNO_UNDORECORD_TYPES = 3
};
UintR tableId;
UintR rootFragId;
@@ -661,9 +608,10 @@ struct Fragmentrec {
//-----------------------------------------------------------------------------
// elementLength: Length of element in bucket and overflow pages
// keyLength: Length of key (== 0 if long key or variable key length)
+// wl-2066 always Length of key
//-----------------------------------------------------------------------------
Uint8 elementLength;
- Uint8 keyLength;
+ Uint16 keyLength;
//-----------------------------------------------------------------------------
// This flag is used to avoid sending a big number of expand or shrink signals
@@ -783,7 +731,7 @@ struct Operationrec {
Uint8 dirtyRead;
Uint8 commitDeleteCheckFlag;
Uint8 isAccLockReq;
- Uint32 nextOpList;
+ Uint8 isUndoLogReq;
}; /* p2c: size = 168 bytes */
typedef Ptr<Operationrec> OperationrecPtr;
@@ -914,6 +862,9 @@ public:
Dbacc(const class Configuration &);
virtual ~Dbacc();
+ // pointer to TUP instance in this thread
+ Dbtup* c_tup;
+
private:
BLOCK_DEFINES(Dbacc);
@@ -977,10 +928,8 @@ private:
void initFragGeneral(FragmentrecPtr);
void verifyFragCorrect(FragmentrecPtr regFragPtr);
void sendFSREMOVEREQ(Signal* signal, Uint32 tableId);
- void sendDROP_TABFILECONF(Signal* signal, TabrecPtr tabPtr);
void releaseFragResources(Signal* signal, Uint32 fragIndex);
void releaseRootFragRecord(Signal* signal, RootfragmentrecPtr rootPtr);
- void sendREL_TABMEMCONF(Signal* signal, TabrecPtr tabPtr);
void releaseRootFragResources(Signal* signal, Uint32 tableId);
void releaseDirResources(Signal* signal,
Uint32 fragIndex,
@@ -1056,7 +1005,6 @@ private:
void releaseScanRec(Signal* signal);
bool searchScanContainer(Signal* signal);
void sendNextScanConf(Signal* signal);
- void sendScaninfo(Signal* signal);
void setlock(Signal* signal);
void takeOutActiveScanOp(Signal* signal);
void takeOutScanLockQueue(Uint32 scanRecIndex);
@@ -1068,15 +1016,8 @@ private:
void increaselistcont(Signal* signal);
void seizeLeftlist(Signal* signal);
void seizeRightlist(Signal* signal);
- void allocLongOverflowPage(Signal* signal);
- void allocSpecificLongOverflowPage(Signal* signal);
- void getLongKeyPage(Signal* signal);
- void initLongOverpage(Signal* signal);
- void storeLongKeys(Signal* signal);
- void storeLongKeysAtPos(Signal* signal);
- void reorgLongPage(Signal* signal);
+ void readTablePk(Uint32 localkey1);
void getElement(Signal* signal);
- void searchLongKey(Signal* signal);
void getdirindex(Signal* signal);
void commitdelete(Signal* signal, bool systemRestart);
void deleteElement(Signal* signal);
@@ -1084,15 +1025,6 @@ private:
void releaseLeftlist(Signal* signal);
void releaseRightlist(Signal* signal);
void checkoverfreelist(Signal* signal);
- void deleteLongKey(Signal* signal);
- void removeFromPageArrayList(Signal* signal);
- void insertPageArrayList(Signal* signal);
- void checkPageArrayList(Signal* signal, const char *);
- void checkPageB4Insert(Uint32, const char *);
- void checkPageB4Remove(Uint32, const char *);
- void checkIndexInLongKeyPage(Uint32, const char *);
- void printoutInfoAndShutdown(LongKeyPage *);
- void releaseLongPage(Signal* signal);
void abortOperation(Signal* signal);
void accAbortReqLab(Signal* signal, bool sendConf);
void commitOperation(Signal* signal);
@@ -1108,7 +1040,6 @@ private:
void initLcpConnRec(Signal* signal);
void initOverpage(Signal* signal);
void initPage(Signal* signal);
- void initPageZero(Signal* signal);
void initRootfragrec(Signal* signal);
void putOpInFragWaitQue(Signal* signal);
void putOverflowRecInFrag(Signal* signal);
@@ -1162,8 +1093,6 @@ private:
void refaccConnectLab(Signal* signal);
void srReadOverPagesLab(Signal* signal);
void releaseScanLab(Signal* signal);
- void exeoperationLab(Signal* signal);
- void saveKeyDataLab(Signal* signal);
void lcpOpenUndofileConfLab(Signal* signal);
void srFsOpenConfLab(Signal* signal);
void checkSyncUndoPagesLab(Signal* signal);
@@ -1175,13 +1104,12 @@ private:
void srReadPagesLab(Signal* signal);
void srDoUndoLab(Signal* signal);
void ndbrestart1Lab(Signal* signal);
- void initialiseRecordsLab(Signal* signal, Uint32 returnRef, Uint32 retData);
+ void initialiseRecordsLab(Signal* signal, Uint32 ref, Uint32 data);
void srReadPagesAllocLab(Signal* signal);
void checkNextBucketLab(Signal* signal);
void endsavepageLab(Signal* signal);
void saveZeroPageLab(Signal* signal);
void srAllocPage0011Lab(Signal* signal);
- void allocscanrecLab(Signal* signal);
void sendLcpFragidconfLab(Signal* signal);
void savepagesLab(Signal* signal);
void saveOverPagesLab(Signal* signal);
@@ -1285,8 +1213,6 @@ private:
/* --------------------------------------------------------------------------------- */
Page8 *page8;
/* 8 KB PAGE */
- Page8Ptr aslpPageptr;
- Page8Ptr alpPageptr;
Page8Ptr ancPageptr;
Page8Ptr colPageptr;
Page8Ptr ccoPageptr;
@@ -1297,29 +1223,17 @@ private:
Page8Ptr gdiPageptr;
Page8Ptr gePageptr;
Page8Ptr gflPageptr;
- Page8Ptr glkPageptr;
Page8Ptr idrPageptr;
Page8Ptr ilcPageptr;
- Page8Ptr iloPageptr;
Page8Ptr inpPageptr;
Page8Ptr iopPageptr;
- Page8Ptr ipzPageptr;
Page8Ptr lastPageptr;
Page8Ptr lastPrevpageptr;
Page8Ptr lcnPageptr;
Page8Ptr lcnCopyPageptr;
Page8Ptr lupPageptr;
- Page8Ptr dlkPageptr;
- Page8Ptr ipaPagePtr;
Page8Ptr priPageptr;
Page8Ptr pwiPageptr;
- Page8Ptr rfpPageptr;
- Page8Ptr relpPageptr;
- Page8Ptr rlopPageptr;
- Page8Ptr slkPageptr;
- Page8Ptr slkCopyPageptr;
- Page8Ptr slkapPageptr;
- Page8Ptr slkapCopyPageptr;
Page8Ptr ciPageidptr;
Page8Ptr gsePageidptr;
Page8Ptr isoPageptr;
@@ -1333,7 +1247,6 @@ private:
Page8Ptr ropPageptr;
Page8Ptr rpPageptr;
Page8Ptr slPageptr;
- Page8Ptr slpPageptr;
Page8Ptr spPageptr;
Uint32 cfirstfreepage;
Uint32 cfreepage;
@@ -1351,7 +1264,6 @@ private:
/* --------------------------------------------------------------------------------- */
Rootfragmentrec *rootfragmentrec;
RootfragmentrecPtr rootfragrecptr;
- RootfragmentrecPtr tmprootfrgptr;
Uint32 crootfragmentsize;
Uint32 cfirstfreerootfrag;
/* --------------------------------------------------------------------------------- */
@@ -1384,7 +1296,6 @@ private:
Uint32 tpriElementptr;
Uint32 tgseElementptr;
Uint32 tgseContainerptr;
- Uint32 tiloIndex;
Uint32 trlHead;
Uint32 trlRelCon;
Uint32 trlNextused;
@@ -1393,20 +1304,12 @@ private:
Uint32 tlupElemIndex;
Uint32 tlupIndex;
Uint32 tlupForward;
- Uint32 tslkPageIndex;
- Uint32 tslkKeyLen;
- Uint32 tslkapKeyLen;
- Uint32 tslkapPageIndex;
- Uint32 tipaArrayPos;
- Uint32 trfpArrayPos;
- Uint32 tdlkLogicalPageIndex;
Uint32 tancNext;
Uint32 tancBufType;
Uint32 tancContainerptr;
Uint32 tancPageindex;
Uint32 tancPageid;
Uint32 tidrResult;
- Uint32 tidrKeyLen;
Uint32 tidrElemhead;
Uint32 tidrForward;
Uint32 tidrPageindex;
@@ -1424,15 +1327,11 @@ private:
Uint32 tdelForward;
Uint32 tiopPageId;
Uint32 tipPageId;
- Uint32 ttupKeyLength;
Uint32 tgeLocked;
Uint32 tgeResult;
Uint32 tgeContainerptr;
Uint32 tgeElementptr;
Uint32 tgeForward;
- Uint32 tslcResult;
- Uint32 tslcPagedir;
- Uint32 tslcPageIndex;
Uint32 tundoElemIndex;
Uint32 texpReceivedBucket;
Uint32 texpDirInd;
@@ -1457,7 +1356,6 @@ private:
Uint32 tscanFlag;
Uint32 theadundoindex;
Uint32 tgflBufType;
- Uint32 thashvalue;
Uint32 tgseIsforward;
Uint32 tsscIsforward;
Uint32 trscIsforward;
@@ -1466,21 +1364,10 @@ private:
Uint32 tisoIsforward;
Uint32 tgseIsLocked;
Uint32 tsscIsLocked;
- Uint32 tkey1;
- Uint32 tkey2;
- Uint32 tkey3;
- Uint32 tkey4;
Uint32 tkeylen;
- Uint32 tkSize;
- Uint32 tlhfragbits;
- Uint32 tlhdirbits;
- Uint32 tlocalkeylen;
- Uint32 tmaxloadfactor;
- Uint32 tminloadfactor;
Uint32 tmp;
Uint32 tmpP;
Uint32 tmpP2;
- Uint32 taslpDirIndex;
Uint32 tmp1;
Uint32 tmp2;
Uint32 tgflPageindex;
@@ -1494,9 +1381,6 @@ private:
Uint32 trsbPageindex;
Uint32 tnciPageindex;
Uint32 tlastPrevconptr;
- Uint32 treqinfo;
- Uint32 transactionid1;
- Uint32 transactionid2;
Uint32 tresult;
Uint32 tslUpdateHeader;
Uint32 tuserptr;
@@ -1509,16 +1393,13 @@ private:
Uint32 tgdiPageindex;
Uint32 tiopIndex;
Uint32 tnciTmp;
- Uint32 tlenKeyinfo;
Uint32 tullIndex;
Uint32 turlIndex;
Uint32 tlfrTmp1;
Uint32 tlfrTmp2;
Uint32 tgnptNrTransaction;
- Uint32 tudqeIndex;
Uint32 tscanTrid1;
Uint32 tscanTrid2;
- Uint32 taccscanTmp;
Uint16 clastUndoPageIdWritten;
Uint32 cactiveCheckpId;
@@ -1562,10 +1443,13 @@ private:
Uint32 cexcPrevpageindex;
Uint32 cexcPrevforward;
Uint32 clocalkey[32];
+ union {
Uint32 ckeys[2048];
+ Uint64 ckeys_align;
+ };
Uint32 c_errorInsert3000_TableId;
- Uint32 cSrUndoRecords[5];
+ Uint32 cSrUndoRecords[UndoHeader::ZNO_UNDORECORD_TYPES];
};
#endif
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
index 2705f95f6dd..c9b6c0ea17d 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccInit.cpp
@@ -133,7 +133,8 @@ void Dbacc::initRecords()
}//Dbacc::initRecords()
Dbacc::Dbacc(const class Configuration & conf):
- SimulatedBlock(DBACC, conf)
+ SimulatedBlock(DBACC, conf),
+ c_tup(0)
{
Uint32 log_page_size= 0;
BLOCK_CONSTRUCTOR(Dbacc);
diff --git a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
index 9a1bbd86562..1a5e22ac70a 100644
--- a/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
+++ b/ndb/src/kernel/blocks/dbacc/DbaccMain.cpp
@@ -570,7 +570,14 @@ void Dbacc::execNDB_STTOR(Signal* signal)
void Dbacc::execSTTOR(Signal* signal)
{
jamEntry();
- // tstartphase = signal->theData[1];
+ Uint32 tstartphase = signal->theData[1];
+ switch (tstartphase) {
+ case 1:
+ jam();
+ c_tup = (Dbtup*)globalData.getBlock(DBTUP);
+ ndbrequire(c_tup != 0);
+ break;
+ }
tuserblockref = signal->theData[3];
csignalkey = signal->theData[6];
sttorrysignalLab(signal);
@@ -1062,7 +1069,21 @@ void Dbacc::execACCFRAGREQ(Signal* signal)
{
const AccFragReq * const req = (AccFragReq*)&signal->theData[0];
jamEntry();
+ if (ERROR_INSERTED(3001)) {
+ jam();
+ addFragRefuse(signal, 1);
+ CLEAR_ERROR_INSERT_VALUE;
+ return;
+ }
tabptr.i = req->tableId;
+#ifndef VM_TRACE
+ // config mismatch - do not crash if release compiled
+ if (tabptr.i >= ctablesize) {
+ jam();
+ addFragRefuse(signal, 800);
+ return;
+ }
+#endif
ptrCheckGuard(tabptr, ctablesize, tabrec);
ndbrequire((req->reqInfo & 0xF) == ZADDFRAG);
ndbrequire(!getrootfragmentrec(signal, rootfragrecptr, req->fragId));
@@ -1567,6 +1588,9 @@ void Dbacc::initOpRec(Signal* signal)
// bit to mark lock operation
operationRecPtr.p->isAccLockReq = (Treqinfo >> 31) & 0x1;
+
+ // undo log is not run via ACCKEYREQ
+ operationRecPtr.p->isUndoLogReq = 0;
}//Dbacc::initOpRec()
/* --------------------------------------------------------------------------------- */
@@ -1807,8 +1831,6 @@ void Dbacc::insertExistElemLab(Signal* signal)
/* --------------------------------------------------------------------------------- */
void Dbacc::insertelementLab(Signal* signal)
{
- Uint32 tinsKeyLen;
-
if (fragrecptr.p->createLcp == ZTRUE) {
if (remainingUndoPages() < ZMIN_UNDO_PAGES_AT_OPERATION) {
jam();
@@ -1828,44 +1850,6 @@ void Dbacc::insertelementLab(Signal* signal)
if (fragrecptr.p->keyLength != operationRecPtr.p->tupkeylen) {
ndbrequire(fragrecptr.p->keyLength == 0);
}//if
- if (fragrecptr.p->keyLength != 0) {
- ndbrequire(operationRecPtr.p->tupkeylen <= 8);
- for (Uint32 i = 0; i < operationRecPtr.p->tupkeylen; i++) {
- jam();
- ckeys[i] = signal->theData[i + 7];
- }//for
- tinsKeyLen = operationRecPtr.p->tupkeylen;
- } else {
- jam();
- seizePage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- acckeyref1Lab(signal, tresult);
- return;
- }//if
- operationRecPtr.p->keyinfoPage = spPageptr.i;
- for (Uint32 i = 0; i < signal->theData[4]; i++) {
- spPageptr.p->word32[i] = signal->theData[i + 7];
- }//for
-
- getLongKeyPage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- acckeyref1Lab(signal, tresult);
- return;
- }//if
- slkPageptr = glkPageptr;
- slkCopyPageptr.i = operationRecPtr.p->keyinfoPage;
- ptrCheckGuard(slkCopyPageptr, cpagesize, page8);
- tslkKeyLen = operationRecPtr.p->tupkeylen;
- storeLongKeys(signal);
- ckeys[0] = (slkPageptr.p->word32[ZPOS_PAGE_ID] << 10) + tslkPageIndex;
- tinsKeyLen = ZACTIVE_LONG_KEY_LEN;
- rpPageptr.i = operationRecPtr.p->keyinfoPage;
- ptrCheckGuard(rpPageptr, cpagesize, page8);
- releasePage(signal);
- operationRecPtr.p->keyinfoPage = RNIL;
- }//if
signal->theData[0] = operationRecPtr.p->userptr;
Uint32 blockNo = refToBlock(operationRecPtr.p->userblockref);
@@ -1889,7 +1873,6 @@ void Dbacc::insertelementLab(Signal* signal)
idrPageptr = gdiPageptr;
tidrPageindex = tgdiPageindex;
tidrForward = ZTRUE;
- tidrKeyLen = tinsKeyLen;
idrOperationRecPtr = operationRecPtr;
clocalkey[0] = localKey;
operationRecPtr.p->localdata[0] = localKey;
@@ -2484,6 +2467,7 @@ void Dbacc::execACC_LOCKREQ(Signal* signal)
signal->theData[4] = 1; // fake primKeyLen
signal->theData[5] = req->transId1;
signal->theData[6] = req->transId2;
+ // enter local key in place of PK
signal->theData[7] = req->tupAddr;
EXECUTE_DIRECT(DBACC, GSN_ACCKEYREQ, signal, 8);
// translate the result
@@ -2861,14 +2845,6 @@ void Dbacc::insertContainer(Signal* signal)
idrPageptr.p->word32[tidrIndex] = clocalkey[tidrInputIndex]; /* INSERTS LOCALKEY */
tidrIndex += tidrForward;
}//for
- guard26 = tidrKeyLen - 1;
- arrGuard(guard26, 8);
- for (tidrInputIndex = 0; tidrInputIndex <= guard26; tidrInputIndex++) {
- dbgWord32(idrPageptr, tidrIndex, ckeys[tidrInputIndex]);
- arrGuard(tidrIndex, 2048);
- idrPageptr.p->word32[tidrIndex] = ckeys[tidrInputIndex]; /* INSERTS TUPLE KEY */
- tidrIndex += tidrForward;
- }//for
tidrContLen = idrPageptr.p->word32[tidrContainerptr] << 6;
tidrContLen = tidrContLen >> 6;
dbgWord32(idrPageptr, tidrContainerptr, (tidrContainerlen << 26) | tidrContLen);
@@ -3202,1215 +3178,6 @@ void Dbacc::seizeRightlist(Signal* signal)
increaselistcont(signal);
}//Dbacc::seizeRightlist()
-
-//---------------------------------------------------------------------------------
-// ALLOC_SPECIFIC_LONG_OVERFLOW_PAGE
-//
-// DESCRIPTION: ALLOCATES A LONG OVER FLOW PAGE AND PUTS IT IN A SPECIFIED
-// DIRINDEX. THIS IS TO SUPPORT AN UNDO_DELETE AFTER AN
-// UNDO_INSERT ON THE SAME LONG KEY IN A LCP.
-// UNDO_INSERT ONLY HAVE A REFERENCE TO THE KEY AND TO MAKE
-// IT POSSIBLE TO DELETE THE KEY, THE REFERENCE MUST BE
-// ACCURATE, WHICH MEANS THE KEY MUST BE SAVED ON THE SAME
-// PLACE IT WAS DELETED FROM.
-//---------------------------------------------------------------------------------
-void Dbacc::allocSpecificLongOverflowPage(Signal* signal)
-{
- DirRangePtr aloDirRangePtr;
- DirectoryarrayPtr aloOverflowDirptr;
-
- if ((cfirstfreepage == RNIL) &&
- (cfreepage >= cpagesize)) {
- jam();
- zpagesize_error("Dbacc::allocSpecificLongOverflowPage");
- tresult = ZPAGESIZE_ERROR;
- return;
- }
-
- if ((cfirstfreedir == RNIL) &&
- (cdirarraysize <= cdirmemory)) {
- jam();
- tresult = ZDIRSIZE_ERROR;
- return;
- }
-
- tmpP = taslpDirIndex;
- aloDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(aloDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
-
- if (aloDirRangePtr.p->dirArray[tmpP2] == RNIL) {
- jam();
- seizeDirectory(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- sendSystemerror(signal);
- return;
- }
- aloDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- } else {
- jam();
- sdDirptr.i = RNIL;
- ptrNull(sdDirptr);
- }
-
- aloOverflowDirptr.i = aloDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(aloOverflowDirptr, cdirarraysize, directoryarray);
- seizePage(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- sendSystemerror(signal);
- return;
- }//if
-
- if (aloOverflowDirptr.p->pagep[tmpP] != RNIL) {
- jam();
- sendSystemerror(signal);
- return;
- }
-
- aloOverflowDirptr.p->pagep[tmpP] = spPageptr.i;
- iloPageptr.p = spPageptr.p;
- iloPageptr.i = spPageptr.i;
- tiloIndex = taslpDirIndex;
- initLongOverpage(signal);
- aslpPageptr.i = spPageptr.i;
- aslpPageptr.p = spPageptr.p;
-}//Dbacc::allocSpecificLongOverflowPage
-
-/* --------------------------------------------------------------------------------- */
-/* ALLOC_LONG_OVERFLOW_PAGE */
-/* DESCRIPTION: */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::allocLongOverflowPage(Signal* signal)
-{
- DirRangePtr aloDirRangePtr;
- DirectoryarrayPtr aloOverflowDirptr;
- OverflowRecordPtr aloOverflowRecPtr;
- Uint32 taloIndex;
-
- if ((cfirstfreepage == RNIL) &&
- (cfreepage >= cpagesize)) {
- jam();
- zpagesize_error("Dbacc::allocLongOverflowPage");
- tresult = ZPAGESIZE_ERROR;
- return;
- }//if
- if ((cfirstfreedir == RNIL) &&
- (cdirarraysize <= cdirmemory)) {
- jam();
- tresult = ZDIRSIZE_ERROR;
- return;
- }//if
- if (fragrecptr.p->firstFreeDirindexRec != RNIL) {
- jam();
- aloOverflowRecPtr.i = fragrecptr.p->firstFreeDirindexRec;
- ptrCheckGuard(aloOverflowRecPtr, coverflowrecsize, overflowRecord);
- troOverflowRecPtr.p = aloOverflowRecPtr.p;
- takeRecOutOfFreeOverdir(signal);
- taloIndex = aloOverflowRecPtr.p->dirindex;
- rorOverflowRecPtr = aloOverflowRecPtr;
- releaseOverflowRec(signal);
- } else {
- jam();
- taloIndex = fragrecptr.p->lastOverIndex;
- fragrecptr.p->lastOverIndex++;
- }//if
- tmpP = taloIndex;
- aloDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(aloDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- if (aloDirRangePtr.p->dirArray[tmpP2] == RNIL) {
- jam();
- seizeDirectory(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- aloDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- } else {
- jam();
- sdDirptr.i = RNIL;
- ptrNull(sdDirptr);
- }//if
- aloOverflowDirptr.i = aloDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(aloOverflowDirptr, cdirarraysize, directoryarray);
- seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
- aloOverflowDirptr.p->pagep[tmpP] = spPageptr.i;
- iloPageptr = spPageptr;
- tiloIndex = taloIndex;
- initLongOverpage(signal);
- alpPageptr = spPageptr;
- ipaPagePtr = spPageptr;
- tipaArrayPos = 3;
- insertPageArrayList(signal);
-}//Dbacc::allocLongOverflowPage()
-
-/* --------------------------------------------------------------------------------- */
-/* GET_LONG_KEY_PAGE */
-/* DESCRIPTION: SEARCH FOR A FREE OVERFLOW PAGE TO STORE A LONG KEY. */
-/* LONG_KEY_PAGE_PTR IS RETURNED. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::getLongKeyPage(Signal* signal)
-{
- LongKeyPage *glkPage;
-
- jam();
-
- Uint32 tglkLongIndex = 0;
-
- ndbrequire(operationRecPtr.p->tupkeylen <= ZWORDS_IN_PAGE - ZHEAD_SIZE);
-
- // Do not look in longKeyPageArray[tglkLongIndex] where the pages are to small.
- if(operationRecPtr.p->tupkeylen < 128) {
- jam();
- tglkLongIndex = 0;
- } else {
- jam();
- tglkLongIndex = (operationRecPtr.p->tupkeylen - 128) / 512;
- }//if
-
- // Go through the longKeyPageArray and search for a page.
- for (; tglkLongIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; tglkLongIndex++) {
- jam();
- glkPageptr.i = fragrecptr.p->longKeyPageArray[tglkLongIndex];
-
- if (glkPageptr.i != RNIL) {
- // A page is found.
- jam();
- do {
- ptrCheckGuard(glkPageptr, cpagesize, page8);
- glkPage = (LongKeyPage *) &glkPageptr.p->word32[0];
-
- // Check page if there is enough memory available. Accept only page
- // with free_area > tupkeylen, this leaves at least one word for eventually
- // an increase in the index area.
- if (glkPage->header.freeArea > operationRecPtr.p->tupkeylen){
- // The page found is OK
- jam();
- return;
- } else {
- // Not enough space in page, look in the next page if not RNIL,
- // otherwise continue with for-loop.
- jam();
- glkPageptr.i = glkPage->header.nextPage;
- }
- }//do
- while (glkPageptr.i != RNIL);
- }//if
- }//for
-
- // No page with enough space was available, allocate a new page!
- jam();
- allocLongOverflowPage(signal);
- glkPageptr = alpPageptr;
-}//Dbacc::getLongKeyPage()
-
-/* --------------------------------------------------------------------------------- */
-/* INIT_LONG_OVERPAGE */
-/* INPUT. ILO_PAGEPTR, POINTER TO AN OVERFLOW PAGE RECORD */
-/* DESCRIPTION: CONTAINERS AND FREE LISTS OF THE PAGE, GET INITIALE VALUE */
-/* ACCORDING TO LH3 AND PAGE STRUCTOR DISACRIPTION OF NDBACC BLOCK */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::initLongOverpage(Signal* signal)
-{
- iloPageptr.p->word32[ZPOS_PAGE_ID] = tiloIndex;
- iloPageptr.p->word32[ZPOS_PAGE_TYPE] = ZLONG_PAGE_TYPE << ZPOS_PAGE_TYPE_BIT;
- iloPageptr.p->word32[ZPOS_NO_ELEM_IN_PAGE] = 0;
- iloPageptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- iloPageptr.p->word32[ZPOS_FREE_AREA_IN_PAGE] = ZWORDS_IN_PAGE - ZHEAD_SIZE;
- iloPageptr.p->word32[ZPOS_LAST_INDEX] = 0;
- iloPageptr.p->word32[ZPOS_INSERT_INDEX] = ZHEAD_SIZE;
- iloPageptr.p->word32[ZPOS_ARRAY_POS] = ZDEFAULT_LIST;
- iloPageptr.p->word32[ZPOS_NEXT_FREE_INDEX] = 0;
- iloPageptr.p->word32[ZPOS_NEXT_PAGE] = RNIL;
- iloPageptr.p->word32[ZPOS_PREV_PAGE] = RNIL;
- iloPageptr.p->word32[12] = 0;
- iloPageptr.p->word32[13] = 0;
- iloPageptr.p->word32[14] = 0;
- iloPageptr.p->word32[15] = 0;
- // Initialize free indexes
- for (int i = 1; i < (ZWORDS_IN_PAGE - ZHEAD_SIZE); i++)
- iloPageptr.p->word32[ZWORDS_IN_PAGE - i] = i + 1;
-}//Dbacc::initLongOverpage()
-
-//---------------------------------------------------------------------------------
-// STORE_LONG_KEYS_AT_POS
-//
-// INPUT: SLKAP_PAGEPTR
-// SLKAP_COPY_PAGEPTR
-// TSLKAP_KEY_LEN
-// TSLKAP_PAGE_INDEX
-//
-// DESCRIPTION: A LONG ELEMENT IS STORED ON A LONG_KEY_PAGE AT A
-// SPECIFIC POSITION. THIS FUNCTION IS USED BY UNDO_DELETE.
-//---------------------------------------------------------------------------------
-void Dbacc::storeLongKeysAtPos(Signal* signal)
-{
- Uint32 tslkapHighestIndex;
- Uint32 tslkapLastSize;
- Uint32 tslkapInsertIndex;
- Uint32 tslkapIndexIncreaseSize;
- Uint32 tslkapTmp;
-
- LongKeyPage *slkapPage;
-
- jam();
- slkapPage = (LongKeyPage *) &slkapPageptr.p->word32[0];
-
-#ifdef VM_TRACE
- checkIndexInLongKeyPage(slkapPageptr.i, "storeLongKeysAtPos");
-#endif
-
- // if (csystemRestart != ZTRUE) {
- if (cundoLogActive != ZTRUE) {
- //-------------------------------------------------------------
- // This function is only allowed to be called during
- // undolog execution.
- //-------------------------------------------------------------
- jam();
- sendSystemerror(signal);
- return;
- }
-
- if (slkapPage->word32[ZWORDS_IN_PAGE - tslkapPageIndex] >> 16 != 0 ) {
- //-------------------------------------------------------------
- // The index should be empty, we have a serious problem.
- //-------------------------------------------------------------
- jam();
- sendSystemerror(signal);
- return;
- }
-
- //-------------------------------------------------------------
- // Calculate some variables to use later.
- //-------------------------------------------------------------
- tslkapHighestIndex = slkapPage->header.highestIndex;
- tslkapPageIndex > tslkapHighestIndex ?
- tslkapIndexIncreaseSize = tslkapPageIndex - tslkapHighestIndex :
- tslkapIndexIncreaseSize = 0;
-
- slkapPage->header.highestIndex += tslkapIndexIncreaseSize;
-
- if ((slkapPage->header.freeArea - tslkapIndexIncreaseSize)
- < tslkapKeyLen) {
- //-------------------------------------------------------------
- // Not enough area in the page, a serious problem.
- //-------------------------------------------------------------
- jam();
- sendSystemerror(signal);
- return;
- }
-
- //-------------------------------------------------------------
- // Fix the free index list. We might put in a key in the
- // middle of the list, so we must fix the free list and the
- // free index pointers.
- //-------------------------------------------------------------
- slkapPage->header.nextFreeIndex = 0;
-
- for (Uint32 i = tslkapHighestIndex + tslkapIndexIncreaseSize; i > 0; i--) {
- if (i == tslkapPageIndex) {
- // The key index shall not be in the free list.
- continue;
- }
-
- if (slkapPage->word32[ZWORDS_IN_PAGE - i] >> 16 == 0 ) {
- // Go through all empty indexes.
- slkapPage->word32[ZWORDS_IN_PAGE - i] = slkapPage->header.nextFreeIndex;
- arrGuard(i, 2048);
- slkapPage->header.nextFreeIndex = i;
- }
- }
-
- //-------------------------------------------------------------
- // Decrement the free area in page according to the above
- // increase in index size.
- //-------------------------------------------------------------
- slkapPage->header.freeArea -= tslkapIndexIncreaseSize;
-
- tslkapLastSize = ZWORDS_IN_PAGE - slkapPage->header.highestIndex
- - slkapPage->header.insertPos;
-
- //-------------------------------------------------------------
- // Check if we have to reorganize the page.
- //-------------------------------------------------------------
- if (tslkapLastSize >= tslkapKeyLen) {
- jam();
- } else {
- jam();
- relpPageptr.p = slkapPageptr.p;
- reorgLongPage(signal);
- }
-
- //-------------------------------------------------------------
- // Insert the key and update page attributes.
- //-------------------------------------------------------------
- jam();
- // Increase the number of element in the page.
- slkapPage->header.noOfElements++;
- jam();
- // Put in the key reference into the index. The reference
- // consists of key length and insert position.
- arrGuard(ZWORDS_IN_PAGE - tslkapPageIndex, 2048);
- slkapPage->word32[ZWORDS_IN_PAGE - tslkapPageIndex] =
- slkapPage->header.insertPos | (tslkapKeyLen << 16);
- jam();
- // Increase the key insert position.
- tslkapInsertIndex = slkapPage->header.insertPos;
- slkapPage->header.insertPos += tslkapKeyLen;
- jam();
- // Decrease the free area.
- slkapPage->header.freeArea -= tslkapKeyLen;
- jam();
-
- // Update pageArrayPos. insertPageArrayList() called from execACC_OVER_REC
- // needs this value.
- if (slkapPage->header.freeArea < 128) {
- jam();
- slkapPage->header.pageArrayPos = 4;
- } else {
- jam();
- slkapPage->header.pageArrayPos = (slkapPage->header.freeArea - 128) / 512;
- }//if
-
- // Store the actual key at the insert position.
- Uint32 guard27 = tslkapKeyLen - 1;
- arrGuard(guard27 + tslkapInsertIndex, 2048);
- for (tslkapTmp = 0; tslkapTmp <= guard27; tslkapTmp++) {
- jam();
- slkapPage->word32[tslkapTmp + tslkapInsertIndex] = slkapCopyPageptr.p->word32[tslkapTmp];
- }//for
-}//Dbacc::storeLongKeysAtPos
-
-/* --------------------------------------------------------------------------------- */
-/* STORE_LONG_KEYS */
-/* INPUT: SLK_PAGEPTR */
-/* SLK_COPY_PAGEPTR */
-/* TSLK_KEY_LEN */
-/* OUTPUT: TSLK_PAGE_INDEX */
-/* */
-/* DESCRIPTION: A LONG ELEMENT IS STORED ON A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::storeLongKeys(Signal* signal)
-{
- Uint32 tslkLastSize;
- Uint32 tslkInsertIndex;
- Uint32 tslkArrayPos;
- Uint32 tslkTmp;
- Uint32 guard27;
- LongKeyPage *slkPage;
-
- jam();
- slkPage = (LongKeyPage *) &slkPageptr.p->word32[0];
-
-#ifdef VM_TRACE
- checkIndexInLongKeyPage(slkPageptr.i, "storeLongKeys1");
-#endif
-
- // Accept only page with free_area > tupkeylen, this leaves at least
- // one word for eventually an increase in the index area.
- ndbrequire(slkPage->header.freeArea > tslkKeyLen);
-
- dbgWord32(slkPageptr, ZPOS_LAST_INDEX, slkPage->header.highestIndex);
- dbgWord32(slkPageptr, ZPOS_INSERT_INDEX, slkPage->header.insertPos);
-
- tslkLastSize = ZWORDS_IN_PAGE - slkPage->header.highestIndex - slkPage->header.insertPos;
-
- if (tslkLastSize > operationRecPtr.p->tupkeylen) {
- // WE DO NOT NEED TO REORGANIZE THE PAGE TO INSERT THE NEW KEY. IT FITS INTO THE
- // SIZE REMAINING AT THE END.
- jam();
- } else {
- // THE KEY FITS INTO THE PAGE BUT ONLY AFTER REORGANISING THE PAGE.
- jam();
- relpPageptr.p = slkPageptr.p;
- reorgLongPage(signal);
- }//if
-
- if (slkPage->header.nextFreeIndex == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE INDEX HAS NO EMPTY SLOTS. WE MUST EXTEND THE PAGE INDEX BY ONE NEW SLOT.*/
- /* --------------------------------------------------------------------------------- */
- tslkPageIndex = slkPage->header.highestIndex + 1;
- } else {
- jam();
- tslkPageIndex = slkPage->header.nextFreeIndex;
- }//if
-
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* ON LONG PAGES WE USE A PHYSIOLOGICAL LOGGING SCHEME. THIS MEANS THAT WE ONLY NEED*/
- /* TO SPECIFY WHICH INDEX TO DELETE IN ORDER TO UNDO THE CHANGES WE DO. THE */
- /* POSSIBLE REORGANISATION DO NOT CHANGE THE LOGICAL LAYOUT OF THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- datapageptr.p = slkPageptr.p;
- cundoElemIndex = tslkPageIndex;
- cundoinfolength = 0;
- undoWritingProcess(signal);
- }//if
-
- if (slkPage->header.nextFreeIndex == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE INDEX HAS NO EMPTY SLOTS. WE MUST EXTEND THE PAGE INDEX BY ONE NEW SLOT.*/
- /* --------------------------------------------------------------------------------- */
- dbgWord32(slkPageptr, ZPOS_LAST_INDEX, slkPage->header.highestIndex + 1);
- slkPage->header.highestIndex++;
- ndbrequire(slkPage->header.insertPos < (ZWORDS_IN_PAGE - slkPage->header.highestIndex));
- // Reset index. We have already checked that we can increase "highestIndex" value
- // without overwriting the data part.
- slkPage->word32[ZWORDS_IN_PAGE - slkPage->header.highestIndex] = 0;
- dbgWord32(slkPageptr, ZPOS_FREE_AREA_IN_PAGE, slkPage->header.freeArea - 1);
- slkPage->header.freeArea--;
- } else {
- jam();
- dbgWord32(slkPageptr, ZPOS_NEXT_FREE_INDEX, slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex]);
- arrGuard(ZWORDS_IN_PAGE - tslkPageIndex, 2048);
- arrGuard(slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex], 2048);
-
- slkPage->header.nextFreeIndex = slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex];
- if(slkPage->header.nextFreeIndex > slkPage->header.highestIndex){
- slkPage->header.nextFreeIndex = 0;
- dbgWord32(slkPageptr, ZPOS_NEXT_FREE_INDEX, slkPage->header.nextFreeIndex);
- }
- }//if
-
- dbgWord32(slkPageptr, ZWORDS_IN_PAGE - tslkPageIndex, tslkKeyLen);
- dbgWord32(slkPageptr, ZWORDS_IN_PAGE - tslkPageIndex, slkPage->header.insertPos);
- arrGuard(ZWORDS_IN_PAGE - tslkPageIndex, 2048);
- slkPage->word32[ZWORDS_IN_PAGE - tslkPageIndex] =
- slkPage->header.insertPos | (tslkKeyLen << 16);
-
- dbgWord32(slkPageptr, ZPOS_INSERT_INDEX, slkPage->header.insertPos);
- tslkInsertIndex = slkPage->header.insertPos;
- slkPage->header.insertPos += tslkKeyLen;
-
- dbgWord32(slkPageptr, ZPOS_FREE_AREA_IN_PAGE, slkPage->header.freeArea - tslkKeyLen);
- slkPage->header.freeArea = slkPage->header.freeArea - tslkKeyLen;
- if (slkPage->header.freeArea < 128) {
- jam();
- tslkArrayPos = 4;
- } else {
- jam();
- tslkArrayPos = (slkPage->header.freeArea - 128) / 512;
- }//if
-
- if (tslkArrayPos != slkPage->header.pageArrayPos) {
- jam();
- if (cundoLogActive != ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE ONLY HANDLE THE LISTS WHEN WE ARE NOT IN A SYSTEM RESTART. */
- /* --------------------------------------------------------------------------------- */
- rfpPageptr = slkPageptr;
- trfpArrayPos = slkPage->header.pageArrayPos;
- removeFromPageArrayList(signal);
- ipaPagePtr = slkPageptr;
- tipaArrayPos = tslkArrayPos;
- slkPage->header.pageArrayPos = tipaArrayPos;
- if (tslkArrayPos != 4) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE WILL STILL BE ON ONE OF THE FREE LISTS SINCE AT LEAST 128 * 4 */
- /* BYTES OF FREE SPACE REMAINS ON THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- insertPageArrayList(signal);
- }//if
- } else {
- // This should never happen. Should use storeLongKeysAtPos() instead when executing
- // undolog.
- ndbrequire(false);
- }
- }//if
- /* --------------------------------------------------------------------------------- */
- /* INCREASE THE NUMBER OF ELEMENTS IN THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(slkPageptr, ZPOS_NO_ELEM_IN_PAGE, slkPage->header.noOfElements + 1);
- slkPage->header.noOfElements++;
-
- guard27 = tslkKeyLen - 1;
- arrGuard(guard27 + tslkInsertIndex, 2048);
- for (tslkTmp = 0; tslkTmp <= guard27; tslkTmp++) {
- dbgWord32(slkPageptr, tslkTmp + tslkInsertIndex, slkCopyPageptr.p->word32[tslkTmp]);
- slkPage->word32[tslkTmp + tslkInsertIndex] = slkCopyPageptr.p->word32[tslkTmp];
- }//for
-
- // Used by abortoperation() in case of an abort.
- operationRecPtr.p->longPagePtr = slkPageptr.i;
-
- // This is for an eventual LCP start in the middle of this locked operation.
- operationRecPtr.p->longKeyPageIndex = tslkPageIndex;
-
-#ifdef VM_TRACE
- if (cundoLogActive != ZTRUE) checkPageArrayList(signal, "storeLongKeys");
- checkIndexInLongKeyPage(slkPageptr.i, "storeLongKeys2");
-#endif
-
-}//Dbacc::storeLongKeys()
-
-/* --------------------------------------------------------------------------------- */
-/* REORGANIZE THE PAGE BY COPYING IT TEMPORARILY TO A NEW AREA AND THEN SIMPLY */
-/* PUTTING THE OBJECTS BACK ON THE PAGE IN THE SAME ORDER AS THEY ARE PLACED IN THE */
-/* INDEX. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::reorgLongPage(Signal* signal)
-{
- Uint32 indexStartPos;
- Uint32 pagePos;
- Uint32 pagePos2;
- Uint32 indexNo;
- Uint32 insertPos;
- Uint32 indexValue;
- Uint32 keyLength;
- Uint32 keyPos;
- Uint32 keyEndPos;
- LongKeyPage *reOrgPage;
-
- ptrGuard(relpPageptr);
- reOrgPage = (LongKeyPage *) &relpPageptr.p->word32[0];
-
- dbgWord32(relpPageptr, ZPOS_LAST_INDEX, reOrgPage->header.highestIndex);
- indexStartPos = ZWORDS_IN_PAGE - reOrgPage->header.highestIndex;
-
- // Copy key data part of page to a temporary page.
- for (pagePos = ZHEAD_SIZE; pagePos < indexStartPos; pagePos++) {
- jam();
- arrGuard(pagePos, 2048);
- ckeys[pagePos] = reOrgPage->word32[pagePos];
- }//for
-
- insertPos = ZHEAD_SIZE;
-
- // Walk through all the indexes.
- for (indexNo = 1; indexNo <= reOrgPage->header.highestIndex; indexNo++) {
- jam();
- arrGuard(ZWORDS_IN_PAGE - indexNo, 2048);
- dbgWord32(relpPageptr, ZWORDS_IN_PAGE - indexNo, reOrgPage->word32[ZWORDS_IN_PAGE - indexNo]);
- indexValue = reOrgPage->word32[ZWORDS_IN_PAGE - indexNo];
-
- if ((indexValue >> 16) != 0) {
- // The index contains a reference to a key.
- jam();
- keyPos = indexValue & 0xffff;
- keyLength = indexValue >> 16;
- dbgWord32(relpPageptr, ZWORDS_IN_PAGE - indexNo, insertPos + (keyLength << 16));
- arrGuard(ZWORDS_IN_PAGE - indexNo, 2048);
-
- // Refresh the index data with the new key start position in the data part.
- reOrgPage->word32[ZWORDS_IN_PAGE - indexNo] = insertPos + (keyLength << 16);
- keyEndPos = keyPos + keyLength;
- arrGuard(keyEndPos, 2048);
-
- // Copy the key from the temporary page
- // to the insert position at original page.
- for (pagePos2 = keyPos; pagePos2 < keyEndPos; pagePos2++, insertPos++) {
- jam();
- dbgWord32(relpPageptr, insertPos, ckeys[pagePos2]);
- arrGuard(insertPos, 2048);
- arrGuard(pagePos2, 2048);
- reOrgPage->word32[insertPos] = ckeys[pagePos2];
- }//for
- }//if
- }//for
- dbgWord32(relpPageptr, ZPOS_INSERT_INDEX, insertPos);
- reOrgPage->header.insertPos = insertPos;
-}//Dbacc::reorgLongPage()
-
-
-/* --------------------------------------------------------------------------------- */
-/* DELETE_LONG_KEY */
-/* INPUT: DLK_PAGEPTR PAGE POINTER OF DELETED KEY OBJECT */
-/* TDLK_LOGICAL_PAGE_INDEX LOGICAL PAGE INDEX OF DELETED KEY OBJECT */
-/* */
-/* DESCRIPTION: DELETE AN ELEMENT OF A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::deleteLongKey(Signal* signal)
-{
- Uint32 tdlkLastIndex;
- Uint32 tdlkNextPosition;
- Uint32 tdlkFreeArea;
- Uint32 tdlkArrayPos;
- Uint32 tdlkOldArrayPos;
- LongKeyPage *dlkPage;
-
- jam();
- dlkPage = (LongKeyPage *) &dlkPageptr.p->word32[0];
-
-#ifdef VM_TRACE
- checkIndexInLongKeyPage(dlkPageptr.i, "deleteLongKey1");
-#endif
-
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] >> 16);
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] & 0xffff);
- arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048);
-
- const Uint32 tdlkIndexValue = dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex];
- const Uint32 tdlkKeyLen = tdlkIndexValue >> 16;
- const Uint32 tdlkPhysPageIndex = tdlkIndexValue & 0xffff;
-
- if (fragrecptr.p->createLcp == ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE LOG THE DELETE LONG KEY BY LOGGING THE DELETED KEY AND ITS LOGICAL INDEX.*/
- /* --------------------------------------------------------------------------------- */
- datapageptr.p = dlkPageptr.p;
- cundoElemIndex = tdlkLogicalPageIndex;
- cundoinfolength = tdlkKeyLen;
- undoWritingProcess(signal);
- }//if
- /* --------------------------------------------------------------------------------- */
- /* DECREASE THE NUMBER OF ELEMENTS IN THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_NO_ELEM_IN_PAGE, dlkPage->header.noOfElements - 1);
- dlkPage->header.noOfElements--;
-
- arrGuard(dlkPage->header.noOfElements, ZMAX_NO_OF_LONGKEYS_IN_PAGE);
-
- /* --------------------------------------------------------------------------------- */
- /* INCREASE THE FREE AREA IN THE PAGE. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_FREE_AREA_IN_PAGE, dlkPage->header.freeArea + tdlkKeyLen);
- dbgWord32(dlkPageptr, ZPOS_LAST_INDEX, dlkPage->header.highestIndex);
-
- dlkPage->header.freeArea += tdlkKeyLen;
-
- if (dlkPage->header.noOfElements == 0) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE IS NOW EMPTY, WE CAN RELEASE IT. */
- /* --------------------------------------------------------------------------------- */
- if (dlkPage->header.freeArea !=
- (ZWORDS_IN_PAGE - ZHEAD_SIZE - dlkPage->header.highestIndex )) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* SOME AREA IN THE PAGE IS STILL LEFT BUT NO ELEMENTS, INCONSISTENT */
- /* --------------------------------------------------------------------------------- */
- sendSystemerror(signal);
- }//if
- /* --------------------------------------------------------------------------------- */
- /* WE REMOVE THE PAGE FROM THE LIST OF FREE LONG PAGES. THERE IS NO RISK THAT IT */
- /* DID NOT BELONG TO ANY SINCE IT IS NOT ALLOWED TO HAVE THAT LARGE KEYS. */
- /* --------------------------------------------------------------------------------- */
-
- if (cundoLogActive != ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WHEN DELETING KEYS DURING SYSTEM RESTART WE NEED NOT UPDATE THE LISTS. */
- /* --------------------------------------------------------------------------------- */
- // REMOVEFROMLIST is done by releaseLongPage(). EDTJAMO.
- // rfpPageptr = dlkPageptr;
- // trfpArrayPos = dlkPage->header.pageArrayPos;
- // removeFromPageArrayList(signal, "deleteLongKey");
- rlopPageptr = dlkPageptr;
- releaseLongPage(signal);
- return;
- } else {
- // Must remove reference to the removed key, otherwise left in index. EDTJAMO.
- arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048);
- arrGuard(tdlkLogicalPageIndex, 2048);
-
- tdlkNextPosition = dlkPage->header.nextFreeIndex;
- dlkPage->header.nextFreeIndex = tdlkLogicalPageIndex;
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, tdlkNextPosition);
- dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] = tdlkNextPosition;
- }
- } else {
- /* --------------------------------------------------------------------------------- */
- /* THE PAGE IS NOT EMPTY SO WE WILL REMOVE THE KEY OBJECT AND UPDATE THE */
- /* HEADER INFORMATION AND PLACE THE PAGE IN THE PROPER PAGE LIST. */
- /* --------------------------------------------------------------------------------- */
- tdlkLastIndex = dlkPage->header.highestIndex;
- arrGuard(ZWORDS_IN_PAGE - tdlkLastIndex, 2048);
- if (tdlkLastIndex == tdlkLogicalPageIndex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE DELETE THE LAST PAGE INDEX SO WE NEED TO UPDATE THE VALUE. WE MOVE */
- /* BACKWARDS UNTIL WE EITHER FIND A USED INDEX OR THAT WE COME TO INDEX ZERO. */
- /* --------------------------------------------------------------------------------- */
- tdlkLastIndex--;
- while( (tdlkLastIndex > 1) &&
- (dlkPage->word32[ZWORDS_IN_PAGE - tdlkLastIndex] >> 16) == 0 ) {
- jam();
- tdlkLastIndex--;
- }
- //-----------------------------------------------------
- // Reorganize the rest of the index. Set up the free
- // list and the free index.
- //-----------------------------------------------------
- UintR dlkTmp = tdlkLastIndex;
- dlkPage->header.nextFreeIndex = 0;
- while( dlkTmp > 0) {
- if ( (dlkPage->word32[ZWORDS_IN_PAGE - dlkTmp] >> 16) == 0 ) {
- jam();
- dlkPage->word32[ZWORDS_IN_PAGE - dlkTmp] = dlkPage->header.nextFreeIndex;
- arrGuard(dlkTmp, 2048);
- dlkPage->header.nextFreeIndex = dlkTmp;
- }
- dlkTmp--;
- }
- //-----------------------------------------------------
- // Update free area in page and last index.
- //-----------------------------------------------------
- dbgWord32(dlkPageptr, ZPOS_LAST_INDEX, tdlkLastIndex);
- dlkPage->header.highestIndex = tdlkLastIndex;
- dlkPage->header.freeArea = tdlkLogicalPageIndex +
- dlkPage->header.freeArea - tdlkLastIndex;
- tdlkNextPosition = 0;
- } else {
- if (dlkPage->header.highestIndex > tdlkLogicalPageIndex) {
- jam();
- tdlkNextPosition = dlkPage->header.nextFreeIndex;
- dbgWord32(dlkPageptr, ZPOS_NEXT_FREE_INDEX, tdlkLogicalPageIndex);
- arrGuard(tdlkLogicalPageIndex, 2048);
- dlkPage->header.nextFreeIndex = tdlkLogicalPageIndex;
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* LOGICAL PAGE INDEX LARGER THAN LARGEST INDEX, INCONSISTENT. */
- /* --------------------------------------------------------------------------------- */
- sendSystemerror(signal);
- return; // Just to keep compiler happy
- }//if
- }//if
- /* --------------------------------------------------------------------------------- */
- /* WE INSERT ZERO INTO THE LENGTH PART TO INDICATE A FREE INDEX POSITION. */
- /* WE INSERT A POINTER TO THE NEXT FREE INDEX TO AS TO PUT IT INTO A FREE */
- /* LIST OF INDEX POSITIONS. WE ONLY DO SO IF IT WAS NOT THE LAST INDEX. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZWORDS_IN_PAGE - tdlkLogicalPageIndex, tdlkNextPosition);
- arrGuard(ZWORDS_IN_PAGE - tdlkLogicalPageIndex, 2048);
- dlkPage->word32[ZWORDS_IN_PAGE - tdlkLogicalPageIndex] = tdlkNextPosition;
- if (dlkPage->header.insertPos == (tdlkPhysPageIndex + tdlkKeyLen)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THIS ENTRY IS THE LAST ON THE PAGE SO WE WILL UPDATE THE INSERT INDEX */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_INSERT_INDEX, tdlkPhysPageIndex);
- dlkPage->header.insertPos = tdlkPhysPageIndex;
- }//if
- }//if
- dbgWord32(dlkPageptr, ZPOS_FREE_AREA_IN_PAGE, dlkPage->header.freeArea);
- tdlkFreeArea = dlkPage->header.freeArea;
- ndbrequire(tdlkFreeArea <= (ZWORDS_IN_PAGE - ZHEAD_SIZE));
- if (tdlkFreeArea < 128) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* FREE AREA IS STILL LESS THAN 128 WORDS SO IT SHOULD NOT BE PLACED IN ANY OF THE */
- /* FREE LISTS. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_ARRAY_POS, dlkPage->header.pageArrayPos);
- ndbrequire(dlkPage->header.pageArrayPos == 4);
- } else {
- jam();
- // Calculate an eventually new arraypos.
- dbgWord32(dlkPageptr, 0, (tdlkFreeArea - 128) / 512);
- tdlkArrayPos = (tdlkFreeArea - 128) / 512;
-
- if (cundoLogActive != ZTRUE) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WHEN DELETING KEYS DURING SYSTEM RESTART WE NEED NOT UPDATE THE LISTS. */
- /* --------------------------------------------------------------------------------- */
- dbgWord32(dlkPageptr, ZPOS_ARRAY_POS, dlkPage->header.pageArrayPos);
- tdlkOldArrayPos = dlkPage->header.pageArrayPos;
- if (tdlkArrayPos != tdlkOldArrayPos) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THE NEW MEMORY AREA HAS ENABLED THE PAGE TO MOVE TO A NEW FREE PAGE LIST */
- /* --------------------------------------------------------------------------------- */
- rfpPageptr = dlkPageptr;
- trfpArrayPos = tdlkOldArrayPos;
- if (tdlkOldArrayPos != 4) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THERE WAS A FREE PAGE LIST TO REMOVE THE PAGE FROM. IF FREE SPACE IS LESS THAN */
- /* 128 BYTES THEN IT IS NOT ON ANY FREE LIST. */
- /* --------------------------------------------------------------------------------- */
- removeFromPageArrayList(signal);
- }//if
- dlkPage->header.pageArrayPos = tdlkArrayPos;
- ipaPagePtr = dlkPageptr;
- tipaArrayPos = tdlkArrayPos;
- insertPageArrayList(signal);
- }//if
- } else {
- // Update pageArrayPos. We are in a SR, executing undolog, insertPageArrayList() called
- // from execACC_OVER_REC needs this value later.
- dlkPage->header.pageArrayPos = tdlkArrayPos;
- }
- }//if
-#ifdef VM_TRACE
- if (cundoLogActive != ZTRUE) checkPageArrayList(signal, "deleteLongKey");
- checkIndexInLongKeyPage(dlkPageptr.i, "deleteLongKey2");
-#endif
-}//Dbacc::deleteLongKey()
-
-
-void Dbacc::checkIndexInLongKeyPage(Uint32 pageId, const char *calledFrom) {
- Page8Ptr pagePtr;
- LongKeyPage *page;
- Uint32 indexNo;
- Uint32 indexValue;
- Uint32 keyLength;
- Uint32 keyPos;
-
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- // Check the header variables.
- if (page->header.nextFreeIndex > 2048 ||
- page->header.highestIndex > 2048 ||
- page->header.insertPos > 2048 ||
- page->header.freeArea > 2048 ||
- page->header.noOfElements > 225) {
- ndbout << " ERROR in checkIndexInLongKeyPage, called from " << calledFrom << endl
- << " pagePtr.i = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
-
- // Walk through all the indexes.
- for (indexNo = 1; indexNo <= page->header.highestIndex; indexNo++) {
- jam();
- indexValue = page->word32[ZWORDS_IN_PAGE - indexNo];
-
- if ((indexValue >> 16) == 0) {
- ; // key length is 0, means no key reference at this position in index.
- } else {
- // The index contains a reference to a key.
- jam();
- keyPos = indexValue & 0xffff;
- keyLength = indexValue >> 16;
- if (keyPos >= ZWORDS_IN_PAGE || keyLength >= ZWORDS_IN_PAGE) {
- jam();
- ndbout << " ERROR in checkIndexInLongKeyPage, called from " << calledFrom << endl
- << " keyPos = " << keyPos << endl
- << " keyLength = " << keyLength << endl
- << " page->header.noOfElements = " << page->header.noOfElements << endl
- << " page->header.freeArea = " << page->header.freeArea << endl
- << " indexNo = " << indexNo << endl
- << " page->header.highestIndex = " << page->header.highestIndex << endl;
- ndbrequire(false);
- }
- }
- }
-}//Dbacc::checkIndexInLongKeyPage
-
-
-/* --------------------------------------------------------------------------------- */
-/* REMOVE A PAGE FROM THE PAGE ARRAY LIST. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::removeFromPageArrayList(Signal* signal)
-{
- Page8Ptr rfpPrevPageptr;
- Page8Ptr rfpNextPageptr;
- LongKeyPage *page;
- LongKeyPage *prevPage;
- LongKeyPage *nextPage;
-
- jam();
-
-#ifdef VM_TRACE
- checkPageB4Remove(rfpPageptr.i, "removeFromPageArrayList");
-#endif
-
- page = (LongKeyPage *) &rfpPageptr.p->word32[0];
-
- if (page->header.prevPage == RNIL) {
- jam();
- arrGuard(trfpArrayPos, 4);
- // This page was first in list, remove reference
- // to this page from the start of the list.
- ndbrequire(fragrecptr.p->longKeyPageArray[trfpArrayPos] == rfpPageptr.i);
- fragrecptr.p->longKeyPageArray[trfpArrayPos] = page->header.nextPage;
- } else {
- jam();
- rfpPrevPageptr.i = page->header.prevPage;
- ptrCheckGuard(rfpPrevPageptr, cpagesize, page8);
- prevPage = (LongKeyPage *) &rfpPrevPageptr.p->word32[0];
- // This page wasn't first in list, remove reference
- // to this page from the previous page.
- ndbrequire(prevPage->header.nextPage == rfpPageptr.i);
- prevPage->header.nextPage = page->header.nextPage;
- }//if
-
- if (page->header.nextPage != RNIL) {
- jam();
- rfpNextPageptr.i = page->header.nextPage;
- ptrCheckGuard(rfpNextPageptr, cpagesize, page8);
- nextPage = (LongKeyPage *) &rfpNextPageptr.p->word32[0];
- // This page wasn't last in list, remove reference
- // to this page from the next page.
- ndbrequire(nextPage->header.prevPage == rfpPageptr.i);
- nextPage->header.prevPage = page->header.prevPage;
- // Remove reference to next page in list.
- page->header.nextPage = RNIL;
- }//if
-
- // This couldn't be set until now.
- // Remove reference to previous page in list.
- page->header.prevPage = RNIL;
-
-#ifdef VM_TRACE
- checkPageArrayList(signal, "removeFromPageArrayList");
-#endif
-}//Dbacc::removeFromPageArrayList()
-
-/* --------------------------------------------------------------------------------- */
-/* INSERT A PAGE INTO THE PAGE ARRAY LIST. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::insertPageArrayList(Signal* signal)
-{
- Page8Ptr ipaNextPagePtr;
- LongKeyPage *page;
- LongKeyPage *nextPage;
-
- jam();
-
-#ifdef VM_TRACE
- checkPageArrayList(signal, "insertPageArrayList1");
- checkPageB4Insert(ipaPagePtr.i, "insertPageArrayList1");
-#endif
-
- page = (LongKeyPage *) &ipaPagePtr.p->word32[0];
-
- arrGuard(tipaArrayPos, 4);
-
- if (fragrecptr.p->longKeyPageArray[tipaArrayPos] != RNIL) {
- jam();
- ipaNextPagePtr.i = fragrecptr.p->longKeyPageArray[tipaArrayPos];
- ptrCheckGuard(ipaNextPagePtr, cpagesize, page8);
- nextPage = (LongKeyPage *) &ipaNextPagePtr.p->word32[0];
-
- // A page already existed in the list, add reference
- // to this page in the next page.
- nextPage->header.prevPage = ipaPagePtr.i;
- }//if
-
- page->header.prevPage = RNIL;
- page->header.nextPage = fragrecptr.p->longKeyPageArray[tipaArrayPos];
- page->header.pageArrayPos = tipaArrayPos;
-
- fragrecptr.p->longKeyPageArray[tipaArrayPos] = ipaPagePtr.i;
-
-#ifdef VM_TRACE
- checkPageArrayList(signal, "insertPageArrayList2");
-#endif
-}//Dbacc::insertPageArrayList()
-
-// --------------------------------------------------------------------------------- */
-// Check the page array list.
-// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageArrayList(Signal* signal, const char *calledFrom)
-{
- Page8Ptr pagePtr;
- Uint32 pageArrayIndex;
- LongKeyPage *page;
- Uint32 prevPage;
-
- // Go through the longKeyPageArray and search for a page.
- for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) {
- jam();
- pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex];
- prevPage = RNIL;
-
- if (pagePtr.i != RNIL) {
- // A page is found.
- jam();
- do {
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- if ((page->header.freeArea >= 128) &&
- (((page->header.freeArea - 128) / 512) == page->header.pageArrayPos) &&
- (pageArrayIndex == page->header.pageArrayPos) &&
- (page->header.prevPage == prevPage)) {
- // The page found is OK, test next page.
- prevPage = pagePtr.i;
- pagePtr.i = page->header.nextPage;
- jam();
- } else {
- jam();
- ndbout << " ERROR in checkPageArrayList, called from " << calledFrom << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " prevPage = " << prevPage << endl
- << " pageArrayIndex = " << pageArrayIndex << endl;
- printoutInfoAndShutdown(page);
- }
- }//do
- while (pagePtr.i != RNIL);
- }//if
- }//for
-}//Dbacc::checkPageArrayList()
-
-// --------------------------------------------------------------------------------- */
-// Check the page to put into the pageArrayList.
-// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageB4Insert(Uint32 pageId, const char *calledFrom) {
- Page8Ptr pagePtr;
- Uint32 pageArrayIndex;
- LongKeyPage *page;
-
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- if ((page->header.nextPage != RNIL) ||
- (page->header.prevPage != RNIL)) {
- jam();
- ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " page->header.nextPage = " << page->header.nextPage << endl
- << " page->header.prevPage = " << page->header.prevPage << endl;
- ndbrequire(false);
- }
-
- // Page should not be inserted in list if free area is less than 512 byte.
- if (page->header.freeArea < 128) {
- jam();
- ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << " Page has to little free area to be in list." << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " tipaArrayPos = " << tipaArrayPos << endl;
- printoutInfoAndShutdown(page);
- }
-
- // Check if position in list is correct
- if ((((page->header.freeArea - 128) / 512) != page->header.pageArrayPos) ||
- (page->header.pageArrayPos != tipaArrayPos)) {
- ndbout << " ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << " Incorrect position in list." << endl
- << " pagePtr.i = " << pagePtr.i << endl
- << " tipaArrayPos = " << tipaArrayPos << endl;
- printoutInfoAndShutdown(page);
- }
-
- // Check if page is already in list.
- for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) {
- jam();
- pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex];
-
- if (pagePtr.i != RNIL) {
- // A page is found.
- jam();
- do {
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
- if (pagePtr.i == pageId) {
- jam();
- ndbout << "ERROR in checkPageB4Insert, called from " << calledFrom << endl
- << "Page exists already in list." << endl
- << " pagePtr.i = " << pagePtr.i << endl;
- printoutInfoAndShutdown(page);
- }
- pagePtr.i = page->header.nextPage;
- }//do
- while (pagePtr.i != RNIL);
- }//if
- }//for
-}//Dbacc::checkPageB4Insert()
-
-// --------------------------------------------------------------------------------- */
-// Check the page to remove from the pageArrayList.
-// --------------------------------------------------------------------------------- */
-void Dbacc::checkPageB4Remove(Uint32 pageId, const char *calledFrom) {
- Page8Ptr pagePtr;
- Uint32 pageArrayIndex;
- Uint32 noOfOccurrence = 0;
- Uint32 noOfPagesInList = 0;
- LongKeyPage *page;
-
- LongKeyPage *prevPage;
- LongKeyPage *nextPage;
- Page8Ptr rfpPrevPageptr;
- Page8Ptr rfpNextPageptr;
-
-
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
-
- // Check that page is in list.
- for (pageArrayIndex = 0; pageArrayIndex <= ZMAX_LONG_KEY_ARRAY_INDEX; pageArrayIndex++) {
- jam();
- pagePtr.i = fragrecptr.p->longKeyPageArray[pageArrayIndex];
-
- if (pagePtr.i != RNIL) {
- // A page is found.
- jam();
- do {
- noOfPagesInList++;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
- if (pagePtr.i == pageId) {
- // Check the consistent in list.
- if (page->header.prevPage != RNIL) {
- rfpPrevPageptr.i = page->header.prevPage;
- ptrCheckGuard(rfpPrevPageptr, cpagesize, page8);
- prevPage = (LongKeyPage *) &rfpPrevPageptr.p->word32[0];
- if (prevPage->header.nextPage != pageId) {
- ndbout << "ERROR: inconsistent in checkPageB4Remove, called from " << calledFrom << endl
- << "prevPage->header.nextPage = " << prevPage->header.nextPage << endl
- << "pageId = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
- }
- // Check the consistent in list.
- if (page->header.nextPage != RNIL) {
- rfpNextPageptr.i = page->header.nextPage;
- ptrCheckGuard(rfpNextPageptr, cpagesize, page8);
- nextPage = (LongKeyPage *) &rfpNextPageptr.p->word32[0];
- if (nextPage->header.prevPage != pageId) {
- ndbout << "ERROR: inconsistent in checkPageB4Remove, called from " << calledFrom << endl
- << "nextPage->header.prevPage = " << nextPage->header.prevPage << endl
- << "pageId = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
- }
- jam();
- noOfOccurrence++;
- }
- pagePtr.i = page->header.nextPage;
- }//do
- while (pagePtr.i != RNIL);
- }//if
- }//for
-
- if (noOfOccurrence != 1) {
- pagePtr.i = pageId;
- ptrCheckGuard(pagePtr, cpagesize, page8);
- page = (LongKeyPage *) &pagePtr.p->word32[0];
- ndbout << "ERROR in checkPageB4Remove, called from " << calledFrom << endl
- << "Page occur " << noOfOccurrence << " times in list" << endl
- << "pageId = " << pageId << endl;
- printoutInfoAndShutdown(page);
- }
-}//Dbacc::checkPageB4Remove()
-
-
-// --------------------------------------------------------------------------------- */
-// Printout an error message and shutdown node.
-// --------------------------------------------------------------------------------- */
-void Dbacc::printoutInfoAndShutdown(LongKeyPage *page) {
- ndbout << " page->header.pageArrayPos = " << page->header.pageArrayPos << endl
- << " ((page->header.freeArea - 128) / 512) = "
- << ((page->header.freeArea - 128) / 512) << endl
- << " page->header.freeArea = " << page->header.freeArea << endl
- << " page->header.noOfElements = " << page->header.noOfElements << endl
- << " page->header.nextPage = " << page->header.nextPage << endl
- << " page->header.prevPage = " << page->header.prevPage << endl
- << " page->header.nextFreeIndex = " << page->header.nextFreeIndex << endl
- << " page->header.insertPos = " << page->header.insertPos << endl
- << " page->header.highestIndex = " << page->header.highestIndex << endl
- << " page->header.pageId = " << page->header.pageId << endl;
- ndbrequire(false);
-}//Dbacc::printoutInfoAndShutdown()
-
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
@@ -4423,7 +3190,7 @@ void Dbacc::printoutInfoAndShutdown(LongKeyPage *page) {
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* */
-/* MODULE: READ */
+/* MODULE: GET_ELEMENT */
/* THE FOLLOWING SUBROUTINES ARE ONLY USED BY GET_ELEMENT AND */
/* GETDIRINDEX. THIS ROUTINE IS THE SOLE INTERFACE TO GET ELEMENTS */
/* FROM THE INDEX. CURRENT USERS ARE ALL REQUESTS AND EXECUTE UNDO LOG */
@@ -4484,6 +3251,20 @@ void Dbacc::getdirindex(Signal* signal)
ptrCheckGuard(gdiPageptr, cpagesize, page8);
}//Dbacc::getdirindex()
+void
+Dbacc::readTablePk(Uint32 localkey1)
+{
+ Uint32 tableId = fragrecptr.p->myTableId;
+ Uint32 fragId = fragrecptr.p->myfid;
+ Uint32 fragPageId = localkey1 >> MAX_TUPLES_BITS;
+ Uint32 pageIndex = localkey1 & ((1 << MAX_TUPLES_BITS ) - 1);
+#ifdef VM_TRACE
+ memset(ckeys, 0x1f, fragrecptr.p->keyLength << 2);
+#endif
+ int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, ckeys);
+ ndbrequire(ret == fragrecptr.p->keyLength);
+}
+
/* --------------------------------------------------------------------------------- */
/* GET_ELEMENT */
/* INPUT: */
@@ -4501,6 +3282,17 @@ void Dbacc::getdirindex(Signal* signal)
/* BUCKET, AND SERCH FOR ELEMENT.THE PRIMARY KEYS WHICH IS SAVED */
/* IN THE OPERATION REC ARE THE CHECK ITEMS IN THE SEARCHING. */
/* --------------------------------------------------------------------------------- */
+
+#if __ia64 == 1
+#if __INTEL_COMPILER == 810
+int ndb_acc_ia64_icc810_dummy_var = 0;
+void ndb_acc_ia64_icc810_dummy_func()
+{
+ ndb_acc_ia64_icc810_dummy_var++;
+}
+#endif
+#endif
+
void Dbacc::getElement(Signal* signal)
{
DirRangePtr geOverflowrangeptr;
@@ -4523,19 +3315,15 @@ void Dbacc::getElement(Signal* signal)
gePageptr = gdiPageptr;
tgeResult = ZFALSE;
tgeCompareLen = fragrecptr.p->keyLength;
- const Uint32 isAccLockReq = operationRecPtr.p->isAccLockReq;
- if (isAccLockReq) {
- jam();
- tgeCompareLen = 0;
- }
+ /*
+ * The value seached is
+ * - table key for ACCKEYREQ, stored in TUP
+ * - local key (1 word) for ACC_LOCKREQ and UNDO, stored in ACC
+ */
+ const bool searchLocalKey =
+ operationRecPtr.p->isAccLockReq || operationRecPtr.p->isUndoLogReq;
- // We can handle keylength up to 8, but not more (0 means dynamic)
- if (tgeCompareLen >= 9) {
- ACCKEY_error(2); return;
- }//if
- if (TelemLen < 3) {
- ACCKEY_error(3); return;
- }//if
+ ndbrequire(TelemLen == ZELEM_HEAD_SIZE + fragrecptr.p->localkeylen);
tgeNextptrtype = ZLEFT;
tgeLocked = 0;
@@ -4566,7 +3354,7 @@ void Dbacc::getElement(Signal* signal)
} else {
ACCKEY_error(6); return;
}//if
- if (tgeRemLen >= TelemLen) {
+ if (tgeRemLen >= ZCON_HEAD_SIZE + TelemLen) {
if (tgeRemLen > ZBUF_SIZE) {
ACCKEY_error(7); return;
}//if
@@ -4574,137 +3362,43 @@ void Dbacc::getElement(Signal* signal)
// There is at least one element in this container. Check if it is the element
// searched for.
/* --------------------------------------------------------------------------------- */
- if (tgeCompareLen != 0) {
- /* --------------------------------------------------------------------------------- */
- /* THIS PART IS USED TO SEARCH FOR KEYS WITH FIXED SIZE. THE LOOP TAKES CARE */
- /* OF SEARCHING THROUGH ALL ELEMENTS IN ONE CONTAINER. */
- /* --------------------------------------------------------------------------------- */
- do {
- register Uint32 TdataIndex = 0;
- register Uint32 TgeIndex = 0;
+ do {
+ tgeElementHeader = gePageptr.p->word32[tgeElementptr];
+ tgeRemLen = tgeRemLen - TelemLen;
+ Uint32 hashValuePart;
+ if (ElementHeader::getLocked(tgeElementHeader)) {
jam();
- tgeRemLen = tgeRemLen - TelemLen;
- do {
- if (gePageptr.p->word32[tgeKeyptr + TgeIndex] != Tkeydata[TdataIndex]) {
- goto compare_next;
- }//if
- TdataIndex++;
- TgeIndex += tgeForward;
- } while (TdataIndex < tgeCompareLen);
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE FOUND THE ELEMENT. GET THE LOCK INDICATOR AND RETURN FOUND. */
- /* --------------------------------------------------------------------------------- */
+ geTmpOperationRecPtr.i = ElementHeader::getOpPtrI(tgeElementHeader);
+ ptrCheckGuard(geTmpOperationRecPtr, coprecsize, operationrec);
+ hashValuePart = geTmpOperationRecPtr.p->hashvaluePart;
+ } else {
jam();
- tgeLocked = ElementHeader::getLocked(gePageptr.p->word32[tgeElementptr]);
- tgeResult = ZTRUE;
- TdataIndex = tgeElementptr + tgeForward;
- TgeIndex = TdataIndex + tgeForward;
- operationRecPtr.p->localdata[0] = gePageptr.p->word32[TdataIndex];
- operationRecPtr.p->localdata[1] = gePageptr.p->word32[TgeIndex];
- return;
- /* --------------------------------------------------------------------------------- */
- /* COMPARE NEXT ELEMENT */
- /* --------------------------------------------------------------------------------- */
- compare_next:
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }//if
- tgeKeyptr = tgeKeyptr + tgeElemStep;
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (1);
- } else if (! isAccLockReq) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* THIS PART IS USED TO SEARCH FOR KEYS WITH VARIABLE LENGTH OR FIXED LENGTH */
- /* GREATER THAN 32 BYTES. IN THIS CASE THE KEY PART IS STORED IN A SPECIAL */
- /* LONG PAGE PART AND THE HASH INDEX CONTAINS A REFERENCE TO THERE PLUS A */
- /* PART OF THE HASH VALUE. */
- /* --------------------------------------------------------------------------------- */
- do {
- tgeElementHeader = gePageptr.p->word32[tgeElementptr];
- tgeRemLen = tgeRemLen - TelemLen;
- Uint32 hashValuePart;
- if (ElementHeader::getLocked(tgeElementHeader)) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* IN THIS CASE THE HASH VALUE PART OF THE ELEMENT HEADER IS STORED IN THE */
- /* OPERATION THAT OWNS THE LOCK. IN THIS CASE WE MIGHT AS WELL GO AHEAD AND */
- /* CHECK THE KEY IN THE LONG PAGE. */
- /* --------------------------------------------------------------------------------- */
- geTmpOperationRecPtr.i =
- ElementHeader::getOpPtrI(tgeElementHeader);
- ptrCheckGuard(geTmpOperationRecPtr, coprecsize, operationrec);
- hashValuePart = geTmpOperationRecPtr.p->hashvaluePart;
+ hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader);
+ }
+ if (hashValuePart == opHashValuePart) {
+ jam();
+ Uint32 localkey1 = gePageptr.p->word32[tgeElementptr + tgeForward];
+ Uint32 localkey2 = 0;
+ bool found;
+ if (! searchLocalKey) {
+ readTablePk(localkey1);
+ found = (memcmp(Tkeydata, ckeys, fragrecptr.p->keyLength << 2) == 0);
} else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* IN THIS CASE THE HASH VALUE PART CAN BE CHECKED TO SEE IF THE HASH VALUE */
- /* GIVES US A REASON TO CONTINUE CHECKING THE FULL KEY. */
- /* --------------------------------------------------------------------------------- */
- hashValuePart = ElementHeader::getHashValuePart(tgeElementHeader);
- }//if
-
- if (hashValuePart == opHashValuePart) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* IF THE HASH VALUES ARE EQUAL THEN XOR-ING THEM WILL GIVE THE RESULT 0. */
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE FOUND A KEY WITH IDENTICAL HASH VALUE. MOST LIKELY WE HAVE FOUND THE*/
- /* ELEMENT BUT FIRST WE NEED TO PERFORM A KEY COMPARISON. */
- /* --------------------------------------------------------------------------------- */
- tslcPageIndex = gePageptr.p->word32[tgeKeyptr] & 0x3ff;
- tslcPagedir = gePageptr.p->word32[tgeKeyptr] >> 10;
- searchLongKey(signal);
- if (tslcResult == ZTRUE) {
- register Uint32 TlocData1, TlocData2;
- jam();
- /* --------------------------------------------------------------------------------- */
- /* WE HAVE FOUND THE ELEMENT. GET THE LOCK INDICATOR AND RETURN FOUND. */
- /* --------------------------------------------------------------------------------- */
- tgeLocked = ElementHeader::getLocked(tgeElementHeader);
- tgeResult = ZTRUE;
- TlocData1 = tgeElementptr + tgeForward;
- TlocData2 = TlocData1 + tgeForward;
- operationRecPtr.p->localdata[0] = gePageptr.p->word32[TlocData1];
- operationRecPtr.p->localdata[1] = gePageptr.p->word32[TlocData2];
- return;
- }//if
+ found = (localkey1 == Tkeydata[0]);
}
- /* --------------------------------------------------------------------------------- */
- /* COMPARE NEXT ELEMENT */
- /* --------------------------------------------------------------------------------- */
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }//if
- tgeKeyptr = tgeKeyptr + tgeElemStep;
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (1);
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* Search for local key in a lock request */
- /* --------------------------------------------------------------------------------- */
- do {
- tgeRemLen = tgeRemLen - TelemLen;
- // position of local key word 1
- Uint32 TdataIndex = tgeElementptr + tgeForward;
- // XXX assume localkeylen is 1
- if (gePageptr.p->word32[TdataIndex] == Tkeydata[0]) {
- jam();
- tgeLocked = ElementHeader::getLocked(gePageptr.p->word32[tgeElementptr]);
+ if (found) {
+ tgeLocked = ElementHeader::getLocked(tgeElementHeader);
tgeResult = ZTRUE;
- // position of local key word 2
- Uint32 TgeIndex = TdataIndex + tgeForward;
- operationRecPtr.p->localdata[0] = gePageptr.p->word32[TdataIndex];
- operationRecPtr.p->localdata[1] = gePageptr.p->word32[TgeIndex];
+ operationRecPtr.p->localdata[0] = localkey1;
+ operationRecPtr.p->localdata[1] = localkey2;
return;
- }//if
- if (tgeRemLen <= ZCON_HEAD_SIZE) {
- break;
- }//if
- tgeElementptr = tgeElementptr + tgeElemStep;
- } while (1);
- }//if
+ }
+ }
+ if (tgeRemLen <= ZCON_HEAD_SIZE) {
+ break;
+ }
+ tgeElementptr = tgeElementptr + tgeElemStep;
+ } while (true);
}//if
if (tgeRemLen != ZCON_HEAD_SIZE) {
ACCKEY_error(8); return;
@@ -4735,67 +3429,6 @@ void Dbacc::getElement(Signal* signal)
}//Dbacc::getElement()
/* --------------------------------------------------------------------------------- */
-/* SEARCH_LONG_KEY */
-/* INPUT: */
-/* TSLC_PAGEDIR PAGE DIRECTORY OF LONG PAGE */
-/* TSLC_PAGE_INDEX PAGE INDEX IN LONG PAGE */
-/* GE_OPERATION_REC_PTR */
-/* OUTPUT: */
-/* TSLC_RESULT */
-/* DESCRIPTION: SEARCH FOR AN ELEMENT IN A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::searchLongKey(Signal* signal)
-{
- DirRangePtr slcOverflowrangeptr;
- DirectoryarrayPtr slcOverflowDirptr;
- Page8Ptr slcPageptr;
- Uint32 tslcIndexValue;
- Uint32 tslcStartIndex;
- Uint32 tslcIndex;
- Uint32 guard30;
- Uint32* Tkeydata = (Uint32*)&signal->theData[7];
-
-
- slcOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(slcOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tslcPagedir >> 8), 256);
- slcOverflowDirptr.i = slcOverflowrangeptr.p->dirArray[tslcPagedir >> 8];
- ptrCheckGuard(slcOverflowDirptr, cdirarraysize, directoryarray);
-
- // dbgWord32(slcOverflowDirptr, (int) (tslcPagedir & 0xff), slcOverflowDirptr.p->pagep[tslcPagedir & 0xff]);
-
- slcPageptr.i = slcOverflowDirptr.p->pagep[tslcPagedir & 0xff];
- ptrCheckGuard(slcPageptr, cpagesize, page8);
- arrGuard(ZWORDS_IN_PAGE - tslcPageIndex, 2048);
- dbgWord32(slcPageptr, ZWORDS_IN_PAGE - tslcPageIndex, (int)slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex] & 0xffff);
- dbgWord32(slcPageptr, ZWORDS_IN_PAGE - tslcPageIndex, slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex] >> 16);
- tslcIndexValue = slcPageptr.p->word32[ZWORDS_IN_PAGE - tslcPageIndex];
- if ((tslcIndexValue >> 16) != operationRecPtr.p->tupkeylen) {
- jam();
- tslcResult = ZFALSE;
- return;
- }//if
- tslcStartIndex = tslcIndexValue & 0xffff;
- guard30 = operationRecPtr.p->tupkeylen - 1;
- arrGuard(guard30, 2048);
- arrGuard(guard30 + tslcStartIndex, 2048);
- for (tslcIndex = 0; tslcIndex <= guard30; tslcIndex++) {
- dbgWord32(slcPageptr, tslcIndex + tslcStartIndex, slcPageptr.p->word32[tslcIndex + tslcStartIndex]);
- if (slcPageptr.p->word32[tslcIndex + tslcStartIndex] != Tkeydata[tslcIndex]) {
- jam();
- tslcResult = ZFALSE;
- return;
- }//if
- }//for
- jam();
- tslcResult = ZTRUE;
- operationRecPtr.p->longPagePtr = slcPageptr.i;
- operationRecPtr.p->longKeyPageIndex = tslcPageIndex;
- arrGuard(tslcPageIndex, ZMAX_NO_OF_LONGKEYS_IN_PAGE);
- arrGuard(slcPageptr.i, cpagesize);
-}//Dbacc::searchLongKey()
-
-/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* --------------------------------------------------------------------------------- */
/* */
@@ -4838,13 +3471,6 @@ void Dbacc::commitdelete(Signal* signal, bool systemRestart)
EXECUTE_DIRECT(DBTUP, GSN_TUP_DEALLOCREQ, signal, 4);
jamEntry();
}//if
- if (fragrecptr.p->keyLength == 0) {
- jam();
- tdlkLogicalPageIndex = operationRecPtr.p->longKeyPageIndex;
- dlkPageptr.i = operationRecPtr.p->longPagePtr;
- ptrCheckGuard(dlkPageptr, cpagesize, page8);
- deleteLongKey(signal);
- }//if
getdirindex(signal);
tlastPageindex = tgdiPageindex;
lastPageptr.i = gdiPageptr.i;
@@ -5403,50 +4029,6 @@ void Dbacc::checkoverfreelist(Signal* signal)
}//if
}//Dbacc::checkoverfreelist()
-/* --------------------------------------------------------------------------------- */
-/* RELEASE_LONG_PAGE */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::releaseLongPage(Signal* signal)
-{
- DirRangePtr rlpOverflowrangeptr;
- DirectoryarrayPtr rlpOverflowDirptr;
- Uint32 trlpTmp1;
- Uint32 trlpTmp2;
- Uint32 trlpTmp3;
-
- jam();
- seizeOverRec(signal);
- sorOverflowRecPtr.p->dirindex = rlopPageptr.p->word32[ZPOS_PAGE_ID];
- sorOverflowRecPtr.p->overpage = RNIL;
- priOverflowRecPtr = sorOverflowRecPtr;
- putRecInFreeOverdir(signal);
- trlpTmp1 = sorOverflowRecPtr.p->dirindex;
- rlpOverflowrangeptr.i = fragrecptr.p->overflowdir;
- trlpTmp2 = trlpTmp1 >> 8;
- trlpTmp3 = trlpTmp1 & 0xff;
- ptrCheckGuard(rlpOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard(trlpTmp2, 256);
- rlpOverflowDirptr.i = rlpOverflowrangeptr.p->dirArray[trlpTmp2];
- ptrCheckGuard(rlpOverflowDirptr, cdirarraysize, directoryarray);
- rlpOverflowDirptr.p->pagep[trlpTmp3] = RNIL;
-
- if (cundoLogActive != ZTRUE) {
- // Remove from page array.
- trfpArrayPos = rlopPageptr.p->word32[ZPOS_ARRAY_POS];
- rfpPageptr = rlopPageptr;
- removeFromPageArrayList(signal);
- }
-
- // Reset page header
- iloPageptr = rlopPageptr;
- tiloIndex = rlopPageptr.p->word32[ZPOS_PAGE_ID];
- initLongOverpage(signal);
-
- rpPageptr = rlopPageptr;
- releasePage(signal);
-}//Dbacc::releaseLongPage()
-
-
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
/* ------------------------------------------------------------------------- */
@@ -6590,14 +5172,8 @@ void Dbacc::expandcontainer(Signal* signal)
Uint32 texcHashvalue;
Uint32 texcTmp;
Uint32 texcIndex;
- Uint32 texpKeyLen;
Uint32 guard20;
- texpKeyLen = fragrecptr.p->keyLength;
- if (texpKeyLen == 0) {
- jam();
- texpKeyLen = ZACTIVE_LONG_KEY_LEN;
- }//if
cexcPrevpageptr = RNIL;
cexcPrevconptr = 0;
cexcForward = ZTRUE;
@@ -6684,18 +5260,10 @@ void Dbacc::expandcontainer(Signal* signal)
clocalkey[texcIndex] = excPageptr.p->word32[texcTmp];
texcTmp = texcTmp + cexcForward;
}//for
- guard20 = texpKeyLen - 1;
- for (texcIndex = 0; texcIndex <= guard20; texcIndex++) {
- arrGuard(texcIndex, 2048);
- arrGuard(texcTmp, 2048);
- ckeys[texcIndex] = excPageptr.p->word32[texcTmp];
- texcTmp = texcTmp + cexcForward;
- }//for
tidrPageindex = fragrecptr.p->expReceiveIndex;
idrPageptr.i = fragrecptr.p->expReceivePageptr;
ptrCheckGuard(idrPageptr, cpagesize, page8);
tidrForward = fragrecptr.p->expReceiveForward;
- tidrKeyLen = texpKeyLen;
insertElement(signal);
fragrecptr.p->expReceiveIndex = tidrPageindex;
fragrecptr.p->expReceivePageptr = idrPageptr.i;
@@ -6777,17 +5345,10 @@ void Dbacc::expandcontainer(Signal* signal)
clocalkey[texcIndex] = lastPageptr.p->word32[texcTmp];
texcTmp = texcTmp + tlastForward;
}//for
- for (texcIndex = 0; texcIndex < texpKeyLen; texcIndex++) {
- arrGuard(texcIndex, 2048);
- arrGuard(texcTmp, 2048);
- ckeys[texcIndex] = lastPageptr.p->word32[texcTmp];
- texcTmp = texcTmp + tlastForward;
- }//for
tidrPageindex = fragrecptr.p->expReceiveIndex;
idrPageptr.i = fragrecptr.p->expReceivePageptr;
ptrCheckGuard(idrPageptr, cpagesize, page8);
tidrForward = fragrecptr.p->expReceiveForward;
- tidrKeyLen = texpKeyLen;
insertElement(signal);
fragrecptr.p->expReceiveIndex = tidrPageindex;
fragrecptr.p->expReceivePageptr = idrPageptr.i;
@@ -7268,18 +5829,12 @@ void Dbacc::shrinkcontainer(Signal* signal)
Uint32 tshrElementptr;
Uint32 tshrRemLen;
Uint32 tshrInc;
- Uint32 tshrKeyLen;
Uint32 tshrTmp;
Uint32 tshrIndex;
Uint32 guard21;
tshrRemLen = cexcContainerlen - ZCON_HEAD_SIZE;
- tshrKeyLen = fragrecptr.p->keyLength;
- if (tshrKeyLen == 0) {
- jam();
- tshrKeyLen = ZACTIVE_LONG_KEY_LEN;
- }//if
- tshrInc = (ZELEM_HEAD_SIZE + tshrKeyLen) + fragrecptr.p->localkeylen;
+ tshrInc = fragrecptr.p->elementLength;
if (cexcForward == ZTRUE) {
jam();
tshrElementptr = cexcContainerptr + ZCON_HEAD_SIZE;
@@ -7328,18 +5883,10 @@ void Dbacc::shrinkcontainer(Signal* signal)
clocalkey[tshrIndex] = excPageptr.p->word32[tshrTmp];
tshrTmp = tshrTmp + cexcForward;
}//for
- guard21 = tshrKeyLen - 1;
- for (tshrIndex = 0; tshrIndex <= guard21; tshrIndex++) {
- arrGuard(tshrIndex, 2048);
- arrGuard(tshrTmp, 2048);
- ckeys[tshrIndex] = excPageptr.p->word32[tshrTmp];
- tshrTmp = tshrTmp + cexcForward;
- }//for
tidrPageindex = fragrecptr.p->expReceiveIndex;
idrPageptr.i = fragrecptr.p->expReceivePageptr;
ptrCheckGuard(idrPageptr, cpagesize, page8);
tidrForward = fragrecptr.p->expReceiveForward;
- tidrKeyLen = tshrKeyLen;
insertElement(signal);
/* --------------------------------------------------------------------------------- */
/* TAKE CARE OF RESULT FROM INSERT_ELEMENT. */
@@ -8067,14 +6614,6 @@ void Dbacc::saveOverPagesLab(Signal* signal)
jam();
ropPageptr = sopPageptr;
releaseOverpage(signal);
- } else if (((sopPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) ==
- ZLONG_PAGE_TYPE) {
- //----------------------------------------------------------------------
- // The long key page is empty, release it.
- //----------------------------------------------------------------------
- jam();
- rlopPageptr = sopPageptr;
- releaseLongPage(signal);
} else {
jam();
sendSystemerror(signal);
@@ -8450,66 +6989,63 @@ void Dbacc::lcpCopyPage(Signal* signal)
}//for
}//for
tlcnChecksum = Tchs;
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZLONG_PAGE_TYPE) {
- jam();
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
- jam();
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
- /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
- /* HEADER OF 2 WORDS. */
- /*-----------------------------------------------------------------*/
- tlcnConIndex = ZHEAD_SIZE;
- tlupForward = 1;
- for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- lcpUpdatePage(signal);
- tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
- }//for
- }//if
+ if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
+ jam();
/*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
+ /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
+ /* HEADER OF 2 WORDS. */
/*-----------------------------------------------------------------*/
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlcnConIndex = ZHEAD_SIZE;
+ tlupForward = 1;
+ for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
tlupIndex = tlcnConIndex;
tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- tlupForward = 1;
- lcpUpdatePage(signal);
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- sendSystemerror(signal);
- return;
- }//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
- /*-----------------------------------------------------------------*/
- tlupForward = cminusOne;
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex - 1;
lcpUpdatePage(signal);
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
- jam();
- sendSystemerror(signal);
- return;
- }//if
+ tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
+ }//for
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
+ tlupForward = 1;
+ lcpUpdatePage(signal);
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ sendSystemerror(signal);
+ return;
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlupForward = cminusOne;
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex - 1;
+ lcpUpdatePage(signal);
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ sendSystemerror(signal);
+ return;
}//if
lcnCopyPageptr.p->word32[ZPOS_CHECKSUM] = tlcnChecksum;
}//Dbacc::lcpCopyPage()
@@ -8570,78 +7106,75 @@ void Dbacc::srCheckPage(Signal* signal)
Uint32 tlcnIndex;
lupPageptr.p = lcnCopyPageptr.p;
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) != ZLONG_PAGE_TYPE) {
- jam();
- if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
- jam();
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
- /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
- /* HEADER OF 2 WORDS. */
- /*-----------------------------------------------------------------*/
- tlcnConIndex = ZHEAD_SIZE;
- tlupForward = 1;
- for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- srCheckContainer(signal);
- if (tresult != 0) {
- jam();
- return;
- }//if
- tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
- }//for
- }//if
+ if (((lcnCopyPageptr.p->word32[ZPOS_PAGE_TYPE] >> ZPOS_PAGE_TYPE_BIT) & 3) == ZNORMAL_PAGE_TYPE) {
+ jam();
/*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /* TAKE CARE OF ALL 64 BUFFERS ADDRESSED BY ALGORITHM IN */
+ /* FIRST PAGE. IF THEY ARE EMPTY THEY STILL HAVE A CONTAINER */
+ /* HEADER OF 2 WORDS. */
/*-----------------------------------------------------------------*/
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlcnConIndex = ZHEAD_SIZE;
+ tlupForward = 1;
+ for (tlcnIndex = 0; tlcnIndex <= ZNO_CONTAINERS - 1; tlcnIndex++) {
tlupIndex = tlcnConIndex;
tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
- tlupForward = 1;
srCheckContainer(signal);
if (tresult != 0) {
jam();
return;
}//if
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
+ tlcnConIndex = tlcnConIndex + ZBUF_SIZE;
+ }//for
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE LEFT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 23) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ZHEAD_SIZE;
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex + ZCON_HEAD_SIZE;
+ tlupForward = 1;
+ srCheckContainer(signal);
+ if (tresult != 0) {
jam();
- tresult = 4;
return;
}//if
- /*-----------------------------------------------------------------*/
- /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
- /*-----------------------------------------------------------------*/
- tlupForward = cminusOne;
- tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
- while (tlcnNextContainer < ZEMPTYLIST) {
- tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
- tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
- tlupIndex = tlcnConIndex;
- tlupElemIndex = tlcnConIndex - 1;
- srCheckContainer(signal);
- if (tresult != 0) {
- jam();
- return;
- }//if
- tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
- }//while
- if (tlcnNextContainer == ZEMPTYLIST) {
- jam();
- /*empty*/;
- } else {
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ tresult = 4;
+ return;
+ }//if
+ /*-----------------------------------------------------------------*/
+ /* TAKE CARE OF ALL USED BUFFERS ON THE RIGHT SIDE. */
+ /*-----------------------------------------------------------------*/
+ tlupForward = cminusOne;
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[ZPOS_EMPTY_LIST] >> 16) & 0x7f;
+ while (tlcnNextContainer < ZEMPTYLIST) {
+ tlcnConIndex = (tlcnNextContainer << ZSHIFT_PLUS) - (tlcnNextContainer << ZSHIFT_MINUS);
+ tlcnConIndex = tlcnConIndex + ((ZHEAD_SIZE + ZBUF_SIZE) - ZCON_HEAD_SIZE);
+ tlupIndex = tlcnConIndex;
+ tlupElemIndex = tlcnConIndex - 1;
+ srCheckContainer(signal);
+ if (tresult != 0) {
jam();
- tresult = 4;
return;
}//if
+ tlcnNextContainer = (lcnCopyPageptr.p->word32[tlcnConIndex] >> 11) & 0x7f;
+ }//while
+ if (tlcnNextContainer == ZEMPTYLIST) {
+ jam();
+ /*empty*/;
+ } else {
+ jam();
+ tresult = 4;
+ return;
}//if
}//Dbacc::srCheckPage()
@@ -8825,50 +7358,14 @@ void Dbacc::undoWritingProcess(Signal* signal)
writeUndoDataInfo(signal);
checkUndoPages(signal);
}//if
- } else if (tpageType != ZLONG_PAGE_TYPE) {
+ } else {
jam();
/* --------------------------------------------------------------------------- */
/* ONLY PAGE INFO AND OVERFLOW PAGE INFO CAN BE LOGGED BY THIS ROUTINE. A */
/* SERIOUS ERROR. */
/* --------------------------------------------------------------------------- */
sendSystemerror(signal);
- } else {
- /* --------------------------------------------------------------------------------- */
- /* THIS LOG RECORD IS GENERATED ON A LONG KEY PAGE. THESE PAGES USE LOGICAL */
- /* LOGGING. */
- /* --------------------------------------------------------------------------------- */
- if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW PAGES SINCE THE */
- /* START OF THE LOCAL CHECKPOINT. WE NEED NOT LOG ANY UPDATES OF PAGES THAT DID*/
- /* NOT EXIST AT START OF LCP. */
- /* --------------------------------------------------------------------------------- */
- /*empty*/;
- } else {
- jam();
- /* --------------------------------------------------------------------------------- */
- /* LOGICAL LOGGING OF LONG KEY PAGES CAN EITHER BE UNDO OF AN INSERT OR UNDO */
- /* OF A DELETE KEY. UNDO OF DELETE NEEDS TO LOG THE KEY TO BE REINSERTED WHILE */
- /* UNDO OF INSERT ONLY NEEDS TO LOG THE INDEX TO BE DELETED. */
- /* --------------------------------------------------------------------------------- */
- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
- if (cundoinfolength == 0) {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_INSERT_LONG_KEY);
- } else {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_DELETE_LONG_KEY);
- arrGuard(ZWORDS_IN_PAGE - cundoElemIndex, 2048);
- tundoElemIndex = datapageptr.p->word32[ZWORDS_IN_PAGE - cundoElemIndex] & 0xffff;
- writeUndoDataInfo(signal);
- }//if
- checkUndoPages(signal);
- }//if
- }//if
+ }
} else {
if (fragrecptr.p->fragState == LCP_SEND_OVER_PAGES) {
jam();
@@ -8903,46 +7400,7 @@ void Dbacc::undoWritingProcess(Signal* signal)
checkUndoPages(signal);
}//if
}//if
- } else if (tpageType == ZLONG_PAGE_TYPE) {
- if (tactivePageDir < fragrecptr.p->lcpDirIndex) {
- jam();
- // -------------------------------------------------------------
- // THIS PAGE HAS ALREADY BEEN WRITTEN IN THE LOCAL CHECKPOINT.
- // -------------------------------------------------------------
- } else {
- if (tactivePageDir >= fragrecptr.p->lcpMaxOverDirIndex) {
- jam();
- // -------------------------------------------------------------
- // OBVIOUSLY THE FRAGMENT HAS EXPANDED THE NUMBER OF OVERFLOW
- // PAGES SINCE THE START OF THE LOCAL CHECKPOINT. WE NEED NOT
- // LOG ANY UPDATES OF PAGES THAT DID NOT EXIST AT START OF LCP.
- // -------------------------------------------------------------
- } else {
- jam();
- // -------------------------------------------------------------
- // LOGICAL LOGGING OF LONG KEY PAGES CAN EITHER BE UNDO OF AN
- // INSERT OR UNDO OF A DELETE KEY. UNDO OF DELETE NEEDS TO LOG
- // THE KEY TO BE REINSERTED WHILE UNDO OF INSERT ONLY NEEDS TO
- // LOG THE INDEX TO BE DELETED.
- // -------------------------------------------------------------
- undopageptr.i = (cundoposition >> ZUNDOPAGEINDEXBITS) & (cundopagesize - 1);
- ptrAss(undopageptr, undopage);
- theadundoindex = cundoposition & ZUNDOPAGEINDEX_MASK;
- tundoindex = theadundoindex + ZUNDOHEADSIZE;
- if (cundoinfolength == 0) {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_INSERT_LONG_KEY);
- } else {
- jam();
- writeUndoHeader(signal, tactivePageDir, UndoHeader::ZUNDO_DELETE_LONG_KEY);
- arrGuard(ZWORDS_IN_PAGE - cundoElemIndex, 2048);
- tundoElemIndex = datapageptr.p->word32[ZWORDS_IN_PAGE - cundoElemIndex] & 0xffff;
- writeUndoDataInfo(signal);
- }//if
- checkUndoPages(signal);
- }//if
- }//if
- }//if
+ }
}//if
}//if
}//Dbacc::undoWritingProcess()
@@ -8995,8 +7453,9 @@ void Dbacc::writeUndoHeader(Signal* signal,
(UndoHeader *) &undopageptr.p->undoword[theadundoindex];
undoHeaderPtr->tableId = rootfragrecptr.p->mytabptr;
- undoHeaderPtr->rootFragId = rootfragrecptr.p->fragmentid[0];
+ undoHeaderPtr->rootFragId = rootfragrecptr.p->fragmentid[0] >> 1;
undoHeaderPtr->localFragId = fragrecptr.p->myfid;
+ ndbrequire((undoHeaderPtr->localFragId >> 1) == undoHeaderPtr->rootFragId);
Uint32 Ttmp = cundoinfolength;
Ttmp = (Ttmp << 4) + pageType;
Ttmp = Ttmp << 14;
@@ -9026,52 +7485,16 @@ void Dbacc::writeUndoOpInfo(Signal* signal)
undopageptr.p->undoword[tundoindex + 1] = operationRecPtr.p->hashValue;
undopageptr.p->undoword[tundoindex + 2] = operationRecPtr.p->tupkeylen;
tundoindex = tundoindex + 3;
- if (fragrecptr.p->keyLength != 0) {
- // Fixed size keys
- jam();
- locPageptr.i = operationRecPtr.p->elementPage;
- ptrCheckGuard(locPageptr, cpagesize, page8);
- Uint32 Tforward = operationRecPtr.p->elementIsforward;
- Uint32 TelemPtr = operationRecPtr.p->elementPointer;
- TelemPtr += Tforward;
- TelemPtr += Tforward;
- //---------------------------------------------------------------------------------
- // Now the pointer is at the start of the key part of the element. Now copy from there
- // to the UNDO log.
- //---------------------------------------------------------------------------------
- Uint32 keyLen = operationRecPtr.p->tupkeylen;
- ndbrequire(keyLen <= 8);
- arrGuard(tundoindex+keyLen, 8192);
- for (Uint32 twuoiIndex = 0; twuoiIndex < keyLen; twuoiIndex++) {
- jam();
- arrGuard(TelemPtr, 2048);
- undopageptr.p->undoword[tundoindex] = locPageptr.p->word32[TelemPtr];
- tundoindex++;
- TelemPtr += Tforward;
- }//for
- cundoinfolength = ZOP_HEAD_INFO_LN + operationRecPtr.p->tupkeylen;
- } else {
- // Long keys
- jam();
-
- arrGuard(operationRecPtr.p->longKeyPageIndex, ZMAX_NO_OF_LONGKEYS_IN_PAGE);
- locPageptr.i = operationRecPtr.p->longPagePtr;
- ptrCheckGuard(locPageptr, cpagesize, page8);
-
- Uint32 indexValue =
- locPageptr.p->word32[ZWORDS_IN_PAGE - operationRecPtr.p->longKeyPageIndex];
- Uint32 keyLen = indexValue >> 16;
- Uint32 physPageIndex = indexValue & 0xffff;
- ndbrequire(keyLen == operationRecPtr.p->tupkeylen);
-
- arrGuard(tundoindex+keyLen, 8192);
- arrGuard(physPageIndex+keyLen, 2048);
- for (Uint32 i = 0; i < keyLen; i++){
- undopageptr.p->undoword[tundoindex + i] = locPageptr.p->word32[physPageIndex+i];
- }
- tundoindex = tundoindex + keyLen;
- cundoinfolength = ZOP_HEAD_INFO_LN + keyLen;
- }//if
+ // log localkey1
+ locPageptr.i = operationRecPtr.p->elementPage;
+ ptrCheckGuard(locPageptr, cpagesize, page8);
+ Uint32 Tforward = operationRecPtr.p->elementIsforward;
+ Uint32 TelemPtr = operationRecPtr.p->elementPointer;
+ TelemPtr += Tforward; // ZELEM_HEAD_SIZE
+ arrGuard(tundoindex+1, 8192);
+ undopageptr.p->undoword[tundoindex] = locPageptr.p->word32[TelemPtr];
+ tundoindex++;
+ cundoinfolength = ZOP_HEAD_INFO_LN + 1;
}//Dbacc::writeUndoOpInfo()
/* --------------------------------------------------------------------------------- */
@@ -9255,7 +7678,7 @@ void Dbacc::initFragAdd(Signal* signal,
}//if
regFragPtr.p->fragState = ACTIVEFRAG;
// NOTE: next line must match calculation in Dblqh::execLQHFRAGREQ
- regFragPtr.p->myfid = (rootFragIndex << (lhFragBits - 1)) | req->fragId;
+ regFragPtr.p->myfid = (req->fragId << 1) | rootFragIndex;
regFragPtr.p->myroot = rootIndex;
regFragPtr.p->myTableId = req->tableId;
ndbrequire(req->kValue == 6);
@@ -9283,13 +7706,8 @@ void Dbacc::initFragAdd(Signal* signal,
regFragPtr.p->dirsize = 1;
regFragPtr.p->loadingFlag = ZFALSE;
regFragPtr.p->keyLength = req->keyLength;
- if (req->keyLength == 0) {
- jam();
- regFragPtr.p->elementLength = (1 + ZELEM_HEAD_SIZE) + regFragPtr.p->localkeylen;
- } else {
- jam();
- regFragPtr.p->elementLength = (ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen) + regFragPtr.p->keyLength;
- }//if
+ ndbrequire(req->keyLength != 0);
+ regFragPtr.p->elementLength = ZELEM_HEAD_SIZE + regFragPtr.p->localkeylen;
Uint32 Tmp1 = (regFragPtr.p->maxp + 1) + regFragPtr.p->p;
Uint32 Tmp2 = regFragPtr.p->maxloadfactor - regFragPtr.p->minloadfactor;
Tmp2 = Tmp1 * Tmp2;
@@ -10091,6 +8509,7 @@ void Dbacc::srDoUndoLab(Signal* signal)
// ROOT FRAGMENT ID
tfid = undoHeaderPtr->rootFragId;
+ ndbrequire((undoHeaderPtr->localFragId >> 1) == undoHeaderPtr->rootFragId);
if (!getrootfragmentrec(signal, rootfragrecptr, tfid)) {
jam();
/*---------------------------------------------------------------------*/
@@ -10100,7 +8519,10 @@ void Dbacc::srDoUndoLab(Signal* signal)
creadyUndoaddress = cprevUndoaddress;
// PREVIOUS UNDO LOG RECORD FOR ALL FRAGMENTS
cprevUndoaddress = undoHeaderPtr->prevUndoAddress;
- undoNext2Lab(signal);
+ undoNext2Lab(signal);
+#ifdef VM_TRACE
+ ndbout_c("ignoring root fid %d", (int)tfid);
+#endif
return;
}//if
/*-----------------------------------------------------------------------*/
@@ -10210,103 +8632,6 @@ void Dbacc::srDoUndoLab(Signal* signal)
break;
}
- case UndoHeader::ZUNDO_INSERT_LONG_KEY:{
- jam();
- /*---------------------------------------------------------------------*/
- /* WE WILL UNDO AN INSERT OF A LONG KEY. THIS IS PERFORMED BY DELETING */
- /* THE LONG KEY. */
- /*---------------------------------------------------------------------*/
- souDirRangePtr.i = fragrecptr.p->overflowdir;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- arrGuard(tmpP2, 256);
- ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange);
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
- ptrCheckGuard(souDirptr, cdirarraysize, directoryarray);
- dlkPageptr.i = souDirptr.p->pagep[tmpP];
- ptrCheckGuard(dlkPageptr, cpagesize, page8);
- tdlkLogicalPageIndex = tundoPageindex;
- deleteLongKey(signal);
- break;
- }
-
- case UndoHeader::ZUNDO_DELETE_LONG_KEY: {
- jam();
- /*----------------------------------------------------------------------*/
- /* WE WILL UNDO DELETE OF A LONG KEY. THIS IS PERFORMED BY INSERTING */
- /* IT AGAIN. */
- /*----------------------------------------------------------------------*/
- souDirRangePtr.i = fragrecptr.p->overflowdir;
- taslpDirIndex = tmpP;
- tmpP2 = tmpP >> 8;
- tmpP = tmpP & 0xff;
- ptrCheckGuard(souDirRangePtr, cdirrangesize, dirRange);
- arrGuard(tmpP2, 256);
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
-
- if(souDirptr.i == RNIL) {
- //----------------------------------------------------------------
- // Allocate a directory.
- //----------------------------------------------------------------
- jam();
- seizeDirectory(signal);
- if (tresult > ZLIMIT_OF_ERROR) {
- jam();
- sendSystemerror(signal);
- return;
- }
- souDirRangePtr.p->dirArray[tmpP2] = sdDirptr.i;
- souDirptr.i = souDirRangePtr.p->dirArray[tmpP2];
- }
-
- ptrCheckGuard(souDirptr, cdirarraysize, directoryarray);
- slkapPageptr.i = souDirptr.p->pagep[tmpP];
-
- if(slkapPageptr.i == RNIL) {
- //----------------------------------------------------------------
- // The delete operation was probably the last on the page and the
- // page was released and not written down to disk. We need to
- // allocate a page and put it in the same dirindex as it was in
- // before it was released.
- // This is because an eventual UNDO_INSERT on the same key in the
- // same LCP must be able to find the key and it has only the
- // dirindex to go on, the key itself is not saved on disk in a
- // UNDO_INSERT.
- //----------------------------------------------------------------
- jam();
- allocSpecificLongOverflowPage(signal);
- slkapPageptr.i = aslpPageptr.i;
- }
-
- ptrCheckGuard(slkapPageptr, cpagesize, page8);
- seizePage(signal);
- ndbrequire(tresult <= ZLIMIT_OF_ERROR);
-
- slkapCopyPageptr = spPageptr;
- ndbrequire(cundoinfolength <= 2048);
-
- for (Uint32 tmp = 0; tmp < cundoinfolength; tmp++) {
- dbgWord32(slkapCopyPageptr, tmp, undopageptr.p->undoword[tmpindex]);
- slkapCopyPageptr.p->word32[tmp] = undopageptr.p->undoword[tmpindex];
- tmpindex = tmpindex + 1;
- }//for
- jam();
- //----------------------------------------------------------------
- // We must store the key at the same place it was deleted from.
- // This is because an eventual UNDO_INSERT on the same key in the
- // same LCP must be able to find the key and it has only the index
- // information stored on disk to go on, the key itself is not
- // saved on disk in an UNDO_INSERT.
- //----------------------------------------------------------------
- tslkapKeyLen = cundoinfolength;
- tslkapPageIndex = tundoPageindex;
- storeLongKeysAtPos(signal);
-
- rpPageptr = slkapCopyPageptr;
- releasePage(signal);
- break;
- }
-
case UndoHeader::ZOP_INFO: {
jam();
/*---------------------------------------------------------------------*/
@@ -10345,6 +8670,7 @@ void Dbacc::srDoUndoLab(Signal* signal)
operationRecPtr.p->longKeyPageIndex = RNIL;
operationRecPtr.p->scanRecPtr = RNIL;
operationRecPtr.p->isAccLockReq = ZFALSE;
+ operationRecPtr.p->isUndoLogReq = ZTRUE;
// Read operation values from undo page
operationRecPtr.p->operation = undopageptr.p->undoword[tmpindex];
@@ -10356,15 +8682,12 @@ void Dbacc::srDoUndoLab(Signal* signal)
operationRecPtr.p->tupkeylen = tkeylen;
operationRecPtr.p->fragptr = fragrecptr.i;
- ndbrequire((fragrecptr.p->keyLength == 0) ||
- ((fragrecptr.p->keyLength != 0) &&
- (fragrecptr.p->keyLength == tkeylen)));
+ ndbrequire(fragrecptr.p->keyLength != 0 &&
+ fragrecptr.p->keyLength == tkeylen);
- // Read keydata from undo page
- for (Uint32 tmp = 0; tmp < tkeylen; tmp++) {
- signal->theData[7+tmp] = undopageptr.p->undoword[tmpindex];
- tmpindex = tmpindex + 1;
- }//for
+ // Read localkey1 from undo page
+ signal->theData[7 + 0] = undopageptr.p->undoword[tmpindex];
+ tmpindex = tmpindex + 1;
arrGuard((tmpindex - 1), 8192);
getElement(signal);
if (tgeResult != ZTRUE) {
@@ -10547,43 +8870,25 @@ void Dbacc::execACC_OVER_REC(Signal* signal)
ptrCheckGuard(pnoPageidptr, cpagesize, page8);
tpnoPageType = pnoPageidptr.p->word32[ZPOS_PAGE_TYPE];
tpnoPageType = (tpnoPageType >> ZPOS_PAGE_TYPE_BIT) & 3;
- if (tpnoPageType == ZLONG_PAGE_TYPE) {
+ if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
jam();
- // This is to clean the list parameters.
- pnoPageidptr.p->word32[ZPOS_PREV_PAGE] = RNIL;
- pnoPageidptr.p->word32[ZPOS_NEXT_PAGE] = RNIL;
- if (pnoPageidptr.p->word32[ZPOS_ARRAY_POS] != 4) {
- jam();
- /*---------------------------------------------------------------------------*/
- /* THE PAGE WAS A LONG PAGE AND IT BELONGED TO A FREE LIST. PUT IT INTO ONE */
- /* OF THE FREE LIST THEN. */
- /*---------------------------------------------------------------------------*/
- // Insert page!
- ipaPagePtr = pnoPageidptr;
- tipaArrayPos = pnoPageidptr.p->word32[ZPOS_ARRAY_POS];
- insertPageArrayList(signal);
- }//if
+ dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, RNIL);
+ pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
+ ndbrequire(pnoPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage);
} else {
- if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] > ZFREE_LIMIT) {
- jam();
- dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, RNIL);
- pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = RNIL;
- ndbrequire(pnoPageidptr.p->word32[ZPOS_PAGE_ID] == fragrecptr.p->nextAllocPage);
- } else {
+ jam();
+ seizeOverRec(signal);
+ sorOverflowRecPtr.p->dirindex = pnoPageidptr.p->word32[ZPOS_PAGE_ID];
+ ndbrequire(sorOverflowRecPtr.p->dirindex == fragrecptr.p->nextAllocPage);
+ dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
+ pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
+ sorOverflowRecPtr.p->overpage = pnoPageidptr.i;
+ porOverflowRecPtr = sorOverflowRecPtr;
+ putOverflowRecInFrag(signal);
+ if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0) {
jam();
- seizeOverRec(signal);
- sorOverflowRecPtr.p->dirindex = pnoPageidptr.p->word32[ZPOS_PAGE_ID];
- ndbrequire(sorOverflowRecPtr.p->dirindex == fragrecptr.p->nextAllocPage);
- dbgWord32(pnoPageidptr, ZPOS_OVERFLOWREC, sorOverflowRecPtr.i);
- pnoPageidptr.p->word32[ZPOS_OVERFLOWREC] = sorOverflowRecPtr.i;
- sorOverflowRecPtr.p->overpage = pnoPageidptr.i;
- porOverflowRecPtr = sorOverflowRecPtr;
- putOverflowRecInFrag(signal);
- if (pnoPageidptr.p->word32[ZPOS_ALLOC_CONTAINERS] == 0) {
- jam();
- ropPageptr = pnoPageidptr;
- releaseOverpage(signal);
- }//if
+ ropPageptr = pnoPageidptr;
+ releaseOverpage(signal);
}//if
}//if
}//if
@@ -10658,7 +8963,6 @@ void Dbacc::execACC_SCANREQ(Signal* signal)
rootfragrecptr.p->scan[i] = scanPtr.i;
scanPtr.p->scanBucketState = ScanRec::FIRST_LAP;
scanPtr.p->scanLockMode = AccScanReq::getLockMode(tscanFlag);
- scanPtr.p->scanKeyinfoFlag = AccScanReq::getKeyinfoFlag(tscanFlag);
scanPtr.p->scanReadCommittedFlag = AccScanReq::getReadCommittedFlag(tscanFlag);
/* TWELVE BITS OF THE ELEMENT HEAD ARE SCAN */
@@ -11406,11 +9710,6 @@ void Dbacc::initScanOpRec(Signal* signal)
Uint32 tisoTmp;
Uint32 tisoLocalPtr;
Uint32 guard24;
- Uint32 tisoPageIndex;
- Uint32 tisoPagedir;
- DirRangePtr tisoOverflowrangeptr;
- DirectoryarrayPtr tisoOverflowDirptr;
- Page8Ptr tisoPageptr;
scanPtr.p->scanOpsAllocated++;
@@ -11439,6 +9738,7 @@ void Dbacc::initScanOpRec(Signal* signal)
operationRecPtr.p->elementPointer = tisoElementptr;
operationRecPtr.p->elementPage = isoPageptr.i;
operationRecPtr.p->isAccLockReq = ZFALSE;
+ operationRecPtr.p->isUndoLogReq = ZFALSE;
tisoLocalPtr = tisoElementptr + tisoIsforward;
guard24 = fragrecptr.p->localkeylen - 1;
for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) {
@@ -11449,40 +9749,7 @@ void Dbacc::initScanOpRec(Signal* signal)
}//for
arrGuard(tisoLocalPtr, 2048);
operationRecPtr.p->keydata[0] = isoPageptr.p->word32[tisoLocalPtr];
- if (fragrecptr.p->keyLength != 0) {
- jam();
- operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength;
- guard24 = fragrecptr.p->keyLength - 1;
- for (tisoTmp = 0; tisoTmp <= guard24; tisoTmp++) {
- arrGuard(tisoTmp, 8);
- arrGuard(tisoLocalPtr, 2048);
- operationRecPtr.p->keydata[tisoTmp] = isoPageptr.p->word32[tisoLocalPtr];
- tisoLocalPtr = tisoLocalPtr + tisoIsforward;
- }//for
- } else {
- // Long key handling. Put the long key reference in the operation records.
- tisoPageIndex = operationRecPtr.p->keydata[0] & 0x3ff;
- arrGuard(ZWORDS_IN_PAGE - tisoPageIndex, 2048);
-
- tisoPagedir = operationRecPtr.p->keydata[0] >> 10;
- arrGuard((tisoPagedir >> 8), 256);
-
- tisoOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(tisoOverflowrangeptr, cdirrangesize, dirRange);
-
- tisoOverflowDirptr.i = tisoOverflowrangeptr.p->dirArray[tisoPagedir >> 8];
- ptrCheckGuard(tisoOverflowDirptr, cdirarraysize, directoryarray);
-
- tisoPageptr.i = tisoOverflowDirptr.p->pagep[tisoPagedir & 0xff];
- ptrCheckGuard(tisoPageptr, cpagesize, page8);
-
- operationRecPtr.p->longPagePtr = tisoPageptr.i;
- operationRecPtr.p->longKeyPageIndex = tisoPageIndex;
-
- // Read length of key from page
- Uint32 tmp = tisoPageptr.p->word32[ZWORDS_IN_PAGE - tisoPageIndex];
- operationRecPtr.p->tupkeylen = tmp >> 16;
- }
+ operationRecPtr.p->tupkeylen = fragrecptr.p->keyLength;
}//Dbacc::initScanOpRec()
/* --------------------------------------------------------------------------------- */
@@ -11677,21 +9944,15 @@ void Dbacc::releaseScanContainer(Signal* signal)
Uint32 trscElemlens;
Uint32 trscElemlen;
- if (trscContainerlen < 5) {
+ if (trscContainerlen < 4) {
if (trscContainerlen != ZCON_HEAD_SIZE) {
jam();
sendSystemerror(signal);
}//if
- return; /* 3 IS THE MINIMUM SIZE OF THE ELEMENT */
- }//if
- trscElemlens = trscContainerlen - 2;
- if (fragrecptr.p->keyLength != 0) {
- jam();
- trscElemlen = (1 + fragrecptr.p->keyLength) + fragrecptr.p->localkeylen; /* LENGTH OF THE ELEMENT */
- } else {
- jam();
- trscElemlen = (1 + ZACTIVE_LONG_KEY_LEN) + fragrecptr.p->localkeylen; /* LENGTH OF THE ELEMENT */
+ return; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
}//if
+ trscElemlens = trscContainerlen - ZCON_HEAD_SIZE;
+ trscElemlen = fragrecptr.p->elementLength;
if (trscIsforward == 1) {
jam();
trscElementptr = trscContainerptr + ZCON_HEAD_SIZE;
@@ -11718,7 +9979,7 @@ void Dbacc::releaseScanContainer(Signal* signal)
}//if
trscElemlens = trscElemlens - trscElemlen;
trscElementptr = trscElementptr + trscElemStep;
- } while (trscElemlens > 2);
+ } while (trscElemlens > 1);
if (trscElemlens != 0) {
jam();
sendSystemerror(signal);
@@ -11777,19 +10038,12 @@ bool Dbacc::searchScanContainer(Signal* signal)
Uint32 tsscElemlen;
Uint32 tsscElemStep;
- if (tsscContainerlen < 5) {
+ if (tsscContainerlen < 4) {
jam();
- return false; /* 3 IS THE MINIMUM SIZE OF THE ELEMENT */
+ return false; /* 2 IS THE MINIMUM SIZE OF THE ELEMENT */
}//if
tsscElemlens = tsscContainerlen - ZCON_HEAD_SIZE;
- if (fragrecptr.p->keyLength == 0) {
- jam();
- tsscElemlen = (ZELEM_HEAD_SIZE + ZACTIVE_LONG_KEY_LEN) + fragrecptr.p->localkeylen;
- } else {
- jam();
- /* LENGTH OF THE ELEMENT */
- tsscElemlen = (ZELEM_HEAD_SIZE + fragrecptr.p->keyLength) + fragrecptr.p->localkeylen;
- }//if
+ tsscElemlen = fragrecptr.p->elementLength;
/* LENGTH OF THE ELEMENT */
if (tsscIsforward == 1) {
jam();
@@ -11827,7 +10081,7 @@ bool Dbacc::searchScanContainer(Signal* signal)
/* THE ELEMENT IS ALREADY SENT. */
/* SEARCH FOR NEXT ONE */
tsscElemlens = tsscElemlens - tsscElemlen;
- if (tsscElemlens > 2) {
+ if (tsscElemlens > 1) {
jam();
tsscElementptr = tsscElementptr + tsscElemStep;
goto SCANELEMENTLOOP001;
@@ -11842,174 +10096,20 @@ void Dbacc::sendNextScanConf(Signal* signal)
{
scanPtr.p->scanTimer = scanPtr.p->scanContinuebCounter;
Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref);
- if (!scanPtr.p->scanKeyinfoFlag){
- jam();
- /** ---------------------------------------------------------------------
- * LQH WILL NOT HAVE ANY USE OF THE TUPLE KEY LENGTH IN THIS CASE AND
- * SO WE DO NOT PROVIDE IT. IN THIS CASE THESE VALUES ARE UNDEFINED.
- * ---------------------------------------------------------------------- */
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = operationRecPtr.p->localdata[0];
- signal->theData[4] = operationRecPtr.p->localdata[1];
- signal->theData[5] = fragrecptr.p->localkeylen;
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 6);
- return;
- }//if
-
- fragrecptr.i = operationRecPtr.p->fragptr;
- ptrCheckGuard(fragrecptr, cfragmentsize, fragmentrec);
- if (fragrecptr.p->keyLength != 0) {
- jam();
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = operationRecPtr.p->localdata[0];
- signal->theData[4] = operationRecPtr.p->localdata[1];
- signal->theData[5] = fragrecptr.p->localkeylen;
- signal->theData[6] = fragrecptr.p->keyLength;
- signal->theData[7] = operationRecPtr.p->keydata[0];
- signal->theData[8] = operationRecPtr.p->keydata[1];
- signal->theData[9] = operationRecPtr.p->keydata[2];
- signal->theData[10] = operationRecPtr.p->keydata[3];
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 11);
- if (fragrecptr.p->keyLength > ZKEYINKEYREQ) {
- jam();
- /* = 4 */
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = fragrecptr.p->keyLength - ZKEYINKEYREQ;
- signal->theData[4] = operationRecPtr.p->keydata[4];
- signal->theData[5] = operationRecPtr.p->keydata[5];
- signal->theData[6] = operationRecPtr.p->keydata[6];
- signal->theData[7] = operationRecPtr.p->keydata[7];
- EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO, signal, 8);
- return;
- }//if
- } else {
- jam();
- sendScaninfo(signal);
- return;
- }//if
-}//Dbacc::sendNextScanConf()
-
-/* --------------------------------------------------------------------------------- */
-/* SEND_SCANINFO */
-/* DESCRIPTION: SCAN AN ELEMENT OF A LONG_KEY_PAGE. */
-/* --------------------------------------------------------------------------------- */
-void Dbacc::sendScaninfo(Signal* signal)
-{
- DirRangePtr ssiOverflowrangeptr;
- DirectoryarrayPtr ssiOverflowDirptr;
- Page8Ptr ssiPageptr;
- Uint32 tssiPageIndex;
- Uint32 tssiPagedir;
- Uint32 tssiKeyLen;
- Uint32 tssiStartIndex;
- Uint32 tssiIndexValue;
- Uint32 tssiTmp;
-
- Uint32 blockNo = refToBlock(scanPtr.p->scanUserblockref);
-
- tssiPageIndex = operationRecPtr.p->keydata[0] & 0x3ff;
- tssiPagedir = operationRecPtr.p->keydata[0] >> 10;
- ssiOverflowrangeptr.i = fragrecptr.p->overflowdir;
- ptrCheckGuard(ssiOverflowrangeptr, cdirrangesize, dirRange);
- arrGuard((tssiPagedir >> 8), 256);
- ssiOverflowDirptr.i = ssiOverflowrangeptr.p->dirArray[tssiPagedir >> 8];
- ptrCheckGuard(ssiOverflowDirptr, cdirarraysize, directoryarray);
- ssiPageptr.i = ssiOverflowDirptr.p->pagep[tssiPagedir & 0xff];
- ptrCheckGuard(ssiPageptr, cpagesize, page8);
- arrGuard(ZWORDS_IN_PAGE - tssiPageIndex, 2048);
- tssiIndexValue = ssiPageptr.p->word32[ZWORDS_IN_PAGE - tssiPageIndex];
- tssiStartIndex = tssiIndexValue & 0xffff;
- tssiKeyLen = tssiIndexValue >> 16;
+ jam();
+ /** ---------------------------------------------------------------------
+ * LQH WILL NOT HAVE ANY USE OF THE TUPLE KEY LENGTH IN THIS CASE AND
+ * SO WE DO NOT PROVIDE IT. IN THIS CASE THESE VALUES ARE UNDEFINED.
+ * ---------------------------------------------------------------------- */
signal->theData[0] = scanPtr.p->scanUserptr;
signal->theData[1] = operationRecPtr.i;
signal->theData[2] = operationRecPtr.p->fid;
signal->theData[3] = operationRecPtr.p->localdata[0];
signal->theData[4] = operationRecPtr.p->localdata[1];
signal->theData[5] = fragrecptr.p->localkeylen;
- signal->theData[6] = tssiKeyLen;
- arrGuard(tssiStartIndex + 3, 2048);
- signal->theData[7] = ssiPageptr.p->word32[tssiStartIndex];
- signal->theData[8] = ssiPageptr.p->word32[tssiStartIndex + 1];
- signal->theData[9] = ssiPageptr.p->word32[tssiStartIndex + 2];
- signal->theData[10] = ssiPageptr.p->word32[tssiStartIndex + 3];
- EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 11);
- if (tssiKeyLen > 4) {
- tssiKeyLen = tssiKeyLen - 4;
- tssiStartIndex = tssiStartIndex + 4;
- SSI_LOOP_10:
- jamEntry();
- if (tssiKeyLen > ZMAXSCANSIGNALLEN) {
- jam();
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- signal->theData[3] = ZMAXSCANSIGNALLEN;
- arrGuard(tssiStartIndex + 19, 2048);
- signal->theData[4] = ssiPageptr.p->word32[tssiStartIndex];
- signal->theData[5] = ssiPageptr.p->word32[tssiStartIndex + 1];
- signal->theData[6] = ssiPageptr.p->word32[tssiStartIndex + 2];
- signal->theData[7] = ssiPageptr.p->word32[tssiStartIndex + 3];
- signal->theData[8] = ssiPageptr.p->word32[tssiStartIndex + 4];
- signal->theData[9] = ssiPageptr.p->word32[tssiStartIndex + 5];
- signal->theData[10] = ssiPageptr.p->word32[tssiStartIndex + 6];
- signal->theData[11] = ssiPageptr.p->word32[tssiStartIndex + 7];
- signal->theData[12] = ssiPageptr.p->word32[tssiStartIndex + 8];
- signal->theData[13] = ssiPageptr.p->word32[tssiStartIndex + 9];
- signal->theData[14] = ssiPageptr.p->word32[tssiStartIndex + 10];
- signal->theData[15] = ssiPageptr.p->word32[tssiStartIndex + 11];
- signal->theData[16] = ssiPageptr.p->word32[tssiStartIndex + 12];
- signal->theData[17] = ssiPageptr.p->word32[tssiStartIndex + 13];
- signal->theData[18] = ssiPageptr.p->word32[tssiStartIndex + 14];
- signal->theData[19] = ssiPageptr.p->word32[tssiStartIndex + 15];
- signal->theData[20] = ssiPageptr.p->word32[tssiStartIndex + 16];
- signal->theData[21] = ssiPageptr.p->word32[tssiStartIndex + 17];
- signal->theData[22] = ssiPageptr.p->word32[tssiStartIndex + 18];
- signal->theData[23] = ssiPageptr.p->word32[tssiStartIndex + 19];
- EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO24, signal, 24);
- tssiStartIndex = tssiStartIndex + ZMAXSCANSIGNALLEN;
- tssiKeyLen = tssiKeyLen - ZMAXSCANSIGNALLEN;
- goto SSI_LOOP_10;
- } else {
- jam();
- ndbrequire((tssiStartIndex + tssiKeyLen) <= 2048);
- for (tssiTmp = 0; tssiTmp < tssiKeyLen; tssiTmp++) {
- ckeys[tssiTmp] = ssiPageptr.p->word32[tssiStartIndex + tssiTmp];
- }//for
- signal->theData[0] = scanPtr.p->scanUserptr;
- signal->theData[1] = operationRecPtr.i;
- signal->theData[2] = operationRecPtr.p->fid;
- /* LOCAL FRAGMENT IDENTITY */
- signal->theData[3] = tssiKeyLen;
- signal->theData[4] = ckeys[0];
- signal->theData[5] = ckeys[1];
- signal->theData[6] = ckeys[2];
- signal->theData[7] = ckeys[3];
- signal->theData[8] = ckeys[4];
- signal->theData[9] = ckeys[5];
- signal->theData[10] = ckeys[6];
- signal->theData[11] = ckeys[7];
- signal->theData[12] = ckeys[8];
- signal->theData[13] = ckeys[9];
- signal->theData[14] = ckeys[10];
- signal->theData[15] = ckeys[11];
- signal->theData[16] = ckeys[12];
- signal->theData[17] = ckeys[13];
- signal->theData[18] = ckeys[14];
- signal->theData[19] = ckeys[15];
- signal->theData[20] = ckeys[16];
- signal->theData[21] = ckeys[17];
- signal->theData[22] = ckeys[18];
- signal->theData[23] = ckeys[19];
- EXECUTE_DIRECT(blockNo, GSN_ACC_SCAN_INFO24, signal, 24);
- }//if
- }//if
-}//Dbacc::sendScaninfo()
+ EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, 6);
+ return;
+}//Dbacc::sendNextScanConf()
/*---------------------------------------------------------------------------
* sendScanHbRep
@@ -13112,13 +11212,12 @@ Dbacc::execDUMP_STATE_ORD(Signal* signal)
scanPtr.p->minBucketIndexToRescan,
scanPtr.p->maxBucketIndexToRescan);
infoEvent(" scanBucketState=%d, scanLockHeld=%d, userBlockRef=%d, "
- "scanMask=%d scanLockMode=%d, keyInfoFlag=%d",
+ "scanMask=%d scanLockMode=%d",
scanPtr.p->scanBucketState,
scanPtr.p->scanLockHeld,
scanPtr.p->scanUserblockref,
scanPtr.p->scanMask,
- scanPtr.p->scanLockMode,
- scanPtr.p->scanKeyinfoFlag);
+ scanPtr.p->scanLockMode);
return;
}
diff --git a/ndb/src/kernel/blocks/dbacc/Makefile.am b/ndb/src/kernel/blocks/dbacc/Makefile.am
index 7ccfbe22f76..eeca061dead 100644
--- a/ndb/src/kernel/blocks/dbacc/Makefile.am
+++ b/ndb/src/kernel/blocks/dbacc/Makefile.am
@@ -3,6 +3,8 @@ noinst_LIBRARIES = libdbacc.a
libdbacc_a_SOURCES = DbaccInit.cpp DbaccMain.cpp
+INCLUDES_LOC = -I$(top_srcdir)/ndb/src/kernel/blocks/dbtup
+
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_kernel.mk.am
diff --git a/ndb/src/kernel/blocks/dbacc/Makefile_old b/ndb/src/kernel/blocks/dbacc/Makefile_old
deleted file mode 100644
index 93a830cec95..00000000000
--- a/ndb/src/kernel/blocks/dbacc/Makefile_old
+++ /dev/null
@@ -1,11 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := dbacc
-
-SOURCES = \
- DbaccInit.cpp \
- DbaccMain.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
index d1a8128ea7f..8327b7fe390 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.cpp
@@ -239,7 +239,11 @@ Dbdict::packTableIntoPagesImpl(SimpleProperties::Writer & w,
w.add(DictTabInfo::TableName, tablePtr.p->tableName);
w.add(DictTabInfo::TableId, tablePtr.i);
+#ifdef HAVE_TABLE_REORG
w.add(DictTabInfo::SecondTableId, tablePtr.p->secondTable);
+#else
+ w.add(DictTabInfo::SecondTableId, (Uint32)0);
+#endif
w.add(DictTabInfo::TableVersion, tablePtr.p->tableVersion);
w.add(DictTabInfo::NoOfKeyAttr, tablePtr.p->noOfPrimkey);
w.add(DictTabInfo::NoOfAttributes, tablePtr.p->noOfAttributes);
@@ -1436,6 +1440,7 @@ Uint32 Dbdict::getFreeTableRecord(Uint32 primaryTableId)
jam();
return RNIL;
}//if
+#ifdef HAVE_TABLE_REORG
bool secondFound = false;
for (tablePtr.i = firstTablePtr.i + 1; tablePtr.i < tabSize ; tablePtr.i++) {
jam();
@@ -1455,6 +1460,7 @@ Uint32 Dbdict::getFreeTableRecord(Uint32 primaryTableId)
firstTablePtr.p->tabState = TableRecord::NOT_DEFINED;
return RNIL;
}//if
+#endif
return firstTablePtr.i;
}//Dbdict::getFreeTableRecord()
@@ -3661,9 +3667,8 @@ Dbdict::execCREATE_FRAGMENTATION_CONF(Signal* signal){
req->tableId = tabPtr.i;
req->tableVersion = tabEntry->m_tableVersion + 1;
- sendSignal(rg, GSN_CREATE_TAB_REQ, signal,
- CreateTabReq::SignalLength, JBB);
-
+ sendFragmentedSignal(rg, GSN_CREATE_TAB_REQ, signal,
+ CreateTabReq::SignalLength, JBB);
return;
}
@@ -4097,14 +4102,14 @@ Dbdict::execADD_FRAGREQ(Signal* signal) {
req->maxLoadFactor = tabPtr.p->maxLoadFactor;
req->minLoadFactor = tabPtr.p->minLoadFactor;
req->kValue = tabPtr.p->kValue;
- req->lh3DistrBits = lhDistrBits;
- req->lh3PageBits = lhPageBits;
+ req->lh3DistrBits = 0; //lhDistrBits;
+ req->lh3PageBits = 0; //lhPageBits;
req->noOfAttributes = tabPtr.p->noOfAttributes;
req->noOfNullAttributes = tabPtr.p->noOfNullAttr;
req->noOfPagesToPreAllocate = 0;
req->schemaVersion = tabPtr.p->tableVersion;
Uint32 keyLen = tabPtr.p->tupKeyLength;
- req->keyLength = keyLen > 8 ? 0 : keyLen; // Put this into ACC instead
+ req->keyLength = keyLen; // wl-2066 no more "long keys"
req->nextLCP = lcpNo;
req->noOfKeyAttr = tabPtr.p->noOfPrimkey;
@@ -4624,7 +4629,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
jam();
tablePtr.p->tabState = TableRecord::DEFINING;
}//if
-
+#ifdef HAVE_TABLE_REORG
/* ---------------------------------------------------------------- */
// Get id of second table id and check that table doesn't already exist
// and set up links between first and second table.
@@ -4638,7 +4643,7 @@ void Dbdict::handleTabInfoInit(SimpleProperties::Reader & it,
secondTablePtr.p->tabState = TableRecord::REORG_TABLE_PREPARED;
secondTablePtr.p->secondTable = tablePtr.i;
tablePtr.p->secondTable = secondTablePtr.i;
-
+#endif
/* ---------------------------------------------------------------- */
// Set table version
/* ---------------------------------------------------------------- */
@@ -5536,10 +5541,12 @@ void Dbdict::releaseTableObject(Uint32 tableId, bool removeFromHash)
nextAttrRecord = attrPtr.p->nextAttrInTable;
c_attributeRecordPool.release(attrPtr);
}//if
+#ifdef HAVE_TABLE_REORG
Uint32 secondTableId = tablePtr.p->secondTable;
initialiseTableRecord(tablePtr);
c_tableRecordPool.getPtr(tablePtr, secondTableId);
initialiseTableRecord(tablePtr);
+#endif
return;
}//releaseTableObject()
diff --git a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
index 19c03a86e22..af80bcf5f94 100644
--- a/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
+++ b/ndb/src/kernel/blocks/dbdict/Dbdict.hpp
@@ -151,10 +151,10 @@ public:
/* Temporary record used during add/drop table */
Uint32 myConnect;
-
+#ifdef HAVE_TABLE_REORG
/* Second table used by this table (for table reorg) */
Uint32 secondTable;
-
+#endif
/* Next record in Pool */
Uint32 nextPool;
diff --git a/ndb/src/kernel/blocks/dbdict/Makefile_old b/ndb/src/kernel/blocks/dbdict/Makefile_old
deleted file mode 100644
index 46d938114fb..00000000000
--- a/ndb/src/kernel/blocks/dbdict/Makefile_old
+++ /dev/null
@@ -1,12 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := dbdict
-
-SOURCES = \
- Dbdict.cpp
-
-DIRS := printSchemafile
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
index 14fa262f871..0a2d50cb876 100644
--- a/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
+++ b/ndb/src/kernel/blocks/dbdih/Dbdih.hpp
@@ -147,7 +147,6 @@ public:
Uint32 nfConnect;
Uint32 table;
Uint32 userpointer;
- Uint32 nodeCount;
BlockReference userblockref;
};
typedef Ptr<ConnectRecord> ConnectRecordPtr;
diff --git a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
index 76aa745c3e0..c84908848f2 100644
--- a/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
+++ b/ndb/src/kernel/blocks/dbdih/DbdihMain.cpp
@@ -6852,8 +6852,7 @@ void Dbdih::execDIGETNODESREQ(Signal* signal)
TabRecord* regTabDesc = tabRecord;
jamEntry();
ptrCheckGuard(tabPtr, ttabFileSize, regTabDesc);
- hashValue = hashValue >> tabPtr.p->kvalue;
- Uint32 fragId = tabPtr.p->mask & hashValue;
+ Uint32 fragId = hashValue & tabPtr.p->mask;
ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
if (fragId < tabPtr.p->hashpointer) {
jam();
@@ -7080,24 +7079,22 @@ void Dbdih::execDIGETPRIMREQ(Signal* signal)
ndbrequire(tabPtr.p->tabStatus == TabRecord::TS_ACTIVE);
connectPtr.i = signal->theData[0];
- if(connectPtr.i != RNIL){
+ if(connectPtr.i != RNIL)
+ {
jam();
ptrCheckGuard(connectPtr, cconnectFileSize, connectRecord);
- ndbrequire(connectPtr.p->connectState == ConnectRecord::INUSE);
- getFragstore(tabPtr.p, fragId, fragPtr);
- connectPtr.p->nodeCount = extractNodeInfo(fragPtr.p, connectPtr.p->nodes);
signal->theData[0] = connectPtr.p->userpointer;
- signal->theData[1] = passThrough;
- signal->theData[2] = connectPtr.p->nodes[0];
- sendSignal(connectPtr.p->userblockref, GSN_DIGETPRIMCONF, signal, 3, JBB);
- return;
- }//if
- //connectPtr.i == RNIL -> question without connect record
+ }
+ else
+ {
+ jam();
+ signal->theData[0] = RNIL;
+ }
+
Uint32 nodes[MAX_REPLICAS];
getFragstore(tabPtr.p, fragId, fragPtr);
Uint32 count = extractNodeInfo(fragPtr.p, nodes);
- signal->theData[0] = RNIL;
signal->theData[1] = passThrough;
signal->theData[2] = nodes[0];
signal->theData[3] = nodes[1];
diff --git a/ndb/src/kernel/blocks/dbdih/Makefile_old b/ndb/src/kernel/blocks/dbdih/Makefile_old
deleted file mode 100644
index 83c1b95b5c4..00000000000
--- a/ndb/src/kernel/blocks/dbdih/Makefile_old
+++ /dev/null
@@ -1,13 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := dbdih
-
-DIRS := printSysfile
-
-SOURCES = \
- DbdihInit.cpp \
- DbdihMain.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
index d6987f3e478..ad19fc917e0 100644
--- a/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
+++ b/ndb/src/kernel/blocks/dblqh/Dblqh.hpp
@@ -29,6 +29,9 @@
#include <signaldata/LqhTransConf.hpp>
#include <signaldata/LqhFrag.hpp>
+// primary key is stored in TUP
+#include <../dbtup/Dbtup.hpp>
+
#ifdef DBLQH_C
// Constants
/* ------------------------------------------------------------------------- */
@@ -500,9 +503,7 @@ public:
WAIT_DELETE_STORED_PROC_ID_COPY = 6,
WAIT_ACC_COPY = 7,
WAIT_ACC_SCAN = 8,
- WAIT_SCAN_KEYINFO = 9,
WAIT_SCAN_NEXTREQ = 10,
- WAIT_COPY_KEYINFO = 11,
WAIT_CLOSE_SCAN = 12,
WAIT_CLOSE_COPY = 13,
WAIT_RELEASE_LOCK = 14,
@@ -550,6 +551,11 @@ public:
UintR scanErrorCounter;
UintR scanLocalFragid;
UintR scanSchemaVersion;
+
+ /**
+ * This is _always_ main table, even in range scan
+ * in which case scanTcrec->fragmentptr is different
+ */
Uint32 fragPtrI;
UintR scanStoredProcId;
ScanState scanState;
@@ -862,10 +868,6 @@ public:
*/
Uint8 fragDistributionKey;
/**
- * Used to calculate which local fragment to use.
- */
- Uint8 hashCheckBit;
- /**
* The identity of the next local checkpoint this fragment
* should perform.
*/
@@ -2029,6 +2031,7 @@ public:
Uint8 opExec;
Uint8 operation;
Uint8 reclenAiLqhkey;
+ Uint8 m_offset_current_keybuf;
Uint8 replicaType;
Uint8 simpleRead;
Uint8 seqNoReplica;
@@ -2132,8 +2135,6 @@ private:
void execACC_SCANREF(Signal* signal);
void execNEXT_SCANCONF(Signal* signal);
void execNEXT_SCANREF(Signal* signal);
- void execACC_SCAN_INFO(Signal* signal);
- void execACC_SCAN_INFO24(Signal* signal);
void execACC_TO_REF(Signal* signal);
void execSTORED_PROCCONF(Signal* signal);
void execSTORED_PROCREF(Signal* signal);
@@ -2254,7 +2255,7 @@ private:
void finishScanrec(Signal* signal);
void releaseScanrec(Signal* signal);
void seizeScanrec(Signal* signal);
- void sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *);
+ Uint32 sendKeyinfo20(Signal* signal, ScanRecord *, TcConnectionrec *);
void sendScanFragConf(Signal* signal, Uint32 scanCompleted);
void initCopyrec(Signal* signal);
void initCopyTc(Signal* signal);
@@ -2383,6 +2384,8 @@ private:
void seizeAttrinbuf(Signal* signal);
Uint32 seize_attrinbuf();
Uint32 release_attrinbuf(Uint32);
+ Uint32 copy_bounds(Uint32 * dst, TcConnectionrec*);
+
void seizeFragmentrec(Signal* signal);
void seizePageRef(Signal* signal);
void seizeTcrec();
@@ -2429,7 +2432,6 @@ private:
void localCommitLab(Signal* signal);
void abortErrorLab(Signal* signal);
void continueAfterReceivingAllAiLab(Signal* signal);
- void sendScanFragRefLateLab(Signal* signal);
void abortStateHandlerLab(Signal* signal);
void writeAttrinfoLab(Signal* signal);
void scanAttrinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
@@ -2474,7 +2476,7 @@ private:
void sendExecFragRefLab(Signal* signal);
void fragrefLab(Signal* signal, BlockReference retRef,
Uint32 retPtr, Uint32 errorCode);
- void accFragRefLab(Signal* signal);
+ void abortAddFragOps(Signal* signal);
void rwConcludedLab(Signal* signal);
void sendsttorryLab(Signal* signal);
void initialiseRecordsLab(Signal* signal, Uint32 data, Uint32, Uint32);
@@ -2496,7 +2498,7 @@ private:
void nextScanConfScanLab(Signal* signal);
void nextScanConfCopyLab(Signal* signal);
void continueScanNextReqLab(Signal* signal);
- bool keyinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length);
+ void keyinfoLab(const Uint32 * src, const Uint32 * end);
void copySendTupkeyReqLab(Signal* signal);
void storedProcConfScanLab(Signal* signal);
void storedProcConfCopyLab(Signal* signal);
@@ -2552,7 +2554,6 @@ private:
void accScanConfScanLab(Signal* signal);
void accScanConfCopyLab(Signal* signal);
void scanLockReleasedLab(Signal* signal);
- void accScanInfoEnterLab(Signal* signal, Uint32* dataPtr, Uint32 length);
void openSrFourthNextLab(Signal* signal);
void closingInitLab(Signal* signal);
void closeExecSrCompletedLab(Signal* signal);
@@ -2567,6 +2568,8 @@ private:
void initData();
void initRecords();
+ Dbtup* c_tup;
+ Uint32 readPrimaryKeys(ScanRecord*, TcConnectionrec*, Uint32 * dst);
// ----------------------------------------------------------------
// These are variables handling the records. For most records one
// pointer to the array of structs, one pointer-struct, a file size
@@ -2925,4 +2928,23 @@ Dblqh::ScanRecord::check_scan_batch_completed() const
(max_bytes > 0 && (m_curr_batch_size_bytes >= max_bytes));
}
+inline
+void
+Dblqh::i_get_acc_ptr(ScanRecord* scanP, Uint32* &acc_ptr, Uint32 index)
+{
+ if (index == 0) {
+ acc_ptr= (Uint32*)&scanP->scan_acc_op_ptr[0];
+ } else {
+ Uint32 attr_buf_index, attr_buf_rec;
+
+ AttrbufPtr regAttrPtr;
+ jam();
+ attr_buf_rec= (index + 31) / 32;
+ attr_buf_index= (index - 1) & 31;
+ regAttrPtr.i= scanP->scan_acc_op_ptr[attr_buf_rec];
+ ptrCheckGuard(regAttrPtr, cattrinbufFileSize, attrbuf);
+ acc_ptr= (Uint32*)&regAttrPtr.p->attrbuf[attr_buf_index];
+ }
+}
+
#endif
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
index d0fef8753cb..f8ce8845a51 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhInit.cpp
@@ -274,8 +274,6 @@ Dblqh::Dblqh(const class Configuration & conf):
addRecSignal(GSN_ACC_SCANREF, &Dblqh::execACC_SCANREF);
addRecSignal(GSN_NEXT_SCANCONF, &Dblqh::execNEXT_SCANCONF);
addRecSignal(GSN_NEXT_SCANREF, &Dblqh::execNEXT_SCANREF);
- addRecSignal(GSN_ACC_SCAN_INFO, &Dblqh::execACC_SCAN_INFO);
- addRecSignal(GSN_ACC_SCAN_INFO24, &Dblqh::execACC_SCAN_INFO24);
addRecSignal(GSN_STORED_PROCCONF, &Dblqh::execSTORED_PROCCONF);
addRecSignal(GSN_STORED_PROCREF, &Dblqh::execSTORED_PROCREF);
addRecSignal(GSN_COPY_FRAGREQ, &Dblqh::execCOPY_FRAGREQ);
diff --git a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
index cd15ad0c3b2..2b531ede3d1 100644
--- a/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
+++ b/ndb/src/kernel/blocks/dblqh/DblqhMain.cpp
@@ -490,6 +490,8 @@ void Dblqh::execSTTOR(Signal* signal)
jam();
cstartPhase = tstartPhase;
sttorStartphase1Lab(signal);
+ c_tup = (Dbtup*)globalData.getBlock(DBTUP);
+ ndbrequire(c_tup != 0);
return;
break;
default:
@@ -912,6 +914,10 @@ void Dblqh::execREAD_CONFIG_REQ(Signal* signal)
/* *********************************************************> */
/* LQHFRAGREQ: Create new fragments for a table. Sender DICT */
/* *********************************************************> */
+
+// this unbelievable mess could be replaced by one signal to LQH
+// and execute direct to local DICT to get everything at once
+
void Dblqh::execLQHFRAGREQ(Signal* signal)
{
jamEntry();
@@ -1049,6 +1055,11 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
addfragptr.p->lh3DistrBits = tlhstar;
addfragptr.p->tableType = tableType;
addfragptr.p->primaryTableId = primaryTableId;
+ //
+ addfragptr.p->tup1Connectptr = RNIL;
+ addfragptr.p->tup2Connectptr = RNIL;
+ addfragptr.p->tux1Connectptr = RNIL;
+ addfragptr.p->tux2Connectptr = RNIL;
if (DictTabInfo::isTable(tableType) ||
DictTabInfo::isHashIndex(tableType)) {
@@ -1078,8 +1089,8 @@ void Dblqh::execLQHFRAGREQ(Signal* signal)
if (DictTabInfo::isOrderedIndex(tableType)) {
jam();
// NOTE: next 2 lines stolen from ACC
- addfragptr.p->fragid1 = (0 << tlhstar) | fragId;
- addfragptr.p->fragid2 = (1 << tlhstar) | fragId;
+ addfragptr.p->fragid1 = (fragId << 1) | 0;
+ addfragptr.p->fragid2 = (fragId << 1) | 1;
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
sendAddFragReq(signal);
return;
@@ -1099,7 +1110,6 @@ void Dblqh::execACCFRAGCONF(Signal* signal)
Uint32 fragId2 = signal->theData[3];
Uint32 accFragPtr1 = signal->theData[4];
Uint32 accFragPtr2 = signal->theData[5];
- Uint32 hashCheckBit = signal->theData[6];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
ndbrequire(addfragptr.p->addfragStatus == AddFragRecord::ACC_ADDFRAG);
@@ -1110,7 +1120,6 @@ void Dblqh::execACCFRAGCONF(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
fragptr.p->accFragptr[0] = accFragPtr1;
fragptr.p->accFragptr[1] = accFragPtr2;
- fragptr.p->hashCheckBit = hashCheckBit;
addfragptr.p->addfragStatus = AddFragRecord::WAIT_TWO_TUP;
sendAddFragReq(signal);
@@ -1268,7 +1277,7 @@ Dblqh::sendAddFragReq(Signal* signal)
tuxreq->noOfAttr = addfragptr.p->noOfAttr - 1; /* skip NDB$TNODE */
tuxreq->fragId =
addfragptr.p->addfragStatus == AddFragRecord::WAIT_TWO_TUX
- ? addfragptr.p->fragid1 : addfragptr.p->fragid2;
+ ? addfragptr.p->fragid1: addfragptr.p->fragid2;
tuxreq->fragOff = addfragptr.p->lh3DistrBits;
tuxreq->tableType = addfragptr.p->tableType;
tuxreq->primaryTableId = addfragptr.p->primaryTableId;
@@ -1329,15 +1338,21 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
{
jamEntry();
addfragptr.i = signal->theData[0];
+ // implies that operation was released on the other side
+ const bool lastAttr = signal->theData[1];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
switch (addfragptr.p->addfragStatus) {
case AddFragRecord::TUP_ATTR_WAIT1:
jam();
+ if (lastAttr)
+ addfragptr.p->tup1Connectptr = RNIL;
addfragptr.p->addfragStatus = AddFragRecord::TUP_ATTR_WAIT2;
sendAddAttrReq(signal);
break;
case AddFragRecord::TUP_ATTR_WAIT2:
jam();
+ if (lastAttr)
+ addfragptr.p->tup2Connectptr = RNIL;
if (DictTabInfo::isOrderedIndex(addfragptr.p->tableType)) {
addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT1;
sendAddAttrReq(signal);
@@ -1347,11 +1362,15 @@ void Dblqh::execTUP_ADD_ATTCONF(Signal* signal)
break;
case AddFragRecord::TUX_ATTR_WAIT1:
jam();
+ if (lastAttr)
+ addfragptr.p->tux1Connectptr = RNIL;
addfragptr.p->addfragStatus = AddFragRecord::TUX_ATTR_WAIT2;
sendAddAttrReq(signal);
break;
case AddFragRecord::TUX_ATTR_WAIT2:
jam();
+ if (lastAttr)
+ addfragptr.p->tux2Connectptr = RNIL;
goto done_with_attr;
break;
done_with_attr:
@@ -1455,6 +1474,7 @@ Dblqh::sendAddAttrReq(Signal* signal)
jam();
TupAddAttrConf* tupconf = (TupAddAttrConf*)signal->getDataPtrSend();
tupconf->userPtr = addfragptr.i;
+ tupconf->lastAttr = false;
sendSignal(reference(), GSN_TUP_ADD_ATTCONF,
signal, TupAddAttrConf::SignalLength, JBB);
return;
@@ -1485,6 +1505,7 @@ Dblqh::sendAddAttrReq(Signal* signal)
jam();
TuxAddAttrConf* tuxconf = (TuxAddAttrConf*)signal->getDataPtrSend();
tuxconf->userPtr = addfragptr.i;
+ tuxconf->lastAttr = false;
sendSignal(reference(), GSN_TUX_ADD_ATTRCONF,
signal, TuxAddAttrConf::SignalLength, JBB);
return;
@@ -1549,6 +1570,40 @@ void Dblqh::fragrefLab(Signal* signal,
return;
}//Dblqh::fragrefLab()
+/*
+ * Abort on-going ops.
+ */
+void Dblqh::abortAddFragOps(Signal* signal)
+{
+ fragptr.i = addfragptr.p->fragmentPtr;
+ ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
+ signal->theData[0] = (Uint32)-1;
+ if (addfragptr.p->tup1Connectptr != RNIL) {
+ jam();
+ signal->theData[1] = addfragptr.p->tup1Connectptr;
+ sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
+ addfragptr.p->tup1Connectptr = RNIL;
+ }
+ if (addfragptr.p->tup2Connectptr != RNIL) {
+ jam();
+ signal->theData[1] = addfragptr.p->tup2Connectptr;
+ sendSignal(fragptr.p->tupBlockref, GSN_TUPFRAGREQ, signal, 2, JBB);
+ addfragptr.p->tup2Connectptr = RNIL;
+ }
+ if (addfragptr.p->tux1Connectptr != RNIL) {
+ jam();
+ signal->theData[1] = addfragptr.p->tux1Connectptr;
+ sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
+ addfragptr.p->tux1Connectptr = RNIL;
+ }
+ if (addfragptr.p->tux2Connectptr != RNIL) {
+ jam();
+ signal->theData[1] = addfragptr.p->tux2Connectptr;
+ sendSignal(fragptr.p->tuxBlockref, GSN_TUXFRAGREQ, signal, 2, JBB);
+ addfragptr.p->tux2Connectptr = RNIL;
+ }
+}
+
/* ************>> */
/* ACCFRAGREF > */
/* ************>> */
@@ -1582,6 +1637,27 @@ void Dblqh::execTUPFRAGREF(Signal* signal)
fragptr.i = addfragptr.p->fragmentPtr;
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
addfragptr.p->addfragErrorCode = terrorCode;
+
+ // no operation to release, just add some jams
+ switch (addfragptr.p->addfragStatus) {
+ case AddFragRecord::WAIT_TWO_TUP:
+ jam();
+ break;
+ case AddFragRecord::WAIT_ONE_TUP:
+ jam();
+ break;
+ case AddFragRecord::WAIT_TWO_TUX:
+ jam();
+ break;
+ case AddFragRecord::WAIT_ONE_TUX:
+ jam();
+ break;
+ default:
+ ndbrequire(false);
+ break;
+ }
+ abortAddFragOps(signal);
+
const Uint32 ref = addfragptr.p->dictBlockref;
const Uint32 senderData = addfragptr.p->dictConnectptr;
const Uint32 errorCode = addfragptr.p->addfragErrorCode;
@@ -1605,11 +1681,38 @@ void Dblqh::execTUXFRAGREF(Signal* signal)
void Dblqh::execTUP_ADD_ATTRREF(Signal* signal)
{
jamEntry();
-
addfragptr.i = signal->theData[0];
ptrCheckGuard(addfragptr, caddfragrecFileSize, addFragRecord);
terrorCode = signal->theData[1];
addfragptr.p->addfragErrorCode = terrorCode;
+
+ // operation was released on the other side
+ switch (addfragptr.p->addfragStatus) {
+ case AddFragRecord::TUP_ATTR_WAIT1:
+ jam();
+ ndbrequire(addfragptr.p->tup1Connectptr != RNIL);
+ addfragptr.p->tup1Connectptr = RNIL;
+ break;
+ case AddFragRecord::TUP_ATTR_WAIT2:
+ jam();
+ ndbrequire(addfragptr.p->tup2Connectptr != RNIL);
+ addfragptr.p->tup2Connectptr = RNIL;
+ break;
+ case AddFragRecord::TUX_ATTR_WAIT1:
+ jam();
+ ndbrequire(addfragptr.p->tux1Connectptr != RNIL);
+ addfragptr.p->tux1Connectptr = RNIL;
+ break;
+ case AddFragRecord::TUX_ATTR_WAIT2:
+ jam();
+ ndbrequire(addfragptr.p->tux2Connectptr != RNIL);
+ addfragptr.p->tux2Connectptr = RNIL;
+ break;
+ default:
+ ndbrequire(false);
+ break;
+ }
+ abortAddFragOps(signal);
const Uint32 Ref = addfragptr.p->dictBlockref;
const Uint32 senderData = addfragptr.p->dictConnectptr;
@@ -2981,6 +3084,7 @@ void Dblqh::execATTRINFO(Signal* signal)
return;
break;
default:
+ ndbout_c("%d", regTcPtr->transactionState);
ndbrequire(false);
break;
}//switch
@@ -3420,7 +3524,7 @@ void Dblqh::execLQHKEYREQ(Signal* signal)
LQHKEY_error(signal, 6);
return;
}//if
- regTcPtr->localFragptr = (regTcPtr->hashValue >> fragptr.p->hashCheckBit) & 1;
+ regTcPtr->localFragptr = regTcPtr->hashValue & 1;
Uint8 TcopyType = fragptr.p->fragCopy;
tfragDistKey = fragptr.p->fragDistributionKey;
if (fragptr.p->fragStatus == Fragrecord::ACTIVE_CREATION) {
@@ -6729,49 +6833,6 @@ Dblqh::scanMarkers(Signal* signal,
* ALL TUPLES IN THE FRAGMENT. TUP PERFORMS THE NECESSARY SEARCH CONDITIONS
* TO ENSURE THAT ONLY VALID TUPLES ARE RETURNED TO THE APPLICATION.
* ------------------------------------------------------------------------- */
-
-void Dblqh::execACC_SCAN_INFO(Signal* signal)
-{
- jamEntry();
- scanptr.i = signal->theData[0];
- c_scanRecordPool.getPtr(scanptr);
- Uint32 length = signal->theData[3];
- ndbrequire(length <= 4);
- accScanInfoEnterLab(signal, &signal->theData[4], length);
-}//Dblqh::execACC_SCAN_INFO()
-
-
-void Dblqh::execACC_SCAN_INFO24(Signal* signal)
-{
- jamEntry();
- scanptr.i = signal->theData[0];
- c_scanRecordPool.getPtr(scanptr);
- Uint32 length = signal->theData[3];
- ndbrequire(length <= 20);
- accScanInfoEnterLab(signal, &signal->theData[4], length);
-}//Dblqh::execACC_SCAN_INFO24()
-
-void Dblqh::accScanInfoEnterLab(Signal* signal,
- Uint32* dataPtr,
- Uint32 length)
-{
- ndbrequire(length != 0);
- if (scanptr.p->scanState == ScanRecord::WAIT_SCAN_KEYINFO) {
- jam();
- if (keyinfoLab(signal, dataPtr, length)) {
- jam();
- nextScanConfLoopLab(signal);
- }//if
- } else {
- ndbrequire(scanptr.p->scanState == ScanRecord::WAIT_COPY_KEYINFO);
- jam();
- if (keyinfoLab(signal, dataPtr, length)) {
- jam();
- copySendTupkeyReqLab(signal);
- }//if
- }//if
-}//Dblqh::accScanInfoEnterLab()
-
/* *************** */
/* ACC_SCANCONF > */
/* *************** */
@@ -6901,6 +6962,7 @@ void Dblqh::execSTORED_PROCREF(Signal* signal)
switch (scanptr.p->scanState) {
case ScanRecord::WAIT_STORED_PROC_SCAN:
jam();
+ scanptr.p->scanCompletedStatus = ZTRUE;
scanptr.p->scanStoredProcId = signal->theData[2];
tcConnectptr.p->errorCode = errorCode;
closeScanLab(signal);
@@ -7058,10 +7120,7 @@ void Dblqh::continueScanNextReqLab(Signal* signal)
// Update timer on tcConnectRecord
tcConnectptr.p->tcTimer = cLqhTimeOutCount;
-
init_acc_ptr_list(scanptr.p);
- scanptr.p->m_curr_batch_size_rows = 0;
- scanptr.p->m_curr_batch_size_bytes= 0;
scanptr.p->scanFlag = NextScanReq::ZSCAN_NEXT;
scanNextLoopLab(signal);
}//Dblqh::continueScanNextReqLab()
@@ -7140,7 +7199,6 @@ void Dblqh::closeScanRequestLab(Signal* signal)
jam();
tupScanCloseConfLab(signal);
break;
- case ScanRecord::WAIT_SCAN_KEYINFO:
case ScanRecord::WAIT_NEXT_SCAN:
jam();
/* -------------------------------------------------------------------
@@ -7204,6 +7262,7 @@ void Dblqh::closeScanRequestLab(Signal* signal)
* WE ARE STILL WAITING FOR THE ATTRIBUTE INFORMATION THAT
* OBVIOUSLY WILL NOT ARRIVE. WE CAN QUIT IMMEDIATELY HERE.
* --------------------------------------------------------------------- */
+ //XXX jonas this have to be wrong...
releaseOprec(signal);
if (tcConnectptr.p->abortState == TcConnectionrec::NEW_FROM_TC) {
jam();
@@ -7219,6 +7278,8 @@ void Dblqh::closeScanRequestLab(Signal* signal)
scanptr.p->m_curr_batch_size_rows = 0;
scanptr.p->m_curr_batch_size_bytes= 0;
sendScanFragConf(signal, ZTRUE);
+ abort_scan(signal, scanptr.i, 0);
+ return;
break;
case TcConnectionrec::SCAN_TUPKEY:
case TcConnectionrec::SCAN_FIRST_STOPPED:
@@ -7260,22 +7321,32 @@ void Dblqh::scanLockReleasedLab(Signal* signal)
tcConnectptr.i = scanptr.p->scanTcrec;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
releaseActiveFrag(signal);
+
if (scanptr.p->scanReleaseCounter == scanptr.p->m_curr_batch_size_rows) {
if ((scanptr.p->scanErrorCounter > 0) ||
(scanptr.p->scanCompletedStatus == ZTRUE)) {
jam();
+ scanptr.p->m_curr_batch_size_rows = 0;
+ scanptr.p->m_curr_batch_size_bytes = 0;
closeScanLab(signal);
} else if (scanptr.p->check_scan_batch_completed() &&
scanptr.p->scanLockHold != ZTRUE) {
jam();
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
sendScanFragConf(signal, ZFALSE);
+ } else if (scanptr.p->m_last_row && !scanptr.p->scanLockHold) {
+ jam();
+ closeScanLab(signal);
+ return;
} else {
jam();
/*
- We came here after releasing locks after receiving SCAN_NEXTREQ from TC. We only
- come here when scanHoldLock == ZTRUE
- */
+ * We came here after releasing locks after
+ * receiving SCAN_NEXTREQ from TC. We only come here
+ * when scanHoldLock == ZTRUE
+ */
+ scanptr.p->m_curr_batch_size_rows = 0;
+ scanptr.p->m_curr_batch_size_bytes = 0;
continueScanNextReqLab(signal);
}//if
} else if (scanptr.p->scanReleaseCounter < scanptr.p->m_curr_batch_size_rows) {
@@ -7362,25 +7433,6 @@ Dblqh::init_acc_ptr_list(ScanRecord* scanP)
scanP->scan_acc_index = 0;
}
-inline
-void
-Dblqh::i_get_acc_ptr(ScanRecord* scanP, Uint32* &acc_ptr, Uint32 index)
-{
- if (index == 0) {
- acc_ptr= (Uint32*)&scanP->scan_acc_op_ptr[0];
- } else {
- Uint32 attr_buf_index, attr_buf_rec;
-
- AttrbufPtr regAttrPtr;
- jam();
- attr_buf_rec= (index + 31) / 32;
- attr_buf_index= (index - 1) & 31;
- regAttrPtr.i= scanP->scan_acc_op_ptr[attr_buf_rec];
- ptrCheckGuard(regAttrPtr, cattrinbufFileSize, attrbuf);
- acc_ptr= (Uint32*)&regAttrPtr.p->attrbuf[attr_buf_index];
- }
-}
-
Uint32
Dblqh::get_acc_ptr_from_scan_record(ScanRecord* scanP,
Uint32 index,
@@ -7576,7 +7628,6 @@ void Dblqh::continueAfterReceivingAllAiLab(Signal* signal)
req->fragmentNo = tcConnectptr.p->fragmentid;
req->requestInfo = 0;
AccScanReq::setLockMode(req->requestInfo, scanptr.p->scanLockMode);
- AccScanReq::setKeyinfoFlag(req->requestInfo, scanptr.p->scanKeyinfoFlag);
AccScanReq::setReadCommittedFlag(req->requestInfo, scanptr.p->readCommitted);
req->transId1 = tcConnectptr.p->transid[0];
req->transId2 = tcConnectptr.p->transid[1];
@@ -7611,18 +7662,25 @@ void Dblqh::abort_scan(Signal* signal, Uint32 scan_ptr_i, Uint32 errcode){
jam();
scanptr.i = scan_ptr_i;
c_scanRecordPool.getPtr(scanptr);
+
+ fragptr.i = tcConnectptr.p->fragmentptr;
+ ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
finishScanrec(signal);
releaseScanrec(signal);
tcConnectptr.p->transactionState = TcConnectionrec::IDLE;
tcConnectptr.p->abortState = TcConnectionrec::ABORT_ACTIVE;
-
- ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
- ref->senderData = tcConnectptr.p->clientConnectrec;
- ref->transId1 = tcConnectptr.p->transid[0];
- ref->transId2 = tcConnectptr.p->transid[1];
- ref->errorCode = errcode;
- sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
- ScanFragRef::SignalLength, JBB);
+
+ if(errcode)
+ {
+ jam();
+ ScanFragRef * ref = (ScanFragRef*)&signal->theData[0];
+ ref->senderData = tcConnectptr.p->clientConnectrec;
+ ref->transId1 = tcConnectptr.p->transid[0];
+ ref->transId2 = tcConnectptr.p->transid[1];
+ ref->errorCode = errcode;
+ sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGREF, signal,
+ ScanFragRef::SignalLength, JBB);
+ }
deleteTransidHash(signal);
releaseOprec(signal);
releaseTcrec(signal, tcConnectptr);
@@ -7674,11 +7732,6 @@ void Dblqh::execSCAN_HBREP(Signal* signal)
}
}
-void Dblqh::sendScanFragRefLateLab(Signal* signal)
-{
-}//Dblqh::sendScanFragRefLateLab()
-
-
void Dblqh::accScanConfScanLab(Signal* signal)
{
AccScanConf * const accScanConf = (AccScanConf *)&signal->theData[0];
@@ -7697,17 +7750,15 @@ void Dblqh::accScanConfScanLab(Signal* signal)
return;
}//if
scanptr.p->scanAccPtr = accScanConf->accPtr;
- Uint32 boundAiLength = tcConnectptr.p->primKeyLen - 4;
if (scanptr.p->rangeScan) {
jam();
- TuxBoundInfo* const req = (TuxBoundInfo*)signal->getDataPtrSend();
+ TuxBoundInfo* req = (TuxBoundInfo*)signal->getDataPtrSend();
req->errorCode = RNIL;
req->tuxScanPtrI = scanptr.p->scanAccPtr;
- req->boundAiLength = boundAiLength;
- if(boundAiLength > 0)
- sendKeyinfoAcc(signal, TuxBoundInfo::SignalLength);
- EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO,
- signal, TuxBoundInfo::SignalLength + boundAiLength);
+ Uint32 len = req->boundAiLength = copy_bounds(req->data, tcConnectptr.p);
+ EXECUTE_DIRECT(DBTUX, GSN_TUX_BOUND_INFO, signal,
+ TuxBoundInfo::SignalLength + len);
+
jamEntry();
if (req->errorCode != 0) {
jam();
@@ -7719,35 +7770,175 @@ void Dblqh::accScanConfScanLab(Signal* signal)
tcConnectptr.p->errorCode = req->errorCode;
}
}
- scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
- signal->theData[0] = tcConnectptr.p->tupConnectrec;
- signal->theData[1] = tcConnectptr.p->tableref;
- signal->theData[2] = scanptr.p->scanSchemaVersion;
- signal->theData[3] = ZSTORED_PROC_SCAN;
- signal->theData[4] = scanptr.p->scanAiLength;
- sendSignal(tcConnectptr.p->tcTupBlockref,
- GSN_STORED_PROCREQ, signal, 5, JBB);
-
- signal->theData[0] = tcConnectptr.p->tupConnectrec;
- AttrbufPtr regAttrinbufptr;
- regAttrinbufptr.i = tcConnectptr.p->firstAttrinbuf;
- while (regAttrinbufptr.i != RNIL) {
- ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
+ scanptr.p->scanState = ScanRecord::WAIT_STORED_PROC_SCAN;
+ if(scanptr.p->scanStoredProcId == RNIL)
+ {
jam();
- Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
- ndbrequire(dataLen != 0);
- // first 3 words already set in STORED_PROCREQ
- MEMCOPY_NO_WORDS(&signal->theData[3],
- &regAttrinbufptr.p->attrbuf[0],
- dataLen);
+ signal->theData[0] = tcConnectptr.p->tupConnectrec;
+ signal->theData[1] = tcConnectptr.p->tableref;
+ signal->theData[2] = scanptr.p->scanSchemaVersion;
+ signal->theData[3] = ZSTORED_PROC_SCAN;
+
+ signal->theData[4] = scanptr.p->scanAiLength;
sendSignal(tcConnectptr.p->tcTupBlockref,
- GSN_ATTRINFO, signal, dataLen + 3, JBB);
- regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
- }//while
- releaseOprec(signal);
+ GSN_STORED_PROCREQ, signal, 5, JBB);
+
+ signal->theData[0] = tcConnectptr.p->tupConnectrec;
+ AttrbufPtr regAttrinbufptr;
+ Uint32 firstAttr = regAttrinbufptr.i = tcConnectptr.p->firstAttrinbuf;
+ while (regAttrinbufptr.i != RNIL) {
+ ptrCheckGuard(regAttrinbufptr, cattrinbufFileSize, attrbuf);
+ jam();
+ Uint32 dataLen = regAttrinbufptr.p->attrbuf[ZINBUF_DATA_LEN];
+ ndbrequire(dataLen != 0);
+ // first 3 words already set in STORED_PROCREQ
+ MEMCOPY_NO_WORDS(&signal->theData[3],
+ &regAttrinbufptr.p->attrbuf[0],
+ dataLen);
+ sendSignal(tcConnectptr.p->tcTupBlockref,
+ GSN_ATTRINFO, signal, dataLen + 3, JBB);
+ regAttrinbufptr.i = regAttrinbufptr.p->attrbuf[ZINBUF_NEXT];
+ c_no_attrinbuf_recs++;
+ }//while
+
+ /**
+ * Release attr info
+ */
+ if(firstAttr != RNIL)
+ {
+ regAttrinbufptr.p->attrbuf[ZINBUF_NEXT] = cfirstfreeAttrinbuf;
+ cfirstfreeAttrinbuf = firstAttr;
+ tcConnectptr.p->firstAttrinbuf = tcConnectptr.p->lastAttrinbuf = RNIL;
+ }
+ }
+ else
+ {
+ jam();
+ storedProcConfScanLab(signal);
+ }
}//Dblqh::accScanConfScanLab()
+#define print_buf(s,idx,len) {\
+ printf(s); Uint32 t2=len; DatabufPtr t3; t3.i = idx; \
+ while(t3.i != RNIL && t2-- > 0){\
+ ptrCheckGuard(t3, cdatabufFileSize, databuf);\
+ printf("%d ", t3.i); t3.i= t3.p->nextDatabuf;\
+ } printf("\n"); }
+
+Uint32
+Dblqh::copy_bounds(Uint32 * dst, TcConnectionrec* tcPtrP)
+{
+ /**
+ * copy_bounds handles multiple bounds by
+ * in the 16 upper bits of the first words (used to specify bound type)
+ * setting the length of this specific bound
+ *
+ */
+
+ DatabufPtr regDatabufptr;
+ Uint32 left = 4 - tcPtrP->m_offset_current_keybuf; // left in buf
+ Uint32 totalLen = tcPtrP->primKeyLen - 4;
+ regDatabufptr.i = tcPtrP->firstTupkeybuf;
+
+ ndbassert(tcPtrP->primKeyLen >= 4);
+ ndbassert(tcPtrP->m_offset_current_keybuf < 4);
+ ndbassert(!(totalLen == 0 && regDatabufptr.i != RNIL));
+ ndbassert(!(totalLen != 0 && regDatabufptr.i == RNIL));
+
+ if(totalLen)
+ {
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ Uint32 sig0 = regDatabufptr.p->data[0];
+ Uint32 sig1 = regDatabufptr.p->data[1];
+ Uint32 sig2 = regDatabufptr.p->data[2];
+ Uint32 sig3 = regDatabufptr.p->data[3];
+
+ switch(left){
+ case 4:
+ * dst++ = sig0;
+ case 3:
+ * dst++ = sig1;
+ case 2:
+ * dst++ = sig2;
+ case 1:
+ * dst++ = sig3;
+ }
+
+ Uint32 first = (* (dst - left)); // First word in range
+ (* (dst - left)) = (first & 0xFFFF); // Remove length (16 upper bits)
+
+ // Length of this range
+ Uint8 offset;
+ const Uint32 len = (first >> 16) ? (first >> 16) : totalLen;
+
+ if(len < left)
+ {
+ offset = len;
+ }
+ else
+ {
+ Databuf * lastP;
+ left = (len - left);
+ regDatabufptr.i = regDatabufptr.p->nextDatabuf;
+
+ while(left >= 4)
+ {
+ left -= 4;
+ lastP = regDatabufptr.p;
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ sig0 = regDatabufptr.p->data[0];
+ sig1 = regDatabufptr.p->data[1];
+ sig2 = regDatabufptr.p->data[2];
+ sig3 = regDatabufptr.p->data[3];
+ regDatabufptr.i = regDatabufptr.p->nextDatabuf;
+
+ * dst++ = sig0;
+ * dst++ = sig1;
+ * dst++ = sig2;
+ * dst++ = sig3;
+ }
+
+ if(left > 0)
+ {
+ lastP = regDatabufptr.p;
+ ptrCheckGuard(regDatabufptr, cdatabufFileSize, databuf);
+ sig0 = regDatabufptr.p->data[0];
+ sig1 = regDatabufptr.p->data[1];
+ sig2 = regDatabufptr.p->data[2];
+ sig3 = regDatabufptr.p->data[3];
+ * dst++ = sig0;
+ * dst++ = sig1;
+ * dst++ = sig2;
+ * dst++ = sig3;
+ }
+ else
+ {
+ lastP = regDatabufptr.p;
+ }
+ offset = left & 3;
+ lastP->nextDatabuf = cfirstfreeDatabuf;
+ cfirstfreeDatabuf = tcPtrP->firstTupkeybuf;
+ ndbassert(cfirstfreeDatabuf != RNIL);
+ }
+
+ if(len == totalLen && regDatabufptr.i != RNIL)
+ {
+ regDatabufptr.p->nextDatabuf = cfirstfreeDatabuf;
+ cfirstfreeDatabuf = regDatabufptr.i;
+ tcPtrP->lastTupkeybuf = regDatabufptr.i = RNIL;
+ ndbassert(cfirstfreeDatabuf != RNIL);
+ }
+
+ tcPtrP->m_offset_current_keybuf = offset;
+ tcPtrP->firstTupkeybuf = regDatabufptr.i;
+ tcPtrP->primKeyLen = 4 + totalLen - len;
+
+ return len;
+ }
+ return totalLen;
+}
+
/* -------------------------------------------------------------------------
* ENTER STORED_PROCCONF WITH
* TC_CONNECTPTR,
@@ -7798,7 +7989,6 @@ void Dblqh::continueFirstScanAfterBlockedLab(Signal* signal)
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
scanptr.p->scanState = ScanRecord::WAIT_NEXT_SCAN;
- init_acc_ptr_list(scanptr.p);
signal->theData[0] = scanptr.p->scanAccPtr;
signal->theData[1] = RNIL;
signal->theData[2] = NextScanReq::ZSCAN_NEXT;
@@ -7904,6 +8094,13 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
/*************************************************************
* STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
************************************************************ */
+ if (!scanptr.p->scanLockHold)
+ {
+ jam();
+ closeScanLab(signal);
+ return;
+ }
+
if (scanptr.p->scanCompletedStatus == ZTRUE) {
if ((scanptr.p->scanLockHold == ZTRUE) &&
(scanptr.p->m_curr_batch_size_rows > 0)) {
@@ -7919,7 +8116,10 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
if (scanptr.p->m_curr_batch_size_rows > 0) {
jam();
- scanptr.p->scanCompletedStatus = ZTRUE;
+
+ if((tcConnectptr.p->primKeyLen - 4) == 0)
+ scanptr.p->scanCompletedStatus = ZTRUE;
+
scanptr.p->scanState = ScanRecord::WAIT_SCAN_NEXTREQ;
sendScanFragConf(signal, ZFALSE);
return;
@@ -7974,22 +8174,6 @@ void Dblqh::nextScanConfScanLab(Signal* signal)
scanptr.p->scanLocalref[0] = nextScanConf->localKey[0];
scanptr.p->scanLocalref[1] = nextScanConf->localKey[1];
scanptr.p->scanLocalFragid = nextScanConf->fragId;
- if (scanptr.p->scanKeyinfoFlag) {
- jam();
- tcConnectptr.p->primKeyLen = nextScanConf->keyLength;
- seizeTupkeybuf(signal);
- databufptr.p->data[0] = nextScanConf->key[0];
- databufptr.p->data[1] = nextScanConf->key[1];
- databufptr.p->data[2] = nextScanConf->key[2];
- databufptr.p->data[3] = nextScanConf->key[3];
- if (nextScanConf->keyLength > 4) {
- jam();
- tcConnectptr.p->save1 = 4;
- scanptr.p->scanState = ScanRecord::WAIT_SCAN_KEYINFO;
- return;
- }//if
- }//if
- jam();
nextScanConfLoopLab(signal);
}//Dblqh::nextScanConfScanLab()
@@ -8001,7 +8185,6 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
if (scanptr.p->scanCompletedStatus == ZTRUE) {
jam();
releaseActiveFrag(signal);
- releaseOprec(signal);
if ((scanptr.p->scanLockHold == ZTRUE) &&
(scanptr.p->m_curr_batch_size_rows > 0)) {
jam();
@@ -8023,13 +8206,7 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
if (! scanptr.p->rangeScan) {
tableRef = tcConnectptr.p->tableref;
- if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[0];
- } else {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[1];
- }//if
+ tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
} else {
jam();
// for ordered index use primary table
@@ -8037,13 +8214,7 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
tFragPtr.i = fragptr.p->tableFragptr;
ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
tableRef = tFragPtr.p->tabRef;
- if (tFragPtr.p->fragId == scanptr.p->scanLocalFragid) {
- jam();
- tupFragPtr = tFragPtr.p->tupFragptr[0];
- } else {
- jam();
- tupFragPtr = tFragPtr.p->tupFragptr[1];
- }//if
+ tupFragPtr = tFragPtr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
}
{
jam();
@@ -8078,33 +8249,46 @@ void Dblqh::nextScanConfLoopLab(Signal* signal)
* -------------------------------------------------------------------------
* PRECONDITION: SCAN_STATE = WAIT_SCAN_KEYINFO
* ------------------------------------------------------------------------- */
-bool Dblqh::keyinfoLab(Signal* signal, Uint32* dataPtr, Uint32 length)
+void
+Dblqh::keyinfoLab(const Uint32 * src, const Uint32 * end)
{
- tcConnectptr.i = scanptr.p->scanTcrec;
- ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
- Uint32 index = 0;
do {
jam();
- seizeTupkeybuf(signal);
- databufptr.p->data[0] = dataPtr[index];
- databufptr.p->data[1] = dataPtr[index + 1];
- databufptr.p->data[2] = dataPtr[index + 2];
- databufptr.p->data[3] = dataPtr[index + 3];
- index += 4;
- tcConnectptr.p->save1 = tcConnectptr.p->save1 + 4;
- if (tcConnectptr.p->save1 >= tcConnectptr.p->primKeyLen) {
- jam();
- return true;
- }//if
- if (index >= length) {
- jam();
- return false;
- }//if
- } while (index < 20);
- ndbrequire(false);
- return false;
+ seizeTupkeybuf(0);
+ databufptr.p->data[0] = * src ++;
+ databufptr.p->data[1] = * src ++;
+ databufptr.p->data[2] = * src ++;
+ databufptr.p->data[3] = * src ++;
+ } while (src < end);
}//Dblqh::keyinfoLab()
+Uint32
+Dblqh::readPrimaryKeys(ScanRecord *scanP, TcConnectionrec *tcConP, Uint32 *dst)
+{
+ Uint32 tableId = tcConP->tableref;
+ Uint32 fragId = scanP->scanLocalFragid;
+ Uint32 fragPageId = scanP->scanLocalref[0];
+ Uint32 pageIndex = scanP->scanLocalref[1];
+
+ if(scanP->rangeScan)
+ {
+ jam();
+ // for ordered index use primary table
+ FragrecordPtr tFragPtr;
+ tFragPtr.i = fragptr.p->tableFragptr;
+ ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+ tableId = tFragPtr.p->tabRef;
+ }
+
+ int ret = c_tup->accReadPk(tableId, fragId, fragPageId, pageIndex, dst);
+ if(0)
+ ndbout_c("readPrimaryKeys(table: %d fragment: %d [ %d %d ] -> %d",
+ tableId, fragId, fragPageId, pageIndex, ret);
+ ndbassert(ret > 0);
+
+ return ret;
+}
+
/* -------------------------------------------------------------------------
* ENTER TUPKEYCONF
* -------------------------------------------------------------------------
@@ -8124,7 +8308,6 @@ void Dblqh::scanTupkeyConfLab(Signal* signal)
/* ---------------------------------------------------------------------
* STOP THE SCAN PROCESS IF THIS HAS BEEN REQUESTED.
* --------------------------------------------------------------------- */
- releaseOprec(signal);
if ((scanptr.p->scanLockHold == ZTRUE) &&
(scanptr.p->m_curr_batch_size_rows > 0)) {
jam();
@@ -8138,10 +8321,8 @@ void Dblqh::scanTupkeyConfLab(Signal* signal)
}//if
if (scanptr.p->scanKeyinfoFlag) {
jam();
- sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
- releaseOprec(signal);
-
- tdata4 += tcConnectptr.p->primKeyLen;// Inform API about keyinfo len aswell
+ // Inform API about keyinfo len aswell
+ tdata4 += sendKeyinfo20(signal, scanptr.p, tcConnectptr.p);
}//if
ndbrequire(scanptr.p->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
scanptr.p->m_curr_batch_size_bytes+= tdata4;
@@ -8243,7 +8424,6 @@ void Dblqh::scanTupkeyRefLab(Signal* signal)
tcConnectptr.p->transactionState = TcConnectionrec::SCAN_STATE_USED;
scanptr.i = tcConnectptr.p->tcScanRec;
releaseActiveFrag(signal);
- releaseOprec(signal);
c_scanRecordPool.getPtr(scanptr);
if (scanptr.p->scanCompletedStatus == ZTRUE) {
/* ---------------------------------------------------------------------
@@ -8365,8 +8545,18 @@ void Dblqh::continueCloseScanAfterBlockedLab(Signal* signal)
void Dblqh::accScanCloseConfLab(Signal* signal)
{
tcConnectptr.i = scanptr.p->scanTcrec;
- scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN;
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
+
+ if((tcConnectptr.p->primKeyLen - 4) > 0 &&
+ scanptr.p->scanCompletedStatus != ZTRUE)
+ {
+ jam();
+ releaseActiveFrag(signal);
+ continueAfterReceivingAllAiLab(signal);
+ return;
+ }
+
+ scanptr.p->scanState = ScanRecord::WAIT_DELETE_STORED_PROC_ID_SCAN;
signal->theData[0] = tcConnectptr.p->tupConnectrec;
signal->theData[1] = tcConnectptr.p->tableref;
signal->theData[2] = scanptr.p->scanSchemaVersion;
@@ -8404,8 +8594,6 @@ void Dblqh::tupScanCloseConfLab(Signal* signal)
ScanFragRef::SignalLength, JBB);
} else {
jam();
- scanptr.p->m_curr_batch_size_rows = 0;
- scanptr.p->m_curr_batch_size_bytes= 0;
sendScanFragConf(signal, ZSCAN_FRAG_CLOSED);
}//if
finishScanrec(signal);
@@ -8461,6 +8649,7 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
scanptr.p->scanNumber = ~0;
scanptr.p->scanApiOpPtr = scanFragReq->clientOpPtr;
scanptr.p->m_last_row = 0;
+ scanptr.p->scanStoredProcId = RNIL;
if (max_rows == 0 || (max_bytes > 0 && max_rows > max_bytes)){
jam();
@@ -8477,7 +8666,7 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
tFragPtr.i = fragptr.p->tableFragptr;
ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
scanptr.p->fragPtrI = fragptr.p->tableFragptr;
-
+
/**
* !idx uses 1 - (MAX_PARALLEL_SCANS_PER_FRAG - 1) = 1-11
* idx uses from MAX_PARALLEL_SCANS_PER_FRAG - MAX = 12-42)
@@ -8486,10 +8675,10 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
Uint32 stop = (idx ? MAX_PARALLEL_INDEX_SCANS_PER_FRAG : MAX_PARALLEL_SCANS_PER_FRAG - 1);
stop += start;
Uint32 free = tFragPtr.p->m_scanNumberMask.find(start);
-
+
if(free == Fragrecord::ScanNumberMask::NotFound || free >= stop){
jam();
-
+
if(scanPrio == 0){
jam();
return ScanFragRef::ZTOO_MANY_ACTIVE_SCAN_ERROR;
@@ -8500,16 +8689,15 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
*/
scanptr.p->scanState = ScanRecord::IN_QUEUE;
LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
- tFragPtr.p->m_queuedScans);
+ fragptr.p->m_queuedScans);
queue.add(scanptr);
return ZOK;
}
-
scanptr.p->scanNumber = free;
tFragPtr.p->m_scanNumberMask.clear(free);// Update mask
-
- LocalDLList<ScanRecord> active(c_scanRecordPool, tFragPtr.p->m_activeScans);
+
+ LocalDLList<ScanRecord> active(c_scanRecordPool, fragptr.p->m_activeScans);
active.add(scanptr);
if(scanptr.p->scanKeyinfoFlag){
jam();
@@ -8520,7 +8708,8 @@ Uint32 Dblqh::initScanrec(const ScanFragReq* scanFragReq)
#ifdef TRACE_SCAN_TAKEOVER
ndbout_c("adding (%d %d) table: %d fragId: %d frag.i: %d tableFragptr: %d",
scanptr.p->scanNumber, scanptr.p->fragPtrI,
- tabptr.i, scanFragReq->fragmentNo, fragptr.i, fragptr.p->tableFragptr);
+ tabptr.i, scanFragReq->fragmentNoKeyLen & 0xFFFF,
+ fragptr.i, fragptr.p->tableFragptr);
#endif
c_scanTakeOverHash.add(scanptr);
}
@@ -8556,6 +8745,7 @@ void Dblqh::initScanTc(Signal* signal,
tcConnectptr.p->operation = ZREAD;
tcConnectptr.p->listState = TcConnectionrec::NOT_IN_LIST;
tcConnectptr.p->commitAckMarker = RNIL;
+ tcConnectptr.p->m_offset_current_keybuf = 0;
tabptr.p->usageCount++;
}//Dblqh::initScanTc()
@@ -8569,12 +8759,8 @@ void Dblqh::finishScanrec(Signal* signal)
{
release_acc_ptr_list(scanptr.p);
- FragrecordPtr tFragPtr;
- tFragPtr.i = scanptr.p->fragPtrI;
- ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
-
LocalDLFifoList<ScanRecord> queue(c_scanRecordPool,
- tFragPtr.p->m_queuedScans);
+ fragptr.p->m_queuedScans);
if(scanptr.p->scanState == ScanRecord::IN_QUEUE){
jam();
@@ -8592,9 +8778,13 @@ void Dblqh::finishScanrec(Signal* signal)
ndbrequire(tmp.p == scanptr.p);
}
- LocalDLList<ScanRecord> scans(c_scanRecordPool, tFragPtr.p->m_activeScans);
+ LocalDLList<ScanRecord> scans(c_scanRecordPool, fragptr.p->m_activeScans);
scans.release(scanptr);
+ FragrecordPtr tFragPtr;
+ tFragPtr.i = scanptr.p->fragPtrI;
+ ptrCheckGuard(tFragPtr, cfragrecFileSize, fragrecord);
+
const Uint32 scanNumber = scanptr.p->scanNumber;
ndbrequire(!tFragPtr.p->m_scanNumberMask.get(scanNumber));
ScanRecordPtr restart;
@@ -8621,7 +8811,7 @@ void Dblqh::finishScanrec(Signal* signal)
ptrCheckGuard(tcConnectptr, ctcConnectrecFileSize, tcConnectionrec);
restart.p->scanNumber = scanNumber;
restart.p->scanState = ScanRecord::WAIT_ACC_SCAN;
-
+
queue.remove(restart);
scans.add(restart);
if(restart.p->scanKeyinfoFlag){
@@ -8661,23 +8851,17 @@ void Dblqh::releaseScanrec(Signal* signal)
* ------- SEND KEYINFO20 TO API -------
*
* ------------------------------------------------------------------------ */
-void Dblqh::sendKeyinfo20(Signal* signal,
- ScanRecord * scanP,
- TcConnectionrec * tcConP)
+Uint32 Dblqh::sendKeyinfo20(Signal* signal,
+ ScanRecord * scanP,
+ TcConnectionrec * tcConP)
{
ndbrequire(scanP->m_curr_batch_size_rows < MAX_PARALLEL_OP_PER_SCAN);
KeyInfo20 * keyInfo = (KeyInfo20 *)&signal->theData[0];
- DatabufPtr TdataBuf;
- TdataBuf.i = tcConP->firstTupkeybuf;
- Uint32 keyLen = tcConP->primKeyLen;
- const Uint32 dataBufSz = cdatabufFileSize;
-
/**
* Note that this code requires signal->theData to be big enough for
* a entire key
*/
- ndbrequire(keyLen * 4 <= sizeof(signal->theData));
const BlockReference ref = scanP->scanApiBlockref;
const Uint32 scanOp = scanP->m_curr_batch_size_rows;
const Uint32 nodeId = refToNode(ref);
@@ -8690,24 +8874,12 @@ void Dblqh::sendKeyinfo20(Signal* signal,
Uint32 * dst = keyInfo->keyData;
dst += nodeId == getOwnNodeId() ? 0 : KeyInfo20::DataLength;
- /**
- * Copy keydata from data buffer into signal
- *
- */
- for(Uint32 i = 0; i < keyLen; i += 4){
- ptrCheckGuard(TdataBuf, dataBufSz, databuf);
- * dst++ = TdataBuf.p->data[0];
- * dst++ = TdataBuf.p->data[1];
- * dst++ = TdataBuf.p->data[2];
- * dst++ = TdataBuf.p->data[3];
- TdataBuf.i = TdataBuf.p->nextDatabuf;
- }
-
+ Uint32 keyLen = readPrimaryKeys(scanP, tcConP, dst);
+ Uint32 fragId = tcConP->fragmentid;
keyInfo->clientOpPtr = scanP->scanApiOpPtr;
keyInfo->keyLen = keyLen;
- keyInfo->scanInfo_Node = KeyInfo20::setScanInfo(scanOp,
- scanP->scanNumber)+
- (getOwnNodeId() << 20);
+ keyInfo->scanInfo_Node =
+ KeyInfo20::setScanInfo(scanOp, scanP->scanNumber) + (fragId << 20);
keyInfo->transId1 = tcConP->transid[0];
keyInfo->transId2 = tcConP->transid[1];
@@ -8725,12 +8897,12 @@ void Dblqh::sendKeyinfo20(Signal* signal,
sendSignal(ref, GSN_KEYINFO20, signal, 25, JBB);
src += KeyInfo20::DataLength;;
keyLen -= KeyInfo20::DataLength;
- } while(keyLen >= KeyInfo20::DataLength);
+ }
MEMCOPY_NO_WORDS(keyInfo->keyData, src, keyLen);
sendSignal(ref, GSN_KEYINFO20, signal,
KeyInfo20::HeaderLength+keyLen, JBB);
- return;
+ return keyLen;
}
LinearSectionPtr ptr[3];
@@ -8738,13 +8910,13 @@ void Dblqh::sendKeyinfo20(Signal* signal,
ptr[0].sz = keyLen;
sendSignal(ref, GSN_KEYINFO20, signal, KeyInfo20::HeaderLength,
JBB, ptr, 1);
- return;
+ return keyLen;
}
EXECUTE_DIRECT(refToBlock(ref), GSN_KEYINFO20, signal,
KeyInfo20::HeaderLength + keyLen);
jamEntry();
- return;
+ return keyLen;
}
/**
@@ -8770,7 +8942,7 @@ void Dblqh::sendKeyinfo20(Signal* signal,
keyInfo->keyData[keyLen] = ref;
sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
KeyInfo20::HeaderLength+keyLen+1, JBB);
- return;
+ return keyLen;
}
keyInfo->keyData[0] = ref;
@@ -8779,7 +8951,7 @@ void Dblqh::sendKeyinfo20(Signal* signal,
ptr[0].sz = keyLen;
sendSignal(routeBlockref, GSN_KEYINFO20_R, signal,
KeyInfo20::HeaderLength+1, JBB, ptr, 1);
- return;
+ return keyLen;
}
/* ------------------------------------------------------------------------
@@ -8809,6 +8981,13 @@ void Dblqh::sendScanFragConf(Signal* signal, Uint32 scanCompleted)
conf->total_len= total_len;
sendSignal(tcConnectptr.p->clientBlockref, GSN_SCAN_FRAGCONF,
signal, ScanFragConf::SignalLength, JBB);
+
+ if(!scanptr.p->scanLockHold)
+ {
+ jam();
+ scanptr.p->m_curr_batch_size_rows = 0;
+ scanptr.p->m_curr_batch_size_bytes= 0;
+ }
}//Dblqh::sendScanFragConf()
/* ######################################################################### */
@@ -8948,7 +9127,6 @@ void Dblqh::execCOPY_FRAGREQ(Signal* signal)
req->fragmentNo = fragId;
req->requestInfo = 0;
AccScanReq::setLockMode(req->requestInfo, 0);
- AccScanReq::setKeyinfoFlag(req->requestInfo, 1);
AccScanReq::setReadCommittedFlag(req->requestInfo, 0);
req->transId1 = tcConnectptr.p->transid[0];
req->transId2 = tcConnectptr.p->transid[1];
@@ -9101,12 +9279,6 @@ void Dblqh::nextScanConfCopyLab(Signal* signal)
set_acc_ptr_in_scan_record(scanptr.p, 0, nextScanConf->accOperationPtr);
initCopyTc(signal);
- if (tcConnectptr.p->primKeyLen > 4) {
- jam();
- tcConnectptr.p->save1 = 4;
- scanptr.p->scanState = ScanRecord::WAIT_COPY_KEYINFO;
- return;
- }//if
copySendTupkeyReqLab(signal);
return;
}//Dblqh::nextScanConfCopyLab()
@@ -9122,13 +9294,7 @@ void Dblqh::copySendTupkeyReqLab(Signal* signal)
scanptr.p->scanState = ScanRecord::WAIT_TUPKEY_COPY;
fragptr.i = tcConnectptr.p->fragmentptr;
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
- if (fragptr.p->fragId == scanptr.p->scanLocalFragid) {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[0];
- } else {
- jam();
- tupFragPtr = fragptr.p->tupFragptr[1];
- }//if
+ tupFragPtr = fragptr.p->tupFragptr[scanptr.p->scanLocalFragid & 1];
{
TupKeyReq * const tupKeyReq = (TupKeyReq *)signal->getDataPtrSend();
@@ -9206,6 +9372,7 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
scanptr.i = tcConnectptr.p->tcScanRec;
c_scanRecordPool.getPtr(scanptr);
+ ScanRecord* scanP = scanptr.p;
releaseActiveFrag(signal);
if (tcConnectptr.p->errorCode != 0) {
jam();
@@ -9220,9 +9387,23 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
closeCopyLab(signal);
return;
}//if
+ TcConnectionrec * tcConP = tcConnectptr.p;
tcConnectptr.p->totSendlenAi = readLength;
tcConnectptr.p->connectState = TcConnectionrec::COPY_CONNECTED;
- calculateHash(signal);
+
+ // Read primary keys (used to get here via scan keyinfo)
+ Uint32* tmp = signal->getDataPtrSend()+24;
+ Uint32 len= tcConnectptr.p->primKeyLen = readPrimaryKeys(scanP, tcConP, tmp);
+
+ // Calculate hash (no need to linearies key)
+ tcConnectptr.p->hashValue = md5_hash((Uint64*)tmp, len);
+
+ // Move into databuffer to make packLqhkeyreqLab happy
+ memcpy(tcConP->tupkeyData, tmp, 4*4);
+ if(len > 4)
+ keyinfoLab(tmp+4, tmp + len);
+ LqhKeyReq::setKeyLen(tcConP->reqinfo, len);
+
/*---------------------------------------------------------------------------*/
// To avoid using up to many operation records in ACC we will increase the
// constant to ensure that we never send more than 40 records at a time.
@@ -9233,7 +9414,7 @@ void Dblqh::copyTupkeyConfLab(Signal* signal)
// records to ensure that node recovery does not fail because of simultaneous
// scanning.
/*---------------------------------------------------------------------------*/
- UintR TnoOfWords = readLength + tcConnectptr.p->primKeyLen;
+ UintR TnoOfWords = readLength + len;
TnoOfWords = TnoOfWords + MAGIC_CONSTANT;
TnoOfWords = TnoOfWords + (TnoOfWords >> 2);
@@ -9555,7 +9736,6 @@ void Dblqh::closeCopyRequestLab(Signal* signal)
scanptr.p->scanErrorCounter++;
switch (scanptr.p->scanState) {
case ScanRecord::WAIT_TUPKEY_COPY:
- case ScanRecord::WAIT_COPY_KEYINFO:
case ScanRecord::WAIT_NEXT_SCAN_COPY:
jam();
/*---------------------------------------------------------------------------*/
@@ -9786,11 +9966,6 @@ void Dblqh::execCOPY_STATEREQ(Signal* signal)
void Dblqh::initCopyTc(Signal* signal)
{
const NextScanConf * const nextScanConf = (NextScanConf *)&signal->theData[0];
- tcConnectptr.p->primKeyLen = nextScanConf->keyLength;
- tcConnectptr.p->tupkeyData[0] = nextScanConf->key[0];
- tcConnectptr.p->tupkeyData[1] = nextScanConf->key[1];
- tcConnectptr.p->tupkeyData[2] = nextScanConf->key[2];
- tcConnectptr.p->tupkeyData[3] = nextScanConf->key[3];
scanptr.p->scanLocalref[0] = nextScanConf->localKey[0];
scanptr.p->scanLocalref[1] = nextScanConf->localKey[1];
scanptr.p->scanLocalFragid = nextScanConf->fragId;
@@ -9799,7 +9974,6 @@ void Dblqh::initCopyTc(Signal* signal)
tcConnectptr.p->opExec = 0; /* NOT INTERPRETED MODE */
tcConnectptr.p->schemaVersion = scanptr.p->scanSchemaVersion;
Uint32 reqinfo = 0;
- LqhKeyReq::setKeyLen(reqinfo, nextScanConf->keyLength);
LqhKeyReq::setLockType(reqinfo, ZINSERT);
LqhKeyReq::setDirtyFlag(reqinfo, 1);
LqhKeyReq::setSimpleFlag(reqinfo, 1);
@@ -13390,7 +13564,6 @@ void Dblqh::execSR_FRAGIDCONF(Signal* signal)
ptrCheckGuard(fragptr, cfragrecFileSize, fragrecord);
fragptr.p->accFragptr[0] = srFragidConf->fragPtr[0];
fragptr.p->accFragptr[1] = srFragidConf->fragPtr[1];
- fragptr.p->hashCheckBit = srFragidConf->hashCheckBit;
Uint32 noLocFrag = srFragidConf->noLocFrag;
ndbrequire(noLocFrag == 2);
Uint32 fragid[2];
diff --git a/ndb/src/kernel/blocks/dblqh/Makefile_old b/ndb/src/kernel/blocks/dblqh/Makefile_old
deleted file mode 100644
index 520486d8058..00000000000
--- a/ndb/src/kernel/blocks/dblqh/Makefile_old
+++ /dev/null
@@ -1,12 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := dblqh
-DIRS := redoLogReader
-
-SOURCES = \
- DblqhInit.cpp \
- DblqhMain.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
index a209df24c44..ccb7d55396d 100644
--- a/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
+++ b/ndb/src/kernel/blocks/dbtc/Dbtc.hpp
@@ -561,7 +561,7 @@ public:
Uint32 expectedTransIdAI;
AttributeBuffer transIdAI; // For accumulating TransId_AI
- TcIndxReq tcIndxReq;
+ TcKeyReq tcIndxReq;
UintR connectionIndex;
UintR indexReadTcConnect; //
@@ -897,11 +897,11 @@ public:
UintR hashValue; /* THE HASH VALUE USED TO LOCATE FRAGMENT */
Uint8 distributionKeyIndicator;
- Uint8 distributionGroupIndicator;
- Uint8 distributionGroupType;
+ Uint8 unused1;
+ Uint8 unused2;
Uint8 lenAiInTckeyreq; /* LENGTH OF ATTRIBUTE INFORMATION IN TCKEYREQ */
- Uint8 distributionKey;
+ Uint8 fragmentDistributionKey; /* DIH generation no */
/**
* EXECUTION MODE OF OPERATION
@@ -925,16 +925,16 @@ public:
// Second 16 byte cache line in second 64 byte cache
// line. Diverse use.
//---------------------------------------------------
- UintR distributionGroup;
+ UintR distributionKey;
UintR nextCacheRec;
- UintR distributionKeySize;
+ UintR unused3;
Uint32 scanInfo;
//---------------------------------------------------
// Third 16 byte cache line in second 64
// byte cache line. Diverse use.
//---------------------------------------------------
- Uint32 scanNode;
+ Uint32 unused4;
Uint32 scanTakeOverInd;
UintR firstKeybuf; /* POINTER THE LINKED LIST OF KEY BUFFERS */
UintR lastKeybuf; /* VARIABLE POINTING TO THE LAST KEY BUFFER */
@@ -1054,9 +1054,8 @@ public:
// Id of the ScanRecord this fragment scan belongs to
Uint32 scanRec;
- // The maximum number of operations that can be scanned before
- // returning to TC
- Uint16 scanFragConcurrency;
+ // The value of fragmentCompleted in the last received SCAN_FRAGCONF
+ Uint8 m_scan_frag_conf_status;
inline void startFragTimer(Uint32 timeVal){
scanFragTimer = timeVal;
@@ -1193,8 +1192,10 @@ public:
// Number of operation records per scanned fragment
// Number of operations in first batch
// Max number of bytes per batch
- Uint16 noOprecPerFrag;
- Uint16 first_batch_size;
+ union {
+ Uint16 first_batch_size_rows;
+ Uint16 batch_size_rows;
+ };
Uint32 batch_byte_size;
Uint32 scanRequestInfo; // ScanFrag format
diff --git a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
index d8b3ee10532..42821e4fe7f 100644
--- a/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
+++ b/ndb/src/kernel/blocks/dbtc/DbtcMain.cpp
@@ -2250,29 +2250,17 @@ void Dbtc::hash(Signal* signal)
ti += 4;
}//while
}//if
- UintR ThashValue;
- UintR TdistrHashValue;
- ThashValue = md5_hash((Uint64*)&Tdata32[0], (UintR)regCachePtr->keylen);
+ Uint32 tmp[4];
+ md5_hash(tmp, (Uint64*)&Tdata32[0], (UintR)regCachePtr->keylen);
- if (regCachePtr->distributionGroupIndicator == 1) {
- if (regCachePtr->distributionGroupType == 1) {
- jam();
- TdistrHashValue = (regCachePtr->distributionGroup << 6);
- } else {
- jam();
- Tdata32[0] = regCachePtr->distributionGroup;
- TdistrHashValue = md5_hash((Uint64*)&Tdata32[0], (UintR)1);
- }//if
- } else if (regCachePtr->distributionKeyIndicator == 1) {
+ thashValue = tmp[0];
+ if (regCachePtr->distributionKeyIndicator == 1) {
jam();
- TdistrHashValue = md5_hash((Uint64*)&Tdata32[0],
- (UintR)regCachePtr->distributionKeySize);
+ tdistrHashValue = regCachePtr->distributionKey;
} else {
jam();
- TdistrHashValue = ThashValue;
+ tdistrHashValue = tmp[1];
}//if
- thashValue = ThashValue;
- tdistrHashValue = TdistrHashValue;
}//Dbtc::hash()
/*
@@ -2666,18 +2654,13 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint8 TSimpleFlag = tcKeyReq->getSimpleFlag(Treqinfo);
Uint8 TDirtyFlag = tcKeyReq->getDirtyFlag(Treqinfo);
Uint8 TInterpretedFlag = tcKeyReq->getInterpretedFlag(Treqinfo);
- Uint8 TDistrGroupFlag = tcKeyReq->getDistributionGroupFlag(Treqinfo);
- Uint8 TDistrGroupTypeFlag = tcKeyReq->getDistributionGroupTypeFlag(Treqinfo);
Uint8 TDistrKeyFlag = tcKeyReq->getDistributionKeyFlag(Treqinfo);
Uint8 TexecuteFlag = TexecFlag;
regCachePtr->opSimple = TSimpleFlag;
regCachePtr->opExec = TInterpretedFlag;
regTcPtr->dirtyOp = TDirtyFlag;
-
- regCachePtr->distributionGroupIndicator = TDistrGroupFlag;
- regCachePtr->distributionGroupType = TDistrGroupTypeFlag;
- regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
+ regCachePtr->distributionKeyIndicator = TDistrKeyFlag;
//-------------------------------------------------------------
// The next step is to read the upto three conditional words.
@@ -2686,17 +2669,14 @@ void Dbtc::execTCKEYREQ(Signal* signal)
Uint32* TOptionalDataPtr = (Uint32*)&tcKeyReq->scanInfo;
{
Uint32 TDistrGHIndex = tcKeyReq->getScanIndFlag(Treqinfo);
- Uint32 TDistrKeyIndex = TDistrGHIndex + TDistrGroupFlag;
+ Uint32 TDistrKeyIndex = TDistrGHIndex;
- Uint32 TscanNode = tcKeyReq->getTakeOverScanNode(TOptionalDataPtr[0]);
Uint32 TscanInfo = tcKeyReq->getTakeOverScanInfo(TOptionalDataPtr[0]);
regCachePtr->scanTakeOverInd = TDistrGHIndex;
- regCachePtr->scanNode = TscanNode;
regCachePtr->scanInfo = TscanInfo;
- regCachePtr->distributionGroup = TOptionalDataPtr[TDistrGHIndex];
- regCachePtr->distributionKeySize = TOptionalDataPtr[TDistrKeyIndex];
+ regCachePtr->distributionKey = TOptionalDataPtr[TDistrKeyIndex];
TkeyIndex = TDistrKeyIndex + TDistrKeyFlag;
}
@@ -2957,7 +2937,7 @@ void Dbtc::tckeyreq050Lab(Signal* signal)
tnoOfBackup = tnodeinfo & 3;
tnoOfStandby = (tnodeinfo >> 8) & 3;
- regCachePtr->distributionKey = (tnodeinfo >> 16) & 255;
+ regCachePtr->fragmentDistributionKey = (tnodeinfo >> 16) & 255;
if (Toperation == ZREAD) {
if (Tdirty == 1) {
jam();
@@ -3048,7 +3028,6 @@ void Dbtc::attrinfoDihReceivedLab(Signal* signal)
TcConnectRecord * const regTcPtr = tcConnectptr.p;
Uint16 Tnode = regTcPtr->tcNodedata[0];
Uint16 TscanTakeOverInd = regCachePtr->scanTakeOverInd;
- Uint16 TscanNode = regCachePtr->scanNode;
TableRecordPtr localTabptr;
localTabptr.i = regCachePtr->tableref;
@@ -3061,11 +3040,6 @@ void Dbtc::attrinfoDihReceivedLab(Signal* signal)
TCKEY_abort(signal, 58);
return;
}
- if ((TscanTakeOverInd == 1) &&
- (Tnode != TscanNode)) {
- TCKEY_abort(signal, 15);
- return;
- }//if
arrGuard(Tnode, MAX_NDB_NODES);
packLqhkeyreq(signal, calcLqhBlockRef(Tnode));
}//Dbtc::attrinfoDihReceivedLab()
@@ -3127,7 +3101,7 @@ void Dbtc::sendlqhkeyreq(Signal* signal,
/* ---------------------------------------------------------------------- */
// Bit16 == 0 since StoredProcedures are not yet supported.
/* ---------------------------------------------------------------------- */
- LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->distributionKey);
+ LqhKeyReq::setDistributionKey(tslrAttrLen, regCachePtr->fragmentDistributionKey);
LqhKeyReq::setScanTakeOverFlag(tslrAttrLen, regCachePtr->scanTakeOverInd);
Tdata10 = 0;
@@ -8477,7 +8451,7 @@ void Dbtc::systemErrorLab(Signal* signal)
void Dbtc::execSCAN_TABREQ(Signal* signal)
{
const ScanTabReq * const scanTabReq = (ScanTabReq *)&signal->theData[0];
- const Uint32 reqinfo = scanTabReq->requestInfo;
+ const Uint32 ri = scanTabReq->requestInfo;
const Uint32 aiLength = (scanTabReq->attrLenKeyLen & 0xFFFF);
const Uint32 keyLen = scanTabReq->attrLenKeyLen >> 16;
const Uint32 schemaVersion = scanTabReq->tableSchemaVersion;
@@ -8487,8 +8461,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
const Uint32 buddyPtr = (tmpXX == 0xFFFFFFFF ? RNIL : tmpXX);
Uint32 currSavePointId = 0;
- Uint32 scanConcurrency = scanTabReq->getParallelism(reqinfo);
- Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(reqinfo);
+ Uint32 scanConcurrency = scanTabReq->getParallelism(ri);
+ Uint32 noOprecPerFrag = ScanTabReq::getScanBatch(ri);
Uint32 scanParallel = scanConcurrency;
Uint32 errCode;
ScanRecordPtr scanptr;
@@ -8563,6 +8537,8 @@ void Dbtc::execSCAN_TABREQ(Signal* signal)
seizeCacheRecord(signal);
cachePtr.p->keylen = keyLen;
cachePtr.p->save1 = 0;
+ cachePtr.p->distributionKey = scanTabReq->distributionKey;
+ cachePtr.p->distributionKeyIndicator= ScanTabReq::getDistributionKeyFlag(ri);
scanptr = seizeScanrec(signal);
ndbrequire(transP->apiScanRec == RNIL);
@@ -8639,6 +8615,7 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
UintR scanParallel,
UintR noOprecPerFrag)
{
+ const UintR ri = scanTabReq->requestInfo;
scanptr.p->scanTcrec = tcConnectptr.i;
scanptr.p->scanApiRec = apiConnectptr.i;
scanptr.p->scanAiLength = scanTabReq->attrLenKeyLen & 0xFFFF;
@@ -8646,12 +8623,11 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
scanptr.p->scanTableref = tabptr.i;
scanptr.p->scanSchemaVersion = scanTabReq->tableSchemaVersion;
scanptr.p->scanParallel = scanParallel;
- scanptr.p->noOprecPerFrag = noOprecPerFrag;
- scanptr.p->first_batch_size= scanTabReq->first_batch_size;
- scanptr.p->batch_byte_size= scanTabReq->batch_byte_size;
+ scanptr.p->first_batch_size_rows = scanTabReq->first_batch_size;
+ scanptr.p->batch_byte_size = scanTabReq->batch_byte_size;
+ scanptr.p->batch_size_rows = noOprecPerFrag;
Uint32 tmp = 0;
- const UintR ri = scanTabReq->requestInfo;
ScanFragReq::setLockMode(tmp, ScanTabReq::getLockMode(ri));
ScanFragReq::setHoldLockFlag(tmp, ScanTabReq::getHoldLockFlag(ri));
ScanFragReq::setKeyinfoFlag(tmp, ScanTabReq::getKeyinfoFlag(ri));
@@ -8672,7 +8648,6 @@ void Dbtc::initScanrec(ScanRecordPtr scanptr,
ndbrequire(list.seize(ptr));
ptr.p->scanRec = scanptr.i;
ptr.p->scanFragId = 0;
- ptr.p->scanFragConcurrency = noOprecPerFrag;
ptr.p->m_apiPtr = cdata[i];
}//for
@@ -8767,14 +8742,42 @@ void Dbtc::diFcountReqLab(Signal* signal, ScanRecordPtr scanptr)
return;
}
+ scanptr.p->scanNextFragId = 0;
scanptr.p->scanState = ScanRecord::WAIT_FRAGMENT_COUNT;
- /*************************************************
- * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
- * WE MUST FIRST GET THE NUMBER OF FRAGMENTS IN THE TABLE.
- ***************************************************/
- signal->theData[0] = tcConnectptr.p->dihConnectptr;
- signal->theData[1] = scanptr.p->scanTableref;
- sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal, 2, JBB);
+
+ if(!cachePtr.p->distributionKeyIndicator)
+ {
+ jam();
+ /*************************************************
+ * THE FIRST STEP TO RECEIVE IS SUCCESSFULLY COMPLETED.
+ * WE MUST FIRST GET THE NUMBER OF FRAGMENTS IN THE TABLE.
+ ***************************************************/
+ signal->theData[0] = tcConnectptr.p->dihConnectptr;
+ signal->theData[1] = scanptr.p->scanTableref;
+ sendSignal(cdihblockref, GSN_DI_FCOUNTREQ, signal, 2, JBB);
+ }
+ else
+ {
+ signal->theData[0] = tcConnectptr.p->dihConnectptr;
+ signal->theData[1] = tabPtr.i;
+ signal->theData[2] = cachePtr.p->distributionKey;
+ EXECUTE_DIRECT(DBDIH, GSN_DIGETNODESREQ, signal, 3);
+ UintR TerrorIndicator = signal->theData[0];
+ jamEntry();
+ if (TerrorIndicator != 0) {
+ signal->theData[0] = tcConnectptr.i;
+ //signal->theData[1] Contains error
+ execDI_FCOUNTREF(signal);
+ return;
+ }
+
+ UintR Tdata1 = signal->theData[1];
+ scanptr.p->scanNextFragId = Tdata1;
+
+ signal->theData[0] = tcConnectptr.i;
+ signal->theData[1] = 1; // Frag count
+ execDI_FCOUNTCONF(signal);
+ }
return;
}//Dbtc::diFcountReqLab()
@@ -8791,7 +8794,7 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
{
jamEntry();
tcConnectptr.i = signal->theData[0];
- const UintR tfragCount = signal->theData[1];
+ Uint32 tfragCount = signal->theData[1];
ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
apiConnectptr.i = tcConnectptr.p->apiConnect;
ptrCheckGuard(apiConnectptr, capiConnectFilesize, apiConnectRecord);
@@ -8825,24 +8828,17 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
return;
}
- if(scanptr.p->scanParallel > tfragCount){
- jam();
- abortScanLab(signal, scanptr, ZTOO_HIGH_CONCURRENCY_ERROR);
- return;
- }
-
scanptr.p->scanParallel = tfragCount;
scanptr.p->scanNoFrag = tfragCount;
- scanptr.p->scanNextFragId = 0;
scanptr.p->scanState = ScanRecord::RUNNING;
setApiConTimer(apiConnectptr.i, 0, __LINE__);
updateBuddyTimer(apiConnectptr);
ScanFragRecPtr ptr;
- ScanFragList list(c_scan_frag_pool,
- scanptr.p->m_running_scan_frags);
- for (list.first(ptr); !ptr.isNull(); list.next(ptr)){
+ ScanFragList list(c_scan_frag_pool, scanptr.p->m_running_scan_frags);
+ for (list.first(ptr); !ptr.isNull() && tfragCount;
+ list.next(ptr), tfragCount--){
jam();
ptr.p->lqhBlockref = 0;
@@ -8857,6 +8853,20 @@ void Dbtc::execDI_FCOUNTCONF(Signal* signal)
signal->theData[3] = ptr.p->scanFragId;
sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
}//for
+
+ ScanFragList queued(c_scan_frag_pool, scanptr.p->m_queued_scan_frags);
+ for (; !ptr.isNull();)
+ {
+ ptr.p->m_ops = 0;
+ ptr.p->m_totalLen = 0;
+ ptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
+ ptr.p->stopFragTimer();
+
+ ScanFragRecPtr tmp = ptr;
+ list.next(ptr);
+ list.remove(tmp);
+ queued.add(tmp);
+ }
}//Dbtc::execDI_FCOUNTCONF()
/******************************************************
@@ -8945,6 +8955,25 @@ void Dbtc::execDIGETPRIMCONF(Signal* signal)
scanptr.i = scanFragptr.p->scanRec;
ptrCheckGuard(scanptr, cscanrecFileSize, scanRecord);
+ /**
+ * This must be false as select count(*) otherwise
+ * can "pass" committing on backup fragments and
+ * get incorrect row count
+ */
+ if(false && ScanFragReq::getReadCommittedFlag(scanptr.p->scanRequestInfo))
+ {
+ jam();
+ Uint32 max = 3+signal->theData[6];
+ Uint32 nodeid = getOwnNodeId();
+ for(Uint32 i = 3; i<max; i++)
+ if(signal->theData[i] == nodeid)
+ {
+ jam();
+ tnodeid = nodeid;
+ break;
+ }
+ }
+
{
/**
* Check table
@@ -9141,6 +9170,7 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal)
const ScanFragConf * const conf = (ScanFragConf*)&signal->theData[0];
const Uint32 noCompletedOps = conf->completedOps;
+ const Uint32 status = conf->fragmentCompleted;
scanFragptr.i = conf->senderData;
c_scan_frag_pool.getPtr(scanFragptr);
@@ -9163,11 +9193,9 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal)
ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::LQH_ACTIVE);
- const Uint32 status = conf->fragmentCompleted;
-
if(scanptr.p->scanState == ScanRecord::CLOSING_SCAN){
jam();
- if(status == ZFALSE){
+ if(status == 0){
/**
* We have started closing = we sent a close -> ignore this
*/
@@ -9184,11 +9212,11 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal)
return;
}
- if(status == ZCLOSED && scanptr.p->scanNextFragId < scanptr.p->scanNoFrag){
+ if(noCompletedOps == 0 && status != 0 &&
+ scanptr.p->scanNextFragId < scanptr.p->scanNoFrag){
/**
* Start on next fragment
*/
- ndbrequire(noCompletedOps == 0);
scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
scanFragptr.p->startFragTimer(ctcTimer);
@@ -9218,6 +9246,7 @@ void Dbtc::execSCAN_FRAGCONF(Signal* signal)
scanptr.p->m_queued_count++;
}
+ scanFragptr.p->m_scan_frag_conf_status = status;
scanFragptr.p->m_ops = noCompletedOps;
scanFragptr.p->m_totalLen = total_len;
scanFragptr.p->scanFragState = ScanFragRec::QUEUED_FOR_DELIVERY;
@@ -9311,7 +9340,6 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal)
/*********************************************************************
* APPLICATION IS CLOSING THE SCAN.
**********************************************************************/
- ndbrequire(len == 0);
close_scan_req(signal, scanptr, true);
return;
}//if
@@ -9330,11 +9358,12 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal)
// Copy op ptrs so I dont overwrite them when sending...
memcpy(signal->getDataPtrSend()+25, signal->getDataPtr()+4, 4 * len);
- ScanFragNextReq * nextReq = (ScanFragNextReq*)&signal->theData[0];
- nextReq->closeFlag = ZFALSE;
- nextReq->transId1 = apiConnectptr.p->transid[0];
- nextReq->transId2 = apiConnectptr.p->transid[1];
- nextReq->batch_size_bytes= scanP->batch_byte_size;
+ ScanFragNextReq tmp;
+ tmp.closeFlag = ZFALSE;
+ tmp.transId1 = apiConnectptr.p->transid[0];
+ tmp.transId2 = apiConnectptr.p->transid[1];
+ tmp.batch_size_rows = scanP->batch_size_rows;
+ tmp.batch_size_bytes = scanP->batch_byte_size;
ScanFragList running(c_scan_frag_pool, scanP->m_running_scan_frags);
ScanFragList delivered(c_scan_frag_pool, scanP->m_delivered_scan_frags);
@@ -9344,15 +9373,37 @@ void Dbtc::execSCAN_NEXTREQ(Signal* signal)
c_scan_frag_pool.getPtr(scanFragptr);
ndbrequire(scanFragptr.p->scanFragState == ScanFragRec::DELIVERED);
- scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
scanFragptr.p->startFragTimer(ctcTimer);
-
scanFragptr.p->m_ops = 0;
- nextReq->senderData = scanFragptr.i;
- nextReq->batch_size_rows= scanFragptr.p->scanFragConcurrency;
- sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
- ScanFragNextReq::SignalLength, JBB);
+ if(scanFragptr.p->m_scan_frag_conf_status)
+ {
+ /**
+ * last scan was complete
+ */
+ jam();
+ ndbrequire(scanptr.p->scanNextFragId < scanptr.p->scanNoFrag);
+ scanFragptr.p->scanFragState = ScanFragRec::WAIT_GET_PRIMCONF;
+
+ tcConnectptr.i = scanptr.p->scanTcrec;
+ ptrCheckGuard(tcConnectptr, ctcConnectFilesize, tcConnectRecord);
+ scanFragptr.p->scanFragId = scanptr.p->scanNextFragId++;
+ signal->theData[0] = tcConnectptr.p->dihConnectptr;
+ signal->theData[1] = scanFragptr.i;
+ signal->theData[2] = scanptr.p->scanTableref;
+ signal->theData[3] = scanFragptr.p->scanFragId;
+ sendSignal(cdihblockref, GSN_DIGETPRIMREQ, signal, 4, JBB);
+ }
+ else
+ {
+ jam();
+ scanFragptr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
+ ScanFragNextReq * req = (ScanFragNextReq*)signal->getDataPtrSend();
+ * req = tmp;
+ req->senderData = scanFragptr.i;
+ sendSignal(scanFragptr.p->lqhBlockref, GSN_SCAN_NEXTREQ, signal,
+ ScanFragNextReq::SignalLength, JBB);
+ }
delivered.remove(scanFragptr);
running.add(scanFragptr);
}//for
@@ -9416,7 +9467,7 @@ Dbtc::close_scan_req(Signal* signal, ScanRecordPtr scanPtr, bool req_received){
ndbrequire(curr.p->scanFragState == ScanFragRec::DELIVERED);
delivered.remove(curr);
- if(curr.p->m_ops > 0){
+ if(curr.p->m_ops > 0 && curr.p->m_scan_frag_conf_status == 0){
jam();
running.add(curr);
curr.p->scanFragState = ScanFragRec::LQH_ACTIVE;
@@ -9551,7 +9602,7 @@ void Dbtc::sendScanFragReq(Signal* signal,
req->transId1 = apiConnectptr.p->transid[0];
req->transId2 = apiConnectptr.p->transid[1];
req->clientOpPtr = scanFragP->m_apiPtr;
- req->batch_size_rows= scanFragP->scanFragConcurrency;
+ req->batch_size_rows= scanP->batch_size_rows;
req->batch_size_bytes= scanP->batch_byte_size;
sendSignal(scanFragP->lqhBlockref, GSN_SCAN_FRAGREQ, signal,
ScanFragReq::SignalLength, JBB);
@@ -9573,6 +9624,8 @@ void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
jam();
ops += 21;
}
+
+ Uint32 left = scanPtr.p->scanNoFrag - scanPtr.p->scanNextFragId;
ScanTabConf * conf = (ScanTabConf*)&signal->theData[0];
conf->apiConnectPtr = apiConnectptr.p->ndbapiConnect;
@@ -9588,24 +9641,25 @@ void Dbtc::sendScanTabConf(Signal* signal, ScanRecordPtr scanPtr) {
ScanFragRecPtr curr = ptr; // Remove while iterating...
queued.next(ptr);
+ bool done = curr.p->m_scan_frag_conf_status && --left;
+
* ops++ = curr.p->m_apiPtr;
- * ops++ = curr.i;
+ * ops++ = done ? RNIL : curr.i;
* ops++ = (curr.p->m_totalLen << 10) + curr.p->m_ops;
queued.remove(curr);
- if(curr.p->m_ops > 0){
+ if(!done){
delivered.add(curr);
curr.p->scanFragState = ScanFragRec::DELIVERED;
curr.p->stopFragTimer();
} else {
- (* --ops) = ScanTabConf::EndOfData; ops++;
c_scan_frag_pool.release(curr);
curr.p->scanFragState = ScanFragRec::COMPLETED;
curr.p->stopFragTimer();
}
}
}
-
+
if(scanPtr.p->m_delivered_scan_frags.isEmpty() &&
scanPtr.p->m_running_scan_frags.isEmpty()){
conf->requestInfo = op_count | ScanTabConf::EndOfData;
@@ -10424,9 +10478,8 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
sfp.i,
sfp.p->scanFragState,
sfp.p->scanFragId);
- infoEvent(" nodeid=%d, concurr=%d, timer=%d",
+ infoEvent(" nodeid=%d, timer=%d",
refToNode(sfp.p->lqhBlockref),
- sfp.p->scanFragConcurrency,
sfp.p->scanFragTimer);
}
@@ -10504,7 +10557,7 @@ Dbtc::execDUMP_STATE_ORD(Signal* signal)
sp.p->scanAiLength,
sp.p->scanParallel,
sp.p->scanReceivedOperations,
- sp.p->noOprecPerFrag);
+ sp.p->batch_size_rows);
infoEvent(" schv=%d, tab=%d, sproc=%d",
sp.p->scanSchemaVersion,
sp.p->scanTableref,
@@ -11060,7 +11113,7 @@ void Dbtc::execTCINDXREQ(Signal* signal)
{
jamEntry();
- TcIndxReq * const tcIndxReq = (TcIndxReq *)signal->getDataPtr();
+ TcKeyReq * const tcIndxReq = (TcKeyReq *)signal->getDataPtr();
const UintR TapiIndex = tcIndxReq->apiConnectPtr;
Uint32 tcIndxRequestInfo = tcIndxReq->requestInfo;
Uint32 startFlag = tcIndxReq->getStartFlag(tcIndxRequestInfo);
@@ -11111,7 +11164,7 @@ void Dbtc::execTCINDXREQ(Signal* signal)
// If operation is readTupleExclusive or updateTuple then read index
// table with exclusive lock
- Uint32 indexLength = TcIndxReq::getIndexLength(tcIndxRequestInfo);
+ Uint32 indexLength = TcKeyReq::getKeyLength(tcIndxRequestInfo);
Uint32 attrLength = tcIndxReq->attrLen;
indexOp->expectedKeyInfo = indexLength;
Uint32 includedIndexLength = MIN(indexLength, indexBufSize);
@@ -11524,7 +11577,7 @@ void Dbtc::execTCKEYREF(Signal* signal)
// Send TCINDXREF
jam();
- TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
+ TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
ndbassert(regApiPtr->noIndexOp);
@@ -11719,7 +11772,7 @@ void Dbtc::readIndexTable(Signal* signal,
(Operation_t)TcKeyReq::getOperationType(tcKeyRequestInfo);
// Find index table
- if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.indexId)) == NULL) {
+ if ((indexData = c_theIndexes.getPtr(indexOp->tcIndxReq.tableId)) == NULL) {
jam();
// Failed to find index record
TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
@@ -11736,7 +11789,7 @@ void Dbtc::readIndexTable(Signal* signal,
tcKeyReq->transId2 = transId2;
tcKeyReq->tableId = indexData->indexId;
tcKeyLength += MIN(keyLength, keyBufSize);
- tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.indexSchemaVersion;
+ tcKeyReq->tableSchemaVersion = indexOp->tcIndxReq.tableSchemaVersion;
TcKeyReq::setOperationType(tcKeyRequestInfo,
opType == ZREAD ? ZREAD : ZREAD_EX);
TcKeyReq::setAIInTcKeyReq(tcKeyRequestInfo, 1); // Allways send one AttrInfo
@@ -11828,7 +11881,7 @@ void Dbtc::executeIndexOperation(Signal* signal,
Uint32 keyBufSize = 8; // Maximum for key in TCKEYREQ
Uint32 attrBufSize = 5;
Uint32 dataPos = 0;
- TcIndxReq * const tcIndxReq = &indexOp->tcIndxReq;
+ TcKeyReq * const tcIndxReq = &indexOp->tcIndxReq;
TcKeyReq * const tcKeyReq = (TcKeyReq *)signal->getDataPtrSend();
Uint32 * dataPtr = &tcKeyReq->scanInfo;
Uint32 tcKeyLength = TcKeyReq::StaticLength;
@@ -11839,7 +11892,7 @@ void Dbtc::executeIndexOperation(Signal* signal,
bool moreKeyData = indexOp->transIdAI.first(aiIter);
// Find index table
- if ((indexData = c_theIndexes.getPtr(tcIndxReq->indexId)) == NULL) {
+ if ((indexData = c_theIndexes.getPtr(tcIndxReq->tableId)) == NULL) {
jam();
// Failed to find index record
TcIndxRef * const tcIndxRef = (TcIndxRef *)signal->getDataPtrSend();
diff --git a/ndb/src/kernel/blocks/dbtc/Makefile_old b/ndb/src/kernel/blocks/dbtc/Makefile_old
deleted file mode 100644
index ae876ab1f84..00000000000
--- a/ndb/src/kernel/blocks/dbtc/Makefile_old
+++ /dev/null
@@ -1,11 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := dbtc
-SOURCES = \
- DbtcInit.cpp \
- DbtcMain.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
index 55ad1d0910a..4c34d2ce0db 100644
--- a/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
+++ b/ndb/src/kernel/blocks/dbtup/Dbtup.hpp
@@ -504,6 +504,7 @@ struct Fragoperrec {
Uint32 noOfNewAttrCount;
Uint32 charsetIndex;
BlockReference lqhBlockrefFrag;
+ bool inUse;
};
typedef Ptr<Fragoperrec> FragoperrecPtr;
@@ -1021,6 +1022,13 @@ public:
int tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* dataOut);
/*
+ * ACC reads primary key without headers into an array of words. At
+ * this point in ACC deconstruction, ACC still uses logical references
+ * to fragment and tuple.
+ */
+ int accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIndex, Uint32* dataOut);
+
+ /*
* TUX checks if tuple is visible to scan.
*/
bool tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId);
@@ -1936,6 +1944,7 @@ private:
void setUpKeyArray(Tablerec* const regTabPtr);
bool addfragtotab(Tablerec* const regTabPtr, Uint32 fragId, Uint32 fragIndex);
void deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId);
+ void abortAddFragOp(Signal* signal);
void releaseTabDescr(Tablerec* const regTabPtr);
void getFragmentrec(FragrecordPtr& regFragPtr, Uint32 fragId, Tablerec* const regTabPtr);
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
index 49de0d80bcd..8e3ca6528c2 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp
@@ -1113,6 +1113,7 @@ Dbtup::updateStartLab(Signal* signal,
regOperPtr->attrinbufLen);
if (retValue == -1) {
tupkeyErrorLab(signal);
+ return -1;
}//if
} else {
jam();
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
index 5a8642c4d2e..3b0ba1c196f 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp
@@ -200,8 +200,7 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* data
operPtr.i = RNIL;
operPtr.p = NULL;
// do it
- int ret = readAttributes(pagePtr.p, pageOffset, attrIds,
- numAttrs, dataOut, ZNIL, true);
+ int ret = readAttributes(pagePtr.p, pageOffset, attrIds, numAttrs, dataOut, ZNIL, true);
// restore globals
tabptr = tabptr_old;
fragptr = fragptr_old;
@@ -229,6 +228,27 @@ Dbtup::tuxReadPk(Uint32 fragPtrI, Uint32 pageId, Uint32 pageOffset, Uint32* data
return ret;
}
+int
+Dbtup::accReadPk(Uint32 tableId, Uint32 fragId, Uint32 fragPageId, Uint32 pageIndex, Uint32* dataOut)
+{
+ ljamEntry();
+ // get table
+ TablerecPtr tablePtr;
+ tablePtr.i = tableId;
+ ptrCheckGuard(tablePtr, cnoOfTablerec, tablerec);
+ // get fragment
+ FragrecordPtr fragPtr;
+ getFragmentrec(fragPtr, fragId, tablePtr.p);
+ // get real page id and tuple offset
+ PagePtr pagePtr;
+ Uint32 pageId = getRealpid(fragPtr.p, fragPageId);
+ ndbrequire((pageIndex & 0x1) == 0);
+ Uint32 pageOffset = ZPAGE_HEADER_SIZE + (pageIndex >> 1) * tablePtr.p->tupheadsize;
+ // use TUX routine - optimize later
+ int ret = tuxReadPk(fragPtr.i, pageId, pageOffset, dataOut);
+ return ret;
+}
+
bool
Dbtup::tuxQueryTh(Uint32 fragPtrI, Uint32 tupAddr, Uint32 tupVersion, Uint32 transId1, Uint32 transId2, Uint32 savePointId)
{
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
index efea312b865..405f790954e 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp
@@ -39,11 +39,18 @@
/* ---------------------------------------------------------------- */
void Dbtup::execTUPFRAGREQ(Signal* signal)
{
+ ljamEntry();
+
+ if (signal->theData[0] == (Uint32)-1) {
+ ljam();
+ abortAddFragOp(signal);
+ return;
+ }
+
FragoperrecPtr fragOperPtr;
FragrecordPtr regFragPtr;
TablerecPtr regTabPtr;
- ljamEntry();
Uint32 userptr = signal->theData[0];
Uint32 userblockref = signal->theData[1];
Uint32 reqinfo = signal->theData[2];
@@ -62,6 +69,17 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
Uint32 noOfAttributeGroups = signal->theData[12];
Uint32 globalCheckpointIdIndicator = signal->theData[13];
+#ifndef VM_TRACE
+ // config mismatch - do not crash if release compiled
+ if (regTabPtr.i >= cnoOfTablerec) {
+ ljam();
+ signal->theData[0] = userptr;
+ signal->theData[1] = 800;
+ sendSignal(userblockref, GSN_TUPFRAGREF, signal, 2, JBB);
+ return;
+ }
+#endif
+
ptrCheckGuard(regTabPtr, cnoOfTablerec, tablerec);
if (cfirstfreeFragopr == RNIL) {
ljam();
@@ -132,6 +150,15 @@ void Dbtup::execTUPFRAGREQ(Signal* signal)
return;
}//if
+ if (ERROR_INSERTED(4007) && regTabPtr.p->fragid[0] == fragId ||
+ ERROR_INSERTED(4008) && regTabPtr.p->fragid[1] == fragId) {
+ ljam();
+ terrorCode = 1;
+ fragrefuse4Lab(signal, fragOperPtr, regFragPtr, regTabPtr.p, fragId);
+ CLEAR_ERROR_INSERT_VALUE;
+ return;
+ }
+
if (regTabPtr.p->tableStatus == NOT_DEFINED) {
ljam();
//-------------------------------------------------------------------------------------
@@ -243,6 +270,7 @@ void Dbtup::seizeFragoperrec(FragoperrecPtr& fragOperPtr)
ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
cfirstfreeFragopr = fragOperPtr.p->nextFragoprec;
fragOperPtr.p->nextFragoprec = RNIL;
+ fragOperPtr.p->inUse = true;
}//Dbtup::seizeFragoperrec()
/* **************************************************************** */
@@ -273,6 +301,7 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
ndbrequire(fragOperPtr.p->attributeCount > 0);
fragOperPtr.p->attributeCount--;
+ const bool lastAttr = (fragOperPtr.p->attributeCount == 0);
if ((regTabPtr.p->tableStatus == DEFINING) &&
(fragOperPtr.p->definingFragment)) {
@@ -346,20 +375,30 @@ void Dbtup::execTUP_ADD_ATTRREQ(Signal* signal)
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
return;
}//if
- if ((fragOperPtr.p->attributeCount == 0) &&
- (fragOperPtr.p->freeNullBit != 0)) {
+ if (lastAttr && (fragOperPtr.p->freeNullBit != 0)) {
ljam();
terrorCode = ZINCONSISTENT_NULL_ATTRIBUTE_COUNT;
addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
return;
}//if
}//if
+ if (ERROR_INSERTED(4009) && regTabPtr.p->fragid[0] == fragId && attrId == 0 ||
+ ERROR_INSERTED(4010) && regTabPtr.p->fragid[0] == fragId && lastAttr ||
+ ERROR_INSERTED(4011) && regTabPtr.p->fragid[1] == fragId && attrId == 0 ||
+ ERROR_INSERTED(4012) && regTabPtr.p->fragid[1] == fragId && lastAttr) {
+ ljam();
+ terrorCode = 1;
+ addattrrefuseLab(signal, regFragPtr, fragOperPtr, regTabPtr.p, fragId);
+ CLEAR_ERROR_INSERT_VALUE;
+ return;
+ }
/* **************************************************************** */
/* ************** TUP_ADD_ATTCONF ****************** */
/* **************************************************************** */
signal->theData[0] = fragOperPtr.p->lqhPtrFrag;
- sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, signal, 1, JBB);
- if (fragOperPtr.p->attributeCount > 0) {
+ signal->theData[1] = lastAttr;
+ sendSignal(fragOperPtr.p->lqhBlockrefFrag, GSN_TUP_ADD_ATTCONF, signal, 2, JBB);
+ if (! lastAttr) {
ljam();
return; /* EXIT AND WAIT FOR MORE */
}//if
@@ -491,11 +530,11 @@ void Dbtup::fragrefuseLab(Signal* signal, FragoperrecPtr fragOperPtr)
void Dbtup::releaseFragoperrec(FragoperrecPtr fragOperPtr)
{
+ fragOperPtr.p->inUse = false;
fragOperPtr.p->nextFragoprec = cfirstfreeFragopr;
cfirstfreeFragopr = fragOperPtr.i;
}//Dbtup::releaseFragoperrec()
-
void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
{
for (Uint32 i = 0; i < (2 * MAX_FRAG_PER_NODE); i++) {
@@ -510,6 +549,20 @@ void Dbtup::deleteFragTab(Tablerec* const regTabPtr, Uint32 fragId)
ndbrequire(false);
}//Dbtup::deleteFragTab()
+/*
+ * LQH aborts on-going create table operation. The table is later
+ * dropped by DICT.
+ */
+void Dbtup::abortAddFragOp(Signal* signal)
+{
+ FragoperrecPtr fragOperPtr;
+
+ fragOperPtr.i = signal->theData[1];
+ ptrCheckGuard(fragOperPtr, cnoOfFragoprec, fragoperrec);
+ ndbrequire(fragOperPtr.p->inUse);
+ releaseFragoperrec(fragOperPtr);
+}
+
void
Dbtup::execDROP_TAB_REQ(Signal* signal)
{
diff --git a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
index e6cc6f68842..a8756511ea4 100644
--- a/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
+++ b/ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp
@@ -706,7 +706,10 @@ Dbtup::checkUpdateOfPrimaryKey(Uint32* updateBuffer, Tablerec* const regTabPtr)
tOutBufIndex = 0;
tMaxRead = MAX_KEY_SIZE_IN_WORDS;
+ bool tmp = tXfrmFlag;
+ tXfrmFlag = false;
ndbrequire((this->*f)(&keyReadBuffer[0], ahOut, attrDescriptor, attributeOffset));
+ tXfrmFlag = tmp;
ndbrequire(tOutBufIndex == ahOut->getDataSize());
if (ahIn.getDataSize() != ahOut->getDataSize()) {
ljam();
@@ -987,7 +990,7 @@ Dbtup::read_psuedo(Uint32 attrId, Uint32* outBuffer){
Signal * signal = (Signal*)&tmp;
switch(attrId){
case AttributeHeader::FRAGMENT:
- * outBuffer = operPtr.p->fragId;
+ * outBuffer = operPtr.p->fragId >> 1; // remove "hash" bit
return 1;
case AttributeHeader::ROW_COUNT:
case AttributeHeader::COMMIT_COUNT:
diff --git a/ndb/src/kernel/blocks/dbtup/Makefile_old b/ndb/src/kernel/blocks/dbtup/Makefile_old
deleted file mode 100644
index 87146f4b441..00000000000
--- a/ndb/src/kernel/blocks/dbtup/Makefile_old
+++ /dev/null
@@ -1,26 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := dbtup
-SOURCES = \
- DbtupExecQuery.cpp \
- DbtupBuffer.cpp \
- DbtupRoutines.cpp \
- DbtupCommit.cpp \
- DbtupFixAlloc.cpp \
- DbtupTrigger.cpp \
- DbtupAbort.cpp \
- DbtupLCP.cpp \
- DbtupUndoLog.cpp \
- DbtupPageMap.cpp \
- DbtupPagMan.cpp \
- DbtupStoredProcDef.cpp \
- DbtupMeta.cpp \
- DbtupTabDesMan.cpp \
- DbtupGen.cpp \
- DbtupSystemRestart.cpp \
- DbtupIndex.cpp \
- DbtupDebug.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
index 8896324f793..cd7a97d4b17 100644
--- a/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
+++ b/ndb/src/kernel/blocks/dbtux/Dbtux.hpp
@@ -406,7 +406,6 @@ private:
Uint32 m_accLockOp;
Uint8 m_readCommitted; // no locking
Uint8 m_lockMode;
- Uint8 m_keyInfo;
ScanBound m_boundMin;
ScanBound m_boundMax;
ScanBound* m_bound[2]; // pointers to above 2
@@ -449,7 +448,7 @@ private:
State m_state;
DictTabInfo::TableType m_tableType;
Uint32 m_tableId;
- Uint16 m_fragOff; // offset for duplicate fragId bits
+ Uint16 unused;
Uint16 m_numFrags;
Uint32 m_fragId[MaxIndexFragments];
Uint32 m_fragPtrI[MaxIndexFragments];
@@ -475,7 +474,7 @@ private:
struct Frag {
Uint32 m_tableId; // copy from index level
Uint32 m_indexId;
- Uint16 m_fragOff;
+ Uint16 unused;
Uint16 m_fragId;
Uint32 m_descPage; // copy from index level
Uint16 m_descOff;
@@ -575,6 +574,7 @@ private:
void execDROP_TAB_REQ(Signal* signal);
bool allocDescEnt(IndexPtr indexPtr);
void freeDescEnt(IndexPtr indexPtr);
+ void abortAddFragOp(Signal* signal);
void dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 senderData);
/*
@@ -684,6 +684,7 @@ private:
friend class NdbOut& operator<<(NdbOut&, const ScanOp&);
friend class NdbOut& operator<<(NdbOut&, const Index&);
friend class NdbOut& operator<<(NdbOut&, const Frag&);
+ friend class NdbOut& operator<<(NdbOut&, const FragOp&);
friend class NdbOut& operator<<(NdbOut&, const NodeHandle&);
FILE* debugFile;
NdbOut debugOut;
@@ -1028,7 +1029,6 @@ Dbtux::ScanOp::ScanOp(ScanBoundPool& scanBoundPool) :
m_accLockOp(RNIL),
m_readCommitted(0),
m_lockMode(0),
- m_keyInfo(0),
m_boundMin(scanBoundPool),
m_boundMax(scanBoundPool),
m_scanPos(),
@@ -1072,7 +1072,6 @@ inline
Dbtux::Frag::Frag(ArrayPool<ScanOp>& scanOpPool) :
m_tableId(RNIL),
m_indexId(RNIL),
- m_fragOff(ZNIL),
m_fragId(ZNIL),
m_descPage(RNIL),
m_descOff(0),
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
index c5c22264460..3c2613c6cd1 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp
@@ -347,7 +347,6 @@ operator<<(NdbOut& out, const Dbtux::ScanOp& scan)
out << "]";
out << " [readCommitted " << dec << scan.m_readCommitted << "]";
out << " [lockMode " << dec << scan.m_lockMode << "]";
- out << " [keyInfo " << dec << scan.m_keyInfo << "]";
out << " [pos " << scan.m_scanPos << "]";
out << " [ent " << scan.m_scanEnt << "]";
for (unsigned i = 0; i <= 1; i++) {
@@ -370,7 +369,6 @@ operator<<(NdbOut& out, const Dbtux::Index& index)
{
out << "[Index " << hex << &index;
out << " [tableId " << dec << index.m_tableId << "]";
- out << " [fragOff " << dec << index.m_fragOff << "]";
out << " [numFrags " << dec << index.m_numFrags << "]";
for (unsigned i = 0; i < index.m_numFrags; i++) {
out << " [frag " << dec << i << " ";
@@ -393,7 +391,6 @@ operator<<(NdbOut& out, const Dbtux::Frag& frag)
out << "[Frag " << hex << &frag;
out << " [tableId " << dec << frag.m_tableId << "]";
out << " [indexId " << dec << frag.m_indexId << "]";
- out << " [fragOff " << dec << frag.m_fragOff << "]";
out << " [fragId " << dec << frag.m_fragId << "]";
out << " [descPage " << hex << frag.m_descPage << "]";
out << " [descOff " << dec << frag.m_descOff << "]";
@@ -404,6 +401,19 @@ operator<<(NdbOut& out, const Dbtux::Frag& frag)
}
NdbOut&
+operator<<(NdbOut& out, const Dbtux::FragOp& fragOp)
+{
+ out << "[FragOp " << hex << &fragOp;
+ out << " [userPtr " << dec << fragOp.m_userPtr << "]";
+ out << " [indexId " << dec << fragOp.m_indexId << "]";
+ out << " [fragId " << dec << fragOp.m_fragId << "]";
+ out << " [fragNo " << dec << fragOp.m_fragNo << "]";
+ out << " numAttrsRecvd " << dec << fragOp.m_numAttrsRecvd << "]";
+ out << "]";
+ return out;
+}
+
+NdbOut&
operator<<(NdbOut& out, const Dbtux::NodeHandle& node)
{
const Dbtux::Frag& frag = node.m_frag;
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
index ded02696a89..18aa914de05 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp
@@ -24,13 +24,8 @@ Dbtux::Dbtux(const Configuration& conf) :
#ifdef VM_TRACE
debugFile(0),
debugOut(*new NullOutputStream()),
- // until ndb_mgm supports dump
-#ifdef DBTUX_DEBUG_TREE
- debugFlags(DebugTree),
-#else
debugFlags(0),
#endif
-#endif
c_internalStartPhase(0),
c_typeOfStart(NodeState::ST_ILLEGAL_TYPE),
c_dataBuffer(0)
@@ -86,7 +81,7 @@ Dbtux::execCONTINUEB(Signal* signal)
jamEntry();
const Uint32* data = signal->getDataPtr();
switch (data[0]) {
- case TuxContinueB::DropIndex:
+ case TuxContinueB::DropIndex: // currently unused
{
IndexPtr indexPtr;
c_indexPool.getPtr(indexPtr, data[1]);
@@ -174,7 +169,7 @@ Dbtux::execREAD_CONFIG_REQ(Signal* signal)
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_ATTRIBUTE, &nAttribute));
ndbrequire(!ndb_mgm_get_int_parameter(p, CFG_TUX_SCAN_OP, &nScanOp));
- const Uint32 nDescPage = (nIndex + nAttribute + DescPageSize - 1) / DescPageSize;
+ const Uint32 nDescPage = (nIndex * DescHeadSize + nAttribute * DescAttrSize + DescPageSize - 1) / DescPageSize;
const Uint32 nScanBoundWords = nScanOp * ScanBoundSegmentSize * 4;
c_indexPool.setSize(nIndex);
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
index 30afb51e7d7..2d256487dcc 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp
@@ -57,9 +57,9 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
c_indexPool.getPtr(indexPtr, req->indexId);
ndbrequire(indexPtr.p->m_tableId == req->tableId);
// get base fragment id and extra bits
- const Uint32 fragOff = indexPtr.p->m_fragOff;
- const Uint32 fragId = req->fragId & ((1 << fragOff) - 1);
- const Uint32 fragBit = req->fragId >> fragOff;
+ const Uint32 fragId = req->fragId & ~1;
+ const Uint32 fragBit = req->fragId & 1;
+
// get the fragment
FragPtr fragPtr;
fragPtr.i = RNIL;
@@ -71,6 +71,7 @@ Dbtux::execTUX_MAINT_REQ(Signal* signal)
break;
}
}
+
ndbrequire(fragPtr.i != RNIL);
Frag& frag = *fragPtr.p;
// set up index keys for this operation
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
index 1577c5045e0..cee4aaa8625 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp
@@ -29,6 +29,11 @@ void
Dbtux::execTUXFRAGREQ(Signal* signal)
{
jamEntry();
+ if (signal->theData[0] == (Uint32)-1) {
+ jam();
+ abortAddFragOp(signal);
+ return;
+ }
const TuxFragReq reqCopy = *(const TuxFragReq*)signal->getDataPtr();
const TuxFragReq* const req = &reqCopy;
IndexPtr indexPtr;
@@ -61,6 +66,11 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
fragOpPtr.p->m_fragId = req->fragId;
fragOpPtr.p->m_fragNo = indexPtr.p->m_numFrags;
fragOpPtr.p->m_numAttrsRecvd = 0;
+#ifdef VM_TRACE
+ if (debugFlags & DebugMeta) {
+ debugOut << "Seize frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
+ }
+#endif
// check if index has place for more fragments
ndbrequire(indexPtr.p->m_numFrags < MaxIndexFragments);
// seize new fragment record
@@ -74,7 +84,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
new (fragPtr.p) Frag(c_scanOpPool);
fragPtr.p->m_tableId = req->primaryTableId;
fragPtr.p->m_indexId = req->tableId;
- fragPtr.p->m_fragOff = req->fragOff;
fragPtr.p->m_fragId = req->fragId;
fragPtr.p->m_numAttrs = req->noOfAttr;
fragPtr.p->m_storeNullKey = true; // not yet configurable
@@ -102,7 +111,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
indexPtr.p->m_state = Index::Defining;
indexPtr.p->m_tableType = (DictTabInfo::TableType)req->tableType;
indexPtr.p->m_tableId = req->primaryTableId;
- indexPtr.p->m_fragOff = req->fragOff;
indexPtr.p->m_numAttrs = req->noOfAttr;
indexPtr.p->m_storeNullKey = true; // not yet configurable
// allocate attribute descriptors
@@ -118,7 +126,6 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
indexPtr.p->m_state == Index::Defining &&
indexPtr.p->m_tableType == (DictTabInfo::TableType)req->tableType &&
indexPtr.p->m_tableId == req->primaryTableId &&
- indexPtr.p->m_fragOff == req->fragOff &&
indexPtr.p->m_numAttrs == req->noOfAttr);
}
// copy metadata address to each fragment
@@ -129,6 +136,14 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
debugOut << "Add frag " << fragPtr.i << " " << *fragPtr.p << endl;
}
#endif
+ // error inserts
+ if (ERROR_INSERTED(12001) && fragOpPtr.p->m_fragNo == 0 ||
+ ERROR_INSERTED(12002) && fragOpPtr.p->m_fragNo == 1) {
+ jam();
+ errorCode = (TuxFragRef::ErrorCode)1;
+ CLEAR_ERROR_INSERT_VALUE;
+ break;
+ }
// success
TuxFragConf* const conf = (TuxFragConf*)signal->getDataPtrSend();
conf->userPtr = req->userPtr;
@@ -145,10 +160,18 @@ Dbtux::execTUXFRAGREQ(Signal* signal)
ref->errorCode = errorCode;
sendSignal(req->userRef, GSN_TUXFRAGREF,
signal, TuxFragRef::SignalLength, JBB);
- if (fragOpPtr.i != RNIL)
+ if (fragOpPtr.i != RNIL) {
+#ifdef VM_TRACE
+ if (debugFlags & DebugMeta) {
+ debugOut << "Release on frag error frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
+ }
+#endif
c_fragOpPool.release(fragOpPtr);
- if (indexPtr.i != RNIL)
- dropIndex(signal, indexPtr, 0, 0);
+ }
+ if (indexPtr.i != RNIL) {
+ jam();
+ // let DICT drop the unfinished index
+ }
}
void
@@ -203,7 +226,16 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
}
}
#endif
- if (indexPtr.p->m_numAttrs == fragOpPtr.p->m_numAttrsRecvd) {
+ const bool lastAttr = (indexPtr.p->m_numAttrs == fragOpPtr.p->m_numAttrsRecvd);
+ if (ERROR_INSERTED(12003) && fragOpPtr.p->m_fragNo == 0 && attrId == 0 ||
+ ERROR_INSERTED(12004) && fragOpPtr.p->m_fragNo == 0 && lastAttr ||
+ ERROR_INSERTED(12005) && fragOpPtr.p->m_fragNo == 1 && attrId == 0 ||
+ ERROR_INSERTED(12006) && fragOpPtr.p->m_fragNo == 1 && lastAttr) {
+ errorCode = (TuxAddAttrRef::ErrorCode)1;
+ CLEAR_ERROR_INSERT_VALUE;
+ break;
+ }
+ if (lastAttr) {
jam();
// initialize tree header
TreeHead& tree = fragPtr.p->m_tree;
@@ -246,11 +278,17 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
}
#endif
// fragment is defined
+#ifdef VM_TRACE
+ if (debugFlags & DebugMeta) {
+ debugOut << "Release frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
+ }
+#endif
c_fragOpPool.release(fragOpPtr);
}
// success
TuxAddAttrConf* conf = (TuxAddAttrConf*)signal->getDataPtrSend();
conf->userPtr = fragOpPtr.p->m_userPtr;
+ conf->lastAttr = lastAttr;
sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRCONF,
signal, TuxAddAttrConf::SignalLength, JBB);
return;
@@ -261,8 +299,32 @@ Dbtux::execTUX_ADD_ATTRREQ(Signal* signal)
ref->errorCode = errorCode;
sendSignal(fragOpPtr.p->m_userRef, GSN_TUX_ADD_ATTRREF,
signal, TuxAddAttrRef::SignalLength, JBB);
+#ifdef VM_TRACE
+ if (debugFlags & DebugMeta) {
+ debugOut << "Release on attr error frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
+ }
+#endif
c_fragOpPool.release(fragOpPtr);
- dropIndex(signal, indexPtr, 0, 0);
+ // let DICT drop the unfinished index
+}
+
+/*
+ * LQH aborts on-going create index operation.
+ */
+void
+Dbtux::abortAddFragOp(Signal* signal)
+{
+ FragOpPtr fragOpPtr;
+ IndexPtr indexPtr;
+ c_fragOpPool.getPtr(fragOpPtr, signal->theData[1]);
+ c_indexPool.getPtr(indexPtr, fragOpPtr.p->m_indexId);
+#ifdef VM_TRACE
+ if (debugFlags & DebugMeta) {
+ debugOut << "Release on abort frag op " << fragOpPtr.i << " " << *fragOpPtr.p << endl;
+ }
+#endif
+ c_fragOpPool.release(fragOpPtr);
+ // let DICT drop the unfinished index
}
/*
@@ -341,20 +403,13 @@ Dbtux::dropIndex(Signal* signal, IndexPtr indexPtr, Uint32 senderRef, Uint32 sen
{
jam();
indexPtr.p->m_state = Index::Dropping;
- // drop one fragment at a time
- if (indexPtr.p->m_numFrags > 0) {
+ // drop fragments
+ while (indexPtr.p->m_numFrags > 0) {
jam();
- unsigned i = --indexPtr.p->m_numFrags;
+ Uint32 i = --indexPtr.p->m_numFrags;
FragPtr fragPtr;
c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
c_fragPool.release(fragPtr);
- // the real time break is not used for anything currently
- signal->theData[0] = TuxContinueB::DropIndex;
- signal->theData[1] = indexPtr.i;
- signal->theData[2] = senderRef;
- signal->theData[3] = senderData;
- sendSignal(reference(), GSN_CONTINUEB, signal, 4, JBB);
- return;
}
// drop attributes
if (indexPtr.p->m_descPage != RNIL) {
diff --git a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
index 8677ae741b3..31a11a5c16b 100644
--- a/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
+++ b/ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp
@@ -34,7 +34,7 @@ Dbtux::execACC_SCANREQ(Signal* signal)
fragPtr.i = RNIL;
for (unsigned i = 0; i < indexPtr.p->m_numFrags; i++) {
jam();
- if (indexPtr.p->m_fragId[i] == req->fragmentNo) {
+ if (indexPtr.p->m_fragId[i] == req->fragmentNo << 1) {
jam();
c_fragPool.getPtr(fragPtr, indexPtr.p->m_fragPtrI[i]);
break;
@@ -43,7 +43,6 @@ Dbtux::execACC_SCANREQ(Signal* signal)
ndbrequire(fragPtr.i != RNIL);
Frag& frag = *fragPtr.p;
// must be normal DIH/TC fragment
- ndbrequire(frag.m_fragId < (1 << frag.m_fragOff));
TreeHead& tree = frag.m_tree;
// check for empty fragment
if (tree.m_root == NullTupLoc) {
@@ -74,7 +73,6 @@ Dbtux::execACC_SCANREQ(Signal* signal)
scanPtr.p->m_savePointId = req->savePointId;
scanPtr.p->m_readCommitted = AccScanReq::getReadCommittedFlag(req->requestInfo);
scanPtr.p->m_lockMode = AccScanReq::getLockMode(req->requestInfo);
- scanPtr.p->m_keyInfo = AccScanReq::getKeyinfoFlag(req->requestInfo);
#ifdef VM_TRACE
if (debugFlags & DebugScan) {
debugOut << "Seize scan " << scanPtr.i << " " << *scanPtr.p << endl;
@@ -354,7 +352,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
conf->accOperationPtr = RNIL; // no tuple returned
- conf->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+ conf->fragId = frag.m_fragId | ent.m_fragBit;
unsigned signalLength = 3;
// if TC has ordered scan close, it will be detected here
sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
@@ -397,7 +395,7 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
lockReq->userPtr = scanPtr.i;
lockReq->userRef = reference();
lockReq->tableId = scan.m_tableId;
- lockReq->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+ lockReq->fragId = frag.m_fragId | ent.m_fragBit;
lockReq->fragPtrI = frag.m_accTableFragPtrI[ent.m_fragBit];
const Uint32* const buf32 = static_cast<Uint32*>(pkData);
const Uint64* const buf64 = reinterpret_cast<const Uint64*>(buf32);
@@ -474,13 +472,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
jam();
// read keys if not already done (uses signal)
const TreeEnt ent = scan.m_scanEnt;
- if (scan.m_keyInfo) {
- jam();
- if (pkSize == 0) {
- jam();
- readTablePk(frag, ent, pkData, pkSize);
- }
- }
// conf signal
NextScanConf* const conf = (NextScanConf*)signal->getDataPtrSend();
conf->scanPtr = scan.m_userPtr;
@@ -496,21 +487,12 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
accLockOp = (Uint32)-1;
}
conf->accOperationPtr = accLockOp;
- conf->fragId = frag.m_fragId | (ent.m_fragBit << frag.m_fragOff);
+ conf->fragId = frag.m_fragId | ent.m_fragBit;
conf->localKey[0] = getTupAddr(frag, ent);
conf->localKey[1] = 0;
conf->localKeyLength = 1;
unsigned signalLength = 6;
// add key info
- if (scan.m_keyInfo) {
- jam();
- conf->keyLength = pkSize;
- // piggy-back first 4 words of key data
- for (unsigned i = 0; i < 4; i++) {
- conf->key[i] = i < pkSize ? pkData[i] : 0;
- }
- signalLength = 11;
- }
if (! scan.m_readCommitted) {
sendSignal(scan.m_userRef, GSN_NEXT_SCANCONF,
signal, signalLength, JBB);
@@ -518,24 +500,6 @@ Dbtux::execACC_CHECK_SCAN(Signal* signal)
Uint32 blockNo = refToBlock(scan.m_userRef);
EXECUTE_DIRECT(blockNo, GSN_NEXT_SCANCONF, signal, signalLength);
}
- // send rest of key data
- if (scan.m_keyInfo && pkSize > 4) {
- unsigned total = 4;
- while (total < pkSize) {
- jam();
- unsigned length = pkSize - total;
- if (length > 20)
- length = 20;
- signal->theData[0] = scan.m_userPtr;
- signal->theData[1] = 0;
- signal->theData[2] = 0;
- signal->theData[3] = length;
- memcpy(&signal->theData[4], &pkData[total], length << 2);
- sendSignal(scan.m_userRef, GSN_ACC_SCAN_INFO24,
- signal, 4 + length, JBB);
- total += length;
- }
- }
// next time look for next entry
scan.m_state = ScanOp::Next;
return;
@@ -890,7 +854,7 @@ Dbtux::scanVisible(ScanOpPtr scanPtr, TreeEnt ent)
const Frag& frag = *c_fragPool.getPtr(scan.m_fragPtrI);
Uint32 fragBit = ent.m_fragBit;
Uint32 tableFragPtrI = frag.m_tupTableFragPtrI[fragBit];
- Uint32 fragId = frag.m_fragId | (fragBit << frag.m_fragOff);
+ Uint32 fragId = frag.m_fragId | fragBit;
Uint32 tupAddr = getTupAddr(frag, ent);
Uint32 tupVersion = ent.m_tupVersion;
// check for same tuple twice in row
diff --git a/ndb/src/kernel/blocks/dbtux/Makefile_old b/ndb/src/kernel/blocks/dbtux/Makefile_old
deleted file mode 100644
index 30927c31848..00000000000
--- a/ndb/src/kernel/blocks/dbtux/Makefile_old
+++ /dev/null
@@ -1,17 +0,0 @@
-include .defs.mk
-
-TYPE = kernel
-
-ARCHIVE_TARGET = dbtux
-
-SOURCES = \
- DbtuxGen.cpp \
- DbtuxMeta.cpp \
- DbtuxMaint.cpp \
- DbtuxNode.cpp \
- DbtuxTree.cpp \
- DbtuxScan.cpp \
- DbtuxCmp.cpp \
- DbtuxDebug.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/dbtux/Times.txt b/ndb/src/kernel/blocks/dbtux/Times.txt
index 1e6d0a0a329..68120084846 100644
--- a/ndb/src/kernel/blocks/dbtux/Times.txt
+++ b/ndb/src/kernel/blocks/dbtux/Times.txt
@@ -138,6 +138,14 @@ before mc02/c 5 ms 13 ms 126 pct
after mc02/c 5 ms 10 ms 70 pct
mc02/d 178 ms 242 ms 69 pct
-[ prelim preformance fix for max batch size 16 -> 992 ]
+[ prelim performance fix for max batch size 16 -> 992 ]
+
+wl-2066 mc02/c 5 ms 10 ms 87 pct
+before mc02/d 140 ms 237 ms 69 pct
+
+wl-2066 mc02/c 5 ms 10 ms 69 pct
+after mc02/d 150 ms 229 ms 52 pct
+
+[ wl-2066 = remove ACC storage, use TUX test to see effect ]
vim: set et:
diff --git a/ndb/src/kernel/blocks/dbutil/Makefile_old b/ndb/src/kernel/blocks/dbutil/Makefile_old
deleted file mode 100644
index 54b7326e4e5..00000000000
--- a/ndb/src/kernel/blocks/dbutil/Makefile_old
+++ /dev/null
@@ -1,8 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := dbutil
-SOURCES = DbUtil.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/grep/Makefile_old b/ndb/src/kernel/blocks/grep/Makefile_old
deleted file mode 100644
index 5ad5a0bce3b..00000000000
--- a/ndb/src/kernel/blocks/grep/Makefile_old
+++ /dev/null
@@ -1,9 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := grep
-
-SOURCES = Grep.cpp GrepInit.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/ndbcntr/Makefile_old b/ndb/src/kernel/blocks/ndbcntr/Makefile_old
deleted file mode 100644
index 8e9c4f01027..00000000000
--- a/ndb/src/kernel/blocks/ndbcntr/Makefile_old
+++ /dev/null
@@ -1,12 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := ndbcntr
-
-SOURCES = \
- NdbcntrInit.cpp \
- NdbcntrSysTable.cpp \
- NdbcntrMain.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/ndbfs/Makefile_old b/ndb/src/kernel/blocks/ndbfs/Makefile_old
deleted file mode 100644
index 58e1458bf16..00000000000
--- a/ndb/src/kernel/blocks/ndbfs/Makefile_old
+++ /dev/null
@@ -1,14 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := ndbfs
-
-SOURCES = \
- AsyncFile.cpp \
- Ndbfs.cpp VoidFs.cpp \
- Filename.cpp \
- CircularIndex.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/src/kernel/blocks/qmgr/Makefile_old b/ndb/src/kernel/blocks/qmgr/Makefile_old
deleted file mode 100644
index cd15643ea60..00000000000
--- a/ndb/src/kernel/blocks/qmgr/Makefile_old
+++ /dev/null
@@ -1,11 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := qmgr
-
-SOURCES = \
- QmgrInit.cpp \
- QmgrMain.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
index 41deb3403c8..da8596076ec 100644
--- a/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
+++ b/ndb/src/kernel/blocks/qmgr/QmgrMain.cpp
@@ -1934,17 +1934,27 @@ void Qmgr::execAPI_REGREQ(Signal* signal)
switch(getNodeInfo(apiNodePtr.i).getType()){
case NodeInfo::API:
compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version);
+ if (!compatability_check)
+ infoEvent("Connection attempt from api or mysqld id=%d with %s "
+ "incompatible with %s", apiNodePtr.i,
+ getVersionString(version,""), NDB_VERSION_STRING);
break;
case NodeInfo::MGM:
compatability_check = ndbCompatible_ndb_mgmt(NDB_VERSION, version);
+ if (!compatability_check)
+ infoEvent("Connection attempt from management server id=%d with %s "
+ "incompatible with %s", apiNodePtr.i,
+ getVersionString(version,""), NDB_VERSION_STRING);
break;
case NodeInfo::REP:
- compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version);
- break;
+ // compatability_check = ndbCompatible_ndb_api(NDB_VERSION, version);
+ // break;
case NodeInfo::DB:
case NodeInfo::INVALID:
default:
sendApiRegRef(signal, ref, ApiRegRef::WrongType);
+ infoEvent("Invalid connection attempt with type %d",
+ getNodeInfo(apiNodePtr.i).getType());
return;
}
@@ -2937,6 +2947,12 @@ void Qmgr::sendPrepFailReq(Signal* signal, Uint16 aNode)
*/
/**
+ * Should < 1/2 nodes die unconditionally. Affects only >= 3-way
+ * replication.
+ */
+static const bool g_ndb_arbit_one_half_rule = false;
+
+/**
* Config signals are logically part of CM_INIT.
*/
void
@@ -3147,7 +3163,8 @@ Qmgr::handleArbitCheck(Signal* signal)
ndbrequire(cpresident == getOwnNodeId());
NodeBitmask ndbMask;
computeArbitNdbMask(ndbMask);
- if (2 * ndbMask.count() < cnoOfNodes) {
+ if (g_ndb_arbit_one_half_rule &&
+ 2 * ndbMask.count() < cnoOfNodes) {
jam();
arbitRec.code = ArbitCode::LoseNodes;
} else {
@@ -3171,6 +3188,11 @@ Qmgr::handleArbitCheck(Signal* signal)
case CheckNodeGroups::Partitioning:
jam();
arbitRec.code = ArbitCode::Partitioning;
+ if (g_ndb_arbit_one_half_rule &&
+ 2 * ndbMask.count() > cnoOfNodes) {
+ jam();
+ arbitRec.code = ArbitCode::WinNodes;
+ }
break;
default:
ndbrequire(false);
@@ -3180,8 +3202,12 @@ Qmgr::handleArbitCheck(Signal* signal)
switch (arbitRec.code) {
case ArbitCode::LoseNodes:
jam();
+ case ArbitCode::LoseGroups:
+ jam();
goto crashme;
- case ArbitCode::WinGroups:
+ case ArbitCode::WinNodes:
+ jam();
+ case ArbitCode::WinGroups:
jam();
if (arbitRec.state == ARBIT_RUN) {
jam();
@@ -3190,9 +3216,6 @@ Qmgr::handleArbitCheck(Signal* signal)
arbitRec.state = ARBIT_INIT;
arbitRec.newstate = true;
break;
- case ArbitCode::LoseGroups:
- jam();
- goto crashme;
case ArbitCode::Partitioning:
if (arbitRec.state == ARBIT_RUN) {
jam();
@@ -3752,8 +3775,7 @@ Qmgr::execARBIT_CHOOSEREF(Signal* signal)
}
/**
- * Handle CRASH state. We must crash immediately. But it
- * would be nice to wait until event reports have been sent.
+ * Handle CRASH state. We must crash immediately.
* XXX tell other nodes in our party to crash too.
*/
void
@@ -3763,12 +3785,11 @@ Qmgr::stateArbitCrash(Signal* signal)
if (arbitRec.newstate) {
jam();
CRASH_INSERTION((Uint32)910 + arbitRec.state);
-
arbitRec.setTimestamp();
arbitRec.code = 0;
arbitRec.newstate = false;
}
-#if 0
+#ifdef ndb_arbit_crash_wait_for_event_report_to_get_out
if (! (arbitRec.getTimediff() > getArbitTimeout()))
return;
#endif
diff --git a/ndb/src/kernel/blocks/suma/Makefile_old b/ndb/src/kernel/blocks/suma/Makefile_old
deleted file mode 100644
index 20014c94670..00000000000
--- a/ndb/src/kernel/blocks/suma/Makefile_old
+++ /dev/null
@@ -1,10 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := suma
-
-SOURCES = Suma.cpp SumaInit.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/src/kernel/blocks/suma/Suma.cpp b/ndb/src/kernel/blocks/suma/Suma.cpp
index d11d5f7176a..f6d9a0ac35a 100644
--- a/ndb/src/kernel/blocks/suma/Suma.cpp
+++ b/ndb/src/kernel/blocks/suma/Suma.cpp
@@ -1888,7 +1888,7 @@ SumaParticipant::SyncRecord::nextScan(Signal* signal){
req->requestInfo = 0;
req->savePointId = 0;
ScanFragReq::setLockMode(req->requestInfo, 0);
- ScanFragReq::setHoldLockFlag(req->requestInfo, 0);
+ ScanFragReq::setHoldLockFlag(req->requestInfo, 1);
ScanFragReq::setKeyinfoFlag(req->requestInfo, 0);
ScanFragReq::setAttrLen(req->requestInfo, attrLen);
req->fragmentNoKeyLen = fd.m_fragDesc.m_fragmentNo;
diff --git a/ndb/src/kernel/blocks/trix/Makefile_old b/ndb/src/kernel/blocks/trix/Makefile_old
deleted file mode 100644
index 5ac0da11f33..00000000000
--- a/ndb/src/kernel/blocks/trix/Makefile_old
+++ /dev/null
@@ -1,8 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := trix
-SOURCES = Trix.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/error/ErrorReporter.cpp b/ndb/src/kernel/error/ErrorReporter.cpp
index 35c99b30994..35cd3f099d9 100644
--- a/ndb/src/kernel/error/ErrorReporter.cpp
+++ b/ndb/src/kernel/error/ErrorReporter.cpp
@@ -137,7 +137,7 @@ ErrorReporter::formatMessage(ErrorCategory type,
faultID,
(problemData == NULL) ? "" : problemData,
objRef,
- programName,
+ my_progname,
processId,
theNameOfTheTraceFile ? theNameOfTheTraceFile : "<no tracefile>");
diff --git a/ndb/src/kernel/error/Makefile_old b/ndb/src/kernel/error/Makefile_old
deleted file mode 100644
index 0fe81f083ce..00000000000
--- a/ndb/src/kernel/error/Makefile_old
+++ /dev/null
@@ -1,12 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := error
-
-SOURCES = \
- TimeModule.cpp \
- ErrorReporter.cpp \
- ErrorMessages.cpp
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/kernel/main.cpp b/ndb/src/kernel/main.cpp
index fa44704807d..f34e16318cd 100644
--- a/ndb/src/kernel/main.cpp
+++ b/ndb/src/kernel/main.cpp
@@ -19,7 +19,6 @@
#include <ndb_version.h>
#include "Configuration.hpp"
-#include <LocalConfig.hpp>
#include <TransporterRegistry.hpp>
#include "vm/SimBlockList.hpp"
@@ -53,11 +52,9 @@ extern "C" void handler_error(int signum); // for process signal handling
void systemInfo(const Configuration & conf,
const LogLevel & ll);
-const char programName[] = "NDB Kernel";
-
-NDB_MAIN(ndb_kernel){
-
- ndb_init();
+int main(int argc, char** argv)
+{
+ NDB_INIT(argv[0]);
// Print to stdout/console
g_eventLogger.createConsoleHandler();
g_eventLogger.setCategory("NDB");
@@ -71,16 +68,9 @@ NDB_MAIN(ndb_kernel){
return NRT_Default;
}
- LocalConfig local_config;
- if (!local_config.init(theConfig->getConnectString(),0)){
- local_config.printError();
- local_config.printUsage();
- return NRT_Default;
- }
-
{ // Do configuration
signal(SIGPIPE, SIG_IGN);
- theConfig->fetch_configuration(local_config);
+ theConfig->fetch_configuration();
}
chdir(NdbConfig_get_path(0));
@@ -143,7 +133,7 @@ NDB_MAIN(ndb_kernel){
exit(0);
}
g_eventLogger.info("Ndb has terminated (pid %d) restarting", child);
- theConfig->fetch_configuration(local_config);
+ theConfig->fetch_configuration();
}
g_eventLogger.info("Angel pid: %d ndb pid: %d", getppid(), getpid());
diff --git a/ndb/src/kernel/vm/Configuration.cpp b/ndb/src/kernel/vm/Configuration.cpp
index 706f60fd9cf..931b4da5a17 100644
--- a/ndb/src/kernel/vm/Configuration.cpp
+++ b/ndb/src/kernel/vm/Configuration.cpp
@@ -15,8 +15,8 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <ndb_opts.h>
-#include <LocalConfig.hpp>
#include "Configuration.hpp"
#include <ErrorHandlingMacros.hpp>
#include "GlobalData.hpp"
@@ -28,14 +28,13 @@
#include <NdbOut.hpp>
#include <WatchDog.hpp>
-#include <getarg.h>
-
#include <mgmapi_configuration.hpp>
#include <mgmapi_config_parameters_debug.h>
#include <kernel_config_parameters.h>
#include <kernel_types.h>
#include <ndb_limits.h>
+#include <ndbapi_limits.h>
#include "pc.hpp"
#include <LogLevel.hpp>
#include <NdbSleep.h>
@@ -47,81 +46,86 @@ extern "C" {
#include <EventLogger.hpp>
extern EventLogger g_eventLogger;
+static const char* opt_connect_str= 0;
+static int _daemon, _no_daemon, _initial, _no_start;
+/**
+ * Arguments to NDB process
+ */
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndbd"),
+ { "initial", 256,
+ "Perform initial start of ndbd, including cleaning the file system. "
+ "Consult documentation before using this",
+ (gptr*) &_initial, (gptr*) &_initial, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "nostart", 'n',
+ "Don't start ndbd immediately. Ndbd will await command from ndb_mgmd",
+ (gptr*) &_no_start, (gptr*) &_no_start, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "daemon", 'd', "Start ndbd as daemon (default)",
+ (gptr*) &_daemon, (gptr*) &_daemon, 0,
+ GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
+ { "nodaemon", 257,
+ "Do not start ndbd as daemon, provided for testing purposes",
+ (gptr*) &_no_daemon, (gptr*) &_no_daemon, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void short_usage_sub(void)
+{
+ printf("Usage: %s [OPTIONS]\n", my_progname);
+}
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
+ short_usage_sub();
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndbd.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ }
+ return 0;
+}
+
bool
-Configuration::init(int argc, const char** argv){
+Configuration::init(int argc, char** argv)
+{
+ const char *load_default_groups[]= { "mysql_cluster","ndbd",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
- /**
- * Default values for arguments
- */
- int _no_start = 0;
- int _initial = 0;
- const char* _connect_str = NULL;
- int _daemon = 1;
- int _no_daemon = 0;
- int _help = 0;
- int _print_version = 0;
-#ifndef DBUG_OFF
- const char *debug_option= 0;
-#endif
-
- /**
- * Arguments to NDB process
- */
-
- struct getargs args[] = {
- { "version", 'v', arg_flag, &_print_version, "Print ndbd version", "" },
- { "nostart", 'n', arg_flag, &_no_start,
- "Don't start ndbd immediately. Ndbd will await command from ndb_mgmd", "" },
- { "daemon", 'd', arg_flag, &_daemon, "Start ndbd as daemon (default)", "" },
- { "nodaemon", 0, arg_flag, &_no_daemon, "Do not start ndbd as daemon, provided for testing purposes", "" },
-#ifndef DBUG_OFF
- { "debug", 0, arg_string, &debug_option,
- "Specify debug options e.g. d:t:i:o,out.trace", "options" },
-#endif
- { "initial", 0, arg_flag, &_initial,
- "Perform initial start of ndbd, including cleaning the file system. Consult documentation before using this", "" },
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ exit(ho_error);
- { "connect-string", 'c', arg_string, &_connect_str,
- "Set connect string for connecting to ndb_mgmd. <constr>=\"host=<hostname:port>[;nodeid=<id>]\". Overides specifying entries in NDB_CONNECTSTRING and config file",
- "<constr>" },
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "The MySQL Cluster kernel";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- for (int i = 0; i < argc; i++) {
- if (strcmp("-i",argv[i]) == 0) {
- printf("flag depricated %s, use %s\n", "-i", "--initial");
- }
- }
- return false;
- }
if (_no_daemon) {
_daemon= 0;
}
- // check for depricated flag '-i'
-
-#ifndef DBUG_OFF
- if (debug_option)
- DBUG_PUSH(debug_option);
-#endif
DBUG_PRINT("info", ("no_start=%d", _no_start));
DBUG_PRINT("info", ("initial=%d", _initial));
DBUG_PRINT("info", ("daemon=%d", _daemon));
- DBUG_PRINT("info", ("connect_str=%s", _connect_str));
+ DBUG_PRINT("info", ("connect_str=%s", opt_connect_str));
ndbSetOwnVersion();
- if (_print_version) {
- ndbPrintVersion();
- return false;
- }
-
// Check the start flag
if (_no_start)
globalData.theRestartFlag = initial_state;
@@ -133,8 +137,8 @@ Configuration::init(int argc, const char** argv){
_initialStart = true;
// Check connectstring
- if (_connect_str)
- _connectString = strdup(_connect_str);
+ if (opt_connect_str)
+ _connectString = strdup(opt_connect_str);
// Check daemon flag
if (_daemon)
@@ -185,7 +189,7 @@ Configuration::closeConfiguration(){
}
void
-Configuration::fetch_configuration(LocalConfig &local_config){
+Configuration::fetch_configuration(){
/**
* Fetch configuration from management server
*/
@@ -195,8 +199,17 @@ Configuration::fetch_configuration(LocalConfig &local_config){
m_mgmd_port= 0;
m_mgmd_host= 0;
- m_config_retriever= new ConfigRetriever(local_config, NDB_VERSION, NODE_TYPE_DB);
- if(m_config_retriever->do_connect() == -1){
+ m_config_retriever= new ConfigRetriever(getConnectString(),
+ NDB_VERSION, NODE_TYPE_DB);
+
+ if (m_config_retriever->hasError())
+ {
+ ERROR_SET(fatal, ERR_INVALID_CONFIG,
+ "Could not connect initialize handle to management server",
+ m_config_retriever->getErrorString());
+ }
+
+ if(m_config_retriever->do_connect(12,5,1) == -1){
const char * s = m_config_retriever->getErrorString();
if(s == 0)
s = "No error given!";
@@ -211,13 +224,7 @@ Configuration::fetch_configuration(LocalConfig &local_config){
ConfigRetriever &cr= *m_config_retriever;
- if((globalData.ownId = cr.allocNodeId()) == 0){
- for(Uint32 i = 0; i<3; i++){
- NdbSleep_SecSleep(3);
- if((globalData.ownId = cr.allocNodeId()) != 0)
- break;
- }
- }
+ globalData.ownId = cr.allocNodeId(2 /*retry*/,3 /*delay*/);
if(globalData.ownId == 0){
ERROR_SET(fatal, ERR_INVALID_CONFIG,
@@ -448,6 +455,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
unsigned int noOfTables = 0;
unsigned int noOfUniqueHashIndexes = 0;
unsigned int noOfOrderedIndexes = 0;
+ unsigned int noOfTriggers = 0;
unsigned int noOfReplicas = 0;
unsigned int noOfDBNodes = 0;
unsigned int noOfAPINodes = 0;
@@ -472,6 +480,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
{ CFG_DB_NO_TABLES, &noOfTables, false },
{ CFG_DB_NO_ORDERED_INDEXES, &noOfOrderedIndexes, false },
{ CFG_DB_NO_UNIQUE_HASH_INDEXES, &noOfUniqueHashIndexes, false },
+ { CFG_DB_NO_TRIGGERS, &noOfTriggers, true },
{ CFG_DB_NO_REPLICAS, &noOfReplicas, false },
{ CFG_DB_NO_ATTRIBUTES, &noOfAttributes, false },
{ CFG_DB_NO_OPS, &noOfOperations, false },
@@ -580,12 +589,41 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
ConfigValues::Iterator it2(*ownConfig, db.m_config);
it2.set(CFG_DB_NO_TABLES, noOfTables);
it2.set(CFG_DB_NO_ATTRIBUTES, noOfAttributes);
+ {
+ Uint32 neededNoOfTriggers = /* types: Insert/Update/Delete/Custom */
+ 3 * noOfUniqueHashIndexes + /* for unique hash indexes, I/U/D */
+ 3 * NDB_MAX_ACTIVE_EVENTS + /* for events in suma, I/U/D */
+ 3 * noOfTables + /* for backup, I/U/D */
+ noOfOrderedIndexes; /* for ordered indexes, C */
+ if (noOfTriggers < neededNoOfTriggers)
+ {
+ noOfTriggers= neededNoOfTriggers;
+ it2.set(CFG_DB_NO_TRIGGERS, noOfTriggers);
+ }
+ }
/**
* Do size calculations
*/
ConfigValuesFactory cfg(ownConfig);
+ Uint32 noOfMetaTables= noOfTables + noOfOrderedIndexes +
+ noOfUniqueHashIndexes;
+ if (noOfMetaTables > MAX_TABLES)
+ noOfMetaTables= MAX_TABLES;
+
+ {
+ /**
+ * Dict Size Alt values
+ */
+ cfg.put(CFG_DICT_ATTRIBUTE,
+ noOfAttributes);
+
+ cfg.put(CFG_DICT_TABLE,
+ noOfMetaTables);
+ }
+
+
if (noOfLocalScanRecords == 0) {
noOfLocalScanRecords = (noOfDBNodes * noOfScanRecords) + 1;
}
@@ -595,7 +633,7 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
Uint32 noOfTCScanRecords = noOfScanRecords;
{
- Uint32 noOfAccTables= noOfTables + noOfUniqueHashIndexes;
+ Uint32 noOfAccTables= noOfMetaTables/*noOfTables+noOfUniqueHashIndexes*/;
/**
* Acc Size Alt values
*/
@@ -637,19 +675,6 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
cfg.put(CFG_ACC_SCAN, noOfLocalScanRecords);
}
- Uint32 noOfMetaTables= noOfTables + noOfOrderedIndexes +
- noOfUniqueHashIndexes;
- {
- /**
- * Dict Size Alt values
- */
- cfg.put(CFG_DICT_ATTRIBUTE,
- noOfAttributes);
-
- cfg.put(CFG_DICT_TABLE,
- noOfMetaTables);
- }
-
{
/**
* Dih Size Alt values
@@ -742,8 +767,8 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
noOfMetaTables);
cfg.put(CFG_TUP_TABLE_DESC,
- 4 * NO_OF_FRAG_PER_NODE * noOfAttributes* noOfReplicas +
- 12 * NO_OF_FRAG_PER_NODE * noOfMetaTables* noOfReplicas );
+ 2 * 6 * NO_OF_FRAG_PER_NODE * noOfAttributes * noOfReplicas +
+ 2 * 10 * NO_OF_FRAG_PER_NODE * noOfMetaTables * noOfReplicas );
cfg.put(CFG_TUP_STORED_PROC,
noOfLocalScanRecords);
@@ -754,9 +779,9 @@ Configuration::calcSizeAlt(ConfigValues * ownConfig){
* Tux Size Alt values
*/
cfg.put(CFG_TUX_INDEX,
- noOfOrderedIndexes);
+ noOfMetaTables /*noOfOrderedIndexes*/);
- cfg.put(CFG_TUX_FRAGMENT,
+ cfg.put(CFG_TUX_FRAGMENT,
2 * NO_OF_FRAG_PER_NODE * noOfOrderedIndexes * noOfReplicas);
cfg.put(CFG_TUX_ATTRIBUTE,
diff --git a/ndb/src/kernel/vm/Configuration.hpp b/ndb/src/kernel/vm/Configuration.hpp
index 2ea32ffea37..acf0e163a84 100644
--- a/ndb/src/kernel/vm/Configuration.hpp
+++ b/ndb/src/kernel/vm/Configuration.hpp
@@ -21,7 +21,6 @@
#include <ndb_types.h>
class ConfigRetriever;
-class LocalConfig;
class Configuration {
public:
@@ -31,9 +30,9 @@ public:
/**
* Returns false if arguments are invalid
*/
- bool init(int argc, const char** argv);
+ bool init(int argc, char** argv);
- void fetch_configuration(LocalConfig &local_config);
+ void fetch_configuration();
void setupConfiguration();
void closeConfiguration();
diff --git a/ndb/src/kernel/vm/Emulator.hpp b/ndb/src/kernel/vm/Emulator.hpp
index bd240f8679b..b3c64830802 100644
--- a/ndb/src/kernel/vm/Emulator.hpp
+++ b/ndb/src/kernel/vm/Emulator.hpp
@@ -25,6 +25,7 @@
//
//===========================================================================
#include <kernel_types.h>
+#include <TransporterRegistry.hpp>
extern class JobTable globalJobTable;
extern class TimeQueue globalTimeQueue;
diff --git a/ndb/src/kernel/vm/LongSignal.hpp b/ndb/src/kernel/vm/LongSignal.hpp
index f9ed443d995..9818358011f 100644
--- a/ndb/src/kernel/vm/LongSignal.hpp
+++ b/ndb/src/kernel/vm/LongSignal.hpp
@@ -25,7 +25,7 @@
*/
struct SectionSegment {
- STATIC_CONST( DataLength = 60 );
+ STATIC_CONST( DataLength = NDB_SECTION_SEGMENT_SZ );
Uint32 m_ownerRef;
Uint32 m_sz;
diff --git a/ndb/src/kernel/vm/Makefile_old b/ndb/src/kernel/vm/Makefile_old
deleted file mode 100644
index a162f3672ce..00000000000
--- a/ndb/src/kernel/vm/Makefile_old
+++ /dev/null
@@ -1,30 +0,0 @@
-include .defs.mk
-
-TYPE := kernel
-
-ARCHIVE_TARGET := kernel
-
-SOURCES = \
- SimulatedBlock.cpp \
- FastScheduler.cpp \
- TimeQueue.cpp \
- VMSignal.cpp \
- ThreadConfig.cpp \
- TransporterCallback.cpp \
- Emulator.cpp \
- Configuration.cpp \
- WatchDog.cpp \
- SimplePropertiesSection.cpp \
- SectionReader.cpp \
- MetaData.cpp \
- Mutex.cpp SafeCounter.cpp
-
-CFLAGS_Configuration.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
-
-DIRS := testCopy testDataBuffer testSimplePropertiesSection
-
-ifneq ($(USE_EDITLINE), N)
-DIRS += testLongSig
-endif
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/common/mgmcommon/LocalConfig.cpp b/ndb/src/mgmapi/LocalConfig.cpp
index 3cd4341c6b7..1dc805557ee 100644
--- a/ndb/src/common/mgmcommon/LocalConfig.cpp
+++ b/ndb/src/mgmapi/LocalConfig.cpp
@@ -90,7 +90,7 @@ LocalConfig::init(const char *connectString,
//7. Check
{
char buf[256];
- BaseString::snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_BASE_PORT);
+ BaseString::snprintf(buf, sizeof(buf), "host=localhost:%s", NDB_PORT);
if(readConnectString(buf, "default connect string"))
return true;
}
@@ -124,12 +124,12 @@ void LocalConfig::printUsage() const {
ndbout << "1. Put a Ndb.cfg file in the directory where you start"<<endl
<< " the node. "<< endl
<< " Ex: Ndb.cfg" << endl
- << " | host=localhost:"<<NDB_BASE_PORT<<endl;
+ << " | host=localhost:"<<NDB_PORT<<endl;
ndbout << "2. Use the environment variable NDB_CONNECTSTRING to "<<endl
<< " provide this information." <<endl
<< " Ex: " << endl
- << " >export NDB_CONNECTSTRING=\"host=localhost:"<<NDB_BASE_PORT<<"\""
+ << " >export NDB_CONNECTSTRING=\"host=localhost:"<<NDB_PORT<<"\""
<<endl<<endl;
}
@@ -164,17 +164,25 @@ LocalConfig::parseNodeId(const char * buf){
bool
LocalConfig::parseHostName(const char * buf){
char tempString[1024];
+ char tempString2[1024];
int port;
- for(int i = 0; hostNameTokens[i] != 0; i++) {
- if (sscanf(buf, hostNameTokens[i], tempString, &port) == 2) {
- MgmtSrvrId mgmtSrvrId;
- mgmtSrvrId.type = MgmId_TCP;
- mgmtSrvrId.name.assign(tempString);
- mgmtSrvrId.port = port;
- ids.push_back(mgmtSrvrId);
- return true;
+ do {
+ for(int i = 0; hostNameTokens[i] != 0; i++) {
+ if (sscanf(buf, hostNameTokens[i], tempString, &port) == 2) {
+ MgmtSrvrId mgmtSrvrId;
+ mgmtSrvrId.type = MgmId_TCP;
+ mgmtSrvrId.name.assign(tempString);
+ mgmtSrvrId.port = port;
+ ids.push_back(mgmtSrvrId);
+ return true;
+ }
}
- }
+ if (buf == tempString2)
+ break;
+ // try to add default port to see if it works
+ snprintf(tempString2, sizeof(tempString2),"%s:%s", buf, NDB_PORT);
+ buf= tempString2;
+ } while(1);
return false;
}
@@ -286,4 +294,27 @@ LocalConfig::readConnectString(const char * connectString,
return return_value;
}
+char *
+LocalConfig::makeConnectString(char *buf, int sz)
+{
+ int p= BaseString::snprintf(buf,sz,"nodeid=%d", _ownNodeId);
+ if (p < sz)
+ for (unsigned i = 0; i < ids.size(); i++)
+ {
+ if (ids[i].type != MgmId_TCP)
+ continue;
+ int new_p= p+BaseString::snprintf(buf+p,sz-p,",%s:%d",
+ ids[i].name.c_str(), ids[i].port);
+ if (new_p < sz)
+ p= new_p;
+ else
+ {
+ buf[p]= 0;
+ break;
+ }
+ }
+ buf[sz-1]=0;
+ return buf;
+}
+
template class Vector<MgmtSrvrId>;
diff --git a/ndb/include/mgmcommon/LocalConfig.hpp b/ndb/src/mgmapi/LocalConfig.hpp
index 9ceeffdba36..c415ec1be91 100644
--- a/ndb/include/mgmcommon/LocalConfig.hpp
+++ b/ndb/src/mgmapi/LocalConfig.hpp
@@ -61,6 +61,7 @@ struct LocalConfig {
bool parseHostName(const char *buf);
bool parseFileName(const char *buf);
bool parseString(const char *buf, BaseString &err);
+ char * makeConnectString(char *buf, int sz);
};
#endif // LocalConfig_H
diff --git a/ndb/src/mgmapi/Makefile.am b/ndb/src/mgmapi/Makefile.am
index 0f0e1cea5d8..d64216b56c0 100644
--- a/ndb/src/mgmapi/Makefile.am
+++ b/ndb/src/mgmapi/Makefile.am
@@ -1,10 +1,11 @@
noinst_LTLIBRARIES = libmgmapi.la
-libmgmapi_la_SOURCES = mgmapi.cpp mgmapi_configuration.cpp
+libmgmapi_la_SOURCES = mgmapi.cpp mgmapi_configuration.cpp LocalConfig.cpp
-INCLUDES_LOC = -I$(top_srcdir)/ndb/include/mgmapi -I$(top_srcdir)/ndb/src/common/mgmcommon
-DEFS_LOC = -DNO_DEBUG_MESSAGES
+INCLUDES_LOC = -I$(top_srcdir)/ndb/include/mgmapi
+
+DEFS_LOC = -DNO_DEBUG_MESSAGES -DNDB_PORT="\"@ndb_port@\""
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_util.mk.am
diff --git a/ndb/src/mgmapi/Makefile_old b/ndb/src/mgmapi/Makefile_old
deleted file mode 100644
index fa734f998e6..00000000000
--- a/ndb/src/mgmapi/Makefile_old
+++ /dev/null
@@ -1,27 +0,0 @@
-include .defs.mk
-
-TYPE := util
-
-PIC_ARCHIVE := Y
-ARCHIVE_TARGET := mgmapi
-
-A_LIB := Y
-SO_LIB := Y
-PIC_LIB := Y
-
-#DIRS := test
-
-LIB_TARGET := MGM_API
-LIB_TARGET_ARCHIVES := $(ARCHIVE_TARGET) general portlib
-
-# Source files of non-templated classes (.C files)
-SOURCES = mgmapi.cpp mgmapi_configuration.cpp
-
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \
- -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
-
-CCFLAGS += -DNO_DEBUG_MESSAGES
-
-# -I$(NDB_TOP)/src/common/mgmcommon
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/src/mgmapi/mgmapi.cpp b/ndb/src/mgmapi/mgmapi.cpp
index 4b62df968b3..e22ceffe773 100644
--- a/ndb/src/mgmapi/mgmapi.cpp
+++ b/ndb/src/mgmapi/mgmapi.cpp
@@ -17,8 +17,10 @@
#include <ndb_global.h>
#include <my_sys.h>
+#include <LocalConfig.hpp>
#include <NdbAutoPtr.hpp>
+#include <NdbSleep.h>
#include <NdbTCP.h>
#include "mgmapi.h"
#include "mgmapi_debug.h"
@@ -82,8 +84,7 @@ typedef Parser<ParserDummy> Parser_t;
#define NDB_MGM_MAX_ERR_DESC_SIZE 256
struct ndb_mgm_handle {
- char * hostname;
- unsigned short port;
+ int cfg_i;
int connected;
int last_error;
@@ -94,6 +95,8 @@ struct ndb_mgm_handle {
NDB_SOCKET_TYPE socket;
+ LocalConfig cfg;
+
#ifdef MGMAPI_LOG
FILE* logfile;
#endif
@@ -145,12 +148,16 @@ ndb_mgm_create_handle()
h->connected = 0;
h->last_error = 0;
h->last_error_line = 0;
- h->hostname = 0;
- h->socket = -1;
+ h->socket = NDB_INVALID_SOCKET;
h->read_timeout = 50000;
h->write_timeout = 100;
+ h->cfg_i = 0;
strncpy(h->last_error_desc, "No error", NDB_MGM_MAX_ERR_DESC_SIZE);
+
+ new (&(h->cfg)) LocalConfig;
+ h->cfg.init(0, 0);
+
#ifdef MGMAPI_LOG
h->logfile = 0;
#endif
@@ -158,6 +165,23 @@ ndb_mgm_create_handle()
return h;
}
+extern "C"
+int
+ndb_mgm_set_connectstring(NdbMgmHandle handle, const char * mgmsrv)
+{
+ new (&(handle->cfg)) LocalConfig;
+ if (!handle->cfg.init(mgmsrv, 0) ||
+ handle->cfg.ids.size() == 0)
+ {
+ new (&(handle->cfg)) LocalConfig;
+ handle->cfg.init(0, 0); /* reset the LocalCongig */
+ SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, "");
+ return -1;
+ }
+ handle->cfg_i= 0;
+ return 0;
+}
+
/**
* Destroy a handle
*/
@@ -170,13 +194,13 @@ ndb_mgm_destroy_handle(NdbMgmHandle * handle)
if((* handle)->connected){
ndb_mgm_disconnect(* handle);
}
- my_free((* handle)->hostname,MYF(MY_ALLOW_ZERO_PTR));
#ifdef MGMAPI_LOG
if ((* handle)->logfile != 0){
fclose((* handle)->logfile);
(* handle)->logfile = 0;
}
#endif
+ (*handle)->cfg.~LocalConfig();
my_free((char*)* handle,MYF(MY_ALLOW_ZERO_PTR));
* handle = 0;
}
@@ -220,42 +244,6 @@ ndb_mgm_get_latest_error_msg(const NdbMgmHandle h)
return "Error"; // Unknown Error message
}
-static
-int
-parse_connect_string(const char * connect_string,
- NdbMgmHandle handle)
-{
- if(connect_string == 0){
- SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, "");
- return -1;
- }
-
- char * line = my_strdup(connect_string,MYF(MY_WME));
- My_auto_ptr<char> ap1(line);
- if(line == 0){
- SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY, "");
- return -1;
- }
-
- char * tmp = strchr(line, ':');
- if(tmp == 0){
- SET_ERROR(handle, NDB_MGM_OUT_OF_MEMORY, "");
- return -1;
- }
- * tmp = 0; tmp++;
-
- int port = 0;
- if(sscanf(tmp, "%d", &port) != 1){
- SET_ERROR(handle, NDB_MGM_ILLEGAL_PORT_NUMBER, "");
- return -1;
- }
-
- my_free(handle->hostname,MYF(MY_ALLOW_ZERO_PTR));
- handle->hostname = my_strdup(line,MYF(MY_WME));
- handle->port = port;
- return 0;
-}
-
/*
* Call an operation, and return the reply
*/
@@ -344,15 +332,11 @@ ndb_mgm_call(NdbMgmHandle handle, const ParserRow<ParserDummy> *command_reply,
*/
extern "C"
int
-ndb_mgm_connect(NdbMgmHandle handle, const char * mgmsrv)
+ndb_mgm_connect(NdbMgmHandle handle, int no_retries,
+ int retry_delay_in_seconds, int verbose)
{
SET_ERROR(handle, NDB_MGM_NO_ERROR, "Executing: ndb_mgm_connect");
CHECK_HANDLE(handle, -1);
-
- if(parse_connect_string(mgmsrv, handle) != 0) {
- SET_ERROR(handle, NDB_MGM_ILLEGAL_CONNECT_STRING, "");
- return -1;
- }
#ifdef MGMAPI_LOG
/**
@@ -366,14 +350,61 @@ ndb_mgm_connect(NdbMgmHandle handle, const char * mgmsrv)
/**
* Do connect
*/
- SocketClient s(handle->hostname, handle->port);
- const NDB_SOCKET_TYPE sockfd = s.connect();
- if (sockfd < 0) {
- setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
- "Unable to connect to %s", mgmsrv);
- return -1;
+ LocalConfig &cfg= handle->cfg;
+ NDB_SOCKET_TYPE sockfd= NDB_INVALID_SOCKET;
+ Uint32 i;
+ while (sockfd == NDB_INVALID_SOCKET)
+ {
+ // do all the mgmt servers
+ for (i = 0; i < cfg.ids.size(); i++)
+ {
+ if (cfg.ids[i].type != MgmId_TCP)
+ continue;
+ SocketClient s(cfg.ids[i].name.c_str(), cfg.ids[i].port);
+ sockfd = s.connect();
+ if (sockfd != NDB_INVALID_SOCKET)
+ break;
+ }
+ if (sockfd != NDB_INVALID_SOCKET)
+ break;
+ if (verbose > 0) {
+ char buf[1024];
+ ndbout_c("Unable to connect with connect string: %s",
+ cfg.makeConnectString(buf,sizeof(buf)));
+ verbose= -1;
+ }
+ if (no_retries == 0) {
+ char buf[1024];
+ setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
+ "Unable to connect with connect string: %s",
+ cfg.makeConnectString(buf,sizeof(buf)));
+ if (verbose == -2)
+ ndbout << ", failed." << endl;
+ return -1;
+ }
+ if (verbose == -1) {
+ ndbout << "Retrying every " << retry_delay_in_seconds << " seconds";
+ if (no_retries > 0)
+ ndbout << ". Attempts left:";
+ else
+ ndbout << ", until connected.";;
+ ndbout << flush;
+ verbose= -2;
+ }
+ if (no_retries > 0) {
+ if (verbose == -2) {
+ ndbout << " " << no_retries;
+ ndbout << flush;
+ }
+ no_retries--;
+ }
+ NdbSleep_SecSleep(retry_delay_in_seconds);
}
-
+ if (verbose == -2)
+ ndbout << endl;
+
+ handle->cfg_i = i;
+
handle->socket = sockfd;
handle->connected = 1;
@@ -392,7 +423,7 @@ ndb_mgm_disconnect(NdbMgmHandle handle)
CHECK_CONNECTED(handle, -1);
NDB_CLOSE_SOCKET(handle->socket);
- handle->socket = -1;
+ handle->socket = NDB_INVALID_SOCKET;
handle->connected = 0;
return 0;
@@ -543,7 +574,9 @@ cmp_state(const void *_a, const void *_b)
a = (struct ndb_mgm_node_state *)_a;
b = (struct ndb_mgm_node_state *)_b;
- return a->node_id > b->node_id;
+ if (a->node_id > b->node_id)
+ return 1;
+ return -1;
}
extern "C"
@@ -1080,7 +1113,9 @@ ndb_mgm_listen_event(NdbMgmHandle handle, int filter[])
};
CHECK_HANDLE(handle, -1);
- SocketClient s(handle->hostname, handle->port);
+ const char *hostname= ndb_mgm_get_connected_host(handle);
+ int port= ndb_mgm_get_connected_port(handle);
+ SocketClient s(hostname, port);
const NDB_SOCKET_TYPE sockfd = s.connect();
if (sockfd < 0) {
setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
@@ -1625,16 +1660,43 @@ ndb_mgm_destroy_configuration(struct ndb_mgm_configuration *cfg)
extern "C"
int
-ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, unsigned *pnodeid, int nodetype)
+ndb_mgm_get_configuration_nodeid(NdbMgmHandle handle)
+{
+ CHECK_HANDLE(handle, 0);
+ return handle->cfg._ownNodeId;
+}
+
+extern "C"
+int ndb_mgm_get_connected_port(NdbMgmHandle handle)
+{
+ return handle->cfg.ids[handle->cfg_i].port;
+}
+
+extern "C"
+const char *ndb_mgm_get_connected_host(NdbMgmHandle handle)
{
+ return handle->cfg.ids[handle->cfg_i].name.c_str();
+}
+
+extern "C"
+const char *ndb_mgm_get_connectstring(NdbMgmHandle handle, char *buf, int buf_sz)
+{
+ return handle->cfg.makeConnectString(buf,buf_sz);
+}
+extern "C"
+int
+ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, int nodetype)
+{
CHECK_HANDLE(handle, 0);
CHECK_CONNECTED(handle, 0);
+ int nodeid= handle->cfg._ownNodeId;
+
Properties args;
args.put("version", version);
args.put("nodetype", nodetype);
- args.put("nodeid", *pnodeid);
+ args.put("nodeid", nodeid);
args.put("user", "mysqld");
args.put("password", "mysqld");
args.put("public key", "a public key");
@@ -1650,26 +1712,29 @@ ndb_mgm_alloc_nodeid(NdbMgmHandle handle, unsigned int version, unsigned *pnodei
prop= ndb_mgm_call(handle, reply, "get nodeid", &args);
CHECK_REPLY(prop, -1);
- int res= -1;
+ nodeid= -1;
do {
const char * buf;
if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ const char *hostname= ndb_mgm_get_connected_host(handle);
+ unsigned port= ndb_mgm_get_connected_port(handle);
BaseString err;
err.assfmt("Could not alloc node id at %s port %d: %s",
- handle->hostname, handle->port, buf);
+ hostname, port, buf);
setError(handle, NDB_MGM_COULD_NOT_CONNECT_TO_SOCKET, __LINE__,
err.c_str());
break;
}
- if(!prop->get("nodeid", pnodeid) != 0){
+ Uint32 _nodeid;
+ if(!prop->get("nodeid", &_nodeid) != 0){
ndbout_c("ERROR Message: <nodeid Unspecified>\n");
break;
}
- res= 0;
+ nodeid= _nodeid;
}while(0);
delete prop;
- return res;
+ return nodeid;
}
/*****************************************************************************
@@ -1834,4 +1899,80 @@ ndb_mgm_set_string_parameter(NdbMgmHandle handle,
return res;
}
+extern "C"
+int
+ndb_mgm_purge_stale_sessions(NdbMgmHandle handle, char **purged){
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+
+ Properties args;
+
+ const ParserRow<ParserDummy> reply[]= {
+ MGM_CMD("purge stale sessions reply", NULL, ""),
+ MGM_ARG("purged", String, Optional, ""),
+ MGM_ARG("result", String, Mandatory, "Error message"),
+ MGM_END()
+ };
+
+ const Properties *prop;
+ prop= ndb_mgm_call(handle, reply, "purge stale sessions", &args);
+
+ if(prop == NULL) {
+ SET_ERROR(handle, EIO, "Unable to purge stale sessions");
+ return -1;
+ }
+
+ int res= -1;
+ do {
+ const char * buf;
+ if(!prop->get("result", &buf) || strcmp(buf, "Ok") != 0){
+ ndbout_c("ERROR Message: %s\n", buf);
+ break;
+ }
+ if (purged) {
+ if (prop->get("purged", &buf))
+ *purged= strdup(buf);
+ else
+ *purged= 0;
+ }
+ res= 0;
+ } while(0);
+ delete prop;
+ return res;
+}
+
+extern "C"
+int
+ndb_mgm_check_connection(NdbMgmHandle handle){
+ CHECK_HANDLE(handle, 0);
+ CHECK_CONNECTED(handle, 0);
+ SocketOutputStream out(handle->socket);
+ SocketInputStream in(handle->socket, handle->read_timeout);
+ char buf[32];
+
+ if (out.println("check connection"))
+ goto ndb_mgm_check_connection_error;
+
+ if (out.println(""))
+ goto ndb_mgm_check_connection_error;
+
+ in.gets(buf, sizeof(buf));
+ if(strcmp("check connection reply\n", buf))
+ goto ndb_mgm_check_connection_error;
+
+ in.gets(buf, sizeof(buf));
+ if(strcmp("result: Ok\n", buf))
+ goto ndb_mgm_check_connection_error;
+
+ in.gets(buf, sizeof(buf));
+ if(strcmp("\n", buf))
+ goto ndb_mgm_check_connection_error;
+
+ return 0;
+
+ndb_mgm_check_connection_error:
+ ndb_mgm_disconnect(handle);
+ return -1;
+}
+
template class Vector<const ParserRow<ParserDummy>*>;
diff --git a/ndb/src/mgmclient/CommandInterpreter.cpp b/ndb/src/mgmclient/CommandInterpreter.cpp
index e0935c2104e..7ef62da9bb3 100644
--- a/ndb/src/mgmclient/CommandInterpreter.cpp
+++ b/ndb/src/mgmclient/CommandInterpreter.cpp
@@ -17,7 +17,198 @@
#include <ndb_global.h>
#include <my_sys.h>
-#include "CommandInterpreter.hpp"
+//#define HAVE_GLOBAL_REPLICATION
+
+#include <Vector.hpp>
+#ifdef HAVE_GLOBAL_REPLICATION
+#include "../rep/repapi/repapi.h"
+#endif
+
+#include <mgmapi.h>
+
+class MgmtSrvr;
+
+/**
+ * @class CommandInterpreter
+ * @brief Reads command line in management client
+ *
+ * This class has one public method which reads a command line
+ * from a stream. It then interpret that commmand line and calls a suitable
+ * method in the MgmtSrvr class which executes the command.
+ *
+ * For command syntax, see the HELP command.
+ */
+class CommandInterpreter {
+public:
+ /**
+ * Constructor
+ * @param mgmtSrvr: Management server to use when executing commands
+ */
+ CommandInterpreter(const char *, int verbose);
+ ~CommandInterpreter();
+
+ /**
+ * Reads one line from the stream, parse the line to find
+ * a command and then calls a suitable method which executes
+ * the command.
+ *
+ * @return true until quit/bye/exit has been typed
+ */
+ int execute(const char *_line, int _try_reconnect=-1, int *error= 0);
+
+private:
+ void printError();
+ int execute_impl(const char *_line);
+
+ /**
+ * Analyse the command line, after the first token.
+ *
+ * @param processId: DB process id to send command to or -1 if
+ * command will be sent to all DB processes.
+ * @param allAfterFirstToken: What the client gave after the
+ * first token on the command line
+ */
+ void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr);
+
+ /**
+ * Parse the block specification part of the LOG* commands,
+ * things after LOG*: [BLOCK = {ALL|<blockName>+}]
+ *
+ * @param allAfterLog: What the client gave after the second token
+ * (LOG*) on the command line
+ * @param blocks, OUT: ALL or name of all the blocks
+ * @return: true if correct syntax, otherwise false
+ */
+ bool parseBlockSpecification(const char* allAfterLog,
+ Vector<const char*>& blocks);
+
+ /**
+ * A bunch of execute functions: Executes one of the commands
+ *
+ * @param processId: DB process id to send command to
+ * @param parameters: What the client gave after the command name
+ * on the command line.
+ * For example if complete input from user is: "1 LOGLEVEL 22" then the
+ * parameters argument is the string with everything after LOGLEVEL, in
+ * this case "22". Each function is responsible to check the parameters
+ * argument.
+ */
+ void executeHelp(char* parameters);
+ void executeShow(char* parameters);
+ void executeConnect(char* parameters);
+ void executePurge(char* parameters);
+ int executeShutdown(char* parameters);
+ void executeRun(char* parameters);
+ void executeInfo(char* parameters);
+ void executeClusterLog(char* parameters);
+
+public:
+ void executeStop(int processId, const char* parameters, bool all);
+ void executeEnterSingleUser(char* parameters);
+ void executeExitSingleUser(char* parameters);
+ void executeStart(int processId, const char* parameters, bool all);
+ void executeRestart(int processId, const char* parameters, bool all);
+ void executeLogLevel(int processId, const char* parameters, bool all);
+ void executeError(int processId, const char* parameters, bool all);
+ void executeTrace(int processId, const char* parameters, bool all);
+ void executeLog(int processId, const char* parameters, bool all);
+ void executeLogIn(int processId, const char* parameters, bool all);
+ void executeLogOut(int processId, const char* parameters, bool all);
+ void executeLogOff(int processId, const char* parameters, bool all);
+ void executeTestOn(int processId, const char* parameters, bool all);
+ void executeTestOff(int processId, const char* parameters, bool all);
+ void executeSet(int processId, const char* parameters, bool all);
+ void executeGetStat(int processId, const char* parameters, bool all);
+ void executeStatus(int processId, const char* parameters, bool all);
+ void executeEventReporting(int processId, const char* parameters, bool all);
+ void executeDumpState(int processId, const char* parameters, bool all);
+ int executeStartBackup(char * parameters);
+ void executeAbortBackup(char * parameters);
+
+ void executeRep(char* parameters);
+
+ void executeCpc(char * parameters);
+
+public:
+ bool connect();
+ bool disconnect();
+
+ /**
+ * A execute function definition
+ */
+public:
+ typedef void (CommandInterpreter::* ExecuteFunction)(int processId,
+ const char * param,
+ bool all);
+
+ struct CommandFunctionPair {
+ const char * command;
+ ExecuteFunction executeFunction;
+ };
+private:
+ /**
+ *
+ */
+ void executeForAll(const char * cmd,
+ ExecuteFunction fun,
+ const char * param);
+
+ NdbMgmHandle m_mgmsrv;
+ bool connected;
+ int m_verbose;
+ int try_reconnect;
+ int m_error;
+#ifdef HAVE_GLOBAL_REPLICATION
+ NdbRepHandle m_repserver;
+ const char *rep_host;
+ bool rep_connected;
+#endif
+};
+
+
+/*
+ * Facade object for CommandInterpreter
+ */
+
+#include "ndb_mgmclient.hpp"
+#include "ndb_mgmclient.h"
+
+Ndb_mgmclient::Ndb_mgmclient(const char *host,int verbose)
+{
+ m_cmd= new CommandInterpreter(host,verbose);
+}
+Ndb_mgmclient::~Ndb_mgmclient()
+{
+ delete m_cmd;
+}
+int Ndb_mgmclient::execute(const char *_line, int _try_reconnect, int *error)
+{
+ return m_cmd->execute(_line,_try_reconnect,error);
+}
+int
+Ndb_mgmclient::disconnect()
+{
+ return m_cmd->disconnect();
+}
+
+extern "C" {
+ Ndb_mgmclient_handle ndb_mgmclient_handle_create(const char *connect_string)
+ {
+ return (Ndb_mgmclient_handle) new Ndb_mgmclient(connect_string);
+ }
+ int ndb_mgmclient_execute(Ndb_mgmclient_handle h, int argc, char** argv)
+ {
+ return ((Ndb_mgmclient*)h)->execute(argc, argv, 1);
+ }
+ int ndb_mgmclient_handle_destroy(Ndb_mgmclient_handle h)
+ {
+ delete (Ndb_mgmclient*)h;
+ return 0;
+ }
+}
+/*
+ * The CommandInterpreter
+ */
#include <mgmapi.h>
#include <mgmapi_debug.h>
@@ -33,8 +224,22 @@
#endif // HAVE_GLOBAL_REPLICATION
#include "MgmtErrorReporter.hpp"
-#include "CpcClient.hpp"
+#include <Parser.hpp>
+#include <SocketServer.hpp>
+#include <util/InputStream.hpp>
+#include <util/OutputStream.hpp>
+int Ndb_mgmclient::execute(int argc, char** argv, int _try_reconnect, int *error)
+{
+ if (argc <= 0)
+ return 0;
+ BaseString _line(argv[0]);
+ for (int i= 1; i < argc; i++)
+ {
+ _line.appfmt(" %s", argv[i]);
+ }
+ return m_cmd->execute(_line.c_str(),_try_reconnect, error);
+}
/*****************************************************************************
* HELP
@@ -73,6 +278,8 @@ static const char* helpText =
#ifdef HAVE_GLOBAL_REPLICATION
"REP CONNECT <host:port> Connect to REP server on host:port\n"
#endif
+"PURGE STALE SESSIONS Reset reserved nodeid's in the mgmt server\n"
+"CONNECT [<connectstring>] Connect to management server (reconnect if already connected)\n"
"QUIT Quit management client\n"
;
@@ -171,18 +378,22 @@ convert(const char* s, int& val) {
/*
* Constructor
*/
-CommandInterpreter::CommandInterpreter(const char *_host)
+CommandInterpreter::CommandInterpreter(const char *_host,int verbose)
+ : m_verbose(verbose)
{
m_mgmsrv = ndb_mgm_create_handle();
if(m_mgmsrv == NULL) {
ndbout_c("Cannot create handle to management server.");
+ exit(-1);
+ }
+ if (ndb_mgm_set_connectstring(m_mgmsrv, _host))
+ {
printError();
+ exit(-1);
}
connected = false;
try_reconnect = 0;
-
- host = my_strdup(_host,MYF(MY_WME));
#ifdef HAVE_GLOBAL_REPLICATION
rep_host = NULL;
m_repserver = NULL;
@@ -197,11 +408,9 @@ CommandInterpreter::~CommandInterpreter()
{
connected = false;
ndb_mgm_destroy_handle(&m_mgmsrv);
- my_free((char *)host,MYF(0));
- host = NULL;
}
-bool
+static bool
emptyString(const char* s)
{
if (s == NULL) {
@@ -220,6 +429,8 @@ emptyString(const char* s)
void
CommandInterpreter::printError()
{
+ if (ndb_mgm_check_connection(m_mgmsrv))
+ connected= false;
ndbout_c("* %5d: %s",
ndb_mgm_get_latest_error(m_mgmsrv),
ndb_mgm_get_latest_error_msg(m_mgmsrv));
@@ -233,17 +444,15 @@ bool
CommandInterpreter::connect()
{
if(!connected) {
- int tries = try_reconnect; // tries == 0 => infinite
- while(!connected) {
- if(ndb_mgm_connect(m_mgmsrv, host) == -1) {
- ndbout << "Cannot connect to management server (" << host << ").";
- tries--;
- if (tries == 0)
- break;
- ndbout << "Retrying in 5 seconds." << endl;
- NdbSleep_SecSleep(5);
- } else
- connected = true;
+ if(!ndb_mgm_connect(m_mgmsrv, try_reconnect-1, 5, 1))
+ {
+ connected = true;
+ if (m_verbose)
+ {
+ printf("Connected to Management Server at: %s:%d\n",
+ ndb_mgm_get_connected_host(m_mgmsrv),
+ ndb_mgm_get_connected_port(m_mgmsrv));
+ }
}
}
return connected;
@@ -252,7 +461,7 @@ CommandInterpreter::connect()
bool
CommandInterpreter::disconnect()
{
- if (ndb_mgm_disconnect(m_mgmsrv) == -1) {
+ if (connected && (ndb_mgm_disconnect(m_mgmsrv) == -1)) {
ndbout_c("Could not disconnect from management server");
printError();
}
@@ -264,95 +473,110 @@ CommandInterpreter::disconnect()
//*****************************************************************************
int
-CommandInterpreter::readAndExecute(int _try_reconnect)
+CommandInterpreter::execute(const char *_line, int _try_reconnect,
+ int *error)
{
if (_try_reconnect >= 0)
try_reconnect=_try_reconnect;
+ int result= execute_impl(_line);
+ if (error)
+ *error= m_error;
+ return result;
+}
+
+int
+CommandInterpreter::execute_impl(const char *_line)
+{
+ DBUG_ENTER("CommandInterpreter::execute_impl");
+ DBUG_PRINT("enter",("line=\"%s\"",_line));
+ m_error= 0;
- char* _line = readline_gets();
char * line;
if(_line == NULL) {
// ndbout << endl;
- return false;
+ DBUG_RETURN(false);
}
-
line = my_strdup(_line,MYF(MY_WME));
My_auto_ptr<char> ptr(line);
if (emptyString(line)) {
- return true;
+ DBUG_RETURN(true);
}
- for (unsigned int i = 0; i < strlen(line); ++i) {
- line[i] = toupper(line[i]);
- }
-
// if there is anything in the line proceed
char* firstToken = strtok(line, " ");
char* allAfterFirstToken = strtok(NULL, "");
- if (strcmp(firstToken, "HELP") == 0 ||
- strcmp(firstToken, "?") == 0) {
+ if (strcasecmp(firstToken, "HELP") == 0 ||
+ strcasecmp(firstToken, "?") == 0) {
executeHelp(allAfterFirstToken);
- return true;
+ DBUG_RETURN(true);
}
- else if (strcmp(firstToken, "SHOW") == 0) {
+ else if (strcasecmp(firstToken, "CONNECT") == 0) {
+ executeConnect(allAfterFirstToken);
+ DBUG_RETURN(true);
+ }
+ else if((strcasecmp(firstToken, "QUIT") == 0 ||
+ strcasecmp(firstToken, "EXIT") == 0 ||
+ strcasecmp(firstToken, "BYE") == 0) &&
+ allAfterFirstToken == NULL){
+ DBUG_RETURN(false);
+ }
+
+ if (!connect())
+ DBUG_RETURN(true);
+
+ if (strcasecmp(firstToken, "SHOW") == 0) {
executeShow(allAfterFirstToken);
- return true;
+ DBUG_RETURN(true);
}
- else if (strcmp(firstToken, "SHUTDOWN") == 0) {
- executeShutdown(allAfterFirstToken);
- return true;
+ else if (strcasecmp(firstToken, "SHUTDOWN") == 0) {
+ m_error= executeShutdown(allAfterFirstToken);
+ DBUG_RETURN(true);
}
- else if (strcmp(firstToken, "CLUSTERLOG") == 0){
+ else if (strcasecmp(firstToken, "CLUSTERLOG") == 0){
executeClusterLog(allAfterFirstToken);
- return true;
+ DBUG_RETURN(true);
}
- else if(strcmp(firstToken, "START") == 0 &&
+ else if(strcasecmp(firstToken, "START") == 0 &&
allAfterFirstToken != NULL &&
- strncmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
- executeStartBackup(allAfterFirstToken);
- return true;
+ strncasecmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
+ m_error= executeStartBackup(allAfterFirstToken);
+ DBUG_RETURN(true);
}
- else if(strcmp(firstToken, "ABORT") == 0 &&
+ else if(strcasecmp(firstToken, "ABORT") == 0 &&
allAfterFirstToken != NULL &&
- strncmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
+ strncasecmp(allAfterFirstToken, "BACKUP", sizeof("BACKUP") - 1) == 0){
executeAbortBackup(allAfterFirstToken);
- return true;
+ DBUG_RETURN(true);
}
+ else if (strcasecmp(firstToken, "PURGE") == 0) {
+ executePurge(allAfterFirstToken);
+ DBUG_RETURN(true);
+ }
#ifdef HAVE_GLOBAL_REPLICATION
- else if(strcmp(firstToken, "REPLICATION") == 0 ||
- strcmp(firstToken, "REP") == 0) {
+ else if(strcasecmp(firstToken, "REPLICATION") == 0 ||
+ strcasecmp(firstToken, "REP") == 0) {
executeRep(allAfterFirstToken);
- return true;
+ DBUG_RETURN(true);
}
#endif // HAVE_GLOBAL_REPLICATION
- else if(strcmp(firstToken, "ENTER") == 0 &&
+ else if(strcasecmp(firstToken, "ENTER") == 0 &&
allAfterFirstToken != NULL &&
- strncmp(allAfterFirstToken, "SINGLE USER MODE ",
+ strncasecmp(allAfterFirstToken, "SINGLE USER MODE ",
sizeof("SINGLE USER MODE") - 1) == 0){
executeEnterSingleUser(allAfterFirstToken);
- return true;
+ DBUG_RETURN(true);
}
- else if(strcmp(firstToken, "EXIT") == 0 &&
+ else if(strcasecmp(firstToken, "EXIT") == 0 &&
allAfterFirstToken != NULL &&
- strncmp(allAfterFirstToken, "SINGLE USER MODE ",
+ strncasecmp(allAfterFirstToken, "SINGLE USER MODE ",
sizeof("SINGLE USER MODE") - 1) == 0){
executeExitSingleUser(allAfterFirstToken);
- return true;
+ DBUG_RETURN(true);
}
- else if (strcmp(firstToken, "ALL") == 0) {
+ else if (strcasecmp(firstToken, "ALL") == 0) {
analyseAfterFirstToken(-1, allAfterFirstToken);
- }
- else if((strcmp(firstToken, "QUIT") == 0 ||
- strcmp(firstToken, "EXIT") == 0 ||
- strcmp(firstToken, "BYE") == 0) &&
- allAfterFirstToken == NULL){
- return false;
-#if 0
- } else if(strcmp(firstToken, "CPC") == 0) {
- executeCpc(allAfterFirstToken);
-#endif
} else {
/**
* First token should be a digit, node ID
@@ -360,20 +584,20 @@ CommandInterpreter::readAndExecute(int _try_reconnect)
int nodeId;
if (! convert(firstToken, nodeId)) {
- ndbout << "Invalid command: " << line << endl;
+ ndbout << "Invalid command: " << _line << endl;
ndbout << "Type HELP for help." << endl << endl;
- return true;
+ DBUG_RETURN(true);
}
- if (nodeId < 0) {
+ if (nodeId <= 0) {
ndbout << "Invalid node ID: " << firstToken << "." << endl;
- return true;
+ DBUG_RETURN(true);
}
analyseAfterFirstToken(nodeId, allAfterFirstToken);
}
- return true;
+ DBUG_RETURN(true);
}
@@ -426,7 +650,7 @@ CommandInterpreter::analyseAfterFirstToken(int processId,
ExecuteFunction fun = 0;
const char * command = 0;
for(int i = 0; i<tmpSize; i++){
- if(strcmp(secondToken, commands[i].command) == 0){
+ if(strcasecmp(secondToken, commands[i].command) == 0){
fun = commands[i].executeFunction;
command = commands[i].command;
break;
@@ -442,7 +666,7 @@ CommandInterpreter::analyseAfterFirstToken(int processId,
if(processId == -1){
executeForAll(command, fun, allAfterSecondToken);
} else {
- if(strcmp(command, "STATUS") != 0)
+ if(strcasecmp(command, "STATUS") != 0)
ndbout_c("Executing %s on node %d.", command, processId);
(this->*fun)(processId, allAfterSecondToken, false);
ndbout << endl;
@@ -492,17 +716,16 @@ CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun,
const char * allAfterSecondToken)
{
int nodeId = 0;
- if(strcmp(cmd, "STOP") == 0) {
+ if(strcasecmp(cmd, "STOP") == 0) {
ndbout_c("Executing STOP on all nodes.");
(this->*fun)(nodeId, allAfterSecondToken, true);
- } else if(strcmp(cmd, "RESTART") == 0) {
+ } else if(strcasecmp(cmd, "RESTART") == 0) {
ndbout_c("Executing RESTART on all nodes.");
ndbout_c("Starting shutdown. This may take a while. Please wait...");
(this->*fun)(nodeId, allAfterSecondToken, true);
ndbout_c("Trying to start all nodes of system.");
ndbout_c("Use ALL STATUS to see the system start-up phases.");
} else {
- connect();
struct ndb_mgm_cluster_state *cl= ndb_mgm_get_status(m_mgmsrv);
if(cl == 0){
ndbout_c("Unable get status from management server");
@@ -511,7 +734,7 @@ CommandInterpreter::executeForAll(const char * cmd, ExecuteFunction fun,
}
NdbAutoPtr<char> ap1((char*)cl);
while(get_next_nodeid(cl, &nodeId, NDB_MGM_NODE_TYPE_NDB)) {
- if(strcmp(cmd, "STATUS") != 0)
+ if(strcasecmp(cmd, "STATUS") != 0)
ndbout_c("Executing %s on node %d.", cmd, nodeId);
(this->*fun)(nodeId, allAfterSecondToken, true);
ndbout << endl;
@@ -539,7 +762,7 @@ CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
firstTokenAfterLog[i] = toupper(firstTokenAfterLog[i]);
}
- if (strcmp(firstTokenAfterLog, "BLOCK") != 0) {
+ if (strcasecmp(firstTokenAfterLog, "BLOCK") != 0) {
ndbout << "Unexpected value: " << firstTokenAfterLog
<< ". Expected BLOCK." << endl;
return false;
@@ -552,7 +775,7 @@ CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
}
char* secondTokenAfterLog = strtok(allAfterFirstToken, " ");
- if (strcmp(secondTokenAfterLog, "=") != 0) {
+ if (strcasecmp(secondTokenAfterLog, "=") != 0) {
ndbout << "Unexpected value: " << secondTokenAfterLog
<< ". Expected =." << endl;
return false;
@@ -560,7 +783,7 @@ CommandInterpreter::parseBlockSpecification(const char* allAfterLog,
char* blockName = strtok(NULL, " ");
bool all = false;
- if (blockName != NULL && (strcmp(blockName, "ALL") == 0)) {
+ if (blockName != NULL && (strcasecmp(blockName, "ALL") == 0)) {
all = true;
}
while (blockName != NULL) {
@@ -611,15 +834,15 @@ CommandInterpreter::executeHelp(char* parameters)
ndbout << "<level> = " << "0 - 15" << endl;
ndbout << "<id> = " << "ALL | Any database node id" << endl;
ndbout << endl;
- } else if (strcmp(parameters, "SHOW") == 0) {
+ } else if (strcasecmp(parameters, "SHOW") == 0) {
ndbout << helpTextShow;
#ifdef HAVE_GLOBAL_REPLICATION
- } else if (strcmp(parameters, "REPLICATION") == 0 ||
- strcmp(parameters, "REP") == 0) {
+ } else if (strcasecmp(parameters, "REPLICATION") == 0 ||
+ strcasecmp(parameters, "REP") == 0) {
ndbout << helpTextRep;
#endif // HAVE_GLOBAL_REPLICATION
#ifdef VM_TRACE // DEBUG ONLY
- } else if (strcmp(parameters, "DEBUG") == 0) {
+ } else if (strcasecmp(parameters, "DEBUG") == 0) {
ndbout << helpTextDebug;
#endif
} else {
@@ -633,25 +856,23 @@ CommandInterpreter::executeHelp(char* parameters)
* SHUTDOWN
*****************************************************************************/
-void
+int
CommandInterpreter::executeShutdown(char* parameters)
{
- connect();
-
ndb_mgm_cluster_state *state = ndb_mgm_get_status(m_mgmsrv);
if(state == NULL) {
ndbout_c("Could not get status");
printError();
- return;
+ return 1;
}
NdbAutoPtr<char> ap1((char*)state);
int result = 0;
result = ndb_mgm_stop(m_mgmsrv, 0, 0);
if (result < 0) {
- ndbout << "Shutdown failed." << endl;
+ ndbout << "Shutdown off NDB Cluster storage node(s) failed." << endl;
printError();
- return;
+ return result;
}
ndbout << result << " NDB Cluster storage node(s) have shutdown." << endl;
@@ -666,21 +887,23 @@ CommandInterpreter::executeShutdown(char* parameters)
ndbout << "Unable to locate management server, "
<< "shutdown manually with <id> STOP"
<< endl;
- return;
+ return 1;
}
}
}
- result = 0;
result = ndb_mgm_stop(m_mgmsrv, 1, &mgm_id);
if (result <= 0) {
- ndbout << "Shutdown failed." << endl;
+ ndbout << "Shutdown of NDB Cluster management server failed." << endl;
printError();
- return;
+ if (result == 0)
+ return 1;
+ return result;
}
+ connected = false;
ndbout << "NDB Cluster management server shutdown." << endl;
- exit(0);
+ return 0;
}
/*****************************************************************************
@@ -729,7 +952,7 @@ print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it,
const char *hostname= node_state->connect_address;
if (hostname == 0
|| strlen(hostname) == 0
- || strcmp(hostname,"0.0.0.0") == 0)
+ || strcasecmp(hostname,"0.0.0.0") == 0)
ndbout << " ";
else
ndbout << "\t@" << hostname;
@@ -766,14 +989,49 @@ print_nodes(ndb_mgm_cluster_state *state, ndb_mgm_configuration_iterator *it,
}
void
+CommandInterpreter::executePurge(char* parameters)
+{
+ int command_ok= 0;
+ do {
+ if (emptyString(parameters))
+ break;
+ char* firstToken = strtok(parameters, " ");
+ char* nextToken = strtok(NULL, " \0");
+ if (strcasecmp(firstToken,"STALE") == 0 &&
+ nextToken &&
+ strcasecmp(nextToken, "SESSIONS") == 0) {
+ command_ok= 1;
+ break;
+ }
+ } while(0);
+
+ if (!command_ok) {
+ ndbout_c("Unexpected command, expected: PURGE STALE SESSIONS");
+ return;
+ }
+
+ int i;
+ char *str;
+
+ if (ndb_mgm_purge_stale_sessions(m_mgmsrv, &str)) {
+ ndbout_c("Command failed");
+ return;
+ }
+ if (str) {
+ ndbout_c("Purged sessions with node id's: %s", str);
+ free(str);
+ }
+ else
+ {
+ ndbout_c("No sessions purged");
+ }
+}
+
+void
CommandInterpreter::executeShow(char* parameters)
{
int i;
- connect();
if (emptyString(parameters)) {
- ndbout << "Cluster Configuration" << endl
- << "---------------------" << endl;
-
ndb_mgm_cluster_state *state = ndb_mgm_get_status(m_mgmsrv);
if(state == NULL) {
ndbout_c("Could not get status");
@@ -833,22 +1091,24 @@ CommandInterpreter::executeShow(char* parameters)
}
}
+ ndbout << "Cluster Configuration" << endl
+ << "---------------------" << endl;
print_nodes(state, it, "ndbd", ndb_nodes, NDB_MGM_NODE_TYPE_NDB, master_id);
print_nodes(state, it, "ndb_mgmd", mgm_nodes, NDB_MGM_NODE_TYPE_MGM, 0);
print_nodes(state, it, "mysqld", api_nodes, NDB_MGM_NODE_TYPE_API, 0);
// ndbout << helpTextShow;
return;
- } else if (strcmp(parameters, "PROPERTIES") == 0 ||
- strcmp(parameters, "PROP") == 0) {
+ } else if (strcasecmp(parameters, "PROPERTIES") == 0 ||
+ strcasecmp(parameters, "PROP") == 0) {
ndbout << "SHOW PROPERTIES is not yet implemented." << endl;
// ndbout << "_mgmtSrvr.getConfig()->print();" << endl; /* XXX */
- } else if (strcmp(parameters, "CONFIGURATION") == 0 ||
- strcmp(parameters, "CONFIG") == 0){
+ } else if (strcasecmp(parameters, "CONFIGURATION") == 0 ||
+ strcasecmp(parameters, "CONFIG") == 0){
ndbout << "SHOW CONFIGURATION is not yet implemented." << endl;
//nbout << "_mgmtSrvr.getConfig()->printConfigFile();" << endl; /* XXX */
- } else if (strcmp(parameters, "PARAMETERS") == 0 ||
- strcmp(parameters, "PARAMS") == 0 ||
- strcmp(parameters, "PARAM") == 0) {
+ } else if (strcasecmp(parameters, "PARAMETERS") == 0 ||
+ strcasecmp(parameters, "PARAMS") == 0 ||
+ strcasecmp(parameters, "PARAM") == 0) {
ndbout << "SHOW PARAMETERS is not yet implemented." << endl;
// ndbout << "_mgmtSrvr.getConfig()->getConfigInfo()->print();"
// << endl; /* XXX */
@@ -857,6 +1117,20 @@ CommandInterpreter::executeShow(char* parameters)
}
}
+void
+CommandInterpreter::executeConnect(char* parameters)
+{
+ disconnect();
+ if (!emptyString(parameters)) {
+ if (ndb_mgm_set_connectstring(m_mgmsrv,
+ BaseString(parameters).trim().c_str()))
+ {
+ printError();
+ return;
+ }
+ }
+ connect();
+}
//*****************************************************************************
//*****************************************************************************
@@ -864,7 +1138,6 @@ void
CommandInterpreter::executeClusterLog(char* parameters)
{
int i;
- connect();
if (parameters != 0 && strlen(parameters) != 0) {
enum ndb_mgm_clusterlog_level severity = NDB_MGM_CLUSTERLOG_ALL;
int isOk = true;
@@ -879,7 +1152,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
/********************
* CLUSTERLOG FILTER
********************/
- if (strcmp(item, "FILTER") == 0) {
+ if (strcasecmp(item, "FILTER") == 0) {
item = strtok_r(NULL, " ", &tmpPtr);
if (item == NULL) {
@@ -888,21 +1161,21 @@ CommandInterpreter::executeClusterLog(char* parameters)
while (item != NULL) {
snprintf(name, sizeof(name), item);
- if (strcmp(item, "ALL") == 0) {
+ if (strcasecmp(item, "ALL") == 0) {
severity = NDB_MGM_CLUSTERLOG_ALL;
- } else if (strcmp(item, "ALERT") == 0) {
+ } else if (strcasecmp(item, "ALERT") == 0) {
severity = NDB_MGM_CLUSTERLOG_ALERT;
- } else if (strcmp(item, "CRITICAL") == 0) {
+ } else if (strcasecmp(item, "CRITICAL") == 0) {
severity = NDB_MGM_CLUSTERLOG_CRITICAL;
- } else if (strcmp(item, "ERROR") == 0) {
+ } else if (strcasecmp(item, "ERROR") == 0) {
severity = NDB_MGM_CLUSTERLOG_ERROR;
- } else if (strcmp(item, "WARNING") == 0) {
+ } else if (strcasecmp(item, "WARNING") == 0) {
severity = NDB_MGM_CLUSTERLOG_WARNING;
- } else if (strcmp(item, "INFO") == 0) {
+ } else if (strcasecmp(item, "INFO") == 0) {
severity = NDB_MGM_CLUSTERLOG_INFO;
- } else if (strcmp(item, "DEBUG") == 0) {
+ } else if (strcasecmp(item, "DEBUG") == 0) {
severity = NDB_MGM_CLUSTERLOG_DEBUG;
- } else if (strcmp(item, "OFF") == 0) {
+ } else if (strcasecmp(item, "OFF") == 0) {
severity = NDB_MGM_CLUSTERLOG_OFF;
} else {
isOk = false;
@@ -915,17 +1188,17 @@ CommandInterpreter::executeClusterLog(char* parameters)
ndbout << "Missing argument(s)." << endl;
} else if (isOk) {
if(ndb_mgm_filter_clusterlog(m_mgmsrv, severity, NULL)) {
- if(strcmp(name, "ALL") == 0 || strcmp(name, "all") == 0) {
+ if(strcasecmp(name, "ALL") == 0) {
ndbout << "All severities levels enabled." << endl;
- } else if(strcmp(name, "OFF") == 0 || strcmp(name, "off") == 0) {
+ } else if(strcasecmp(name, "OFF") == 0) {
ndbout << "Cluster logging enabled." << endl;
} else {
ndbout << name << " events disabled." << endl;
}
} else {
- if(strcmp(name, "ALL") == 0) {
+ if(strcasecmp(name, "ALL") == 0) {
ndbout << "All severities levels disabled." << endl;
- } else if(strcmp(name, "OFF") == 0) {
+ } else if(strcasecmp(name, "OFF") == 0) {
ndbout << "Cluster logging disabled." << endl;
} else {
ndbout << name << " events enabled." << endl;
@@ -938,7 +1211,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
/********************
* CLUSTERLOG INFO
********************/
- } else if (strcmp(item, "INFO") == 0) {
+ } else if (strcasecmp(item, "INFO") == 0) {
Uint32 *enabled = ndb_mgm_get_logfilter(m_mgmsrv);
if(enabled == NULL) {
ndbout << "Couldn't get status" << endl;
@@ -963,7 +1236,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
/********************
* CLUSTERLOG OFF
********************/
- } else if (strcmp(item, "OFF") == 0) {
+ } else if (strcasecmp(item, "OFF") == 0) {
Uint32 *enabled = ndb_mgm_get_logfilter(m_mgmsrv);
if(enabled == NULL) {
ndbout << "Couldn't get status" << endl;
@@ -981,7 +1254,7 @@ CommandInterpreter::executeClusterLog(char* parameters)
/********************
* CLUSTERLOG ON
********************/
- } else if (strcmp(item, "ON") == 0) {
+ } else if (strcasecmp(item, "ON") == 0) {
Uint32 *enabled = ndb_mgm_get_logfilter(m_mgmsrv);
if(enabled == NULL) {
ndbout << "Could not get status" << endl;
@@ -1010,7 +1283,6 @@ CommandInterpreter::executeClusterLog(char* parameters)
void
CommandInterpreter::executeStop(int processId, const char *, bool all)
{
- connect();
int result = 0;
if(all) {
result = ndb_mgm_stop(m_mgmsrv, 0, 0);
@@ -1032,7 +1304,6 @@ CommandInterpreter::executeStop(int processId, const char *, bool all)
void
CommandInterpreter::executeEnterSingleUser(char* parameters)
{
- connect();
strtok(parameters, " ");
struct ndb_mgm_reply reply;
char* id = strtok(NULL, " ");
@@ -1059,7 +1330,6 @@ CommandInterpreter::executeEnterSingleUser(char* parameters)
void
CommandInterpreter::executeExitSingleUser(char* parameters)
{
- connect();
int result = ndb_mgm_exit_single_user(m_mgmsrv, 0);
if (result != 0) {
ndbout_c("Exiting single user mode failed.");
@@ -1074,7 +1344,6 @@ void
CommandInterpreter::executeStart(int processId, const char* parameters,
bool all)
{
- connect();
int result;
if(all) {
result = ndb_mgm_start(m_mgmsrv, 0, 0);
@@ -1098,7 +1367,6 @@ void
CommandInterpreter::executeRestart(int processId, const char* parameters,
bool all)
{
- connect();
int result;
int nostart = 0;
int initialstart = 0;
@@ -1110,11 +1378,11 @@ CommandInterpreter::executeRestart(int processId, const char* parameters,
char * tmpPtr = 0;
char * item = strtok_r(tmpString, " ", &tmpPtr);
while(item != NULL){
- if(strcmp(item, "-N") == 0)
+ if(strcasecmp(item, "-N") == 0)
nostart = 1;
- if(strcmp(item, "-I") == 0)
+ if(strcasecmp(item, "-I") == 0)
initialstart = 1;
- if(strcmp(item, "-A") == 0)
+ if(strcasecmp(item, "-A") == 0)
abort = 1;
item = strtok_r(NULL, " ", &tmpPtr);
}
@@ -1144,11 +1412,10 @@ void
CommandInterpreter::executeDumpState(int processId, const char* parameters,
bool all)
{
- if(parameters == 0 || strlen(parameters) == 0){
+ if(emptyString(parameters)){
ndbout << "Expected argument" << endl;
return;
}
- connect();
Uint32 no = 0;
int pars[25];
@@ -1188,7 +1455,6 @@ CommandInterpreter::executeStatus(int processId,
return;
}
- connect();
ndb_mgm_node_status status;
Uint32 startPhase, version;
bool system;
@@ -1239,7 +1505,6 @@ void
CommandInterpreter::executeLogLevel(int processId, const char* parameters,
bool all)
{
- connect();
(void) all;
BaseString tmp(parameters);
@@ -1295,7 +1560,6 @@ void CommandInterpreter::executeError(int processId,
return;
}
- connect();
// Copy parameters since strtok will modify it
char* newpar = my_strdup(parameters,MYF(MY_WME));
My_auto_ptr<char> ap1(newpar);
@@ -1347,7 +1611,7 @@ CommandInterpreter::executeTrace(int /*processId*/,
int result = _mgmtSrvr.setTraceNo(processId, traceNo);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
#endif
}
@@ -1359,7 +1623,6 @@ void
CommandInterpreter::executeLog(int processId,
const char* parameters, bool all)
{
- connect();
struct ndb_mgm_reply reply;
Vector<const char *> blocks;
if (! parseBlockSpecification(parameters, blocks)) {
@@ -1427,7 +1690,6 @@ CommandInterpreter::executeTestOn(int processId,
ndbout << "No parameters expected to this command." << endl;
return;
}
- connect();
struct ndb_mgm_reply reply;
int result = ndb_mgm_start_signallog(m_mgmsrv, processId, &reply);
if (result != 0) {
@@ -1446,7 +1708,6 @@ CommandInterpreter::executeTestOff(int processId,
ndbout << "No parameters expected to this command." << endl;
return;
}
- connect();
struct ndb_mgm_reply reply;
int result = ndb_mgm_stop_signallog(m_mgmsrv, processId, &reply);
if (result != 0) {
@@ -1510,7 +1771,7 @@ CommandInterpreter::executeSet(int /*processId*/,
}
}
else {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
if (configBackupFileUpdated && configPrimaryFileUpdated) {
ndbout << "The configuration files are however updated and "
<< "the value will be used next time the process is restarted."
@@ -1545,7 +1806,7 @@ void CommandInterpreter::executeGetStat(int /*processId*/,
MgmtSrvr::Statistics statistics;
int result = _mgmtSrvr.getStatistics(processId, statistics);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
return;
}
#endif
@@ -1564,8 +1825,10 @@ CommandInterpreter::executeEventReporting(int processId,
const char* parameters,
bool all)
{
- connect();
-
+ if (emptyString(parameters)) {
+ ndbout << "Expected argument" << endl;
+ return;
+ }
BaseString tmp(parameters);
Vector<BaseString> spec;
tmp.split(spec, "=");
@@ -1613,10 +1876,9 @@ CommandInterpreter::executeEventReporting(int processId,
/*****************************************************************************
* Backup
*****************************************************************************/
-void
+int
CommandInterpreter::executeStartBackup(char* /*parameters*/)
{
- connect();
struct ndb_mgm_reply reply;
unsigned int backupId;
@@ -1627,7 +1889,7 @@ CommandInterpreter::executeStartBackup(char* /*parameters*/)
ndbout << "Start of backup failed" << endl;
printError();
close(fd);
- return;
+ return result;
}
char *tmp;
@@ -1658,12 +1920,12 @@ CommandInterpreter::executeStartBackup(char* /*parameters*/)
} while(tmp && tmp[0] != 0);
close(fd);
+ return 0;
}
void
CommandInterpreter::executeAbortBackup(char* parameters)
{
- connect();
strtok(parameters, " ");
struct ndb_mgm_reply reply;
char* id = strtok(NULL, "\0");
@@ -1717,7 +1979,6 @@ CommandInterpreter::executeRep(char* parameters)
return;
}
- connect();
char * line = my_strdup(parameters,MYF(MY_WME));
My_auto_ptr<char> ap1((char*)line);
char * firstToken = strtok(line, " ");
@@ -1726,7 +1987,7 @@ CommandInterpreter::executeRep(char* parameters)
unsigned int repId;
- if (!strcmp(firstToken, "CONNECT")) {
+ if (!strcasecmp(firstToken, "CONNECT")) {
char * host = strtok(NULL, "\0");
for (unsigned int i = 0; i < strlen(host); ++i) {
host[i] = tolower(host[i]);
@@ -1761,30 +2022,30 @@ CommandInterpreter::executeRep(char* parameters)
/********
* START
********/
- if (!strcmp(firstToken, "START")) {
+ if (!strcasecmp(firstToken, "START")) {
unsigned int req;
char *startType = strtok(NULL, "\0");
if (startType == NULL) {
req = GrepReq::START;
- } else if (!strcmp(startType, "SUBSCRIPTION")) {
+ } else if (!strcasecmp(startType, "SUBSCRIPTION")) {
req = GrepReq::START_SUBSCR;
- } else if (!strcmp(startType, "METALOG")) {
+ } else if (!strcasecmp(startType, "METALOG")) {
req = GrepReq::START_METALOG;
- } else if (!strcmp(startType, "METASCAN")) {
+ } else if (!strcasecmp(startType, "METASCAN")) {
req = GrepReq::START_METASCAN;
- } else if (!strcmp(startType, "DATALOG")) {
+ } else if (!strcasecmp(startType, "DATALOG")) {
req = GrepReq::START_DATALOG;
- } else if (!strcmp(startType, "DATASCAN")) {
+ } else if (!strcasecmp(startType, "DATASCAN")) {
req = GrepReq::START_DATASCAN;
- } else if (!strcmp(startType, "REQUESTOR")) {
+ } else if (!strcasecmp(startType, "REQUESTOR")) {
req = GrepReq::START_REQUESTOR;
- } else if (!strcmp(startType, "TRANSFER")) {
+ } else if (!strcasecmp(startType, "TRANSFER")) {
req = GrepReq::START_TRANSFER;
- } else if (!strcmp(startType, "APPLY")) {
+ } else if (!strcasecmp(startType, "APPLY")) {
req = GrepReq::START_APPLY;
- } else if (!strcmp(startType, "DELETE")) {
+ } else if (!strcasecmp(startType, "DELETE")) {
req = GrepReq::START_DELETE;
} else {
ndbout_c("Illegal argument to command 'REPLICATION START'");
@@ -1804,7 +2065,7 @@ CommandInterpreter::executeRep(char* parameters)
/********
* STOP
********/
- if (!strcmp(firstToken, "STOP")) {
+ if (!strcasecmp(firstToken, "STOP")) {
unsigned int req;
char *startType = strtok(NULL, " ");
unsigned int epoch = 0;
@@ -1814,7 +2075,7 @@ CommandInterpreter::executeRep(char* parameters)
* Stop immediately
*/
req = GrepReq::STOP;
- } else if (!strcmp(startType, "EPOCH")) {
+ } else if (!strcasecmp(startType, "EPOCH")) {
char *strEpoch = strtok(NULL, "\0");
if(strEpoch == NULL) {
ndbout_c("Epoch expected!");
@@ -1822,23 +2083,23 @@ CommandInterpreter::executeRep(char* parameters)
}
req = GrepReq::STOP;
epoch=atoi(strEpoch);
- } else if (!strcmp(startType, "SUBSCRIPTION")) {
+ } else if (!strcasecmp(startType, "SUBSCRIPTION")) {
req = GrepReq::STOP_SUBSCR;
- } else if (!strcmp(startType, "METALOG")) {
+ } else if (!strcasecmp(startType, "METALOG")) {
req = GrepReq::STOP_METALOG;
- } else if (!strcmp(startType, "METASCAN")) {
+ } else if (!strcasecmp(startType, "METASCAN")) {
req = GrepReq::STOP_METASCAN;
- } else if (!strcmp(startType, "DATALOG")) {
+ } else if (!strcasecmp(startType, "DATALOG")) {
req = GrepReq::STOP_DATALOG;
- } else if (!strcmp(startType, "DATASCAN")) {
+ } else if (!strcasecmp(startType, "DATASCAN")) {
req = GrepReq::STOP_DATASCAN;
- } else if (!strcmp(startType, "REQUESTOR")) {
+ } else if (!strcasecmp(startType, "REQUESTOR")) {
req = GrepReq::STOP_REQUESTOR;
- } else if (!strcmp(startType, "TRANSFER")) {
+ } else if (!strcasecmp(startType, "TRANSFER")) {
req = GrepReq::STOP_TRANSFER;
- } else if (!strcmp(startType, "APPLY")) {
+ } else if (!strcasecmp(startType, "APPLY")) {
req = GrepReq::STOP_APPLY;
- } else if (!strcmp(startType, "DELETE")) {
+ } else if (!strcasecmp(startType, "DELETE")) {
req = GrepReq::STOP_DELETE;
} else {
ndbout_c("Illegal argument to command 'REPLICATION STOP'");
@@ -1857,7 +2118,7 @@ CommandInterpreter::executeRep(char* parameters)
/*********
* STATUS
*********/
- if (!strcmp(firstToken, "STATUS")) {
+ if (!strcasecmp(firstToken, "STATUS")) {
struct rep_state repstate;
int result =
ndb_rep_get_status(m_repserver, &repId, &reply, &repstate);
@@ -1877,7 +2138,7 @@ CommandInterpreter::executeRep(char* parameters)
/*********
* QUERY (see repapi.h for querable counters)
*********/
- if (!strcmp(firstToken, "QUERY")) {
+ if (!strcasecmp(firstToken, "QUERY")) {
char *query = strtok(NULL, "\0");
int queryCounter=-1;
if(query != NULL) {
@@ -1903,169 +2164,4 @@ CommandInterpreter::executeRep(char* parameters)
}
#endif // HAVE_GLOBAL_REPLICATION
-
-/*****************************************************************************
- * CPC
- *****************************************************************************/
-
-#if 0
-
-#if 0
-//#ifdef NDB_SOLARIS // XXX fix me
-static char* strsep(char** x, const char* y) { return 0; }
-#endif
-
-// Note this code has not been verified
-#if 0
-static char * my_strsep(char **stringp, const char *delim)
-{
- char *tmp= *stringp;
- if (tmp == 0)
- return 0;
- *stringp = strtok(tmp, delim);
- return tmp;
-}
-#endif
-
-void
-CommandInterpreter::executeCpc(char *parameters)
-{
- char *host_str = NULL, *port_str = NULL, *end;
- long port = 1234; /* XXX */
-
- while((host_str = my_strsep(&parameters, " \t:")) != NULL &&
- host_str[0] == '\0');
-
- if(parameters && parameters[0] != '\0') {
- while((port_str = my_strsep(&parameters, " \t:")) != NULL &&
- port_str[0] == '\0');
-
- errno = 0;
- port = strtol(port_str, &end, 0);
- if(end[0] != '\0')
- goto error;
- if((port == LONG_MAX || port == LONG_MIN) &&
- errno == ERANGE)
- goto error;
- }
-
- {
- SimpleCpcClient cpc(host_str, port);
- bool done = false;
-
- if(cpc.connect() < 0) {
- ndbout_c("Cannot connect to %s:%d.", cpc.getHost(), cpc.getPort());
- switch(errno) {
- case ENOENT:
- ndbout << ": " << "No such host" << endl;
- break;
- default:
- ndbout << ": " << strerror(errno) << endl;
- break;
- }
- return;
- }
-
- while(!done) {
- char *line = readline("CPC> ");
- if(line != NULL) {
- add_history(line);
-
- char *cmd = strtok(line, " ");
- char *arg = strtok(NULL, "");
-
- if(arg != NULL) {
- while(arg[0] == ' ')
- arg++;
- if(strlen(arg) == 0)
- arg = NULL;
- }
-
- if(cmd != NULL) {
- if(strcmp(cmd, "exit") == 0)
- done = true;
- else if(strcmp(cmd, "list") == 0)
- cpc.cmd_list(arg);
- else if(strcmp(cmd, "start") == 0)
- cpc.cmd_start(arg);
- else if(strcmp(cmd, "stop") == 0)
- cpc.cmd_stop(arg);
- else if(strcmp(cmd, "help") == 0)
- cpc.cmd_help(arg);
- }
- } else {
- done = true;
- ndbout << endl;
- }
- }
- }
- return;
-
- error:
- ndbout << "Error: expected a tcp port number, got '" << port_str << "'."
- << endl;
- return;
-}
-#endif
-
-#if 0
-static
-void
-CmdBackupCallback(const MgmtSrvr::BackupEvent & event){
- char str[255];
-
- ndbout << endl;
-
- bool ok = false;
- switch(event.Event){
- case MgmtSrvr::BackupEvent::BackupStarted:
- ok = true;
- BaseString::snprintf(str, sizeof(str),
- "Backup %d started", event.Started.BackupId);
- break;
- case MgmtSrvr::BackupEvent::BackupFailedToStart:
- ok = true;
- BaseString::snprintf(str, sizeof(str),
- "Backup failed to start (Error %d)",
- event.FailedToStart.ErrorCode);
- break;
- case MgmtSrvr::BackupEvent::BackupCompleted:
- ok = true;
- BaseString::snprintf(str, sizeof(str),
- "Backup %d completed",
- event.Completed.BackupId);
- ndbout << str << endl;
-
- BaseString::snprintf(str, sizeof(str),
- " StartGCP: %d StopGCP: %d",
- event.Completed.startGCP, event.Completed.stopGCP);
- ndbout << str << endl;
-
- BaseString::snprintf(str, sizeof(str),
- " #Records: %d #LogRecords: %d",
- event.Completed.NoOfRecords, event.Completed.NoOfLogRecords);
- ndbout << str << endl;
-
- BaseString::snprintf(str, sizeof(str),
- " Data: %d bytes Log: %d bytes",
- event.Completed.NoOfBytes, event.Completed.NoOfLogBytes);
- break;
- case MgmtSrvr::BackupEvent::BackupAborted:
- ok = true;
- BaseString::snprintf(str, sizeof(str),
- "Backup %d has been aborted reason %d",
- event.Aborted.BackupId,
- event.Aborted.Reason);
- break;
- }
- if(!ok){
- BaseString::snprintf(str, sizeof(str),
- "Unknown backup event: %d",
- event.Event);
-
- }
- ndbout << str << endl;
-}
-#endif
-
template class Vector<char const*>;
diff --git a/ndb/src/mgmclient/CommandInterpreter.hpp b/ndb/src/mgmclient/CommandInterpreter.hpp
deleted file mode 100644
index eecc48a739e..00000000000
--- a/ndb/src/mgmclient/CommandInterpreter.hpp
+++ /dev/null
@@ -1,197 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-#ifndef CommandInterpreter_H
-#define CommandInterpreter_H
-
-//#define HAVE_GLOBAL_REPLICATION
-//*****************************************************************************
-// Author: Peter Lind
-//*****************************************************************************
-
-#include <ndb_global.h>
-#include <Vector.hpp>
-#include <editline/editline.h>
-
-#ifdef HAVE_GLOBAL_REPLICATION
-#include "../rep/repapi/repapi.h"
-#endif
-
-#include <mgmapi.h>
-
-class MgmtSrvr;
-
-/**
- * @class CommandInterpreter
- * @brief Reads command line in management client
- *
- * This class has one public method which reads a command line
- * from a stream. It then interpret that commmand line and calls a suitable
- * method in the MgmtSrvr class which executes the command.
- *
- * For command syntax, see the HELP command.
- */
-class CommandInterpreter {
-public:
- /**
- * Constructor
- * @param mgmtSrvr: Management server to use when executing commands
- */
- CommandInterpreter(const char *);
- ~CommandInterpreter();
-
- /**
- * Reads one line from the stream, parse the line to find
- * a command and then calls a suitable method which executes
- * the command.
- *
- * @return true until quit/bye/exit has been typed
- */
- int readAndExecute(int _try_reconnect=-1);
-
-private:
- /**
- * Read a string, and return a pointer to it.
- *
- * @return NULL on EOF.
- */
- char *readline_gets ()
- {
- static char *line_read = (char *)NULL;
-
- /* If the buffer has already been allocated, return the memory
- to the free pool. */
- if (line_read)
- {
- free (line_read);
- line_read = (char *)NULL;
- }
-
- /* Get a line from the user. */
- line_read = readline ("NDB> ");
-
- /* If the line has any text in it, save it on the history. */
- if (line_read && *line_read)
- add_history (line_read);
-
- return (line_read);
- }
-
- void printError();
-
- /**
- * Analyse the command line, after the first token.
- *
- * @param processId: DB process id to send command to or -1 if
- * command will be sent to all DB processes.
- * @param allAfterFirstToken: What the client gave after the
- * first token on the command line
- */
- void analyseAfterFirstToken(int processId, char* allAfterFirstTokenCstr);
-
- /**
- * Parse the block specification part of the LOG* commands,
- * things after LOG*: [BLOCK = {ALL|<blockName>+}]
- *
- * @param allAfterLog: What the client gave after the second token
- * (LOG*) on the command line
- * @param blocks, OUT: ALL or name of all the blocks
- * @return: true if correct syntax, otherwise false
- */
- bool parseBlockSpecification(const char* allAfterLog,
- Vector<const char*>& blocks);
-
- /**
- * A bunch of execute functions: Executes one of the commands
- *
- * @param processId: DB process id to send command to
- * @param parameters: What the client gave after the command name
- * on the command line.
- * For example if complete input from user is: "1 LOGLEVEL 22" then the
- * parameters argument is the string with everything after LOGLEVEL, in
- * this case "22". Each function is responsible to check the parameters
- * argument.
- */
- void executeHelp(char* parameters);
- void executeShow(char* parameters);
- void executeShutdown(char* parameters);
- void executeRun(char* parameters);
- void executeInfo(char* parameters);
- void executeClusterLog(char* parameters);
-
-public:
- void executeStop(int processId, const char* parameters, bool all);
- void executeEnterSingleUser(char* parameters);
- void executeExitSingleUser(char* parameters);
- void executeStart(int processId, const char* parameters, bool all);
- void executeRestart(int processId, const char* parameters, bool all);
- void executeLogLevel(int processId, const char* parameters, bool all);
- void executeError(int processId, const char* parameters, bool all);
- void executeTrace(int processId, const char* parameters, bool all);
- void executeLog(int processId, const char* parameters, bool all);
- void executeLogIn(int processId, const char* parameters, bool all);
- void executeLogOut(int processId, const char* parameters, bool all);
- void executeLogOff(int processId, const char* parameters, bool all);
- void executeTestOn(int processId, const char* parameters, bool all);
- void executeTestOff(int processId, const char* parameters, bool all);
- void executeSet(int processId, const char* parameters, bool all);
- void executeGetStat(int processId, const char* parameters, bool all);
- void executeStatus(int processId, const char* parameters, bool all);
- void executeEventReporting(int processId, const char* parameters, bool all);
- void executeDumpState(int processId, const char* parameters, bool all);
- void executeStartBackup(char * parameters);
- void executeAbortBackup(char * parameters);
-
- void executeRep(char* parameters);
-
- void executeCpc(char * parameters);
-
-public:
- bool connect();
- bool disconnect();
-
- /**
- * A execute function definition
- */
-public:
- typedef void (CommandInterpreter::* ExecuteFunction)(int processId,
- const char * param,
- bool all);
-
- struct CommandFunctionPair {
- const char * command;
- ExecuteFunction executeFunction;
- };
-private:
- /**
- *
- */
- void executeForAll(const char * cmd,
- ExecuteFunction fun,
- const char * param);
-
- NdbMgmHandle m_mgmsrv;
- bool connected;
- const char *host;
- int try_reconnect;
-#ifdef HAVE_GLOBAL_REPLICATION
- NdbRepHandle m_repserver;
- const char *rep_host;
- bool rep_connected;
-#endif
-};
-
-#endif // CommandInterpreter_H
diff --git a/ndb/src/mgmclient/Makefile.am b/ndb/src/mgmclient/Makefile.am
index e271c7bed53..b8f9f82e501 100644
--- a/ndb/src/mgmclient/Makefile.am
+++ b/ndb/src/mgmclient/Makefile.am
@@ -1,18 +1,26 @@
+noinst_LTLIBRARIES = libndbmgmclient.la
ndbtools_PROGRAMS = ndb_mgm
-ndb_mgm_SOURCES = \
- main.cpp \
- CommandInterpreter.cpp \
- CpcClient.cpp
+libndbmgmclient_la_SOURCES = CommandInterpreter.cpp
+libndbmgmclient_la_LIBADD = ../mgmapi/libmgmapi.la \
+ ../common/logger/liblogger.la \
+ ../common/portlib/libportlib.la \
+ ../common/util/libgeneral.la \
+ ../common/portlib/libportlib.la
+
+
+ndb_mgm_SOURCES = main.cpp
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_ndbapi.mk.am
-INCLUDES += -I$(top_srcdir)/ndb/include/mgmapi -I$(top_srcdir)/ndb/src/common/mgmcommon
+INCLUDES += -I$(top_srcdir)/ndb/include/mgmapi \
+ -I$(top_srcdir)/ndb/src/common/mgmcommon
-LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la \
- $(top_builddir)/ndb/src/common/editline/libeditline.a \
+LDADD_LOC = $(noinst_LTLIBRARIES) \
+ ../common/portlib/libportlib.la \
+ @readline_link@ \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a \
diff --git a/ndb/src/mgmclient/Makefile_old b/ndb/src/mgmclient/Makefile_old
deleted file mode 100644
index d1b2d60a52a..00000000000
--- a/ndb/src/mgmclient/Makefile_old
+++ /dev/null
@@ -1,25 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi
-
-BIN_TARGET := mgmtclient
-BIN_TARGET_LIBS :=
-BIN_TARGET_ARCHIVES := trace logger mgmapi general mgmsrvcommon portlib repapi
-
-BIN_TARGET_ARCHIVES += editline
-
-DIRS = test_cpcd
-
-# Source files of non-templated classes (.cpp files)
-SOURCES = \
- main.cpp \
- CommandInterpreter.cpp \
- CpcClient.cpp
-
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \
- -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
-
-include $(NDB_TOP)/Epilogue.mk
-
-_bins_mkconfig : $(NDB_TOP)/bin/$(BIN_TARGET)
-
diff --git a/ndb/src/mgmclient/main.cpp b/ndb/src/mgmclient/main.cpp
index cc6d4bf600e..84e27790705 100644
--- a/ndb/src/mgmclient/main.cpp
+++ b/ndb/src/mgmclient/main.cpp
@@ -15,19 +15,32 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <ndb_opts.h>
+
+// copied from mysql.cc to get readline
+extern "C" {
+#if defined( __WIN__) || defined(OS2)
+#include <conio.h>
+#elif !defined(__NETWARE__)
+#include <readline/readline.h>
+extern "C" int add_history(const char *command); /* From readline directory */
+#define HAVE_READLINE
+#endif
+}
#include <NdbMain.h>
#include <NdbHost.h>
-#include <util/getarg.h>
+#include <BaseString.hpp>
+#include <NdbOut.hpp>
#include <mgmapi.h>
-#include <LocalConfig.hpp>
+#include <ndb_version.h>
-#include "CommandInterpreter.hpp"
+#include "ndb_mgmclient.hpp"
const char *progname = "ndb_mgm";
-static CommandInterpreter* com;
+static Ndb_mgmclient* com;
extern "C"
void
@@ -43,59 +56,130 @@ handler(int sig){
}
}
-int main(int argc, const char** argv){
- ndb_init();
- int optind = 0;
- const char *_host = 0;
- int _port = 0;
- int _help = 0;
- int _try_reconnect = 0;
-
- struct getargs args[] = {
- { "try-reconnect", 't', arg_integer, &_try_reconnect, "Specify number of retries for connecting to ndb_mgmd, default infinite", "#" },
- { "usage", '?', arg_flag, &_help, "Print help", "" },
- };
- int num_args = sizeof(args) / sizeof(args[0]); /* Number of arguments */
-
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, progname, "[host [port]]");
- exit(1);
+static const char default_prompt[]= "ndb_mgm> ";
+static unsigned _try_reconnect;
+static char *opt_connect_str= 0;
+static const char *prompt= default_prompt;
+static char *opt_execute_str= 0;
+
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_mgm"),
+ { "execute", 'e',
+ "execute command and exit",
+ (gptr*) &opt_execute_str, (gptr*) &opt_execute_str, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "try-reconnect", 't',
+ "Specify number of tries for connecting to ndb_mgmd (0 = infinite)",
+ (gptr*) &_try_reconnect, (gptr*) &_try_reconnect, 0,
+ GET_UINT, REQUIRED_ARG, 3, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void short_usage_sub(void)
+{
+ printf("Usage: %s [OPTIONS] [hostname [port]]\n", my_progname);
+}
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
+ short_usage_sub();
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_mgm.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
}
+ return 0;
+}
- argv += optind;
- argc -= optind;
-
- LocalConfig cfg;
-
- if(argc >= 1) {
- _host = argv[0];
- if(argc >= 2) {
- _port = atoi(argv[1]);
- }
- } else {
- if(cfg.init(0, 0) && cfg.ids.size() > 0 && cfg.ids[0].type == MgmId_TCP){
- _host = cfg.ids[0].name.c_str();
- _port = cfg.ids[0].port;
- } else {
- cfg.printError();
- cfg.printUsage();
- return 1;
- }
+static int
+read_and_execute(int _try_reconnect)
+{
+ static char *line_read = (char *)NULL;
+
+ /* If the buffer has already been allocated, return the memory
+ to the free pool. */
+ if (line_read)
+ {
+ free (line_read);
+ line_read = (char *)NULL;
}
-
+#ifdef HAVE_READLINE
+ /* Get a line from the user. */
+ line_read = readline (prompt);
+ /* If the line has any text in it, save it on the history. */
+ if (line_read && *line_read)
+ add_history (line_read);
+#else
+ static char linebuffer[254];
+ fputs(prompt, stdout);
+ linebuffer[sizeof(linebuffer)-1]=0;
+ line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
+ if (line_read == linebuffer) {
+ char *q=linebuffer;
+ while (*q > 31) q++;
+ *q=0;
+ line_read= strdup(linebuffer);
+ }
+#endif
+ return com->execute(line_read,_try_reconnect);
+}
+
+int main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char *_host = 0;
+ int _port = 0;
+ const char *load_default_groups[]= { "mysql_cluster","ndb_mgm",0 };
+
+ load_defaults("my",load_default_groups,&argc,&argv);
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ exit(ho_error);
+
char buf[MAXHOSTNAMELEN+10];
- BaseString::snprintf(buf, sizeof(buf), "%s:%d", _host, _port);
+ if(argc == 1) {
+ BaseString::snprintf(buf, sizeof(buf), "%s", argv[0]);
+ opt_connect_str= buf;
+ } else if (argc >= 2) {
+ BaseString::snprintf(buf, sizeof(buf), "%s:%s", argv[0], argv[1]);
+ opt_connect_str= buf;
+ }
- ndbout << "-- NDB Cluster -- Management Client --" << endl;
- printf("Connecting to Management Server: %s\n", buf);
+ if (!isatty(0) || opt_execute_str)
+ {
+ prompt= 0;
+ }
signal(SIGPIPE, handler);
-
- com = new CommandInterpreter(buf);
- while(com->readAndExecute(_try_reconnect));
+ com = new Ndb_mgmclient(opt_connect_str,1);
+ int ret= 0;
+ if (!opt_execute_str)
+ {
+ ndbout << "-- NDB Cluster -- Management Client --" << endl;
+ while(read_and_execute(_try_reconnect));
+ }
+ else
+ {
+ com->execute(opt_execute_str,_try_reconnect, &ret);
+ }
delete com;
- return 0;
+ return ret;
}
diff --git a/ndb/src/common/editline/editline_win32.c b/ndb/src/mgmclient/ndb_mgmclient.h
index 5083edb7fae..b62a33999a3 100644
--- a/ndb/src/common/editline/editline_win32.c
+++ b/ndb/src/mgmclient/ndb_mgmclient.h
@@ -14,19 +14,20 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+#ifndef Ndb_mgmclient_h
+#define Ndb_mgmclient_h
-#include <ndb_global.h>
+#ifdef __cplusplus
+extern "C" {
+#endif
+typedef void* Ndb_mgmclient_handle;
+Ndb_mgmclient_handle ndb_mgmclient_handle_create(const char *connect_string);
+int ndb_mgmclient_execute(Ndb_mgmclient_handle, int argc, char** argv);
+int ndb_mgmclient_handle_destroy(Ndb_mgmclient_handle);
-char* readline(const char* prompt)
-{
- char* szBuf;
- printf(prompt);
- szBuf = (char*)malloc(256);
- return gets(szBuf);
-}
-
-void add_history(char* pch)
-{
+#ifdef __cplusplus
}
+#endif
+#endif /* Ndb_mgmclient_h */
diff --git a/ndb/src/common/editline/unix.h b/ndb/src/mgmclient/ndb_mgmclient.hpp
index 37f461b471d..bffdf69f920 100644
--- a/ndb/src/common/editline/unix.h
+++ b/ndb/src/mgmclient/ndb_mgmclient.hpp
@@ -14,12 +14,20 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-/* $Revision: 1.3 $
-**
-** Editline system header file for Unix.
-*/
+#ifndef Ndb_mgmclient_hpp
+#define Ndb_mgmclient_hpp
-#define CRLF "\r\n"
+class CommandInterpreter;
+class Ndb_mgmclient
+{
+public:
+ Ndb_mgmclient(const char*,int verbose=0);
+ ~Ndb_mgmclient();
+ int execute(const char *_line, int _try_reconnect=-1, int *error= 0);
+ int execute(int argc, char** argv, int _try_reconnect=-1, int *error= 0);
+ int disconnect();
+private:
+ CommandInterpreter *m_cmd;
+};
-#include <ndb_global.h>
-#include <dirent.h>
+#endif // Ndb_mgmclient_hpp
diff --git a/ndb/src/mgmsrv/CommandInterpreter.cpp b/ndb/src/mgmsrv/CommandInterpreter.cpp
index 2a054a01f1e..02bf24f1d9c 100644
--- a/ndb/src/mgmsrv/CommandInterpreter.cpp
+++ b/ndb/src/mgmsrv/CommandInterpreter.cpp
@@ -113,6 +113,11 @@ private:
void * m_ptr;
};
+const char *CommandInterpreter::get_error_text(int err_no)
+{
+ return _mgmtSrvr.getErrorText(err_no, m_err_str, sizeof(m_err_str));
+}
+
//*****************************************************************************
//*****************************************************************************
int CommandInterpreter::readAndExecute() {
@@ -600,8 +605,9 @@ stopCallback(int nodeId, void * anyData, int errCode){
ndbout << "\nNode " << nodeId << " has shutdown" << endl;
} else {
MgmtSrvr * mgm = (MgmtSrvr *)anyData;
+ char err_str[1024];
ndbout << "Node " << nodeId << " has not shutdown: "
- << mgm->getErrorText(errCode) << endl;
+ << mgm->getErrorText(errCode,err_str,sizeof(err_str)) << endl;
}
}
@@ -653,7 +659,8 @@ versionCallback(int nodeId, int version, void * anyData, int errCode){
} else {
MgmtSrvr * mgm = (MgmtSrvr *)anyData;
- ndbout << mgm->getErrorText(errCode) << endl;
+ char err_str[1024];
+ ndbout << mgm->getErrorText(errCode,err_str,sizeof(err_str)) << endl;
}
}
@@ -671,7 +678,7 @@ void CommandInterpreter::executeStop(int processId,
result = _mgmtSrvr.stopNode(processId, false, stopCallback, this);
if(result != 0)
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
@@ -686,7 +693,7 @@ void CommandInterpreter::executeStart(int processId, const char* parameters,
int result = _mgmtSrvr.start(processId);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
}
@@ -719,7 +726,7 @@ CommandInterpreter::executeRestart(int processId, const char* parameters,
stopCallback,
this);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
}
@@ -760,7 +767,7 @@ CommandInterpreter::executeDumpState(int processId, const char* parameters,
free(tmpString);
int result = _mgmtSrvr.dumpState(processId, pars, no);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
}
@@ -781,7 +788,7 @@ void CommandInterpreter::executeStatus(int processId,
&status, &version, &startPhase, &system,
&dynamicId, &nodeGroup, &connectCount);
if(result != 0){
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
return;
}
@@ -875,7 +882,7 @@ void CommandInterpreter::executeLogLevel(int processId,
int result = _mgmtSrvr.setNodeLogLevel(processId, logLevel);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
#endif
}
@@ -913,7 +920,7 @@ void CommandInterpreter::executeError(int processId,
int result = _mgmtSrvr.insertError(processId, errorNo);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
free(newpar);
}
@@ -953,7 +960,7 @@ void CommandInterpreter::executeTrace(int processId,
int result = _mgmtSrvr.setTraceNo(processId, traceNo);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
free(newpar);
}
@@ -974,7 +981,7 @@ void CommandInterpreter::executeLog(int processId,
int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::InOut, blocks);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
}
@@ -995,7 +1002,7 @@ void CommandInterpreter::executeLogIn(int processId,
int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::In, blocks);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
}
@@ -1014,7 +1021,7 @@ void CommandInterpreter::executeLogOut(int processId,
int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Out, blocks);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
}
@@ -1035,7 +1042,7 @@ void CommandInterpreter::executeLogOff(int processId,
int result = _mgmtSrvr.setSignalLoggingMode(processId, MgmtSrvr::Off, blocks);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
}
@@ -1054,7 +1061,7 @@ void CommandInterpreter::executeTestOn(int processId,
int result = _mgmtSrvr.startSignalTracing(processId);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
}
@@ -1073,7 +1080,7 @@ void CommandInterpreter::executeTestOff(int processId,
int result = _mgmtSrvr.stopSignalTracing(processId);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
}
@@ -1126,7 +1133,7 @@ void CommandInterpreter::executeEventReporting(int processId,
ndbout_c("processId %d", processId);
int result = _mgmtSrvr.setEventReportingLevel(processId, logLevel);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
}
#endif
}
@@ -1136,7 +1143,7 @@ CommandInterpreter::executeStartBackup(char* parameters) {
Uint32 backupId;
int result = _mgmtSrvr.startBackup(backupId);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
} else {
// ndbout << "Start of backup ordered" << endl;
}
@@ -1153,7 +1160,7 @@ CommandInterpreter::executeAbortBackup(char* parameters) {
}
int result = _mgmtSrvr.abortBackup(bid);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
} else {
ndbout << "Abort of backup " << bid << " ordered" << endl;
}
@@ -1174,7 +1181,7 @@ CommandInterpreter::executeEnterSingleUser(char* parameters) {
}
int result = _mgmtSrvr.enterSingleUser(0, nodeId,0,0);
if (result != 0) {
- ndbout << _mgmtSrvr.getErrorText(result) << endl;
+ ndbout << get_error_text(result) << endl;
} else {
ndbout << "Entering single user mode, granting access for node "
<< nodeId << " OK." << endl;
diff --git a/ndb/src/mgmsrv/CommandInterpreter.hpp b/ndb/src/mgmsrv/CommandInterpreter.hpp
index 3466ee76226..1a5184361d6 100644
--- a/ndb/src/mgmsrv/CommandInterpreter.hpp
+++ b/ndb/src/mgmsrv/CommandInterpreter.hpp
@@ -23,7 +23,6 @@
#include <ndb_global.h>
#include <Vector.hpp>
-#include <editline/editline.h>
#include <BaseString.hpp>
class MgmtSrvr;
@@ -56,6 +55,9 @@ public:
int readAndExecute();
private:
+ char m_err_str[1024];
+ const char *get_error_text(int err_no);
+
/**
* Read a string, and return a pointer to it.
*
@@ -63,26 +65,27 @@ private:
*/
char *readline_gets ()
{
+ static char linebuffer[254];
static char *line_read = (char *)NULL;
- // Disable the default file-name completion action of TAB
- // rl_bind_key ('\t', rl_insert);
-
/* If the buffer has already been allocated, return the memory
to the free pool. */
if (line_read)
- {
- free (line_read);
- line_read = (char *)NULL;
- }
+ {
+ free (line_read);
+ line_read = (char *)NULL;
+ }
/* Get a line from the user. */
- line_read = readline ("NDB> ");
-
- /* If the line has any text in it, save it on the history. */
- if (line_read && *line_read)
- add_history (line_read);
-
+ fputs("ndb_mgmd> ", stdout);
+ linebuffer[sizeof(linebuffer)-1]=0;
+ line_read = fgets(linebuffer, sizeof(linebuffer)-1, stdin);
+ if (line_read == linebuffer) {
+ char *q=linebuffer;
+ while (*q > 31) q++;
+ *q=0;
+ line_read= strdup(linebuffer);
+ }
return (line_read);
}
diff --git a/ndb/src/mgmsrv/ConfigInfo.cpp b/ndb/src/mgmsrv/ConfigInfo.cpp
index ad346b30ead..4af1556a0c0 100644
--- a/ndb/src/mgmsrv/ConfigInfo.cpp
+++ b/ndb/src/mgmsrv/ConfigInfo.cpp
@@ -1478,7 +1478,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- NDB_BASE_PORT,
+ NDB_PORT,
"0",
STR_VALUE(MAX_INT_RNIL) },
@@ -1490,7 +1490,7 @@ const ConfigInfo::ParamInfo ConfigInfo::m_ParamInfo[] = {
ConfigInfo::USED,
false,
ConfigInfo::INT,
- "2199",
+ UNDEFINED,
"0",
STR_VALUE(MAX_INT_RNIL) },
@@ -3010,7 +3010,7 @@ fixPortNumber(InitConfigFileParser::Context & ctx, const char * data){
if(!(ctx.m_userDefaults &&
ctx.m_userDefaults->get("PortNumber", &base)) &&
!ctx.m_systemDefaults->get("PortNumber", &base)) {
- base= strtoll(NDB_BASE_PORT,0,0)+2;
+ base= strtoll(NDB_BASE_PORT,0,0);
// ctx.reportError("Cannot retrieve base port number");
// return false;
}
@@ -3442,7 +3442,7 @@ static bool add_server_ports(Vector<ConfigInfo::ConfigRuleSection>&sections,
#if 0
Properties * props= ctx.m_config;
Properties computers(true);
- Uint32 port_base = NDB_BASE_PORT+2;
+ Uint32 port_base = NDB_BASE_PORT;
Uint32 nNodes;
ctx.m_userProperties.get("NoOfNodes", &nNodes);
diff --git a/ndb/src/mgmsrv/InitConfigFileParser.cpp b/ndb/src/mgmsrv/InitConfigFileParser.cpp
index fdfe7823fc2..05102255eaa 100644
--- a/ndb/src/mgmsrv/InitConfigFileParser.cpp
+++ b/ndb/src/mgmsrv/InitConfigFileParser.cpp
@@ -213,48 +213,41 @@ InitConfigFileParser::parseConfig(FILE * file) {
// Parse Name-Value Pair
//****************************************************************************
-bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) {
-
- char tmpLine[MAX_LINE_LENGTH];
- char fname[MAX_LINE_LENGTH], rest[MAX_LINE_LENGTH];
- char* t;
- const char *separator_list[]= {":", "=", 0};
- const char *separator= 0;
-
+bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line)
+{
if (ctx.m_currentSection == NULL){
ctx.reportError("Value specified outside section");
return false;
}
- strncpy(tmpLine, line, MAX_LINE_LENGTH);
-
// *************************************
- // Check if a separator exists in line
+ // Split string at first occurrence of
+ // '=' or ':'
// *************************************
- for(int i= 0; separator_list[i] != 0; i++) {
- if(strchr(tmpLine, separator_list[i][0])) {
- separator= separator_list[i];
- break;
- }
- }
- if (separator == 0) {
+ Vector<BaseString> tmp_string_split;
+ if (BaseString(line).split(tmp_string_split,
+ BaseString("=:"),
+ 2) != 2)
+ {
ctx.reportError("Parse error");
return false;
}
- // *******************************************
- // Get pointer to substring before separator
- // *******************************************
- t = strtok(tmpLine, separator);
-
- // *****************************************
- // Count number of tokens before separator
- // *****************************************
- if (sscanf(t, "%120s%120s", fname, rest) != 1) {
- ctx.reportError("Multiple names before \'%c\'", separator[0]);
- return false;
+ // *************************************
+ // Remove leading and trailing chars
+ // *************************************
+ {
+ for (int i = 0; i < 2; i++)
+ tmp_string_split[i].trim("\r\n \t");
}
+
+ // *************************************
+ // First in split is fname
+ // *************************************
+
+ const char *fname= tmp_string_split[0].c_str();
+
if (!ctx.m_currentInfo->contains(fname)) {
ctx.reportError("[%s] Unknown parameter: %s", ctx.fname, fname);
return false;
@@ -273,24 +266,11 @@ bool InitConfigFileParser::parseNameValuePair(Context& ctx, const char* line) {
}
}
- // ******************************************
- // Get pointer to substring after separator
- // ******************************************
- t = strtok(NULL, "\0");
- if (t == NULL) {
- ctx.reportError("No value for parameter");
- return false;
- }
-
- // ******************************************
- // Remove prefix and postfix spaces and tabs
- // *******************************************
- trim(t);
-
// ***********************
// Store name-value pair
// ***********************
- return storeNameValuePair(ctx, fname, t);
+
+ return storeNameValuePair(ctx, fname, tmp_string_split[1].c_str());
}
diff --git a/ndb/src/mgmsrv/Makefile.am b/ndb/src/mgmsrv/Makefile.am
index 3b57b027827..ee5220ef9f8 100644
--- a/ndb/src/mgmsrv/Makefile.am
+++ b/ndb/src/mgmsrv/Makefile.am
@@ -24,7 +24,6 @@ INCLUDES_LOC = -I$(top_srcdir)/ndb/src/ndbapi \
-I$(top_srcdir)/ndb/src/common/mgmcommon
LDADD_LOC = $(top_builddir)/ndb/src/libndbclient.la \
- $(top_builddir)/ndb/src/common/editline/libeditline.a \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/mysys/libmysys.a \
$(top_builddir)/strings/libmystrings.a @NDB_SCI_LIBS@
@@ -34,6 +33,7 @@ DEFS_LOC = -DDEFAULT_MYSQL_HOME="\"$(MYSQLBASEdir)\"" \
-DDATADIR="\"$(MYSQLDATAdir)\"" \
-DSHAREDIR="\"$(MYSQLSHAREdir)\"" \
-DMYSQLCLUSTERDIR="\"$(MYSQLCLUSTERdir)\"" \
+ -DNDB_PORT="\"@ndb_port@\"" \
-DNDB_BASE_PORT="\"@ndb_port_base@\""
include $(top_srcdir)/ndb/config/common.mk.am
diff --git a/ndb/src/mgmsrv/Makefile_old b/ndb/src/mgmsrv/Makefile_old
deleted file mode 100644
index c99875ae8b6..00000000000
--- a/ndb/src/mgmsrv/Makefile_old
+++ /dev/null
@@ -1,41 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi mgmapiclient
-
-BIN_TARGET := mgmtsrvr
-BIN_TARGET_LIBS :=
-BIN_TARGET_ARCHIVES := NDB_API mgmsrvcommon mgmapi general
-
-ifneq ($(USE_EDITLINE), N)
-BIN_TARGET_ARCHIVES += editline
-DIRS := mkconfig
-endif
-BIN_TARGET_ARCHIVES += general
-
-BIN_FLAGS += $(TERMCAP_LIB)
-
-# Source files of non-templated classes (.cpp files)
-SOURCES = \
- MgmtSrvr.cpp \
- MgmtSrvrGeneralSignalHandling.cpp \
- main.cpp \
- Services.cpp \
- convertStrToInt.cpp \
- NodeLogLevel.cpp \
- NodeLogLevelList.cpp \
- SignalQueue.cpp \
- MgmtSrvrConfig.cpp
-
-ifeq ($(findstring OSE, $(NDB_OS)),)
-SOURCES += CommandInterpreter.cpp
-endif
-
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/src/ndbapi) \
- -I$(call fixpath,$(NDB_TOP)/src/mgmapi) \
- -I$(call fixpath,$(NDB_TOP)/include/mgmapi) \
- -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
-
-include $(NDB_TOP)/Epilogue.mk
-
-_bins_mkconfig : $(NDB_TOP)/bin/$(BIN_TARGET)
-
diff --git a/ndb/src/mgmsrv/MgmtSrvr.cpp b/ndb/src/mgmsrv/MgmtSrvr.cpp
index 29df10630f3..061aa2e0cb8 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.cpp
@@ -49,6 +49,8 @@
#include <NdbAutoPtr.hpp>
+#include <ndberror.h>
+
#include <mgmapi.h>
#include <mgmapi_configuration.hpp>
#include <mgmapi_config_parameters.h>
@@ -264,16 +266,6 @@ MgmtSrvr::isEventLogFilterEnabled(int severity)
static ErrorItem errorTable[] =
{
- {200, "Backup undefined error"},
- {202, "Backup failed to allocate buffers (check configuration)"},
- {203, "Backup failed to setup fs buffers (check configuration)"},
- {204, "Backup failed to allocate tables (check configuration)"},
- {205, "Backup failed to insert file header (check configuration)"},
- {206, "Backup failed to insert table list (check configuration)"},
- {207, "Backup failed to allocate table memory (check configuration)"},
- {208, "Backup failed to allocate file record (check configuration)"},
- {209, "Backup failed to allocate attribute record (check configuration)"},
-
{MgmtSrvr::NO_CONTACT_WITH_PROCESS, "No contact with the process (dead ?)."},
{MgmtSrvr::PROCESS_NOT_CONFIGURED, "The process is not configured."},
{MgmtSrvr::WRONG_PROCESS_TYPE,
@@ -399,15 +391,20 @@ MgmtSrvr::getPort() const {
}
/* Constructor */
-MgmtSrvr::MgmtSrvr(NodeId nodeId,
- const BaseString &configFilename,
- LocalConfig &local_config,
- Config * config):
+int MgmtSrvr::init()
+{
+ if ( _ownNodeId > 0)
+ return 0;
+ return -1;
+}
+
+MgmtSrvr::MgmtSrvr(SocketServer *socket_server,
+ const char *config_filename,
+ const char *connect_string) :
_blockNumber(1), // Hard coded block number since it makes it easy to send
// signals to other management servers.
+ m_socket_server(socket_server),
_ownReference(0),
- m_local_config(local_config),
- m_allocated_resources(*this),
theSignalIdleList(NULL),
theWaitState(WAIT_SUBSCRIBE_CONF),
m_statisticsListner(this)
@@ -415,6 +412,8 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
DBUG_ENTER("MgmtSrvr::MgmtSrvr");
+ _ownNodeId= 0;
+
_config = NULL;
_isStopThread = false;
@@ -425,12 +424,48 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
theFacade = 0;
m_newConfig = NULL;
- m_configFilename = configFilename;
+ if (config_filename)
+ m_configFilename.assign(config_filename);
+ else
+ m_configFilename.assign("config.ini");
m_nextConfigGenerationNumber = 0;
- _config = (config == 0 ? readConfig() : config);
-
+ m_config_retriever= new ConfigRetriever(connect_string,
+ NDB_VERSION, NDB_MGM_NODE_TYPE_MGM);
+ // if connect_string explicitly given or
+ // no config filename is given then
+ // first try to allocate nodeid from another management server
+ if ((connect_string || config_filename == NULL) &&
+ (m_config_retriever->do_connect(0,0,0) == 0))
+ {
+ int tmp_nodeid= 0;
+ tmp_nodeid= m_config_retriever->allocNodeId(0 /*retry*/,0 /*delay*/);
+ if (tmp_nodeid == 0)
+ {
+ ndbout_c(m_config_retriever->getErrorString());
+ exit(-1);
+ }
+ // read config from other managent server
+ _config= fetchConfig();
+ if (_config == 0)
+ {
+ ndbout << m_config_retriever->getErrorString() << endl;
+ exit(-1);
+ }
+ _ownNodeId= tmp_nodeid;
+ }
+
+ if (_ownNodeId == 0)
+ {
+ // read config locally
+ _config= readConfig();
+ if (_config == 0) {
+ ndbout << "Unable to read config file" << endl;
+ exit(-1);
+ }
+ }
+
theMgmtWaitForResponseCondPtr = NdbCondition_Create();
m_configMutex = NdbMutex_Create();
@@ -442,9 +477,11 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
nodeTypes[i] = (enum ndb_mgm_node_type)-1;
m_connect_address[i].s_addr= 0;
}
+
{
- ndb_mgm_configuration_iterator * iter = ndb_mgm_create_configuration_iterator
- (config->m_configValues, CFG_SECTION_NODE);
+ ndb_mgm_configuration_iterator
+ *iter = ndb_mgm_create_configuration_iterator(_config->m_configValues,
+ CFG_SECTION_NODE);
for(ndb_mgm_first(iter); ndb_mgm_valid(iter); ndb_mgm_next(iter)){
unsigned type, id;
if(ndb_mgm_get_int_parameter(iter, CFG_TYPE_OF_SECTION, &type) != 0)
@@ -477,47 +514,33 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
}
_props = NULL;
- _ownNodeId= 0;
- NodeId tmp= nodeId;
BaseString error_string;
-#if 0
- char my_hostname[256];
- struct sockaddr_in tmp_addr;
- SOCKET_SIZE_TYPE addrlen= sizeof(tmp_addr);
- if (!g_no_nodeid_checks) {
- if (gethostname(my_hostname, sizeof(my_hostname))) {
- ndbout << "error: gethostname() - " << strerror(errno) << endl;
- exit(-1);
- }
- if (Ndb_getInAddr(&(((sockaddr_in*)&tmp_addr)->sin_addr),my_hostname)) {
- ndbout << "error: Ndb_getInAddr(" << my_hostname << ") - "
- << strerror(errno) << endl;
- exit(-1);
- }
- }
- if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM,
- (struct sockaddr *)&tmp_addr,
- &addrlen, error_string)){
- ndbout << "Unable to obtain requested nodeid: "
- << error_string.c_str() << endl;
- exit(-1);
- }
-#else
- if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM,
- 0, 0, error_string)){
- ndbout << "Unable to obtain requested nodeid: "
- << error_string.c_str() << endl;
+
+ if ((m_node_id_mutex = NdbMutex_Create()) == 0)
+ {
+ ndbout << "mutex creation failed line = " << __LINE__ << endl;
exit(-1);
}
-#endif
- _ownNodeId = tmp;
+ if (_ownNodeId == 0) // we did not get node id from other server
+ {
+ NodeId tmp= m_config_retriever->get_configuration_nodeid();
+
+ if (!alloc_node_id(&tmp, NDB_MGM_NODE_TYPE_MGM,
+ 0, 0, error_string)){
+ ndbout << "Unable to obtain requested nodeid: "
+ << error_string.c_str() << endl;
+ exit(-1);
+ }
+ _ownNodeId = tmp;
+ }
{
DBUG_PRINT("info", ("verifyConfig"));
- ConfigRetriever cr(m_local_config, NDB_VERSION, NDB_MGM_NODE_TYPE_MGM);
- if (!cr.verifyConfig(config->m_configValues, _ownNodeId)) {
- ndbout << cr.getErrorString() << endl;
+ if (!m_config_retriever->verifyConfig(_config->m_configValues,
+ _ownNodeId))
+ {
+ ndbout << m_config_retriever->getErrorString() << endl;
exit(-1);
}
}
@@ -534,12 +557,6 @@ MgmtSrvr::MgmtSrvr(NodeId nodeId,
m_statisticsListner.m_logLevel = se.m_logLevel;
}
- if ((m_node_id_mutex = NdbMutex_Create()) == 0)
- {
- ndbout << "mutex creation failed line = " << __LINE__ << endl;
- exit(-1);
- }
-
DBUG_VOID_RETURN;
}
@@ -656,6 +673,8 @@ MgmtSrvr::~MgmtSrvr()
NdbThread_WaitFor(m_signalRecvThread, &res);
NdbThread_Destroy(&m_signalRecvThread);
}
+ if (m_config_retriever)
+ delete m_config_retriever;
}
//****************************************************************************
@@ -1829,18 +1848,21 @@ MgmtSrvr::dumpState(int processId, const Uint32 args[], Uint32 no)
//****************************************************************************
//****************************************************************************
-const char* MgmtSrvr::getErrorText(int errorCode)
+const char* MgmtSrvr::getErrorText(int errorCode, char *buf, int buf_sz)
{
- static char text[255];
for (int i = 0; i < noOfErrorCodes; ++i) {
if (errorCode == errorTable[i]._errorCode) {
- return errorTable[i]._errorText;
+ BaseString::snprintf(buf, buf_sz, errorTable[i]._errorText);
+ buf[buf_sz-1]= 0;
+ return buf;
}
}
-
- BaseString::snprintf(text, 255, "Unknown management server error code %d", errorCode);
- return text;
+
+ ndb_error_string(errorCode, buf, buf_sz);
+ buf[buf_sz-1]= 0;
+
+ return buf;
}
void
@@ -2095,6 +2117,25 @@ MgmtSrvr::getNodeType(NodeId nodeId) const
return nodeTypes[nodeId];
}
+void
+MgmtSrvr::get_connected_nodes(NodeBitmask &connected_nodes) const
+{
+ if (theFacade && theFacade->theClusterMgr)
+ {
+ for(Uint32 i = 0; i < MAX_NODES; i++)
+ {
+ if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB)
+ {
+ const ClusterMgr::Node &node= theFacade->theClusterMgr->getNodeInfo(i);
+ if (node.connected)
+ {
+ connected_nodes.bitOR(node.m_state.m_connected_nodes);
+ }
+ }
+ }
+ }
+}
+
bool
MgmtSrvr::alloc_node_id(NodeId * nodeId,
enum ndb_mgm_node_type type,
@@ -2107,7 +2148,7 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
*nodeId, type, client_addr));
if (g_no_nodeid_checks) {
if (*nodeId == 0) {
- error_string.appfmt("no-nodeid-ckecks set in manegment server.\n"
+ error_string.appfmt("no-nodeid-checks set in management server.\n"
"node id must be set explicitly in connectstring");
DBUG_RETURN(false);
}
@@ -2116,16 +2157,11 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
Guard g(m_node_id_mutex);
int no_mgm= 0;
NodeBitmask connected_nodes(m_reserved_nodes);
- for(Uint32 i = 0; i < MAX_NODES; i++)
+ get_connected_nodes(connected_nodes);
{
- if (getNodeType(i) == NDB_MGM_NODE_TYPE_NDB &&
- theFacade && theFacade->theClusterMgr) {
- const ClusterMgr::Node &node= theFacade->theClusterMgr->getNodeInfo(i);
- if (node.connected) {
- connected_nodes.bitOR(node.m_state.m_connected_nodes);
- }
- } else if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM)
- no_mgm++;
+ for(Uint32 i = 0; i < MAX_NODES; i++)
+ if (getNodeType(i) == NDB_MGM_NODE_TYPE_MGM)
+ no_mgm++;
}
bool found_matching_id= false;
bool found_matching_type= false;
@@ -2228,6 +2264,10 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
m_connect_address[id_found].s_addr= 0;
}
m_reserved_nodes.set(id_found);
+ char tmp_str[128];
+ m_reserved_nodes.getText(tmp_str);
+ g_EventLogger.info("Mgmt server state: nodeid %d reserved for ip %s, m_reserved_nodes %s.",
+ id_found, get_connect_address(id_found), tmp_str);
DBUG_RETURN(true);
}
@@ -2284,6 +2324,36 @@ MgmtSrvr::alloc_node_id(NodeId * nodeId,
error_string.appfmt("No node defined with id=%d in config file.",
*nodeId);
}
+
+ g_EventLogger.warning("Allocate nodeid (%d) failed. Connection from ip %s. "
+ "Returned error string \"%s\"",
+ *nodeId,
+ client_addr != 0 ? inet_ntoa(((struct sockaddr_in *)(client_addr))->sin_addr) : "<none>",
+ error_string.c_str());
+
+ NodeBitmask connected_nodes2;
+ get_connected_nodes(connected_nodes2);
+ {
+ BaseString tmp_connected, tmp_not_connected;
+ for(Uint32 i = 0; i < MAX_NODES; i++)
+ {
+ if (connected_nodes2.get(i))
+ {
+ if (!m_reserved_nodes.get(i))
+ tmp_connected.appfmt(" %d", i);
+ }
+ else if (m_reserved_nodes.get(i))
+ {
+ tmp_not_connected.appfmt(" %d", i);
+ }
+ }
+ if (tmp_connected.length() > 0)
+ g_EventLogger.info("Mgmt server state: node id's %s connected but not reserved",
+ tmp_connected.c_str());
+ if (tmp_not_connected.length() > 0)
+ g_EventLogger.info("Mgmt server state: node id's %s not connected but reserved",
+ tmp_not_connected.c_str());
+ }
DBUG_RETURN(false);
}
@@ -2532,10 +2602,15 @@ MgmtSrvr::Allocated_resources::~Allocated_resources()
{
Guard g(m_mgmsrv.m_node_id_mutex);
if (!m_reserved_nodes.isclear()) {
+ m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes);
// node has been reserved, force update signal to ndb nodes
global_flag_send_heartbeat_now= 1;
+
+ char tmp_str[128];
+ m_mgmsrv.m_reserved_nodes.getText(tmp_str);
+ g_EventLogger.info("Mgmt server state: nodeid %d freed, m_reserved_nodes %s.",
+ get_nodeid(), tmp_str);
}
- m_mgmsrv.m_reserved_nodes.bitANDC(m_reserved_nodes);
}
void
@@ -2544,6 +2619,17 @@ MgmtSrvr::Allocated_resources::reserve_node(NodeId id)
m_reserved_nodes.set(id);
}
+NodeId
+MgmtSrvr::Allocated_resources::get_nodeid() const
+{
+ for(Uint32 i = 0; i < MAX_NODES; i++)
+ {
+ if (m_reserved_nodes.get(i))
+ return i;
+ }
+ return 0;
+}
+
int
MgmtSrvr::setDbParameter(int node, int param, const char * value,
BaseString& msg){
diff --git a/ndb/src/mgmsrv/MgmtSrvr.hpp b/ndb/src/mgmsrv/MgmtSrvr.hpp
index a5f21b6bc4a..1afb0848ecc 100644
--- a/ndb/src/mgmsrv/MgmtSrvr.hpp
+++ b/ndb/src/mgmsrv/MgmtSrvr.hpp
@@ -96,7 +96,10 @@ public:
// methods to reserve/allocate resources which
// will be freed when running destructor
void reserve_node(NodeId id);
- bool is_reserved(NodeId nodeId) { return m_reserved_nodes.get(nodeId);}
+ bool is_reserved(NodeId nodeId) { return m_reserved_nodes.get(nodeId); }
+ bool is_reserved(NodeBitmask mask) { return !mask.bitAND(m_reserved_nodes).isclear(); }
+ bool isclear() { return m_reserved_nodes.isclear(); }
+ NodeId get_nodeid() const;
private:
MgmtSrvr &m_mgmsrv;
NodeBitmask m_reserved_nodes;
@@ -172,10 +175,10 @@ public:
/* Constructor */
- MgmtSrvr(NodeId nodeId, /* Local nodeid */
- const BaseString &config_filename, /* Where to save config */
- LocalConfig &local_config, /* Ndb.cfg filename */
- Config * config);
+ MgmtSrvr(SocketServer *socket_server,
+ const char *config_filename, /* Where to save config */
+ const char *connect_string);
+ int init();
NodeId getOwnNodeId() const {return _ownNodeId;};
/**
@@ -463,7 +466,7 @@ public:
* @param errorCode: Error code to get a match error text for.
* @return The error text.
*/
- const char* getErrorText(int errorCode);
+ const char* getErrorText(int errorCode, char *buf, int buf_sz);
/**
* Get configuration
@@ -499,6 +502,9 @@ public:
int setDbParameter(int node, int parameter, const char * value, BaseString&);
const char *get_connect_address(Uint32 node_id) { return inet_ntoa(m_connect_address[node_id]); }
+ void get_connected_nodes(NodeBitmask &connected_nodes) const;
+ SocketServer *get_socket_server() { return m_socket_server; }
+
//**************************************************************************
private:
//**************************************************************************
@@ -525,16 +531,16 @@ private:
int _blockNumber;
NodeId _ownNodeId;
+ SocketServer *m_socket_server;
+
BlockReference _ownReference;
NdbMutex *m_configMutex;
const Config * _config;
Config * m_newConfig;
- LocalConfig &m_local_config;
BaseString m_configFilename;
Uint32 m_nextConfigGenerationNumber;
NodeBitmask m_reserved_nodes;
- Allocated_resources m_allocated_resources;
struct in_addr m_connect_address[MAX_NODES];
//**************************************************************************
@@ -747,6 +753,9 @@ private:
Config *_props;
int send(class NdbApiSignal* signal, Uint32 node, Uint32 node_type);
+
+ ConfigRetriever *m_config_retriever;
+
public:
/**
* This method does not exist
diff --git a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
index 1d51061e909..6c4b4e9ae3c 100644
--- a/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
+++ b/ndb/src/mgmsrv/MgmtSrvrConfig.cpp
@@ -272,30 +272,20 @@ MgmtSrvr::saveConfig(const Config *conf) {
Config *
MgmtSrvr::readConfig() {
- Config *conf = NULL;
- if(m_configFilename.length() != 0) {
- /* Use config file */
- InitConfigFileParser parser;
- conf = parser.parseConfig(m_configFilename.c_str());
-
- if(conf == NULL) {
- /* Try to get configuration from other MGM server */
- return fetchConfig();
- }
- }
+ Config *conf;
+ InitConfigFileParser parser;
+ conf = parser.parseConfig(m_configFilename.c_str());
return conf;
}
Config *
MgmtSrvr::fetchConfig() {
- ConfigRetriever cr(m_local_config, NDB_VERSION, NODE_TYPE_MGM);
- struct ndb_mgm_configuration * tmp = cr.getConfig();
+ struct ndb_mgm_configuration * tmp = m_config_retriever->getConfig();
if(tmp != 0){
Config * conf = new Config();
conf->m_configValues = tmp;
return conf;
}
-
return 0;
}
diff --git a/ndb/src/mgmsrv/Services.cpp b/ndb/src/mgmsrv/Services.cpp
index 5b552836955..5834d40cc78 100644
--- a/ndb/src/mgmsrv/Services.cpp
+++ b/ndb/src/mgmsrv/Services.cpp
@@ -242,6 +242,10 @@ ParserRow<MgmApiSession> commands[] = {
MGM_ARG("node", Int, Optional, "Node"),
MGM_ARG("filter", String, Mandatory, "Event category"),
+ MGM_CMD("purge stale sessions", &MgmApiSession::purge_stale_sessions, ""),
+
+ MGM_CMD("check connection", &MgmApiSession::check_connection, ""),
+
MGM_END()
};
@@ -577,7 +581,7 @@ MgmApiSession::insertError(Parser<MgmApiSession>::Context &,
m_output->println("insert error reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("");
@@ -595,7 +599,7 @@ MgmApiSession::setTrace(Parser<MgmApiSession>::Context &,
m_output->println("set trace reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("");
@@ -663,7 +667,7 @@ MgmApiSession::startBackup(Parser<MgmApiSession>::Context &,
m_output->println("start backup reply");
if(result != 0)
- m_output->println("result: %s(%d)", m_mgmsrv.getErrorText(result), result);
+ m_output->println("result: %s(%d)", get_error_text(result), result);
else{
m_output->println("result: Ok");
m_output->println("id: %d", backupId);
@@ -683,7 +687,7 @@ MgmApiSession::startBackup(Parser<MgmApiSession>::Context &,
m_output->println("start backup reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else{
m_output->println("result: Ok");
m_output->println("id: %d", backupId);
@@ -703,7 +707,7 @@ MgmApiSession::abortBackup(Parser<MgmApiSession>::Context &,
m_output->println("abort backup reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("");
@@ -725,7 +729,7 @@ MgmApiSession::repCommand(Parser<MgmApiSession>::Context &,
m_output->println("global replication reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else{
m_output->println("result: Ok");
m_output->println("id: %d", repReqId);
@@ -747,7 +751,7 @@ MgmApiSession::dumpState(Parser<MgmApiSession>::Context &,
int result = m_mgmsrv.dumpState(node, args_str.c_str());
m_output->println("dump state reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("");
@@ -773,8 +777,10 @@ MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
/* XXX should use constants for this value */
if(level > 15) {
- errorString.assign("Invalied loglevel");
- goto error;
+ m_output->println("set cluster loglevel reply");
+ m_output->println("result: Invalid loglevel");
+ m_output->println("");
+ return;
}
EventSubscribeReq req;
@@ -786,11 +792,6 @@ MgmApiSession::setClusterLogLevel(Parser<MgmApiSession>::Context &,
m_output->println("set cluster loglevel reply");
m_output->println("result: Ok");
m_output->println("");
- return;
-error:
- m_output->println("set cluster loglevel reply");
- m_output->println("result: %s", errorString.c_str());
- m_output->println("");
}
void
@@ -807,8 +808,10 @@ MgmApiSession::setLogLevel(Parser<MgmApiSession>::Context &,
/* XXX should use constants for this value */
if(level > 15) {
- errorString.assign("Invalied loglevel");
- goto error;
+ m_output->println("set loglevel reply");
+ m_output->println("result: Invalid loglevel", errorString.c_str());
+ m_output->println("");
+ return;
}
EventSubscribeReq req;
@@ -820,11 +823,6 @@ MgmApiSession::setLogLevel(Parser<MgmApiSession>::Context &,
m_output->println("set loglevel reply");
m_output->println("result: Ok");
m_output->println("");
- return;
- error:
- m_output->println("set loglevel reply");
- m_output->println("result: %s", errorString.c_str());
- m_output->println("");
}
void
@@ -838,7 +836,7 @@ MgmApiSession::stopSignalLog(Parser<MgmApiSession>::Context &,
m_output->println("stop signallog");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("");
@@ -878,7 +876,7 @@ MgmApiSession::restart(Parser<MgmApiSession>::Context &,
m_output->println("restart reply");
if(result != 0){
- m_output->println("result: %d-%s", result, m_mgmsrv.getErrorText(result));
+ m_output->println("result: %d-%s", result, get_error_text(result));
} else
m_output->println("result: Ok");
m_output->println("restarted: %d", restarted);
@@ -902,7 +900,7 @@ MgmApiSession::restartAll(Parser<MgmApiSession>::Context &,
m_output->println("restart reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("restarted: %d", count);
@@ -1033,7 +1031,7 @@ MgmApiSession::stop(Parser<MgmApiSession>::Context &,
m_output->println("stop reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("stopped: %d", stopped);
@@ -1055,7 +1053,7 @@ MgmApiSession::stopAll(Parser<MgmApiSession>::Context &,
m_output->println("stop reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("stopped: %d", stopped);
@@ -1071,7 +1069,7 @@ MgmApiSession::enterSingleUser(Parser<MgmApiSession>::Context &,
int result = m_mgmsrv.enterSingleUser(&stopped, nodeId);
m_output->println("enter single user reply");
if(result != 0) {
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
}
else {
m_output->println("result: Ok");
@@ -1086,7 +1084,7 @@ MgmApiSession::exitSingleUser(Parser<MgmApiSession>::Context &,
int result = m_mgmsrv.exitSingleUser(&stopped, false);
m_output->println("exit single user reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("");
@@ -1104,7 +1102,7 @@ MgmApiSession::startSignalLog(Parser<MgmApiSession>::Context &,
m_output->println("start signallog reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("");
@@ -1149,7 +1147,7 @@ MgmApiSession::logSignals(Parser<MgmApiSession>::Context &,
m_output->println("log signals reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("");
@@ -1166,7 +1164,7 @@ MgmApiSession::start(Parser<MgmApiSession>::Context &,
m_output->println("start reply");
if(result != 0)
- m_output->println("result: %s", m_mgmsrv.getErrorText(result));
+ m_output->println("result: %s", get_error_text(result));
else
m_output->println("result: Ok");
m_output->println("");
@@ -1418,6 +1416,55 @@ done:
m_output->println("");
}
+struct PurgeStruct
+{
+ NodeBitmask free_nodes;/* free nodes as reported
+ * by ndbd in apiRegReqConf
+ */
+ BaseString *str;
+};
+
+void
+MgmApiSession::stop_session_if_not_connected(SocketServer::Session *_s, void *data)
+{
+ MgmApiSession *s= (MgmApiSession *)_s;
+ struct PurgeStruct &ps= *(struct PurgeStruct *)data;
+ if (s->m_allocated_resources->is_reserved(ps.free_nodes))
+ {
+ ps.str->appfmt(" %d", s->m_allocated_resources->get_nodeid());
+ s->stopSession();
+ }
+}
+
+void
+MgmApiSession::purge_stale_sessions(Parser_t::Context &ctx,
+ const class Properties &args)
+{
+ struct PurgeStruct ps;
+ BaseString str;
+ ps.str = &str;
+
+ m_mgmsrv.get_connected_nodes(ps.free_nodes);
+ ps.free_nodes.bitXORC(NodeBitmask()); // invert connected_nodes to get free nodes
+
+ m_mgmsrv.get_socket_server()->foreachSession(stop_session_if_not_connected,&ps);
+
+ m_output->println("purge stale sessions reply");
+ if (str.length() > 0)
+ m_output->println("purged:%s",str.c_str());
+ m_output->println("result: Ok");
+ m_output->println("");
+}
+
+void
+MgmApiSession::check_connection(Parser_t::Context &ctx,
+ const class Properties &args)
+{
+ m_output->println("check connection reply");
+ m_output->println("result: Ok");
+ m_output->println("");
+}
+
template class MutexVector<int>;
template class Vector<ParserRow<MgmApiSession> const*>;
template class Vector<unsigned short>;
diff --git a/ndb/src/mgmsrv/Services.hpp b/ndb/src/mgmsrv/Services.hpp
index e47820826b6..6a5f06a659e 100644
--- a/ndb/src/mgmsrv/Services.hpp
+++ b/ndb/src/mgmsrv/Services.hpp
@@ -28,7 +28,9 @@
/** Undefine this to remove backwards compatibility for "GET CONFIG". */
#define MGM_GET_CONFIG_BACKWARDS_COMPAT
-class MgmApiSession : public SocketServer::Session {
+class MgmApiSession : public SocketServer::Session
+{
+ static void stop_session_if_not_connected(SocketServer::Session *_s, void *data);
private:
typedef Parser<MgmApiSession> Parser_t;
@@ -37,10 +39,13 @@ private:
OutputStream *m_output;
Parser_t *m_parser;
MgmtSrvr::Allocated_resources *m_allocated_resources;
+ char m_err_str[1024];
void getConfig_common(Parser_t::Context &ctx,
const class Properties &args,
bool compat = false);
+ const char *get_error_text(int err_no)
+ { return m_mgmsrv.getErrorText(err_no, m_err_str, sizeof(m_err_str)); }
public:
MgmApiSession(class MgmtSrvr & mgm, NDB_SOCKET_TYPE sock);
@@ -84,6 +89,9 @@ public:
void setParameter(Parser_t::Context &ctx, const class Properties &args);
void listen_event(Parser_t::Context &ctx, const class Properties &args);
+
+ void purge_stale_sessions(Parser_t::Context &ctx, const class Properties &args);
+ void check_connection(Parser_t::Context &ctx, const class Properties &args);
void repCommand(Parser_t::Context &ctx, const class Properties &args);
};
diff --git a/ndb/src/mgmsrv/main.cpp b/ndb/src/mgmsrv/main.cpp
index 5ee48e4cfcc..64a2cb35c1f 100644
--- a/ndb/src/mgmsrv/main.cpp
+++ b/ndb/src/mgmsrv/main.cpp
@@ -15,6 +15,7 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <ndb_opts.h>
#include "MgmtSrvr.hpp"
#include "EventLogger.hpp"
@@ -33,7 +34,6 @@
#include <ndb_version.h>
#include <ConfigRetriever.hpp>
#include <mgmapi_config_parameters.h>
-#include <getarg.h>
#include <NdbAutoPtr.hpp>
@@ -62,7 +62,6 @@ struct MgmGlobals {
int non_interactive;
int interactive;
const char * config_filename;
- const char * local_config_filename;
/** Stuff found in environment or in local config */
NodeId localNodeId;
@@ -70,9 +69,6 @@ struct MgmGlobals {
char * interface_name;
int port;
- /** The configuration of the cluster */
- Config * cluster_config;
-
/** The Mgmt Server */
MgmtSrvr * mgmObject;
@@ -83,13 +79,9 @@ struct MgmGlobals {
int g_no_nodeid_checks= 0;
static MgmGlobals glob;
-
/******************************************************************************
* Function prototypes
******************************************************************************/
-static bool readLocalConfig();
-static bool readGlobalConfig();
-
/**
* Global variables
*/
@@ -97,41 +89,82 @@ bool g_StopServer;
extern EventLogger g_EventLogger;
extern int global_mgmt_server_check;
-int _print_version = 0;
-#ifndef DBUG_OFF
-const char *debug_option= 0;
-#endif
+static char *opt_connect_str= 0;
-struct getargs args[] = {
- { "version", 'v', arg_flag, &_print_version,
- "Print ndb_mgmd version",""},
- { "config-file", 'c', arg_string, &glob.config_filename,
- "Specify cluster configuration file (default config.ini if available)",
- "filename"},
+static struct my_option my_long_options[] =
+{
#ifndef DBUG_OFF
- { "debug", 0, arg_string, &debug_option,
- "Specify debug options e.g. d:t:i:o,out.trace", "options"},
+ { "debug", '#', "Output debug log. Often this is 'd:t:o,filename'.",
+ 0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0 },
#endif
- { "daemon", 'd', arg_flag, &glob.daemon,
- "Run ndb_mgmd in daemon mode (default)",""},
- { NULL, 'l', arg_string, &glob.local_config_filename,
- "Specify configuration file connect string (default Ndb.cfg if available)",
- "filename"},
- { "interactive", 0, arg_flag, &glob.interactive,
- "Run interactive. Not supported but provided for testing purposes", ""},
- { "no-nodeid-checks", 0, arg_flag, &g_no_nodeid_checks,
- "Do not provide any node id checks", ""},
- { "nodaemon", 0, arg_flag, &glob.non_interactive,
- "Don't run as daemon, but don't read from stdin", "non-interactive"}
+ { "usage", '?', "Display this help and exit.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "help", '?', "Display this help and exit.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "version", 'V', "Output version information and exit.", 0, 0, 0,
+ GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "connect-string", 1023,
+ "Set connect string for connecting to ndb_mgmd. "
+ "<constr>=\"host=<hostname:port>[;nodeid=<id>]\". "
+ "Overides specifying entries in NDB_CONNECTSTRING and config file",
+ (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "config-file", 'f', "Specify cluster configuration file",
+ (gptr*) &glob.config_filename, (gptr*) &glob.config_filename, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "daemon", 'd', "Run ndb_mgmd in daemon mode (default)",
+ (gptr*) &glob.daemon, (gptr*) &glob.daemon, 0,
+ GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
+ { "interactive", 256, "Run interactive. Not supported but provided for testing purposes",
+ (gptr*) &glob.interactive, (gptr*) &glob.interactive, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "no-nodeid-checks", 257, "Do not provide any node id checks",
+ (gptr*) &g_no_nodeid_checks, (gptr*) &g_no_nodeid_checks, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "nodaemon", 258, "Don't run as daemon, but don't read from stdin",
+ (gptr*) &glob.non_interactive, (gptr*) &glob.non_interactive, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-
-int num_args = sizeof(args) / sizeof(args[0]);
+static void short_usage_sub(void)
+{
+ printf("Usage: %s [OPTIONS]\n", my_progname);
+}
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
+ short_usage_sub();
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_mgmd.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ }
+ return 0;
+}
/*
* MAIN
*/
-NDB_MAIN(mgmsrv){
- ndb_init();
+int main(int argc, char** argv)
+{
+ NDB_INIT(argv[0]);
/**
* OSE specific. Enable shared ownership of file system resources.
@@ -144,57 +177,32 @@ NDB_MAIN(mgmsrv){
global_mgmt_server_check = 1;
- int optind = 0;
- if(getarg(args, num_args, argc, argv, &optind)) {
- arg_printusage(args, num_args, progname, "");
- exit(1);
- }
+ const char *load_default_groups[]= { "mysql_cluster","ndb_mgmd",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ exit(ho_error);
if (glob.interactive ||
glob.non_interactive) {
glob.daemon= 0;
}
-#ifndef DBUG_OFF
- if (debug_option)
- DBUG_PUSH(debug_option);
-#endif
-
- if (_print_version) {
- ndbPrintVersion();
- exit(0);
- }
-
- if(glob.config_filename == NULL) {
- glob.config_filename= "config.ini";
- }
glob.socketServer = new SocketServer();
MgmApiService * mapi = new MgmApiService();
- /****************************
- * Read configuration files *
- ****************************/
- LocalConfig local_config;
- if(!local_config.init(0,glob.local_config_filename)){
- local_config.printError();
- goto error_end;
- }
- glob.localNodeId = local_config._ownNodeId;
+ glob.mgmObject = new MgmtSrvr(glob.socketServer,
+ glob.config_filename,
+ opt_connect_str);
- if (!readGlobalConfig())
+ if (glob.mgmObject->init())
goto error_end;
- glob.mgmObject = new MgmtSrvr(glob.localNodeId,
- BaseString(glob.config_filename),
- local_config,
- glob.cluster_config);
-
chdir(NdbConfig_get_path(0));
- glob.cluster_config = 0;
glob.localNodeId= glob.mgmObject->getOwnNodeId();
-
if (glob.localNodeId == 0) {
goto error_end;
}
@@ -305,9 +313,7 @@ MgmGlobals::MgmGlobals(){
// Default values
port = 0;
config_filename = NULL;
- local_config_filename = NULL;
interface_name = 0;
- cluster_config = 0;
daemon = 1;
non_interactive = 0;
interactive = 0;
@@ -320,27 +326,6 @@ MgmGlobals::~MgmGlobals(){
delete socketServer;
if (mgmObject)
delete mgmObject;
- if (cluster_config)
- delete cluster_config;
if (interface_name)
free(interface_name);
}
-
-/**
- * @fn readGlobalConfig
- * @param glob : Global variables
- * @return true if success, false otherwise.
- */
-static bool
-readGlobalConfig() {
- if(glob.config_filename == NULL)
- return false;
-
- /* Use config file */
- InitConfigFileParser parser;
- glob.cluster_config = parser.parseConfig(glob.config_filename);
- if(glob.cluster_config == 0){
- return false;
- }
- return true;
-}
diff --git a/ndb/src/ndbapi/Makefile_old b/ndb/src/ndbapi/Makefile_old
deleted file mode 100644
index 54de9ba96f4..00000000000
--- a/ndb/src/ndbapi/Makefile_old
+++ /dev/null
@@ -1,60 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapi
-
-PIC_ARCHIVE := Y
-NONPIC_ARCHIVE := Y
-ARCHIVE_TARGET := ndbapi
-
-A_LIB := Y
-SO_LIB := Y
-PIC_LIB := Y
-LIB_TARGET := NDB_API
-
-LIB_TARGET_ARCHIVES := $(ARCHIVE_TARGET) \
- transporter \
- general \
- signaldataprint \
- mgmapi mgmsrvcommon \
- portlib \
- logger \
- trace
-
-DIRS := signal-sender
-
-CFLAGS_TransporterFacade.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
-CFLAGS_ClusterMgr.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
-
-# Source files of non-templated classes (.cpp files)
-SOURCES = \
- TransporterFacade.cpp \
- ClusterMgr.cpp \
- Ndb.cpp \
- NdbPoolImpl.cpp NdbPool.cpp \
- Ndblist.cpp \
- Ndbif.cpp \
- Ndbinit.cpp \
- ndberror.c Ndberr.cpp NdbErrorOut.cpp \
- NdbConnection.cpp \
- NdbConnectionScan.cpp \
- NdbOperation.cpp \
- NdbOperationSearch.cpp \
- NdbOperationInt.cpp \
- NdbOperationDefine.cpp \
- NdbOperationExec.cpp \
- NdbResultSet.cpp \
- NdbScanOperation.cpp NdbScanFilter.cpp \
- NdbIndexOperation.cpp \
- NdbEventOperation.cpp \
- NdbEventOperationImpl.cpp \
- NdbApiSignal.cpp \
- NdbRecAttr.cpp \
- NdbUtil.cpp \
- NdbReceiver.cpp \
- NdbDictionary.cpp NdbDictionaryImpl.cpp DictCache.cpp
- NdbBlob.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
-###
-# Backward compatible
diff --git a/ndb/src/ndbapi/Ndb.cpp b/ndb/src/ndbapi/Ndb.cpp
index d7b8a695fe2..75ae539fc8b 100644
--- a/ndb/src/ndbapi/Ndb.cpp
+++ b/ndb/src/ndbapi/Ndb.cpp
@@ -1386,6 +1386,7 @@ Ndb::printState(const char* fmt, ...)
va_end(ap);
NdbMutex_Lock(ndb_print_state_mutex);
bool dups = false;
+ unsigned i;
ndbout << buf << " ndb=" << hex << this << dec;
#ifndef NDB_WIN32
ndbout << " thread=" << (int)pthread_self();
@@ -1406,21 +1407,21 @@ Ndb::printState(const char* fmt, ...)
ndbout << "!! DUPS !!" << endl;
dups = true;
}
- for (unsigned i = 0; i < theNoOfPreparedTransactions; i++)
+ for (i = 0; i < theNoOfPreparedTransactions; i++)
thePreparedTransactionsArray[i]->printState();
ndbout << "sent: " << theNoOfSentTransactions<< endl;
if (checkdups(theSentTransactionsArray, theNoOfSentTransactions)) {
ndbout << "!! DUPS !!" << endl;
dups = true;
}
- for (unsigned i = 0; i < theNoOfSentTransactions; i++)
+ for (i = 0; i < theNoOfSentTransactions; i++)
theSentTransactionsArray[i]->printState();
ndbout << "completed: " << theNoOfCompletedTransactions<< endl;
if (checkdups(theCompletedTransactionsArray, theNoOfCompletedTransactions)) {
ndbout << "!! DUPS !!" << endl;
dups = true;
}
- for (unsigned i = 0; i < theNoOfCompletedTransactions; i++)
+ for (i = 0; i < theNoOfCompletedTransactions; i++)
theCompletedTransactionsArray[i]->printState();
NdbMutex_Unlock(ndb_print_state_mutex);
}
diff --git a/ndb/src/ndbapi/NdbApiSignal.cpp b/ndb/src/ndbapi/NdbApiSignal.cpp
index a1d34896968..b1671e593e1 100644
--- a/ndb/src/ndbapi/NdbApiSignal.cpp
+++ b/ndb/src/ndbapi/NdbApiSignal.cpp
@@ -213,7 +213,7 @@ NdbApiSignal::setSignal(int aNdbSignalType)
theTrace = TestOrd::TraceAPI;
theReceiversBlockNumber = DBTC;
theVerId_signalNumber = GSN_TCINDXREQ;
- theLength = TcIndxReq::SignalLength;
+ theLength = TcKeyReq::SignalLength;
}
break;
diff --git a/ndb/src/ndbapi/NdbBlob.cpp b/ndb/src/ndbapi/NdbBlob.cpp
index feab95d8ca5..b75af260105 100644
--- a/ndb/src/ndbapi/NdbBlob.cpp
+++ b/ndb/src/ndbapi/NdbBlob.cpp
@@ -33,21 +33,24 @@
ndbout << prefix << " " << hex << (void*)this << " " << cname; \
ndbout << " " << dec << __LINE__ << " " << x << " " << *this << endl; \
} while (0)
-#else
-#define DBG(x)
-#endif
static char*
ndb_blob_debug(const Uint32* data, unsigned size)
{
- static char buf[128 + 1]; // MT irrelevant
+ static char buf[200]; // MT irrelevant
buf[0] = 0;
- for (unsigned i = 0; i < size && i < 128 / 4; i++) {
- sprintf(buf + strlen(buf), "%*s%08x", i != 0, "", data[i]);
+ for (unsigned i = 0; i < size; i++) {
+ unsigned n = strlen(buf);
+ if (n + 10 < sizeof(buf))
+ sprintf(buf + n, "%*s%08x", i != 0, "", data[i]);
}
return buf;
}
+#else
+#define DBG(x)
+#endif
+
/*
* Reading index table directly (as a table) is faster but there are
* bugs or limitations. Keep the code and make possible to choose.
@@ -94,22 +97,24 @@ NdbBlob::getBlobTable(NdbTableImpl& bt, const NdbTableImpl* t, const NdbColumnIm
bt.setName(btname);
bt.setLogging(t->getLogging());
bt.setFragmentType(t->getFragmentType());
- { NdbDictionary::Column bc("DIST");
+ { NdbDictionary::Column bc("PK");
bc.setType(NdbDictionary::Column::Unsigned);
+ assert(t->m_keyLenInWords != 0);
+ bc.setLength(t->m_keyLenInWords);
bc.setPrimaryKey(true);
bc.setDistributionKey(true);
bt.addColumn(bc);
}
- { NdbDictionary::Column bc("PART");
+ { NdbDictionary::Column bc("DIST");
bc.setType(NdbDictionary::Column::Unsigned);
bc.setPrimaryKey(true);
+ bc.setDistributionKey(true);
bt.addColumn(bc);
}
- { NdbDictionary::Column bc("PK");
+ { NdbDictionary::Column bc("PART");
bc.setType(NdbDictionary::Column::Unsigned);
- assert(t->m_sizeOfKeysInWords != 0);
- bc.setLength(t->m_sizeOfKeysInWords);
bc.setPrimaryKey(true);
+ bc.setDistributionKey(false);
bt.addColumn(bc);
}
{ NdbDictionary::Column bc("DATA");
@@ -162,6 +167,7 @@ NdbBlob::init()
theHead = NULL;
theInlineData = NULL;
theHeadInlineRecAttr = NULL;
+ theHeadInlineReadOp = NULL;
theHeadInlineUpdateFlag = false;
theNullFlag = -1;
theLength = 0;
@@ -206,6 +212,13 @@ NdbBlob::Buf::alloc(unsigned n)
#endif
}
+void
+NdbBlob::Buf::copyfrom(const NdbBlob::Buf& src)
+{
+ assert(size == src.size);
+ memcpy(data, src.data, size);
+}
+
// classify operations (inline)
inline bool
@@ -226,6 +239,7 @@ NdbBlob::isKeyOp()
return
theNdbOp->theOperationType == NdbOperation::InsertRequest ||
theNdbOp->theOperationType == NdbOperation::UpdateRequest ||
+ theNdbOp->theOperationType == NdbOperation::WriteRequest ||
theNdbOp->theOperationType == NdbOperation::ReadRequest ||
theNdbOp->theOperationType == NdbOperation::ReadExclusive ||
theNdbOp->theOperationType == NdbOperation::DeleteRequest;
@@ -254,6 +268,13 @@ NdbBlob::isUpdateOp()
}
inline bool
+NdbBlob::isWriteOp()
+{
+ return
+ theNdbOp->theOperationType == NdbOperation::WriteRequest;
+}
+
+inline bool
NdbBlob::isDeleteOp()
{
return
@@ -325,7 +346,7 @@ int
NdbBlob::setTableKeyValue(NdbOperation* anOp)
{
const Uint32* data = (const Uint32*)theKeyBuf.data;
- DBG("setTableKeyValue key=" << ndb_blob_debug(data, theTable->m_sizeOfKeysInWords));
+ DBG("setTableKeyValue key=" << ndb_blob_debug(data, theTable->m_keyLenInWords));
const unsigned columns = theTable->m_columns.size();
unsigned pos = 0;
for (unsigned i = 0; i < columns; i++) {
@@ -348,7 +369,7 @@ int
NdbBlob::setAccessKeyValue(NdbOperation* anOp)
{
const Uint32* data = (const Uint32*)theAccessKeyBuf.data;
- DBG("setAccessKeyValue key=" << ndb_blob_debug(data, theAccessTable->m_sizeOfKeysInWords));
+ DBG("setAccessKeyValue key=" << ndb_blob_debug(data, theAccessTable->m_keyLenInWords));
const unsigned columns = theAccessTable->m_columns.size();
unsigned pos = 0;
for (unsigned i = 0; i < columns; i++) {
@@ -371,11 +392,12 @@ int
NdbBlob::setPartKeyValue(NdbOperation* anOp, Uint32 part)
{
Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_sizeOfKeysInWords;
+ unsigned size = theTable->m_keyLenInWords;
DBG("setPartKeyValue dist=" << getDistKey(part) << " part=" << part << " key=" << ndb_blob_debug(data, size));
- if (anOp->equal((Uint32)0, getDistKey(part)) == -1 ||
- anOp->equal((Uint32)1, part) == -1 ||
- anOp->equal((Uint32)2, theKeyBuf.data) == -1) {
+ // TODO use attr ids after compatibility with 4.1.7 not needed
+ if (anOp->equal("PK", theKeyBuf.data) == -1 ||
+ anOp->equal("DIST", getDistKey(part)) == -1 ||
+ anOp->equal("PART", part) == -1) {
setErrorCode(anOp);
return -1;
}
@@ -401,7 +423,7 @@ NdbBlob::getHeadFromRecAttr()
theNullFlag = theHeadInlineRecAttr->isNULL();
assert(theNullFlag != -1);
theLength = ! theNullFlag ? theHead->length : 0;
- DBG("getHeadFromRecAttr out");
+ DBG("getHeadFromRecAttr [out]");
}
int
@@ -453,7 +475,7 @@ NdbBlob::setValue(const void* data, Uint32 bytes)
setErrorCode(ErrState);
return -1;
}
- if (! isInsertOp() && ! isUpdateOp()) {
+ if (! isInsertOp() && ! isUpdateOp() && ! isWriteOp()) {
setErrorCode(ErrUsage);
return -1;
}
@@ -466,11 +488,12 @@ NdbBlob::setValue(const void* data, Uint32 bytes)
theGetSetBytes = bytes;
if (isInsertOp()) {
// write inline part now
- if (theSetBuf != 0) {
- unsigned n = theGetSetBytes;
+ if (theSetBuf != NULL) {
+ Uint32 n = theGetSetBytes;
if (n > theInlineSize)
n = theInlineSize;
- if (writeDataPrivate(0, theSetBuf, n) == -1)
+ assert(thePos == 0);
+ if (writeDataPrivate(theSetBuf, n) == -1)
return -1;
} else {
theNullFlag = true;
@@ -555,7 +578,7 @@ NdbBlob::getLength(Uint64& len)
int
NdbBlob::truncate(Uint64 length)
{
- DBG("truncate length=" << length);
+ DBG("truncate [in] length=" << length);
if (theNullFlag == -1) {
setErrorCode(ErrState);
return -1;
@@ -573,7 +596,10 @@ NdbBlob::truncate(Uint64 length)
}
theLength = length;
theHeadInlineUpdateFlag = true;
+ if (thePos > length)
+ thePos = length;
}
+ DBG("truncate [out]");
return 0;
}
@@ -610,32 +636,20 @@ NdbBlob::setPos(Uint64 pos)
int
NdbBlob::readData(void* data, Uint32& bytes)
{
- if (readData(thePos, data, bytes) == -1)
- return -1;
- thePos += bytes;
- assert(thePos <= theLength);
- return 0;
-}
-
-int
-NdbBlob::readData(Uint64 pos, void* data, Uint32& bytes)
-{
if (theState != Active) {
setErrorCode(ErrState);
return -1;
}
char* buf = static_cast<char*>(data);
- return readDataPrivate(pos, buf, bytes);
+ return readDataPrivate(buf, bytes);
}
int
-NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
+NdbBlob::readDataPrivate(char* buf, Uint32& bytes)
{
- DBG("readData pos=" << pos << " bytes=" << bytes);
- if (pos > theLength) {
- setErrorCode(ErrSeek);
- return -1;
- }
+ DBG("readData [in] bytes=" << bytes);
+ assert(thePos <= theLength);
+ Uint64 pos = thePos;
if (bytes > theLength - pos)
bytes = theLength - pos;
Uint32 len = bytes;
@@ -665,7 +679,6 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
if (readParts(thePartBuf.data, part, 1) == -1)
return -1;
// need result now
- DBG("execute pending part reads");
if (executePendingBlobReads() == -1)
return -1;
Uint32 n = thePartSize - off;
@@ -699,7 +712,6 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
if (readParts(thePartBuf.data, part, 1) == -1)
return -1;
// need result now
- DBG("execute pending part reads");
if (executePendingBlobReads() == -1)
return -1;
memcpy(buf, thePartBuf.data, len);
@@ -709,38 +721,29 @@ NdbBlob::readDataPrivate(Uint64 pos, char* buf, Uint32& bytes)
len -= n;
}
assert(len == 0);
- return 0;
-}
-
-int
-NdbBlob::writeData(const void* data, Uint32 bytes)
-{
- if (writeData(thePos, data, bytes) == -1)
- return -1;
- thePos += bytes;
+ thePos = pos;
assert(thePos <= theLength);
+ DBG("readData [out]");
return 0;
}
int
-NdbBlob::writeData(Uint64 pos, const void* data, Uint32 bytes)
+NdbBlob::writeData(const void* data, Uint32 bytes)
{
if (theState != Active) {
setErrorCode(ErrState);
return -1;
}
const char* buf = static_cast<const char*>(data);
- return writeDataPrivate(pos, buf, bytes);
+ return writeDataPrivate(buf, bytes);
}
int
-NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes)
+NdbBlob::writeDataPrivate(const char* buf, Uint32 bytes)
{
- DBG("writeData pos=" << pos << " bytes=" << bytes);
- if (pos > theLength) {
- setErrorCode(ErrSeek);
- return -1;
- }
+ DBG("writeData [in] bytes=" << bytes);
+ assert(thePos <= theLength);
+ Uint64 pos = thePos;
Uint32 len = bytes;
// any write makes blob not NULL
if (theNullFlag) {
@@ -771,14 +774,12 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes)
if (off != 0) {
DBG("partial first block pos=" << pos << " len=" << len);
// flush writes to guarantee correct read
- DBG("execute pending part writes");
if (executePendingBlobWrites() == -1)
return -1;
Uint32 part = (pos - theInlineSize) / thePartSize;
if (readParts(thePartBuf.data, part, 1) == -1)
return -1;
// need result now
- DBG("execute pending part reafs");
if (executePendingBlobReads() == -1)
return -1;
Uint32 n = thePartSize - off;
@@ -822,13 +823,11 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes)
Uint32 part = (pos - theInlineSize) / thePartSize;
if (theLength > pos + len) {
// flush writes to guarantee correct read
- DBG("execute pending part writes");
if (executePendingBlobWrites() == -1)
return -1;
if (readParts(thePartBuf.data, part, 1) == -1)
return -1;
// need result now
- DBG("execute pending part reads");
if (executePendingBlobReads() == -1)
return -1;
memcpy(thePartBuf.data, buf, len);
@@ -855,14 +854,16 @@ NdbBlob::writeDataPrivate(Uint64 pos, const char* buf, Uint32 bytes)
theLength = pos;
theHeadInlineUpdateFlag = true;
}
- DBG("writeData out");
+ thePos = pos;
+ assert(thePos <= theLength);
+ DBG("writeData [out]");
return 0;
}
int
NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
{
- DBG("readParts part=" << part << " count=" << count);
+ DBG("readParts [in] part=" << part << " count=" << count);
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -873,6 +874,7 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
setErrorCode(tOp);
return -1;
}
+ tOp->m_abortOption = AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::ReadRequest);
@@ -884,7 +886,7 @@ NdbBlob::readParts(char* buf, Uint32 part, Uint32 count)
int
NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
{
- DBG("insertParts part=" << part << " count=" << count);
+ DBG("insertParts [in] part=" << part << " count=" << count);
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -895,6 +897,7 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
setErrorCode(tOp);
return -1;
}
+ tOp->m_abortOption = AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::InsertRequest);
@@ -906,7 +909,7 @@ NdbBlob::insertParts(const char* buf, Uint32 part, Uint32 count)
int
NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
{
- DBG("updateParts part=" << part << " count=" << count);
+ DBG("updateParts [in] part=" << part << " count=" << count);
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -917,6 +920,7 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
setErrorCode(tOp);
return -1;
}
+ tOp->m_abortOption = AbortOnError;
buf += thePartSize;
n++;
thePendingBlobOps |= (1 << NdbOperation::UpdateRequest);
@@ -928,7 +932,7 @@ NdbBlob::updateParts(const char* buf, Uint32 part, Uint32 count)
int
NdbBlob::deleteParts(Uint32 part, Uint32 count)
{
- DBG("deleteParts part=" << part << " count=" << count);
+ DBG("deleteParts [in] part=" << part << " count=" << count);
Uint32 n = 0;
while (n < count) {
NdbOperation* tOp = theNdbCon->getNdbOperation(theBlobTable);
@@ -938,6 +942,7 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count)
setErrorCode(tOp);
return -1;
}
+ tOp->m_abortOption = AbortOnError;
n++;
thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
theNdbCon->thePendingBlobOps |= (1 << NdbOperation::DeleteRequest);
@@ -945,6 +950,59 @@ NdbBlob::deleteParts(Uint32 part, Uint32 count)
return 0;
}
+/*
+ * Number of blob parts not known. Used to check for race condition
+ * when writeTuple is used for insert. Deletes all parts found.
+ */
+int
+NdbBlob::deletePartsUnknown(Uint32 part)
+{
+ DBG("deletePartsUnknown [in] part=" << part << " count=all");
+ static const unsigned maxbat = 256;
+ static const unsigned minbat = 1;
+ unsigned bat = minbat;
+ NdbOperation* tOpList[maxbat];
+ Uint32 count = 0;
+ while (true) {
+ Uint32 n;
+ n = 0;
+ while (n < bat) {
+ NdbOperation*& tOp = tOpList[n]; // ref
+ tOp = theNdbCon->getNdbOperation(theBlobTable);
+ if (tOp == NULL ||
+ tOp->deleteTuple() == -1 ||
+ setPartKeyValue(tOp, part + count + n) == -1) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ tOp->m_abortOption = IgnoreError;
+ n++;
+ }
+ DBG("deletePartsUnknown: executeNoBlobs [in] bat=" << bat);
+ if (theNdbCon->executeNoBlobs(NoCommit) == -1)
+ return -1;
+ DBG("deletePartsUnknown: executeNoBlobs [out]");
+ n = 0;
+ while (n < bat) {
+ NdbOperation* tOp = tOpList[n];
+ if (tOp->theError.code != 0) {
+ if (tOp->theError.code != 626) {
+ setErrorCode(tOp);
+ return -1;
+ }
+ // first non-existent part
+ DBG("deletePartsUnknown [out] count=" << count);
+ return 0;
+ }
+ n++;
+ count++;
+ }
+ bat *= 4;
+ if (bat > maxbat)
+ bat = maxbat;
+ }
+}
+
// pending ops
int
@@ -952,8 +1010,10 @@ NdbBlob::executePendingBlobReads()
{
Uint8 flags = (1 << NdbOperation::ReadRequest);
if (thePendingBlobOps & flags) {
+ DBG("executePendingBlobReads: executeNoBlobs [in]");
if (theNdbCon->executeNoBlobs(NoCommit) == -1)
return -1;
+ DBG("executePendingBlobReads: executeNoBlobs [out]");
thePendingBlobOps = 0;
theNdbCon->thePendingBlobOps = 0;
}
@@ -965,8 +1025,10 @@ NdbBlob::executePendingBlobWrites()
{
Uint8 flags = 0xFF & ~(1 << NdbOperation::ReadRequest);
if (thePendingBlobOps & flags) {
+ DBG("executePendingBlobWrites: executeNoBlobs [in]");
if (theNdbCon->executeNoBlobs(NoCommit) == -1)
return -1;
+ DBG("executePendingBlobWrites: executeNoBlobs [out]");
thePendingBlobOps = 0;
theNdbCon->thePendingBlobOps = 0;
}
@@ -978,10 +1040,10 @@ NdbBlob::executePendingBlobWrites()
int
NdbBlob::invokeActiveHook()
{
- DBG("invokeActiveHook");
+ DBG("invokeActiveHook [in]");
assert(theState == Active && theActiveHook != NULL);
int ret = (*theActiveHook)(this, theActiveHookArg);
- DBG("invokeActiveHook ret=" << ret);
+ DBG("invokeActiveHook [out] ret=" << ret);
if (ret != 0) {
// no error is set on blob level
return -1;
@@ -1007,7 +1069,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
theTable = anOp->m_currentTable;
theAccessTable = anOp->m_accessTable;
theColumn = aColumn;
- DBG("atPrepare");
+ DBG("atPrepare [in]");
NdbDictionary::Column::Type partType = NdbDictionary::Column::Undefined;
switch (theColumn->getType()) {
case NdbDictionary::Column::Blob:
@@ -1043,9 +1105,10 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
theBlobTable = &NdbTableImpl::getImpl(*bt);
}
// buffers
- theKeyBuf.alloc(theTable->m_sizeOfKeysInWords << 2);
- theAccessKeyBuf.alloc(theAccessTable->m_sizeOfKeysInWords << 2);
+ theKeyBuf.alloc(theTable->m_keyLenInWords << 2);
+ theAccessKeyBuf.alloc(theAccessTable->m_keyLenInWords << 2);
theHeadInlineBuf.alloc(sizeof(Head) + theInlineSize);
+ theHeadInlineCopyBuf.alloc(sizeof(Head) + theInlineSize);
thePartBuf.alloc(thePartSize);
theHead = (Head*)theHeadInlineBuf.data;
theInlineData = theHeadInlineBuf.data + sizeof(Head);
@@ -1055,7 +1118,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
if (isTableOp()) {
// get table key
Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_sizeOfKeysInWords;
+ unsigned size = theTable->m_keyLenInWords;
if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
setErrorCode(ErrUsage);
return -1;
@@ -1064,7 +1127,7 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
if (isIndexOp()) {
// get index key
Uint32* data = (Uint32*)theAccessKeyBuf.data;
- unsigned size = theAccessTable->m_sizeOfKeysInWords;
+ unsigned size = theAccessTable->m_keyLenInWords;
if (theNdbOp->getKeyFromTCREQ(data, size) == -1) {
setErrorCode(ErrUsage);
return -1;
@@ -1080,6 +1143,12 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
theNullFlag = true;
theLength = 0;
}
+ if (isWriteOp()) {
+ // becomes NULL unless set before execute
+ theNullFlag = true;
+ theLength = 0;
+ theHeadInlineUpdateFlag = true;
+ }
supportedOp = true;
}
if (isScanOp()) {
@@ -1093,19 +1162,21 @@ NdbBlob::atPrepare(NdbConnection* aCon, NdbOperation* anOp, const NdbColumnImpl*
return -1;
}
setState(Prepared);
- DBG("atPrepare out");
+ DBG("atPrepare [out]");
return 0;
}
/*
* Before execute of prepared operation. May add new operations before
* this one. May ask that this operation and all before it (a "batch")
- * is executed immediately in no-commit mode.
+ * is executed immediately in no-commit mode. In this case remaining
+ * prepared operations are saved in a separate list. They are added
+ * back after postExecute.
*/
int
NdbBlob::preExecute(ExecType anExecType, bool& batch)
{
- DBG("preExecute");
+ DBG("preExecute [in]");
if (theState == Invalid)
return -1;
assert(theState == Prepared);
@@ -1120,11 +1191,11 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
if (isInsertOp()) {
if (theSetFlag && theGetSetBytes > theInlineSize) {
// add ops to write rest of a setValue
- assert(theSetBuf != 0);
- Uint64 pos = theInlineSize;
+ assert(theSetBuf != NULL);
const char* buf = theSetBuf + theInlineSize;
Uint32 bytes = theGetSetBytes - theInlineSize;
- if (writeDataPrivate(pos, buf, bytes) == -1)
+ assert(thePos == theInlineSize);
+ if (writeDataPrivate(buf, bytes) == -1)
return -1;
if (theHeadInlineUpdateFlag) {
// add an operation to update head+inline
@@ -1136,11 +1207,12 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setErrorCode(ErrAbort);
return -1;
}
+ DBG("add op to update head+inline");
}
}
}
if (isTableOp()) {
- if (isUpdateOp() || isDeleteOp()) {
+ if (isUpdateOp() || isWriteOp() || isDeleteOp()) {
// add operation before this one to read head+inline
NdbOperation* tOp = theNdbCon->getNdbOperation(theTable, theNdbOp);
if (tOp == NULL ||
@@ -1150,8 +1222,13 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setErrorCode(tOp);
return -1;
}
+ if (isWriteOp()) {
+ tOp->m_abortOption = IgnoreError;
+ }
+ theHeadInlineReadOp = tOp;
// execute immediately
batch = true;
+ DBG("add op before to read head+inline");
}
}
if (isIndexOp()) {
@@ -1170,7 +1247,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
return -1;
}
} else {
- NdbOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp);
+ NdbIndexOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp);
if (tOp == NULL ||
tOp->readTuple() == -1 ||
setAccessKeyValue(tOp) == -1 ||
@@ -1180,6 +1257,7 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
}
}
}
+ DBG("added op before to read table key");
if (isUpdateOp() || isDeleteOp()) {
// add op before this one to read head+inline via index
NdbIndexOperation* tOp = theNdbCon->getNdbIndexOperation(theAccessTable->m_index, theTable, theNdbOp);
@@ -1190,15 +1268,43 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
setErrorCode(tOp);
return -1;
}
+ if (isWriteOp()) {
+ tOp->m_abortOption = IgnoreError;
+ }
+ theHeadInlineReadOp = tOp;
// execute immediately
batch = true;
+ DBG("added index op before to read head+inline");
+ }
+ if (isWriteOp()) {
+ // XXX until IgnoreError fixed for index op
+ batch = true;
+ }
+ }
+ if (isWriteOp()) {
+ if (theSetFlag) {
+ // write head+inline now
+ theNullFlag = true;
+ theLength = 0;
+ if (theSetBuf != NULL) {
+ Uint32 n = theGetSetBytes;
+ if (n > theInlineSize)
+ n = theInlineSize;
+ assert(thePos == 0);
+ if (writeDataPrivate(theSetBuf, n) == -1)
+ return -1;
+ }
+ if (setHeadInlineValue(theNdbOp) == -1)
+ return -1;
+ // the read op before us may overwrite
+ theHeadInlineCopyBuf.copyfrom(theHeadInlineBuf);
}
}
if (theActiveHook != NULL) {
// need blob head for callback
batch = true;
}
- DBG("preExecute out batch=" << batch);
+ DBG("preExecute [out] batch=" << batch);
return 0;
}
@@ -1211,15 +1317,16 @@ NdbBlob::preExecute(ExecType anExecType, bool& batch)
int
NdbBlob::postExecute(ExecType anExecType)
{
- DBG("postExecute type=" << anExecType);
+ DBG("postExecute [in] type=" << anExecType);
if (theState == Invalid)
return -1;
if (theState == Active) {
setState(anExecType == NoCommit ? Active : Closed);
- DBG("postExecute skip");
+ DBG("postExecute [skip]");
return 0;
}
assert(theState == Prepared);
+ setState(anExecType == NoCommit ? Active : Closed);
assert(isKeyOp());
if (isIndexOp()) {
NdbBlob* tFirstBlob = theNdbOp->theBlobList;
@@ -1231,22 +1338,13 @@ NdbBlob::postExecute(ExecType anExecType)
}
if (isReadOp()) {
getHeadFromRecAttr();
- if (theGetFlag && theGetSetBytes > 0) {
- // copy inline bytes to user buffer
- assert(theGetBuf != NULL);
- unsigned n = theGetSetBytes;
- if (n > theInlineSize)
- n = theInlineSize;
- memcpy(theGetBuf, theInlineData, n);
- }
- if (theGetFlag && theGetSetBytes > theInlineSize) {
- // add ops to read rest of a getValue
- assert(anExecType == NoCommit);
- assert(theGetBuf != 0);
- Uint64 pos = theInlineSize;
- char* buf = theGetBuf + theInlineSize;
- Uint32 bytes = theGetSetBytes - theInlineSize;
- if (readDataPrivate(pos, buf, bytes) == -1)
+ if (setPos(0) == -1)
+ return -1;
+ if (theGetFlag) {
+ assert(theGetSetBytes == 0 || theGetBuf != 0);
+ assert(theGetSetBytes <= theInlineSize || anExecType == NoCommit);
+ Uint32 bytes = theGetSetBytes;
+ if (readDataPrivate(theGetBuf, bytes) == -1)
return -1;
}
}
@@ -1255,10 +1353,11 @@ NdbBlob::postExecute(ExecType anExecType)
getHeadFromRecAttr();
if (theSetFlag) {
// setValue overwrites everything
- if (theSetBuf != 0) {
+ if (theSetBuf != NULL) {
if (truncate(0) == -1)
return -1;
- if (writeDataPrivate(0, theSetBuf, theGetSetBytes) == -1)
+ assert(thePos == 0);
+ if (writeDataPrivate(theSetBuf, theGetSetBytes) == -1)
return -1;
} else {
if (setNull() == -1)
@@ -1266,6 +1365,57 @@ NdbBlob::postExecute(ExecType anExecType)
}
}
}
+ if (isWriteOp() && isTableOp()) {
+ assert(anExecType == NoCommit);
+ if (theHeadInlineReadOp->theError.code == 0) {
+ int tNullFlag = theNullFlag;
+ Uint64 tLength = theLength;
+ Uint64 tPos = thePos;
+ getHeadFromRecAttr();
+ DBG("tuple found");
+ if (truncate(0) == -1)
+ return -1;
+ // restore previous head+inline
+ theHeadInlineBuf.copyfrom(theHeadInlineCopyBuf);
+ theNullFlag = tNullFlag;
+ theLength = tLength;
+ thePos = tPos;
+ } else {
+ if (theHeadInlineReadOp->theError.code != 626) {
+ setErrorCode(theHeadInlineReadOp);
+ return -1;
+ }
+ DBG("tuple not found");
+ /*
+ * Read found no tuple but it is possible that a tuple was
+ * created after the read by another transaction. Delete all
+ * blob parts which may exist.
+ */
+ if (deletePartsUnknown(0) == -1)
+ return -1;
+ }
+ if (theSetFlag && theGetSetBytes > theInlineSize) {
+ assert(theSetBuf != NULL);
+ const char* buf = theSetBuf + theInlineSize;
+ Uint32 bytes = theGetSetBytes - theInlineSize;
+ assert(thePos == theInlineSize);
+ if (writeDataPrivate(buf, bytes) == -1)
+ return -1;
+ }
+ }
+ if (isWriteOp() && isIndexOp()) {
+ // XXX until IgnoreError fixed for index op
+ if (deletePartsUnknown(0) == -1)
+ return -1;
+ if (theSetFlag && theGetSetBytes > theInlineSize) {
+ assert(theSetBuf != NULL);
+ const char* buf = theSetBuf + theInlineSize;
+ Uint32 bytes = theGetSetBytes - theInlineSize;
+ assert(thePos == theInlineSize);
+ if (writeDataPrivate(buf, bytes) == -1)
+ return -1;
+ }
+ }
if (isDeleteOp()) {
assert(anExecType == NoCommit);
getHeadFromRecAttr();
@@ -1278,7 +1428,19 @@ NdbBlob::postExecute(ExecType anExecType)
if (invokeActiveHook() == -1)
return -1;
}
- DBG("postExecute out");
+ if (anExecType == NoCommit && theHeadInlineUpdateFlag) {
+ NdbOperation* tOp = theNdbCon->getNdbOperation(theTable);
+ if (tOp == NULL ||
+ tOp->updateTuple() == -1 ||
+ setTableKeyValue(tOp) == -1 ||
+ setHeadInlineValue(tOp) == -1) {
+ setErrorCode(ErrAbort);
+ return -1;
+ }
+ tOp->m_abortOption = AbortOnError;
+ DBG("added op to update head+inline");
+ }
+ DBG("postExecute [out]");
return 0;
}
@@ -1289,12 +1451,12 @@ NdbBlob::postExecute(ExecType anExecType)
int
NdbBlob::preCommit()
{
- DBG("preCommit");
+ DBG("preCommit [in]");
if (theState == Invalid)
return -1;
assert(theState == Active);
assert(isKeyOp());
- if (isInsertOp() || isUpdateOp()) {
+ if (isInsertOp() || isUpdateOp() || isWriteOp()) {
if (theHeadInlineUpdateFlag) {
// add an operation to update head+inline
NdbOperation* tOp = theNdbCon->getNdbOperation(theTable);
@@ -1305,9 +1467,11 @@ NdbBlob::preCommit()
setErrorCode(ErrAbort);
return -1;
}
+ tOp->m_abortOption = AbortOnError;
+ DBG("added op to update head+inline");
}
}
- DBG("preCommit out");
+ DBG("preCommit [out]");
return 0;
}
@@ -1317,41 +1481,26 @@ NdbBlob::preCommit()
int
NdbBlob::atNextResult()
{
- DBG("atNextResult");
+ DBG("atNextResult [in]");
if (theState == Invalid)
return -1;
assert(isScanOp());
- getHeadFromRecAttr();
- // reset position
- thePos = 0;
// get primary key
{ Uint32* data = (Uint32*)theKeyBuf.data;
- unsigned size = theTable->m_sizeOfKeysInWords;
+ unsigned size = theTable->m_keyLenInWords;
if (((NdbScanOperation*)theNdbOp)->getKeyFromKEYINFO20(data, size) == -1) {
setErrorCode(ErrUsage);
return -1;
}
}
- if (! theNullFlag) {
- if (theGetFlag && theGetSetBytes > 0) {
- // copy inline bytes to user buffer
- assert(theGetBuf != NULL);
- unsigned n = theGetSetBytes;
- if (n > theLength)
- n = theLength;
- if (n > theInlineSize)
- n = theInlineSize;
- memcpy(theGetBuf, theInlineData, n);
- }
- if (theGetFlag && theGetSetBytes > theInlineSize && theLength > theInlineSize) {
- // add ops to read rest of a getValue
- assert(theGetBuf != 0);
- Uint64 pos = theInlineSize;
- char* buf = theGetBuf + theInlineSize;
- Uint32 bytes = theGetSetBytes - theInlineSize;
- if (readDataPrivate(pos, buf, bytes) == -1)
- return -1;
- }
+ getHeadFromRecAttr();
+ if (setPos(0) == -1)
+ return -1;
+ if (theGetFlag) {
+ assert(theGetSetBytes == 0 || theGetBuf != 0);
+ Uint32 bytes = theGetSetBytes;
+ if (readDataPrivate(theGetBuf, bytes) == -1)
+ return -1;
}
setState(Active);
// activation callback
@@ -1359,7 +1508,7 @@ NdbBlob::atNextResult()
if (invokeActiveHook() == -1)
return -1;
}
- DBG("atNextResult out");
+ DBG("atNextResult [out]");
return 0;
}
@@ -1444,7 +1593,8 @@ operator<<(NdbOut& out, const NdbBlob& blob)
ndbout << dec << " n=" << blob.theNullFlag;;
ndbout << dec << " l=" << blob.theLength;
ndbout << dec << " p=" << blob.thePos;
- ndbout << dec << " u=" << (Uint32) blob.theHeadInlineUpdateFlag;
+ ndbout << dec << " u=" << (Uint32)blob.theHeadInlineUpdateFlag;
+ ndbout << dec << " g=" << (Uint32)blob.theGetSetBytes;
return out;
}
#endif
diff --git a/ndb/src/ndbapi/NdbConnection.cpp b/ndb/src/ndbapi/NdbConnection.cpp
index 1457792cf28..167f51a5df0 100644
--- a/ndb/src/ndbapi/NdbConnection.cpp
+++ b/ndb/src/ndbapi/NdbConnection.cpp
@@ -55,6 +55,7 @@ NdbConnection::NdbConnection( Ndb* aNdb ) :
theFirstExecOpInList(NULL),
theLastExecOpInList(NULL),
theCompletedFirstOp(NULL),
+ theCompletedLastOp(NULL),
theNoOfOpSent(0),
theNoOfOpCompleted(0),
theNoOfOpFetched(0),
@@ -124,6 +125,7 @@ NdbConnection::init()
theLastExecOpInList = NULL;
theCompletedFirstOp = NULL;
+ theCompletedLastOp = NULL;
theGlobalCheckpointId = 0;
theCommitStatus = Started;
@@ -170,12 +172,14 @@ Remark: Sets an error code on the connection object from an
operation object.
*****************************************************************************/
void
-NdbConnection::setOperationErrorCodeAbort(int error)
+NdbConnection::setOperationErrorCodeAbort(int error, int abortOption)
{
DBUG_ENTER("NdbConnection::setOperationErrorCodeAbort");
+ if (abortOption == -1)
+ abortOption = m_abortOption;
if (theTransactionIsStarted == false) {
theCommitStatus = Aborted;
- } else if ((m_abortOption == AbortOnError) &&
+ } else if ((abortOption == AbortOnError) &&
(theCommitStatus != Committed) &&
(theCommitStatus != Aborted)) {
theCommitStatus = NeedAbort;
@@ -254,6 +258,8 @@ NdbConnection::handleExecuteCompletion()
if (tLastExecOp != NULL) {
tLastExecOp->next(theCompletedFirstOp);
theCompletedFirstOp = tFirstExecOp;
+ if (theCompletedLastOp == NULL)
+ theCompletedLastOp = tLastExecOp;
theFirstExecOpInList = NULL;
theLastExecOpInList = NULL;
}//if
@@ -290,6 +296,8 @@ NdbConnection::execute(ExecType aTypeOfExec,
ExecType tExecType;
NdbOperation* tPrepOp;
+ NdbOperation* tCompletedFirstOp = NULL;
+ NdbOperation* tCompletedLastOp = NULL;
int ret = 0;
do {
@@ -312,6 +320,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
}
tPrepOp = tPrepOp->next();
}
+
// save rest of prepared ops if batch
NdbOperation* tRestOp= 0;
NdbOperation* tLastOp= 0;
@@ -321,6 +330,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
tLastOp = theLastOpInList;
theLastOpInList = tPrepOp;
}
+
if (tExecType == Commit) {
NdbOperation* tOp = theCompletedFirstOp;
while (tOp != NULL) {
@@ -335,8 +345,29 @@ NdbConnection::execute(ExecType aTypeOfExec,
tOp = tOp->next();
}
}
+
+ // completed ops are in unspecified order
+ if (theCompletedFirstOp != NULL) {
+ if (tCompletedFirstOp == NULL) {
+ tCompletedFirstOp = theCompletedFirstOp;
+ tCompletedLastOp = theCompletedLastOp;
+ } else {
+ tCompletedLastOp->next(theCompletedFirstOp);
+ tCompletedLastOp = theCompletedLastOp;
+ }
+ theCompletedFirstOp = NULL;
+ theCompletedLastOp = NULL;
+ }
+
if (executeNoBlobs(tExecType, abortOption, forceSend) == -1)
ret = -1;
+#ifndef VM_TRACE
+ // can happen in complex abort cases
+ theFirstOpInList = theLastOpInList = NULL;
+#else
+ assert(theFirstOpInList == NULL && theLastOpInList == NULL);
+#endif
+
{
NdbOperation* tOp = theCompletedFirstOp;
while (tOp != NULL) {
@@ -352,6 +383,7 @@ NdbConnection::execute(ExecType aTypeOfExec,
tOp = tOp->next();
}
}
+
// add saved prepared ops if batch
if (tPrepOp != NULL && tRestOp != NULL) {
if (theFirstOpInList == NULL)
@@ -360,8 +392,21 @@ NdbConnection::execute(ExecType aTypeOfExec,
theLastOpInList->next(tRestOp);
theLastOpInList = tLastOp;
}
+ assert(theFirstOpInList == NULL || tExecType == NoCommit);
} while (theFirstOpInList != NULL || tExecType != aTypeOfExec);
+ if (tCompletedFirstOp != NULL) {
+ tCompletedLastOp->next(theCompletedFirstOp);
+ theCompletedFirstOp = tCompletedFirstOp;
+ if (theCompletedLastOp == NULL)
+ theCompletedLastOp = tCompletedLastOp;
+ }
+#if ndb_api_count_completed_ops_after_blob_execute
+ { NdbOperation* tOp; unsigned n = 0;
+ for (tOp = theCompletedFirstOp; tOp != NULL; tOp = tOp->next()) n++;
+ ndbout << "completed ops: " << n << endl;
+ }
+#endif
DBUG_RETURN(ret);
}
@@ -883,6 +928,7 @@ NdbConnection::releaseOperations()
releaseOps(theFirstExecOpInList);
theCompletedFirstOp = NULL;
+ theCompletedLastOp = NULL;
theFirstOpInList = NULL;
theFirstExecOpInList = NULL;
theLastOpInList = NULL;
@@ -898,6 +944,7 @@ NdbConnection::releaseCompletedOperations()
{
releaseOps(theCompletedFirstOp);
theCompletedFirstOp = NULL;
+ theCompletedLastOp = NULL;
}//NdbConnection::releaseOperations()
/******************************************************************************
@@ -1073,10 +1120,12 @@ NdbConnection::getNdbIndexScanOperation(const NdbIndexImpl* index,
if (theCommitStatus == Started){
const NdbTableImpl * indexTable = index->getIndexTable();
if (indexTable != 0){
- NdbIndexScanOperation* tOp =
- getNdbScanOperation((NdbTableImpl *) indexTable);
- tOp->m_currentTable = table;
- if(tOp) tOp->m_cursor_type = NdbScanOperation::IndexCursor;
+ NdbIndexScanOperation* tOp = getNdbScanOperation(indexTable);
+ if(tOp)
+ {
+ tOp->m_currentTable = table;
+ tOp->m_cursor_type = NdbScanOperation::IndexCursor;
+ }
return tOp;
} else {
setOperationErrorCodeAbort(theNdb->theError.code);
@@ -1571,9 +1620,6 @@ from other transactions.
/**
* There's always a TCKEYCONF when using IgnoreError
*/
-#ifdef VM_TRACE
- ndbout_c("Not completing transaction 2");
-#endif
return -1;
}
/**********************************************************************/
@@ -1806,11 +1852,12 @@ Parameters: aErrorCode: The error code.
Remark: An operation was completed with failure.
*******************************************************************************/
int
-NdbConnection::OpCompleteFailure(Uint8 abortOption)
+NdbConnection::OpCompleteFailure(Uint8 abortOption, bool setFailure)
{
Uint32 tNoComp = theNoOfOpCompleted;
Uint32 tNoSent = theNoOfOpSent;
- theCompletionStatus = NdbConnection::CompletedFailure;
+ if (setFailure)
+ theCompletionStatus = NdbConnection::CompletedFailure;
tNoComp++;
theNoOfOpCompleted = tNoComp;
if (tNoComp == tNoSent) {
@@ -1824,9 +1871,6 @@ NdbConnection::OpCompleteFailure(Uint8 abortOption)
/**
* There's always a TCKEYCONF when using IgnoreError
*/
-#ifdef VM_TRACE
- ndbout_c("Not completing transaction");
-#endif
return -1;
}
diff --git a/ndb/src/ndbapi/NdbConnectionScan.cpp b/ndb/src/ndbapi/NdbConnectionScan.cpp
index 3fe8993a42b..b0c546c512a 100644
--- a/ndb/src/ndbapi/NdbConnectionScan.cpp
+++ b/ndb/src/ndbapi/NdbConnectionScan.cpp
@@ -56,13 +56,19 @@ NdbConnection::receiveSCAN_TABREF(NdbApiSignal* aSignal){
const ScanTabRef * ref = CAST_CONSTPTR(ScanTabRef, aSignal->getDataPtr());
if(checkState_TransId(&ref->transId1)){
- theScanningOp->theError.code = ref->errorCode;
+ theScanningOp->setErrorCode(ref->errorCode);
+ theScanningOp->execCLOSE_SCAN_REP();
if(!ref->closeNeeded){
- theScanningOp->execCLOSE_SCAN_REP();
return 0;
}
- assert(theScanningOp->m_sent_receivers_count);
+
+ /**
+ * Setup so that close_impl will actually perform a close
+ * and not "close scan"-optimze it away
+ */
theScanningOp->m_conf_receivers_count++;
+ theScanningOp->m_conf_receivers[0] = theScanningOp->m_receivers[0];
+ theScanningOp->m_conf_receivers[0]->m_tcPtrI = ~0;
return 0;
} else {
#ifdef NDB_NO_DROPPED_SIGNAL
@@ -97,7 +103,7 @@ NdbConnection::receiveSCAN_TABCONF(NdbApiSignal* aSignal,
theScanningOp->execCLOSE_SCAN_REP();
return 0;
}
-
+
for(Uint32 i = 0; i<len; i += 3){
Uint32 opCount, totalLen;
Uint32 ptrI = * ops++;
@@ -109,24 +115,12 @@ NdbConnection::receiveSCAN_TABCONF(NdbApiSignal* aSignal,
void * tPtr = theNdb->int2void(ptrI);
assert(tPtr); // For now
NdbReceiver* tOp = theNdb->void2rec(tPtr);
- if (tOp && tOp->checkMagicNumber()){
- if(tOp->execSCANOPCONF(tcPtrI, totalLen, opCount)){
- /**
- *
- */
- theScanningOp->receiver_delivered(tOp);
- } else if(info == ScanTabConf::EndOfData){
+ if (tOp && tOp->checkMagicNumber())
+ {
+ if (tcPtrI == RNIL && opCount == 0)
theScanningOp->receiver_completed(tOp);
- }
- }
- }
- if (conf->requestInfo & ScanTabConf::EndOfData) {
- if(theScanningOp->m_ordered)
- theScanningOp->m_api_receivers_count = 0;
- if(theScanningOp->m_api_receivers_count +
- theScanningOp->m_conf_receivers_count +
- theScanningOp->m_sent_receivers_count){
- abort();
+ else if (tOp->execSCANOPCONF(tcPtrI, totalLen, opCount))
+ theScanningOp->receiver_delivered(tOp);
}
}
return 0;
diff --git a/ndb/src/ndbapi/NdbDictionary.cpp b/ndb/src/ndbapi/NdbDictionary.cpp
index c8414ec16a3..462f04acb88 100644
--- a/ndb/src/ndbapi/NdbDictionary.cpp
+++ b/ndb/src/ndbapi/NdbDictionary.cpp
@@ -176,16 +176,6 @@ NdbDictionary::Column::getPrimaryKey() const {
return m_impl.m_pk;
}
-void
-NdbDictionary::Column::setTupleKey(bool val){
- m_impl.m_tupleKey = val;
-}
-
-bool
-NdbDictionary::Column::getTupleKey() const {
- return m_impl.m_tupleKey;
-}
-
void
NdbDictionary::Column::setDistributionKey(bool val){
m_impl.m_distributionKey = val;
@@ -196,32 +186,6 @@ NdbDictionary::Column::getDistributionKey() const{
return m_impl.m_distributionKey;
}
-void
-NdbDictionary::Column::setDistributionGroup(bool val, int bits){
- m_impl.m_distributionGroup = val;
- m_impl.m_distributionGroupBits = bits;
-}
-
-bool
-NdbDictionary::Column::getDistributionGroup() const {
- return m_impl.m_distributionGroup;
-}
-
-int
-NdbDictionary::Column::getDistributionGroupBits() const{
- return m_impl.m_distributionGroupBits;
-}
-
-void
-NdbDictionary::Column::setIndexOnlyStorage(bool val){
- m_impl.m_indexOnly = val;
-}
-
-bool
-NdbDictionary::Column::getIndexOnlyStorage() const {
- return m_impl.m_indexOnly;
-}
-
const NdbDictionary::Table *
NdbDictionary::Column::getBlobTable() const {
NdbTableImpl * t = m_impl.m_blobTable;
@@ -343,6 +307,18 @@ NdbDictionary::Table::getColumn(const int attrId) const {
return m_impl.getColumn(attrId);
}
+NdbDictionary::Column*
+NdbDictionary::Table::getColumn(const char * name)
+{
+ return m_impl.getColumn(name);
+}
+
+NdbDictionary::Column*
+NdbDictionary::Table::getColumn(const int attrId)
+{
+ return m_impl.getColumn(attrId);
+}
+
void
NdbDictionary::Table::setLogging(bool val){
m_impl.m_logging = val;
@@ -956,6 +932,10 @@ operator<<(NdbOut& out, const NdbDictionary::Column& col)
out << " NOT NULL";
else
out << " NULL";
+
+ if(col.getDistributionKey())
+ out << " DISTRIBUTION KEY";
+
return out;
}
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.cpp b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
index cf51a30fe0b..37dea73838f 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.cpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.cpp
@@ -47,13 +47,13 @@
* Column
*/
NdbColumnImpl::NdbColumnImpl()
- : NdbDictionary::Column(* this), m_facade(this)
+ : NdbDictionary::Column(* this), m_attrId(-1), m_facade(this)
{
init();
}
NdbColumnImpl::NdbColumnImpl(NdbDictionary::Column & f)
- : NdbDictionary::Column(* this), m_facade(&f)
+ : NdbDictionary::Column(* this), m_attrId(-1), m_facade(&f)
{
init();
}
@@ -69,12 +69,8 @@ NdbColumnImpl::operator=(const NdbColumnImpl& col)
m_scale = col.m_scale;
m_length = col.m_length;
m_pk = col.m_pk;
- m_tupleKey = col.m_tupleKey;
m_distributionKey = col.m_distributionKey;
- m_distributionGroup = col.m_distributionGroup;
- m_distributionGroupBits = col.m_distributionGroupBits;
m_nullable = col.m_nullable;
- m_indexOnly = col.m_indexOnly;
m_autoIncrement = col.m_autoIncrement;
m_autoIncrementInitialValue = col.m_autoIncrementInitialValue;
m_defaultValue = col.m_defaultValue;
@@ -93,8 +89,7 @@ NdbColumnImpl::init(Type t)
{
// do not use default_charset_info as it may not be initialized yet
// use binary collation until NDB tests can handle charsets
- CHARSET_INFO* default_cs = &my_charset_latin1_bin;
- m_attrId = -1;
+ CHARSET_INFO* default_cs = &my_charset_bin;
m_type = t;
switch (m_type) {
case Tinyint:
@@ -154,11 +149,7 @@ NdbColumnImpl::init(Type t)
}
m_pk = false;
m_nullable = false;
- m_tupleKey = false;
- m_indexOnly = false;
m_distributionKey = false;
- m_distributionGroup = false;
- m_distributionGroupBits = 8;
m_keyInfoPos = 0;
// next 2 are set at run time
m_attrSize = 0;
@@ -188,22 +179,9 @@ NdbColumnImpl::equal(const NdbColumnImpl& col) const
return false;
}
if(m_pk){
- if(m_tupleKey != col.m_tupleKey){
- return false;
- }
- if(m_indexOnly != col.m_indexOnly){
- return false;
- }
if(m_distributionKey != col.m_distributionKey){
return false;
}
- if(m_distributionGroup != col.m_distributionGroup){
- return false;
- }
- if(m_distributionGroup &&
- (m_distributionGroupBits != col.m_distributionGroupBits)){
- return false;
- }
}
if (m_precision != col.m_precision ||
m_scale != col.m_scale ||
@@ -286,8 +264,9 @@ NdbTableImpl::init(){
m_indexType = NdbDictionary::Index::Undefined;
m_noOfKeys = 0;
+ m_noOfDistributionKeys = 0;
m_fragmentCount = 0;
- m_sizeOfKeysInWords = 0;
+ m_keyLenInWords = 0;
m_noOfBlobs = 0;
}
@@ -366,8 +345,9 @@ NdbTableImpl::assign(const NdbTableImpl& org)
delete m_index;
m_index = org.m_index;
+ m_noOfDistributionKeys = org.m_noOfDistributionKeys;
m_noOfKeys = org.m_noOfKeys;
- m_sizeOfKeysInWords = org.m_sizeOfKeysInWords;
+ m_keyLenInWords = org.m_keyLenInWords;
m_noOfBlobs = org.m_noOfBlobs;
m_version = org.m_version;
@@ -1234,6 +1214,7 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
Uint32 keyInfoPos = 0;
Uint32 keyCount = 0;
Uint32 blobCount = 0;
+ Uint32 distKeys = 0;
for(Uint32 i = 0; i < tableDesc.NoOfAttributes; i++) {
DictTabInfo::Attribute attrDesc; attrDesc.init();
@@ -1287,12 +1268,8 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
col->m_arraySize = attrDesc.AttributeArraySize;
col->m_pk = attrDesc.AttributeKeyFlag;
- col->m_tupleKey = 0;
col->m_distributionKey = attrDesc.AttributeDKey;
- col->m_distributionGroup = attrDesc.AttributeDGroup;
- col->m_distributionGroupBits = 16;
col->m_nullable = attrDesc.AttributeNullableFlag;
- col->m_indexOnly = (attrDesc.AttributeStoredInd ? false : true);
col->m_autoIncrement = (attrDesc.AttributeAutoIncrement ? true : false);
col->m_autoIncrementInitialValue = ~0;
col->m_defaultValue.assign(attrDesc.AttributeDefaultValue);
@@ -1301,6 +1278,9 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
col->m_keyInfoPos = keyInfoPos + 1;
keyInfoPos += ((col->m_attrSize * col->m_arraySize + 3) / 4);
keyCount++;
+
+ if(attrDesc.AttributeDKey)
+ distKeys++;
} else {
col->m_keyInfoPos = 0;
}
@@ -1319,8 +1299,8 @@ NdbDictInterface::parseTableInfo(NdbTableImpl ** ret,
impl->m_noOfKeys = keyCount;
impl->m_keyLenInWords = keyInfoPos;
- impl->m_sizeOfKeysInWords = keyInfoPos;
impl->m_noOfBlobs = blobCount;
+ impl->m_noOfDistributionKeys = distKeys;
* ret = impl;
return 0;
}
@@ -1528,11 +1508,11 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
BaseString::snprintf(tmpAttr.AttributeName, sizeof(tmpAttr.AttributeName),
col->m_name.c_str());
tmpAttr.AttributeId = i;
- tmpAttr.AttributeKeyFlag = col->m_pk || col->m_tupleKey;
+ tmpAttr.AttributeKeyFlag = col->m_pk;
tmpAttr.AttributeNullableFlag = col->m_nullable;
- tmpAttr.AttributeStoredInd = (col->m_indexOnly ? 0 : 1);
+ tmpAttr.AttributeStoredInd = 1;
tmpAttr.AttributeDKey = col->m_distributionKey;
- tmpAttr.AttributeDGroup = col->m_distributionGroup;
+ tmpAttr.AttributeDGroup = 0;
tmpAttr.AttributeExtType =
getKernelConstant(col->m_type,
@@ -1572,7 +1552,13 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
NdbApiSignal tSignal(m_reference);
tSignal.theReceiversBlockNumber = DBDICT;
- if (alter) {
+
+ LinearSectionPtr ptr[3];
+ ptr[0].p = (Uint32*)m_buffer.get_data();
+ ptr[0].sz = m_buffer.length() / 4;
+ int ret;
+ if (alter)
+ {
AlterTableReq * const req =
CAST_PTR(AlterTableReq, tSignal.getDataPtrSend());
@@ -1583,8 +1569,10 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
req->tableVersion = impl.m_version;;
tSignal.theVerId_signalNumber = GSN_ALTER_TABLE_REQ;
tSignal.theLength = AlterTableReq::SignalLength;
+ ret= alterTable(&tSignal, ptr);
}
- else {
+ else
+ {
CreateTableReq * const req =
CAST_PTR(CreateTableReq, tSignal.getDataPtrSend());
@@ -1592,25 +1580,21 @@ NdbDictInterface::createOrAlterTable(Ndb & ndb,
req->senderData = 0;
tSignal.theVerId_signalNumber = GSN_CREATE_TABLE_REQ;
tSignal.theLength = CreateTableReq::SignalLength;
- }
-
- LinearSectionPtr ptr[3];
- ptr[0].p = (Uint32*)m_buffer.get_data();
- ptr[0].sz = m_buffer.length() / 4;
-
- int ret = (alter) ?
- alterTable(&tSignal, ptr)
- : createTable(&tSignal, ptr);
-
- if (!alter && haveAutoIncrement) {
- if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
- autoIncrementValue)) {
- if (ndb.theError.code == 0) {
- m_error.code = 4336;
- ndb.theError = m_error;
- } else
- m_error= ndb.theError;
- ret = -1; // errorcode set in initialize_autoincrement
+ ret= createTable(&tSignal, ptr);
+
+ if (ret)
+ return ret;
+
+ if (haveAutoIncrement) {
+ if (!ndb.setAutoIncrementValue(impl.m_externalName.c_str(),
+ autoIncrementValue)) {
+ if (ndb.theError.code == 0) {
+ m_error.code = 4336;
+ ndb.theError = m_error;
+ } else
+ m_error= ndb.theError;
+ ret = -1; // errorcode set in initialize_autoincrement
+ }
}
}
return ret;
@@ -2030,10 +2014,6 @@ NdbDictInterface::createIndex(Ndb & ndb,
// Copy column definition
*impl.m_columns[i] = *col;
- if(col->m_pk && col->m_indexOnly){
- m_error.code = 4245;
- return -1;
- }
// index key type check
if (it == DictTabInfo::UniqueHashIndex &&
! NdbSqlUtil::usable_in_hash_index(col->m_type, col->m_cs) ||
diff --git a/ndb/src/ndbapi/NdbDictionaryImpl.hpp b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
index 12f0946ab67..38477e95d99 100644
--- a/ndb/src/ndbapi/NdbDictionaryImpl.hpp
+++ b/ndb/src/ndbapi/NdbDictionaryImpl.hpp
@@ -63,12 +63,8 @@ public:
CHARSET_INFO * m_cs; // not const in MySQL
bool m_pk;
- bool m_tupleKey;
bool m_distributionKey;
- bool m_distributionGroup;
- int m_distributionGroupBits;
bool m_nullable;
- bool m_indexOnly;
bool m_autoIncrement;
Uint64 m_autoIncrementInitialValue;
BaseString m_defaultValue;
@@ -128,8 +124,8 @@ public:
int m_kvalue;
int m_minLoadFactor;
int m_maxLoadFactor;
- int m_keyLenInWords;
- int m_fragmentCount;
+ Uint16 m_keyLenInWords;
+ Uint16 m_fragmentCount;
NdbDictionaryImpl * m_dictionary;
NdbIndexImpl * m_index;
@@ -147,9 +143,9 @@ public:
/**
* Aggregates
*/
- Uint32 m_noOfKeys;
- unsigned short m_sizeOfKeysInWords;
- unsigned short m_noOfBlobs;
+ Uint8 m_noOfKeys;
+ Uint8 m_noOfDistributionKeys;
+ Uint8 m_noOfBlobs;
/**
* Equality/assign
@@ -637,11 +633,9 @@ NdbDictionaryImpl::get_local_table_info(const char * internalTableName,
return 0;
}
}
- if (do_add_blob_tables &&
- info->m_table_impl->m_noOfBlobs &&
- addBlobTables(*(info->m_table_impl))) {
- return 0;
- }
+ if (do_add_blob_tables && info->m_table_impl->m_noOfBlobs)
+ addBlobTables(*(info->m_table_impl));
+
return info; // autoincrement already initialized
}
diff --git a/ndb/src/ndbapi/NdbIndexOperation.cpp b/ndb/src/ndbapi/NdbIndexOperation.cpp
index 9abde639914..7b8e15f4d81 100644
--- a/ndb/src/ndbapi/NdbIndexOperation.cpp
+++ b/ndb/src/ndbapi/NdbIndexOperation.cpp
@@ -28,9 +28,7 @@
NdbIndexOperation::NdbIndexOperation(Ndb* aNdb) :
NdbOperation(aNdb),
- m_theIndex(NULL),
- m_theIndexLen(0),
- m_theNoOfIndexDefined(0)
+ m_theIndex(NULL)
{
m_tcReqGSN = GSN_TCINDXREQ;
m_attrInfoGSN = GSN_INDXATTRINFO;
@@ -72,16 +70,7 @@ NdbIndexOperation::indxInit(const NdbIndexImpl * anIndex,
}
m_theIndex = anIndex;
m_accessTable = anIndex->m_table;
- m_theIndexLen = 0;
- m_theNoOfIndexDefined = 0;
- for (Uint32 i=0; i<NDB_MAX_ATTRIBUTES_IN_INDEX; i++)
- for (int j=0; j<3; j++)
- m_theIndexDefined[i][j] = false;
-
- TcIndxReq * const tcIndxReq = CAST_PTR(TcIndxReq, theTCREQ->getDataPtrSend());
- tcIndxReq->scanInfo = 0;
- theKEYINFOptr = &tcIndxReq->keyInfo[0];
- theATTRINFOptr = &tcIndxReq->attrInfo[0];
+ theNoOfTupKeyLeft = m_accessTable->getNoOfPrimaryKeys();
return 0;
}
@@ -102,6 +91,12 @@ int NdbIndexOperation::readTuple(NdbOperation::LockMode lm)
};
}
+int NdbIndexOperation::insertTuple()
+{
+ setErrorCode(4200);
+ return -1;
+}
+
int NdbIndexOperation::readTuple()
{
// First check that index is unique
@@ -172,306 +167,6 @@ int NdbIndexOperation::interpretedDeleteTuple()
return NdbOperation::interpretedDeleteTuple();
}
-int NdbIndexOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
- const char* aValuePassed,
- Uint32 aVariableKeyLen)
-{
- register Uint32 tAttrId;
-
- Uint32 tData;
- Uint32 tKeyInfoPosition;
- const char* aValue = aValuePassed;
- Uint32 xfrmData[1024];
- Uint32 tempData[1024];
-
- if ((theStatus == OperationDefined) &&
- (aValue != NULL) &&
- (tAttrInfo != NULL )) {
- /************************************************************************
- * Start by checking that the attribute is an index key.
- * This value is also the word order in the tuple key of this
- * tuple key attribute.
- * Then check that this tuple key has not already been defined.
- * Finally check if all tuple key attributes have been defined. If
- * this is true then set Operation state to tuple key defined.
- ************************************************************************/
- tAttrId = tAttrInfo->m_attrId;
- tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
- Uint32 i = 0;
-
- // Check that the attribute is part if the index attributes
- // by checking if it is a primary key attribute of index table
- if (tAttrInfo->m_pk) {
- Uint32 tKeyDefined = theTupleKeyDefined[0][2];
- Uint32 tKeyAttrId = theTupleKeyDefined[0][0];
- do {
- if (tKeyDefined == false) {
- goto keyEntryFound;
- } else {
- if (tKeyAttrId != tAttrId) {
- /******************************************************************
- * We read the key defined variable in advance.
- * It could potentially read outside its area when
- * i = MAXNROFTUPLEKEY - 1,
- * it is not a problem as long as the variable
- * theTupleKeyDefined is defined
- * in the middle of the object.
- * Reading wrong data and not using it causes no problems.
- *****************************************************************/
- i++;
- tKeyAttrId = theTupleKeyDefined[i][0];
- tKeyDefined = theTupleKeyDefined[i][2];
- continue;
- } else {
- goto equal_error2;
- }//if
- }//if
- } while (i < NDB_MAX_ATTRIBUTES_IN_INDEX);
- goto equal_error2;
- } else {
- goto equal_error1;
- }
- /**************************************************************************
- * Now it is time to retrieve the tuple key data from the pointer supplied
- * by the application.
- * We have to retrieve the size of the attribute in words and bits.
- *************************************************************************/
- keyEntryFound:
- m_theIndexDefined[i][0] = tAttrId;
- m_theIndexDefined[i][1] = tKeyInfoPosition;
- m_theIndexDefined[i][2] = true;
-
- Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
- {
- /*************************************************************************
- * Check if the pointer of the value passed is aligned on a 4 byte
- * boundary. If so only assign the pointer to the internal variable
- * aValue. If it is not aligned then we start by copying the value to
- * tempData and use this as aValue instead.
- *************************************************************************/
- const int attributeSize = sizeInBytes;
- const int slack = sizeInBytes & 3;
- if ((((UintPtr)aValue & 3) != 0) || (slack != 0)){
- memcpy(&tempData[0], aValue, attributeSize);
- aValue = (char*)&tempData[0];
- if(slack != 0) {
- char * tmp = (char*)&tempData[0];
- memset(&tmp[attributeSize], 0, (4 - slack));
- }//if
- }//if
- }
- const char* aValueToWrite = aValue;
-
- CHARSET_INFO* cs = tAttrInfo->m_cs;
- if (cs != 0) {
- // current limitation: strxfrm does not increase length
- assert(cs->strxfrm_multiply == 1);
- unsigned n =
- (*cs->coll->strnxfrm)(cs,
- (uchar*)xfrmData, sizeof(xfrmData),
- (const uchar*)aValue, sizeInBytes);
- while (n < sizeInBytes)
- ((uchar*)xfrmData)[n++] = 0x20;
- aValue = (char*)xfrmData;
- }
-
- Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
- Uint32 totalSizeInWords = (sizeInBytes + 3)/4;// Inc. bits in last word
- Uint32 sizeInWords = sizeInBytes / 4; // Exc. bits in last word
-
- if (true){ //tArraySize != 0) {
- Uint32 tIndexLen = m_theIndexLen;
-
- m_theIndexLen = tIndexLen + totalSizeInWords;
- if ((aVariableKeyLen == sizeInBytes) ||
- (aVariableKeyLen == 0)) {
- ;
- } else {
- goto equal_error3;
- }
- }
-#if 0
- else {
- /************************************************************************
- * The attribute is a variable array. We need to use the length parameter
- * to know the size of this attribute in the key information and
- * variable area. A key is however not allowed to be larger than 4
- * kBytes and this is checked for variable array attributes
- * used as keys.
- ***********************************************************************/
- Uint32 tMaxVariableKeyLenInWord = (MAXTUPLEKEYLENOFATTERIBUTEINWORD -
- tKeyInfoPosition);
- tAttrSizeInBits = aVariableKeyLen << 3;
- tAttrSizeInWords = tAttrSizeInBits >> 5;
- tAttrBitsInLastWord = tAttrSizeInBits - (tAttrSizeInWords << 5);
- tAttrLenInWords = ((tAttrSizeInBits + 31) >> 5);
- if (tAttrLenInWords > tMaxVariableKeyLenInWord) {
- setErrorCodeAbort(4207);
- return -1;
- }//if
- m_theIndexLen = m_theIndexLen + tAttrLenInWords;
- }//if
-#endif
- int tDistrKey = tAttrInfo->m_distributionKey;
- int tDistrGroup = tAttrInfo->m_distributionGroup;
- OperationType tOpType = theOperationType;
- if ((tDistrKey != 1) && (tDistrGroup != 1)) {
- ;
- } else if (tDistrKey == 1) {
- theDistrKeySize += totalSizeInWords;
- theDistrKeyIndicator = 1;
- } else {
- Uint32 TsizeInBytes = sizeInBytes;
- Uint32 TbyteOrderFix = 0;
- char* TcharByteOrderFix = (char*)&TbyteOrderFix;
- if (tAttrInfo->m_distributionGroupBits == 8) {
- char tFirstChar = aValue[TsizeInBytes - 2];
- char tSecondChar = aValue[TsizeInBytes - 2];
- TcharByteOrderFix[0] = tFirstChar;
- TcharByteOrderFix[1] = tSecondChar;
- TcharByteOrderFix[2] = 0x30;
- TcharByteOrderFix[3] = 0x30;
- theDistrGroupType = 0;
- } else {
- TbyteOrderFix = ((aValue[TsizeInBytes - 2] - 0x30) * 10)
- + (aValue[TsizeInBytes - 1] - 0x30);
- theDistrGroupType = 1;
- }//if
- theDistributionGroup = TbyteOrderFix;
- theDistrGroupIndicator = 1;
- }//if
- /**************************************************************************
- * If the operation is an insert request and the attribute is stored then
- * we also set the value in the stored part through putting the
- * information in the INDXATTRINFO signals.
- *************************************************************************/
- if ((tOpType == InsertRequest) ||
- (tOpType == WriteRequest)) {
- if (!tAttrInfo->m_indexOnly){
- // invalid data can crash kernel
- if (cs != NULL &&
- (*cs->cset->well_formed_len)(cs,
- aValueToWrite,
- aValueToWrite + sizeInBytes,
- sizeInBytes) != sizeInBytes)
- goto equal_error4;
- Uint32 ahValue;
- Uint32 sz = totalSizeInWords;
- AttributeHeader::init(&ahValue, tAttrId, sz);
- insertATTRINFO( ahValue );
- insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords);
- if (bitsInLastWord != 0) {
- tData = *(Uint32*)(aValueToWrite + (sizeInWords << 2));
- tData = convertEndian(tData);
- tData = tData & ((1 << bitsInLastWord) - 1);
- tData = convertEndian(tData);
- insertATTRINFO( tData );
- }//if
- }//if
- }//if
-
- /**************************************************************************
- * Store the Key information in the TCINDXREQ and INDXKEYINFO signals.
- *************************************************************************/
- if (insertKEYINFO(aValue, tKeyInfoPosition,
- totalSizeInWords, bitsInLastWord) != -1) {
- /************************************************************************
- * Add one to number of tuple key attributes defined.
- * If all have been defined then set the operation state to indicate
- * that tuple key is defined.
- * Thereby no more search conditions are allowed in this version.
- ***********************************************************************/
- Uint32 tNoIndexDef = m_theNoOfIndexDefined;
- Uint32 tErrorLine = theErrorLine;
- int tNoIndexAttrs = m_theIndex->m_columns.size();
- unsigned char tInterpretInd = theInterpretIndicator;
- tNoIndexDef++;
- m_theNoOfIndexDefined = tNoIndexDef;
- tErrorLine++;
- theErrorLine = tErrorLine;
- if (int(tNoIndexDef) == tNoIndexAttrs) {
- if (tOpType == UpdateRequest) {
- if (tInterpretInd == 1) {
- theStatus = GetValue;
- } else {
- theStatus = SetValue;
- }//if
- return 0;
- } else if ((tOpType == ReadRequest) || (tOpType == DeleteRequest) ||
- (tOpType == ReadExclusive)) {
- theStatus = GetValue;
- // create blob handles automatically
- if (tOpType == DeleteRequest && m_currentTable->m_noOfBlobs != 0) {
- for (unsigned i = 0; i < m_currentTable->m_columns.size(); i++) {
- NdbColumnImpl* c = m_currentTable->m_columns[i];
- assert(c != 0);
- if (c->getBlobType()) {
- if (getBlobHandle(theNdbCon, c) == NULL)
- return -1;
- }
- }
- }
- return 0;
- } else if ((tOpType == InsertRequest) || (tOpType == WriteRequest)) {
- theStatus = SetValue;
- return 0;
- } else {
- setErrorCodeAbort(4005);
- return -1;
- }//if
- }//if
- return 0;
- } else {
-
- return -1;
- }//if
- } else {
- if (theStatus != OperationDefined) {
- return -1;
- }//if
-
- if (aValue == NULL) {
- setErrorCodeAbort(4505);
- return -1;
- }//if
-
- if ( tAttrInfo == NULL ) {
- setErrorCodeAbort(4004);
- return -1;
- }//if
- }//if
- return -1;
-
- equal_error1:
- setErrorCodeAbort(4205);
- return -1;
-
- equal_error2:
- setErrorCodeAbort(4206);
- return -1;
-
- equal_error3:
- setErrorCodeAbort(4209);
- return -1;
-
- equal_error4:
- setErrorCodeAbort(744);
- return -1;
-}
-
-int NdbIndexOperation::executeCursor(int aProcessorId)
-{
- printf("NdbIndexOperation::executeCursor NYI\n");
- // NYI
- return -1;
-}
-void
-NdbIndexOperation::setLastFlag(NdbApiSignal* signal, Uint32 lastFlag)
-{
- TcIndxReq * const req = CAST_PTR(TcIndxReq, signal->getDataPtrSend());
- TcKeyReq::setExecuteFlag(req->requestInfo, lastFlag);
-}
-
int
NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
{
@@ -512,18 +207,18 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
// We start by filling in the first 8 unconditional words of the
// TCINDXREQ signal.
//-------------------------------------------------------------
- TcIndxReq * const tcIndxReq =
- CAST_PTR(TcIndxReq, theTCREQ->getDataPtrSend());
+ TcKeyReq * tcKeyReq =
+ CAST_PTR(TcKeyReq, theTCREQ->getDataPtrSend());
Uint32 tTotalCurrAI_Len = theTotalCurrAI_Len;
Uint32 tIndexId = m_theIndex->m_indexId;
Uint32 tSchemaVersion = m_theIndex->m_version;
- tcIndxReq->apiConnectPtr = aTC_ConnectPtr;
- tcIndxReq->senderData = ptr2int();
- tcIndxReq->attrLen = tTotalCurrAI_Len;
- tcIndxReq->indexId = tIndexId;
- tcIndxReq->indexSchemaVersion = tSchemaVersion;
+ tcKeyReq->apiConnectPtr = aTC_ConnectPtr;
+ tcKeyReq->senderData = ptr2int();
+ tcKeyReq->attrLen = tTotalCurrAI_Len;
+ tcKeyReq->tableId = tIndexId;
+ tcKeyReq->tableSchemaVersion = tSchemaVersion;
tTransId1 = (Uint32) aTransactionId;
tTransId2 = (Uint32) (aTransactionId >> 32);
@@ -551,59 +246,53 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
Uint8 tSimpleState = tReadInd & tSimpleAlt;
//theNdbCon->theSimpleState = tSimpleState;
- tcIndxReq->transId1 = tTransId1;
- tcIndxReq->transId2 = tTransId2;
+ tcKeyReq->transId1 = tTransId1;
+ tcKeyReq->transId2 = tTransId2;
tReqInfo = 0;
- if (tTotalCurrAI_Len <= TcIndxReq::MaxAttrInfo) {
- tcIndxReq->setAIInTcIndxReq(tReqInfo, tTotalCurrAI_Len);
+ if (tTotalCurrAI_Len <= TcKeyReq::MaxAttrInfo) {
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, tTotalCurrAI_Len);
} else {
- tcIndxReq->setAIInTcIndxReq(tReqInfo, TcIndxReq::MaxAttrInfo);
+ tcKeyReq->setAIInTcKeyReq(tReqInfo, TcKeyReq::MaxAttrInfo);
}//if
- tcIndxReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
- tcIndxReq->setCommitFlag(tReqInfo, tCommitIndicator);
- tcIndxReq->setStartFlag(tReqInfo, tStartIndicator);
+ tcKeyReq->setSimpleFlag(tReqInfo, tSimpleIndicator);
+ tcKeyReq->setCommitFlag(tReqInfo, tCommitIndicator);
+ tcKeyReq->setStartFlag(tReqInfo, tStartIndicator);
const Uint8 tInterpretIndicator = theInterpretIndicator;
- tcIndxReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
+ tcKeyReq->setInterpretedFlag(tReqInfo, tInterpretIndicator);
Uint8 tDirtyIndicator = theDirtyIndicator;
OperationType tOperationType = theOperationType;
- Uint32 tIndexLen = m_theIndexLen;
+ Uint32 tIndexLen = theTupKeyLen;
Uint8 abortOption = theNdbCon->m_abortOption;
- tcIndxReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
- tcIndxReq->setOperationType(tReqInfo, tOperationType);
- tcIndxReq->setIndexLength(tReqInfo, tIndexLen);
- tcIndxReq->setCommitType(tReqInfo, abortOption);
+ tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
+ tcKeyReq->setOperationType(tReqInfo, tOperationType);
+ tcKeyReq->setKeyLength(tReqInfo, tIndexLen);
+ tcKeyReq->setAbortOption(tReqInfo, abortOption);
- Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
- Uint8 tDistrGroupIndicator = theDistrGroupIndicator;
- Uint8 tDistrGroupType = theDistrGroupType;
+ Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
Uint8 tScanIndicator = theScanInfo & 1;
- tcIndxReq->setDistributionGroupFlag(tReqInfo, tDistrGroupIndicator);
- tcIndxReq->setDistributionGroupTypeFlag(tReqInfo, tDistrGroupType);
- tcIndxReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
- tcIndxReq->setScanIndFlag(tReqInfo, tScanIndicator);
+ tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
+ tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
- tcIndxReq->requestInfo = tReqInfo;
+ tcKeyReq->requestInfo = tReqInfo;
//-------------------------------------------------------------
// The next step is to fill in the upto three conditional words.
//-------------------------------------------------------------
- Uint32* tOptionalDataPtr = &tcIndxReq->scanInfo;
+ Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
Uint32 tDistrGHIndex = tScanIndicator;
- Uint32 tDistrKeyIndex = tDistrGHIndex + tDistrGroupIndicator;
+ Uint32 tDistrKeyIndex = tDistrGHIndex;
Uint32 tScanInfo = theScanInfo;
- Uint32 tDistributionGroup = theDistributionGroup;
- Uint32 tDistrKeySize = theDistrKeySize;
+ Uint32 tDistrKey = theDistributionKey;
tOptionalDataPtr[0] = tScanInfo;
- tOptionalDataPtr[tDistrGHIndex] = tDistributionGroup;
- tOptionalDataPtr[tDistrKeyIndex] = tDistrKeySize;
+ tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
//-------------------------------------------------------------
// The next is step is to compress the key data part of the
@@ -611,10 +300,10 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
//-------------------------------------------------------------
Uint32 tKeyIndex = tDistrKeyIndex + tDistrKeyIndicator;
Uint32* tKeyDataPtr = &tOptionalDataPtr[tKeyIndex];
- Uint32 Tdata1 = tcIndxReq->keyInfo[0];
- Uint32 Tdata2 = tcIndxReq->keyInfo[1];
- Uint32 Tdata3 = tcIndxReq->keyInfo[2];
- Uint32 Tdata4 = tcIndxReq->keyInfo[3];
+ Uint32 Tdata1 = tcKeyReq->keyInfo[0];
+ Uint32 Tdata2 = tcKeyReq->keyInfo[1];
+ Uint32 Tdata3 = tcKeyReq->keyInfo[2];
+ Uint32 Tdata4 = tcKeyReq->keyInfo[3];
Uint32 Tdata5;
tKeyDataPtr[0] = Tdata1;
@@ -622,10 +311,10 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
tKeyDataPtr[2] = Tdata3;
tKeyDataPtr[3] = Tdata4;
if (tIndexLen > 4) {
- Tdata1 = tcIndxReq->keyInfo[4];
- Tdata2 = tcIndxReq->keyInfo[5];
- Tdata3 = tcIndxReq->keyInfo[6];
- Tdata4 = tcIndxReq->keyInfo[7];
+ Tdata1 = tcKeyReq->keyInfo[4];
+ Tdata2 = tcKeyReq->keyInfo[5];
+ Tdata3 = tcKeyReq->keyInfo[6];
+ Tdata4 = tcKeyReq->keyInfo[7];
tKeyDataPtr[4] = Tdata1;
tKeyDataPtr[5] = Tdata2;
@@ -639,12 +328,12 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
//-------------------------------------------------------------
Uint32 tAttrInfoIndex;
- if (tIndexLen > TcIndxReq::MaxKeyInfo) {
+ if (tIndexLen > TcKeyReq::MaxKeyInfo) {
/**
* Set transid and TC connect ptr in the INDXKEYINFO signals
*/
- NdbApiSignal* tSignal = theFirstKEYINFO;
- Uint32 remainingKey = tIndexLen - TcIndxReq::MaxKeyInfo;
+ NdbApiSignal* tSignal = theTCREQ->next();
+ Uint32 remainingKey = tIndexLen - TcKeyReq::MaxKeyInfo;
do {
Uint32* tSigDataPtr = tSignal->getDataPtrSend();
@@ -665,7 +354,7 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
}
tSignal = tnextSignal;
} while (tSignal != NULL);
- tAttrInfoIndex = tKeyIndex + TcIndxReq::MaxKeyInfo;
+ tAttrInfoIndex = tKeyIndex + TcKeyReq::MaxKeyInfo;
} else {
tAttrInfoIndex = tKeyIndex + tIndexLen;
}//if
@@ -675,14 +364,14 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
// above.
//-------------------------------------------------------------
Uint32* tAIDataPtr = &tOptionalDataPtr[tAttrInfoIndex];
- Tdata1 = tcIndxReq->attrInfo[0];
- Tdata2 = tcIndxReq->attrInfo[1];
- Tdata3 = tcIndxReq->attrInfo[2];
- Tdata4 = tcIndxReq->attrInfo[3];
- Tdata5 = tcIndxReq->attrInfo[4];
-
- theTCREQ->setLength(tcIndxReq->getAIInTcIndxReq(tReqInfo) +
- tAttrInfoIndex + TcIndxReq::StaticLength);
+ Tdata1 = tcKeyReq->attrInfo[0];
+ Tdata2 = tcKeyReq->attrInfo[1];
+ Tdata3 = tcKeyReq->attrInfo[2];
+ Tdata4 = tcKeyReq->attrInfo[3];
+ Tdata5 = tcKeyReq->attrInfo[4];
+
+ theTCREQ->setLength(tcKeyReq->getAIInTcKeyReq(tReqInfo) +
+ tAttrInfoIndex + TcKeyReq::StaticLength);
tAIDataPtr[0] = Tdata1;
tAIDataPtr[1] = Tdata2;
tAIDataPtr[2] = Tdata3;
@@ -711,11 +400,6 @@ NdbIndexOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransactionId)
return 0;
}
-void NdbIndexOperation::closeScan()
-{
- printf("NdbIndexOperation::closeScan NYI\n");
-}
-
/***************************************************************************
int receiveTCINDXREF( NdbApiSignal* aSignal)
@@ -734,13 +418,10 @@ NdbIndexOperation::receiveTCINDXREF( NdbApiSignal* aSignal)
}//if
theStatus = Finished;
-
+
theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
Uint32 errorCode = tcIndxRef->errorCode;
theError.code = errorCode;
theNdbCon->setOperationErrorCodeAbort(errorCode);
return theNdbCon->OpCompleteFailure(theNdbCon->m_abortOption);
}//NdbIndexOperation::receiveTCINDXREF()
-
-
-
diff --git a/ndb/src/ndbapi/NdbOperation.cpp b/ndb/src/ndbapi/NdbOperation.cpp
index b0b95d0ff43..f0de2242d2a 100644
--- a/ndb/src/ndbapi/NdbOperation.cpp
+++ b/ndb/src/ndbapi/NdbOperation.cpp
@@ -49,7 +49,6 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
theCurrentATTRINFO(NULL),
theTotalCurrAI_Len(0),
theAI_LenInCurrAI(0),
- theFirstKEYINFO(NULL),
theLastKEYINFO(NULL),
theFirstLabel(NULL),
@@ -68,17 +67,16 @@ NdbOperation::NdbOperation(Ndb* aNdb) :
//theSchemaVersion(0),
theTotalNrOfKeyWordInSignal(8),
theTupKeyLen(0),
- theNoOfTupKeyDefined(0),
+ theNoOfTupKeyLeft(0),
theOperationType(NotDefined),
theStatus(Init),
theMagicNumber(0xFE11D0),
theScanInfo(0),
- theDistrKeySize(0),
- theDistributionGroup(0),
m_tcReqGSN(GSN_TCKEYREQ),
m_keyInfoGSN(GSN_KEYINFO),
m_attrInfoGSN(GSN_ATTRINFO),
- theBlobList(NULL)
+ theBlobList(NULL),
+ m_abortOption(-1)
{
theReceiver.init(NdbReceiver::NDB_OPERATION, this);
theError.code = 0;
@@ -144,14 +142,11 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
theFirstATTRINFO = NULL;
theCurrentATTRINFO = NULL;
- theFirstKEYINFO = NULL;
theLastKEYINFO = NULL;
- theTupKeyLen = 0;
- theNoOfTupKeyDefined = 0;
- theDistrKeySize = 0;
- theDistributionGroup = 0;
+ theTupKeyLen = 0;
+ theNoOfTupKeyLeft = tab->getNoOfPrimaryKeys();
theTotalCurrAI_Len = 0;
theAI_LenInCurrAI = 0;
@@ -160,13 +155,12 @@ NdbOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection){
theSimpleIndicator = 0;
theDirtyIndicator = 0;
theInterpretIndicator = 0;
- theDistrGroupIndicator= 0;
- theDistrGroupType = 0;
- theDistrKeyIndicator = 0;
+ theDistrKeyIndicator_ = 0;
theScanInfo = 0;
theTotalNrOfKeyWordInSignal = 8;
theMagicNumber = 0xABCDEF01;
theBlobList = NULL;
+ m_abortOption = -1;
tSignal = theNdb->getSignal();
if (tSignal == NULL)
@@ -208,11 +202,16 @@ NdbOperation::release()
NdbBlob* tBlob;
NdbBlob* tSaveBlob;
- if (theTCREQ != NULL)
+ tSignal = theTCREQ;
+ while (tSignal != NULL)
{
- theNdb->releaseSignal(theTCREQ);
- }
+ tSaveSignal = tSignal;
+ tSignal = tSignal->next();
+ theNdb->releaseSignal(tSaveSignal);
+ }
theTCREQ = NULL;
+ theLastKEYINFO = NULL;
+
tSignal = theFirstATTRINFO;
while (tSignal != NULL)
{
@@ -222,15 +221,7 @@ NdbOperation::release()
}
theFirstATTRINFO = NULL;
theCurrentATTRINFO = NULL;
- tSignal = theFirstKEYINFO;
- while (tSignal != NULL)
- {
- tSaveSignal = tSignal;
- tSignal = tSignal->next();
- theNdb->releaseSignal(tSaveSignal);
- }
- theFirstKEYINFO = NULL;
- theLastKEYINFO = NULL;
+
if (theInterpretIndicator == 1)
{
tBranch = theFirstBranch;
diff --git a/ndb/src/ndbapi/NdbOperationDefine.cpp b/ndb/src/ndbapi/NdbOperationDefine.cpp
index 35abb15b00d..d9aa860f71f 100644
--- a/ndb/src/ndbapi/NdbOperationDefine.cpp
+++ b/ndb/src/ndbapi/NdbOperationDefine.cpp
@@ -350,7 +350,6 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
{
NdbRecAttr* tRecAttr;
if ((tAttrInfo != NULL) &&
- (!tAttrInfo->m_indexOnly) &&
(theStatus != Init)){
if (theStatus != GetValue) {
if (theInterpretIndicator == 1) {
@@ -398,10 +397,6 @@ NdbOperation::getValue_impl(const NdbColumnImpl* tAttrInfo, char* aValue)
setErrorCodeAbort(4004);
return NULL;
}//if
- if (tAttrInfo->m_indexOnly){
- setErrorCodeAbort(4208);
- return NULL;
- }//if
}//if
setErrorCodeAbort(4200);
return NULL;
diff --git a/ndb/src/ndbapi/NdbOperationExec.cpp b/ndb/src/ndbapi/NdbOperationExec.cpp
index f1338ae01e4..fc263609eb4 100644
--- a/ndb/src/ndbapi/NdbOperationExec.cpp
+++ b/ndb/src/ndbapi/NdbOperationExec.cpp
@@ -65,7 +65,7 @@ NdbOperation::doSend(int aNodeId, Uint32 lastFlag)
if (tReturnCode == -1) {
return -1;
}
- NdbApiSignal *tSignal = theFirstKEYINFO;
+ NdbApiSignal *tSignal = theTCREQ->next();
while (tSignal != NULL) {
NdbApiSignal* tnextSignal = tSignal->next();
tReturnCode = tp->sendSignal(tSignal, aNodeId);
@@ -191,7 +191,8 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
Uint8 tDirtyIndicator = theDirtyIndicator;
OperationType tOperationType = theOperationType;
Uint32 tTupKeyLen = theTupKeyLen;
- Uint8 abortOption = theNdbCon->m_abortOption;
+ Uint8 abortOption =
+ m_abortOption != -1 ? m_abortOption : theNdbCon->m_abortOption;
tcKeyReq->setDirtyFlag(tReqInfo, tDirtyIndicator);
tcKeyReq->setOperationType(tReqInfo, tOperationType);
@@ -201,13 +202,9 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
abortOption = tSimpleIndicator ? IgnoreError : abortOption;
tcKeyReq->setAbortOption(tReqInfo, abortOption);
- Uint8 tDistrKeyIndicator = theDistrKeyIndicator;
- Uint8 tDistrGroupIndicator = theDistrGroupIndicator;
- Uint8 tDistrGroupType = theDistrGroupType;
+ Uint8 tDistrKeyIndicator = theDistrKeyIndicator_;
Uint8 tScanIndicator = theScanInfo & 1;
- tcKeyReq->setDistributionGroupFlag(tReqInfo, tDistrGroupIndicator);
- tcKeyReq->setDistributionGroupTypeFlag(tReqInfo, tDistrGroupType);
tcKeyReq->setDistributionKeyFlag(tReqInfo, tDistrKeyIndicator);
tcKeyReq->setScanIndFlag(tReqInfo, tScanIndicator);
@@ -218,15 +215,13 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
//-------------------------------------------------------------
Uint32* tOptionalDataPtr = &tcKeyReq->scanInfo;
Uint32 tDistrGHIndex = tScanIndicator;
- Uint32 tDistrKeyIndex = tDistrGHIndex + tDistrGroupIndicator;
+ Uint32 tDistrKeyIndex = tDistrGHIndex;
Uint32 tScanInfo = theScanInfo;
- Uint32 tDistributionGroup = theDistributionGroup;
- Uint32 tDistrKeySize = theDistrKeySize;
+ Uint32 tDistrKey = theDistributionKey;
tOptionalDataPtr[0] = tScanInfo;
- tOptionalDataPtr[tDistrGHIndex] = tDistributionGroup;
- tOptionalDataPtr[tDistrKeyIndex] = tDistrKeySize;
+ tOptionalDataPtr[tDistrKeyIndex] = tDistrKey;
//-------------------------------------------------------------
// The next is step is to compress the key data part of the
@@ -266,7 +261,7 @@ NdbOperation::prepareSend(Uint32 aTC_ConnectPtr, Uint64 aTransId)
/**
* Set transid, TC connect ptr and length in the KEYINFO signals
*/
- NdbApiSignal* tSignal = theFirstKEYINFO;
+ NdbApiSignal* tSignal = theTCREQ->next();
Uint32 remainingKey = tTupKeyLen - TcKeyReq::MaxKeyInfo;
do {
Uint32* tSigDataPtr = tSignal->getDataPtrSend();
@@ -541,17 +536,20 @@ NdbOperation::receiveTCKEYREF( NdbApiSignal* aSignal)
return -1;
}//if
- AbortOption ao = (AbortOption)theNdbCon->m_abortOption;
+ AbortOption ao = (AbortOption)
+ (m_abortOption != -1 ? m_abortOption : theNdbCon->m_abortOption);
theReceiver.m_received_result_length = ~0;
theStatus = Finished;
- theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
+ // blobs want this
+ if (m_abortOption != IgnoreError)
+ theNdbCon->theReturnStatus = NdbConnection::ReturnFailure;
theError.code = aSignal->readData(4);
- theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4));
+ theNdbCon->setOperationErrorCodeAbort(aSignal->readData(4), m_abortOption);
if(theOperationType != ReadRequest || !theSimpleIndicator) // not simple read
- return theNdbCon->OpCompleteFailure(ao);
+ return theNdbCon->OpCompleteFailure(ao, m_abortOption != IgnoreError);
/**
* If TCKEYCONF has arrived
diff --git a/ndb/src/ndbapi/NdbOperationSearch.cpp b/ndb/src/ndbapi/NdbOperationSearch.cpp
index 69b4e803acd..7ae5bd70a11 100644
--- a/ndb/src/ndbapi/NdbOperationSearch.cpp
+++ b/ndb/src/ndbapi/NdbOperationSearch.cpp
@@ -38,7 +38,9 @@ Adjust: 971022 UABMNST First version.
#include <AttributeHeader.hpp>
#include <signaldata/TcKeyReq.hpp>
+#include <signaldata/KeyInfo.hpp>
#include "NdbDictionaryImpl.hpp"
+#include <md5_hash.hpp>
/******************************************************************************
CondIdType equal(const char* anAttrName, char* aValue, Uint32 aVarKeylen);
@@ -60,8 +62,8 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
Uint32 tData;
Uint32 tKeyInfoPosition;
const char* aValue = aValuePassed;
- Uint32 xfrmData[1024];
- Uint32 tempData[1024];
+ Uint64 xfrmData[512];
+ Uint64 tempData[512];
if ((theStatus == OperationDefined) &&
(aValue != NULL) &&
@@ -76,6 +78,8 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
*****************************************************************************/
tAttrId = tAttrInfo->m_attrId;
tKeyInfoPosition = tAttrInfo->m_keyInfoPos;
+ bool tDistrKey = tAttrInfo->m_distributionKey;
+
Uint32 i = 0;
if (tAttrInfo->m_pk) {
Uint32 tKeyDefined = theTupleKeyDefined[0][2];
@@ -119,30 +123,30 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
{
- /***************************************************************************
- * Check if the pointer of the value passed is aligned on a 4 byte
- * boundary. If so only assign the pointer to the internal variable
- * aValue. If it is not aligned then we start by copying the value to
- * tempData and use this as aValue instead.
- *****************************************************************************/
+ /************************************************************************
+ * Check if the pointer of the value passed is aligned on a 4 byte
+ * boundary. If so only assign the pointer to the internal variable
+ * aValue. If it is not aligned then we start by copying the value to
+ * tempData and use this as aValue instead.
+ ***********************************************************************/
const int attributeSize = sizeInBytes;
const int slack = sizeInBytes & 3;
-
- if ((((UintPtr)aValue & 3) != 0) || (slack != 0)){
+ const int align = UintPtr(aValue) & 7;
+
+ if (((align & 3) != 0) || (slack != 0) || (tDistrKey && (align != 0)))
+ {
+ ((Uint32*)tempData)[attributeSize >> 2] = 0;
memcpy(&tempData[0], aValue, attributeSize);
aValue = (char*)&tempData[0];
- if(slack != 0) {
- char * tmp = (char*)&tempData[0];
- memset(&tmp[attributeSize], 0, (4 - slack));
- }//if
}//if
}
const char* aValueToWrite = aValue;
-
+
CHARSET_INFO* cs = tAttrInfo->m_cs;
if (cs != 0) {
// current limitation: strxfrm does not increase length
- assert(cs->strxfrm_multiply == 1);
+ assert(cs->strxfrm_multiply <= 1);
+ ((Uint32*)xfrmData)[sizeInBytes >> 2] = 0;
unsigned n =
(*cs->coll->strnxfrm)(cs,
(uchar*)xfrmData, sizeof(xfrmData),
@@ -152,9 +156,7 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
aValue = (char*)xfrmData;
}
- Uint32 bitsInLastWord = 8 * (sizeInBytes & 3) ;
Uint32 totalSizeInWords = (sizeInBytes + 3)/4; // Inc. bits in last word
- Uint32 sizeInWords = sizeInBytes / 4; // Exc. bits in last word
if (true){ //tArraySize != 0) {
Uint32 tTupKeyLen = theTupKeyLen;
@@ -190,84 +192,62 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
}//if
#endif
- int tDistrKey = tAttrInfo->m_distributionKey;
- int tDistrGroup = tAttrInfo->m_distributionGroup;
OperationType tOpType = theOperationType;
- if ((tDistrKey != 1) && (tDistrGroup != 1)) {
- ;
- } else if (tDistrKey == 1) {
- theDistrKeySize += totalSizeInWords;
- theDistrKeyIndicator = 1;
- } else {
- Uint32 TsizeInBytes = sizeInBytes;
- Uint32 TbyteOrderFix = 0;
- char* TcharByteOrderFix = (char*)&TbyteOrderFix;
- if (tAttrInfo->m_distributionGroupBits == 8) {
- char tFirstChar = aValue[TsizeInBytes - 2];
- char tSecondChar = aValue[TsizeInBytes - 2];
- TcharByteOrderFix[0] = tFirstChar;
- TcharByteOrderFix[1] = tSecondChar;
- TcharByteOrderFix[2] = 0x30;
- TcharByteOrderFix[3] = 0x30;
- theDistrGroupType = 0;
- } else {
- TbyteOrderFix = ((aValue[TsizeInBytes - 2] - 0x30) * 10)
- + (aValue[TsizeInBytes - 1] - 0x30);
- theDistrGroupType = 1;
- }//if
- theDistributionGroup = TbyteOrderFix;
- theDistrGroupIndicator = 1;
- }//if
- /******************************************************************************
+ /**************************************************************************
* If the operation is an insert request and the attribute is stored then
* we also set the value in the stored part through putting the
* information in the ATTRINFO signals.
- *****************************************************************************/
+ *************************************************************************/
if ((tOpType == InsertRequest) ||
(tOpType == WriteRequest)) {
- if (!tAttrInfo->m_indexOnly){
- // invalid data can crash kernel
- if (cs != NULL &&
- (*cs->cset->well_formed_len)(cs,
- aValueToWrite,
- aValueToWrite + sizeInBytes,
- sizeInBytes) != sizeInBytes)
- goto equal_error4;
- Uint32 ahValue;
- const Uint32 sz = totalSizeInWords;
+ // invalid data can crash kernel
+ if (cs != NULL &&
+ (*cs->cset->well_formed_len)(cs,
+ aValueToWrite,
+ aValueToWrite + sizeInBytes,
+ sizeInBytes) != sizeInBytes)
+ goto equal_error4;
+ Uint32 ahValue;
+ const Uint32 sz = totalSizeInWords;
+
+ // XXX
+ if(m_accessTable == m_currentTable)
+ {
AttributeHeader::init(&ahValue, tAttrId, sz);
- insertATTRINFO( ahValue );
- insertATTRINFOloop((Uint32*)aValueToWrite, sizeInWords);
- if (bitsInLastWord != 0) {
- tData = *(Uint32*)(aValueToWrite + (sizeInWords << 2));
- tData = convertEndian(tData);
- tData = tData & ((1 << bitsInLastWord) - 1);
- tData = convertEndian(tData);
- insertATTRINFO( tData );
- }//if
- }//if
+ }
+ else
+ {
+ assert(m_accessTable->m_index);
+ int attr_id_current_table =
+ m_accessTable->m_index->m_columns[tAttrId]->m_keyInfoPos;
+ AttributeHeader::init(&ahValue, attr_id_current_table, sz);
+ }
+
+ insertATTRINFO( ahValue );
+ insertATTRINFOloop((Uint32*)aValueToWrite, sz);
}//if
- /***************************************************************************
+ /**************************************************************************
* Store the Key information in the TCKEYREQ and KEYINFO signals.
- **************************************************************************/
- if (insertKEYINFO(aValue, tKeyInfoPosition,
- totalSizeInWords, bitsInLastWord) != -1) {
- /*************************************************************************
+ *************************************************************************/
+ if (insertKEYINFO(aValue, tKeyInfoPosition, totalSizeInWords) != -1) {
+ /************************************************************************
* Add one to number of tuple key attributes defined.
* If all have been defined then set the operation state to indicate
* that tuple key is defined.
* Thereby no more search conditions are allowed in this version.
- ************************************************************************/
- Uint32 tNoKeysDef = theNoOfTupKeyDefined;
+ ***********************************************************************/
+ Uint32 tNoKeysDef = theNoOfTupKeyLeft - 1;
Uint32 tErrorLine = theErrorLine;
- int tNoTableKeys = m_currentTable->m_noOfKeys;
unsigned char tInterpretInd = theInterpretIndicator;
- tNoKeysDef++;
- theNoOfTupKeyDefined = tNoKeysDef;
+ theNoOfTupKeyLeft = tNoKeysDef;
tErrorLine++;
theErrorLine = tErrorLine;
- if (int(tNoKeysDef) == tNoTableKeys) {
+
+ if(tDistrKey)
+ handle_distribution_key((Uint64*)aValue, totalSizeInWords);
+
+ if (tNoKeysDef == 0) {
if (tOpType == UpdateRequest) {
if (tInterpretInd == 1) {
theStatus = GetValue;
@@ -297,13 +277,14 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
setErrorCodeAbort(4005);
return -1;
}//if
+ return 0;
}//if
- return 0;
} else {
return -1;
}//if
+ return 0;
}
-
+
if (aValue == NULL) {
// NULL value in primary key
setErrorCodeAbort(4505);
@@ -321,6 +302,8 @@ NdbOperation::equal_impl(const NdbColumnImpl* tAttrInfo,
setErrorCodeAbort(4225);
return -1;
}//if
+
+ ndbout_c("theStatus: %d", theStatus);
// If we come here, set a general errorcode
// and exit
@@ -387,8 +370,7 @@ NdbOperation::setTupleId()
int
NdbOperation::insertKEYINFO(const char* aValue,
register Uint32 aStartPosition,
- register Uint32 anAttrSizeInWords,
- register Uint32 anAttrBitsInLastWord)
+ register Uint32 anAttrSizeInWords)
{
NdbApiSignal* tSignal;
NdbApiSignal* tCurrentKEYINFO;
@@ -408,7 +390,7 @@ NdbOperation::insertKEYINFO(const char* aValue,
*****************************************************************************/
tEndPos = aStartPosition + anAttrSizeInWords - 1;
- if ((tEndPos < 9) && (anAttrBitsInLastWord == 0)) {
+ if ((tEndPos < 9)) {
register Uint32 tkeyData = *(Uint32*)aValue;
//TcKeyReq* tcKeyReq = CAST_PTR(TcKeyReq, tTCREQ->getDataPtrSend());
register Uint32* tDataPtr = (Uint32*)aValue;
@@ -449,10 +431,11 @@ NdbOperation::insertKEYINFO(const char* aValue,
setErrorCodeAbort(4001);
return -1;
}
- if (theFirstKEYINFO != NULL)
+ if (theTCREQ->next() != NULL)
theLastKEYINFO->next(tSignal);
else
- theFirstKEYINFO = tSignal;
+ theTCREQ->next(tSignal);
+
theLastKEYINFO = tSignal;
theLastKEYINFO->next(NULL);
theTotalNrOfKeyWordInSignal += 20;
@@ -465,7 +448,7 @@ NdbOperation::insertKEYINFO(const char* aValue,
* this is the first word in a KEYINFO signal. *
*****************************************************************************/
tPosition = aStartPosition;
- tCurrentKEYINFO = theFirstKEYINFO;
+ tCurrentKEYINFO = theTCREQ->next();
/*****************************************************************************
* Start by filling up Key information in the 8 words allocated in the *
@@ -518,39 +501,20 @@ NdbOperation::insertKEYINFO(const char* aValue,
} while (1);
LastWordLabel:
-
-/*****************************************************************************
- * There could be a last word that only contains partial data. This word*
- * will contain zeroes in the rest of the bits since the index expects *
- * a certain number of words and do not care for parts of words. *
- *****************************************************************************/
- if (anAttrBitsInLastWord != 0) {
- tData = *(Uint32*)(aValue + (anAttrSizeInWords - 1) * 4);
- tData = convertEndian(tData);
- tData = tData & ((1 << anAttrBitsInLastWord) - 1);
- tData = convertEndian(tData);
- if (tPosition > 8) {
- tCurrentKEYINFO->setData(tData, signalCounter);
- signalCounter++;
- } else {
- theTCREQ->setData(tData, (12 + tPosition));
- }//if
- }//if
-
return 0;
}
int
NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
{
- assert(m_accessTable != 0 && m_accessTable->m_sizeOfKeysInWords != 0);
- assert(m_accessTable->m_sizeOfKeysInWords == size);
+ assert(m_accessTable != 0 && m_accessTable->m_keyLenInWords != 0);
+ assert(m_accessTable->m_keyLenInWords == size);
unsigned pos = 0;
while (pos < 8 && pos < size) {
data[pos] = theKEYINFOptr[pos];
pos++;
}
- NdbApiSignal* tSignal = theFirstKEYINFO;
+ NdbApiSignal* tSignal = theTCREQ->next();
unsigned n = 0;
while (pos < size) {
if (n == 20) {
@@ -561,3 +525,113 @@ NdbOperation::getKeyFromTCREQ(Uint32* data, unsigned size)
}
return 0;
}
+
+int
+NdbOperation::handle_distribution_key(const Uint64* value, Uint32 len)
+{
+ if(theDistrKeyIndicator_ == 1 ||
+ (theNoOfTupKeyLeft > 0 && m_accessTable->m_noOfDistributionKeys > 1))
+ {
+ return 0;
+ }
+
+ if(m_accessTable->m_noOfDistributionKeys == 1)
+ {
+ setPartitionHash(value, len);
+ }
+ else
+ {
+ /**
+ * Copy distribution key to linear memory
+ */
+ NdbColumnImpl* const * cols = m_accessTable->m_columns.getBase();
+ Uint32 len = 0;
+ Uint64 tmp[1000];
+
+ Uint32 chunk = 8;
+ Uint32* dst = (Uint32*)tmp;
+ NdbApiSignal* tSignal = theTCREQ;
+ Uint32* src = ((TcKeyReq*)tSignal->getDataPtrSend())->keyInfo;
+ if(tSignal->readSignalNumber() == GSN_SCAN_TABREQ)
+ {
+ tSignal = tSignal->next();
+ src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ chunk = KeyInfo::DataLength;
+ }
+
+ for(unsigned i = m_accessTable->m_columns.size(); i>0; cols++, i--)
+ {
+ if (!(* cols)->getPrimaryKey())
+ continue;
+
+ NdbColumnImpl* tAttrInfo = * cols;
+ Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ Uint32 currLen = (sizeInBytes + 3) >> 2;
+ if (tAttrInfo->getDistributionKey())
+ {
+ while (currLen >= chunk)
+ {
+ memcpy(dst, src, 4*chunk);
+ dst += chunk;
+ tSignal = tSignal->next();
+ src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ currLen -= chunk;
+ chunk = KeyInfo::DataLength;
+ }
+
+ memcpy(dst, src, 4*currLen);
+ dst += currLen;
+ src += currLen;
+ chunk -= currLen;
+ }
+ else
+ {
+ while (currLen >= chunk)
+ {
+ tSignal = tSignal->next();
+ src = ((KeyInfo*)tSignal->getDataPtrSend())->keyData;
+ currLen -= chunk;
+ chunk = KeyInfo::DataLength;
+ }
+
+ src += currLen;
+ chunk -= currLen;
+ }
+ }
+ setPartitionHash(tmp, dst - (Uint32*)tmp);
+ }
+ return 0;
+}
+
+void
+NdbOperation::setPartitionHash(Uint32 value)
+{
+ union {
+ Uint32 tmp32;
+ Uint64 tmp64;
+ };
+
+ tmp32 = value;
+ setPartitionHash(&tmp64, 1);
+}
+
+void
+NdbOperation::setPartitionHash(const Uint64* value, Uint32 len)
+{
+ Uint32 buf[4];
+ md5_hash(buf, value, len);
+ setPartitionId(buf[1]);
+}
+
+void
+NdbOperation::setPartitionId(Uint32 value)
+{
+ theDistributionKey = value;
+ theDistrKeyIndicator_ = 1;
+}
+
+Uint32
+NdbOperation::getPartitionId() const
+{
+ return theDistributionKey;
+}
diff --git a/ndb/src/ndbapi/NdbResultSet.cpp b/ndb/src/ndbapi/NdbResultSet.cpp
index f270584d227..d9d71464026 100644
--- a/ndb/src/ndbapi/NdbResultSet.cpp
+++ b/ndb/src/ndbapi/NdbResultSet.cpp
@@ -44,10 +44,10 @@ void NdbResultSet::init()
{
}
-int NdbResultSet::nextResult(bool fetchAllowed)
+int NdbResultSet::nextResult(bool fetchAllowed, bool forceSend)
{
int res;
- if ((res = m_operation->nextResult(fetchAllowed)) == 0) {
+ if ((res = m_operation->nextResult(fetchAllowed, forceSend)) == 0) {
// handle blobs
NdbBlob* tBlob = m_operation->theBlobList;
while (tBlob != 0) {
@@ -67,9 +67,9 @@ int NdbResultSet::nextResult(bool fetchAllowed)
return res;
}
-void NdbResultSet::close()
+void NdbResultSet::close(bool forceSend)
{
- m_operation->closeScan();
+ m_operation->closeScan(forceSend);
}
NdbOperation*
@@ -98,6 +98,6 @@ NdbResultSet::deleteTuple(NdbConnection * takeOverTrans){
}
int
-NdbResultSet::restart(){
- return m_operation->restart();
+NdbResultSet::restart(bool forceSend){
+ return m_operation->restart(forceSend);
}
diff --git a/ndb/src/ndbapi/NdbScanOperation.cpp b/ndb/src/ndbapi/NdbScanOperation.cpp
index fd63ce96f25..f4973b2e66f 100644
--- a/ndb/src/ndbapi/NdbScanOperation.cpp
+++ b/ndb/src/ndbapi/NdbScanOperation.cpp
@@ -35,6 +35,8 @@
#include <signaldata/AttrInfo.hpp>
#include <signaldata/TcKeyReq.hpp>
+#define DEBUG_NEXT_RESULT 0
+
NdbScanOperation::NdbScanOperation(Ndb* aNdb) :
NdbOperation(aNdb),
m_resultSet(0),
@@ -118,7 +120,7 @@ NdbScanOperation::init(const NdbTableImpl* tab, NdbConnection* myConnection)
theStatus = GetValue;
theOperationType = OpenScanRequest;
theNdbCon->theMagicNumber = 0xFE11DF;
-
+ theNoOfTupKeyLeft = tab->m_noOfDistributionKeys;
return 0;
}
@@ -127,7 +129,6 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
Uint32 parallel)
{
m_ordered = 0;
-
Uint32 fragCount = m_currentTable->m_fragmentCount;
if (parallel > fragCount || parallel == 0) {
@@ -199,6 +200,7 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
return 0;
}//if
+ theSCAN_TABREQ->setSignal(GSN_SCAN_TABREQ);
ScanTabReq * req = CAST_PTR(ScanTabReq, theSCAN_TABREQ->getDataPtrSend());
req->apiConnectPtr = theNdbCon->theTCConPtr;
req->tableId = m_accessTable->m_tableId;
@@ -219,10 +221,11 @@ NdbResultSet* NdbScanOperation::readTuples(NdbScanOperation::LockMode lm,
req->transId1 = (Uint32) transId;
req->transId2 = (Uint32) (transId >> 32);
- NdbApiSignal* tSignal =
- theFirstKEYINFO;
-
- theFirstKEYINFO = (tSignal ? tSignal : tSignal = theNdb->getSignal());
+ NdbApiSignal* tSignal = theSCAN_TABREQ->next();
+ if(!tSignal)
+ {
+ theSCAN_TABREQ->next(tSignal = theNdb->getSignal());
+ }
theLastKEYINFO = tSignal;
tSignal->setSignal(GSN_KEYINFO);
@@ -275,6 +278,9 @@ NdbScanOperation::fix_receivers(Uint32 parallel){
void
NdbScanOperation::receiver_delivered(NdbReceiver* tRec){
if(theError.code == 0){
+ if(DEBUG_NEXT_RESULT)
+ ndbout_c("receiver_delivered");
+
Uint32 idx = tRec->m_list_index;
Uint32 last = m_sent_receivers_count - 1;
if(idx != last){
@@ -298,6 +304,9 @@ NdbScanOperation::receiver_delivered(NdbReceiver* tRec){
void
NdbScanOperation::receiver_completed(NdbReceiver* tRec){
if(theError.code == 0){
+ if(DEBUG_NEXT_RESULT)
+ ndbout_c("receiver_completed");
+
Uint32 idx = tRec->m_list_index;
Uint32 last = m_sent_receivers_count - 1;
if(idx != last){
@@ -348,60 +357,6 @@ NdbScanOperation::getFirstATTRINFOScan()
#define FAKE_PTR 2
#define API_PTR 3
-
-/*
- * After setBound() are done, move the accumulated ATTRINFO signals to
- * a separate list. Then continue with normal scan.
- */
-#if 0
-int
-NdbIndexScanOperation::saveBoundATTRINFO()
-{
- theCurrentATTRINFO->setLength(theAI_LenInCurrAI);
- theBoundATTRINFO = theFirstATTRINFO;
- theTotalBoundAI_Len = theTotalCurrAI_Len;
- theTotalCurrAI_Len = 5;
- theBoundATTRINFO->setData(theTotalBoundAI_Len, 4);
- theBoundATTRINFO->setData(0, 5);
- theBoundATTRINFO->setData(0, 6);
- theBoundATTRINFO->setData(0, 7);
- theBoundATTRINFO->setData(0, 8);
- theStatus = GetValue;
-
- int res = getFirstATTRINFOScan();
-
- /**
- * Define each key with getValue (if ordered)
- * unless the one's with EqBound
- */
- if(!res && m_ordered){
-
- /**
- * If setBound EQ
- */
- Uint32 i = 0;
- while(theTupleKeyDefined[i][0] == SETBOUND_EQ)
- i++;
-
-
- Uint32 cnt = m_accessTable->getNoOfColumns() - 1;
- m_sort_columns = cnt - i;
- for(; i<cnt; i++){
- const NdbColumnImpl* key = m_accessTable->m_index->m_columns[i];
- const NdbColumnImpl* col = m_currentTable->getColumn(key->m_keyInfoPos);
- NdbRecAttr* tmp = NdbScanOperation::getValue_impl(col, (char*)-1);
- UintPtr newVal = UintPtr(tmp);
- theTupleKeyDefined[i][0] = FAKE_PTR;
- theTupleKeyDefined[i][1] = (newVal & 0xFFFFFFFF);
-#if (SIZEOF_CHARP == 8)
- theTupleKeyDefined[i][2] = (newVal >> 32);
-#endif
- }
- }
- return res;
-}
-#endif
-
#define WAITFOR_SCAN_TIMEOUT 120000
int
@@ -445,12 +400,12 @@ NdbScanOperation::executeCursor(int nodeId){
return -1;
}
-#define DEBUG_NEXT_RESULT 0
-int NdbScanOperation::nextResult(bool fetchAllowed)
+int NdbScanOperation::nextResult(bool fetchAllowed, bool forceSend)
{
if(m_ordered)
- return ((NdbIndexScanOperation*)this)->next_result_ordered(fetchAllowed);
+ return ((NdbIndexScanOperation*)this)->next_result_ordered(fetchAllowed,
+ forceSend);
/**
* Check current receiver
@@ -486,8 +441,12 @@ int NdbScanOperation::nextResult(bool fetchAllowed)
Uint32 nodeId = theNdbCon->theDBnode;
TransporterFacade* tp = TransporterFacade::instance();
Guard guard(tp->theMutexPtr);
+ if(theError.code)
+ return -1;
+
Uint32 seq = theNdbCon->theNodeSequence;
- if(seq == tp->getNodeSequence(nodeId) && send_next_scan(idx, false) == 0){
+ if(seq == tp->getNodeSequence(nodeId) && send_next_scan(idx, false,
+ forceSend) == 0){
idx = m_current_api_receiver;
last = m_api_receivers_count;
@@ -578,8 +537,9 @@ int NdbScanOperation::nextResult(bool fetchAllowed)
}
int
-NdbScanOperation::send_next_scan(Uint32 cnt, bool stopScanFlag){
- if(cnt > 0 || stopScanFlag){
+NdbScanOperation::send_next_scan(Uint32 cnt, bool stopScanFlag,
+ bool forceSend){
+ if(cnt > 0){
NdbApiSignal tSignal(theNdb->theMyRef);
tSignal.setSignal(GSN_SCAN_NEXTREQ);
@@ -595,38 +555,57 @@ NdbScanOperation::send_next_scan(Uint32 cnt, bool stopScanFlag){
*/
Uint32 last = m_sent_receivers_count;
Uint32 * prep_array = (cnt > 21 ? m_prepared_receivers : theData + 4);
+ Uint32 sent = 0;
for(Uint32 i = 0; i<cnt; i++){
NdbReceiver * tRec = m_api_receivers[i];
- m_sent_receivers[last+i] = tRec;
- tRec->m_list_index = last+i;
- prep_array[i] = tRec->m_tcPtrI;
- tRec->prepareSend();
+ if((prep_array[sent] = tRec->m_tcPtrI) != RNIL)
+ {
+ m_sent_receivers[last+sent] = tRec;
+ tRec->m_list_index = last+sent;
+ tRec->prepareSend();
+ sent++;
+ }
}
- memcpy(&m_api_receivers[0], &m_api_receivers[cnt], cnt * sizeof(char*));
+ memmove(m_api_receivers, m_api_receivers+cnt,
+ (theParallelism-cnt) * sizeof(char*));
- Uint32 nodeId = theNdbCon->theDBnode;
- TransporterFacade * tp = TransporterFacade::instance();
- int ret;
- if(cnt > 21){
- tSignal.setLength(4);
- LinearSectionPtr ptr[3];
- ptr[0].p = prep_array;
- ptr[0].sz = cnt;
- ret = tp->sendFragmentedSignal(&tSignal, nodeId, ptr, 1);
- } else {
- tSignal.setLength(4+cnt);
- ret = tp->sendSignal(&tSignal, nodeId);
+ int ret = 0;
+ if(sent)
+ {
+ Uint32 nodeId = theNdbCon->theDBnode;
+ TransporterFacade * tp = TransporterFacade::instance();
+ if(cnt > 21){
+ tSignal.setLength(4);
+ LinearSectionPtr ptr[3];
+ ptr[0].p = prep_array;
+ ptr[0].sz = sent;
+ ret = tp->sendSignal(&tSignal, nodeId, ptr, 1);
+ } else {
+ tSignal.setLength(4+sent);
+ ret = tp->sendSignal(&tSignal, nodeId);
+ }
}
+
+ if (!ret) checkForceSend(forceSend);
- m_sent_receivers_count = last + cnt + stopScanFlag;
+ m_sent_receivers_count = last + sent;
m_api_receivers_count -= cnt;
m_current_api_receiver = 0;
-
+
return ret;
}
return 0;
}
+void NdbScanOperation::checkForceSend(bool forceSend)
+{
+ if (forceSend) {
+ TransporterFacade::instance()->forceSend(theNdb->theNdbBlockNumber);
+ } else {
+ TransporterFacade::instance()->checkForceSend(theNdb->theNdbBlockNumber);
+ }//if
+}
+
int
NdbScanOperation::prepareSend(Uint32 TC_ConnectPtr, Uint64 TransactionId)
{
@@ -642,7 +621,7 @@ NdbScanOperation::doSend(int ProcessorId)
return 0;
}
-void NdbScanOperation::closeScan()
+void NdbScanOperation::closeScan(bool forceSend)
{
if(m_transConnection){
if(DEBUG_NEXT_RESULT)
@@ -657,7 +636,7 @@ void NdbScanOperation::closeScan()
TransporterFacade* tp = TransporterFacade::instance();
Guard guard(tp->theMutexPtr);
- close_impl(tp);
+ close_impl(tp, forceSend);
} while(0);
@@ -670,7 +649,6 @@ void NdbScanOperation::closeScan()
void
NdbScanOperation::execCLOSE_SCAN_REP(){
- m_api_receivers_count = 0;
m_conf_receivers_count = 0;
m_sent_receivers_count = 0;
}
@@ -683,12 +661,14 @@ void NdbScanOperation::release()
for(Uint32 i = 0; i<m_allocated_receivers; i++){
m_receivers[i]->release();
}
+
+ NdbOperation::release();
+
if(theSCAN_TABREQ)
{
theNdb->releaseSignal(theSCAN_TABREQ);
theSCAN_TABREQ = 0;
}
- NdbOperation::release();
}
/***************************************************************************
@@ -783,10 +763,6 @@ NdbScanOperation::doSendScan(int aProcessorId)
assert(theSCAN_TABREQ != NULL);
tSignal = theSCAN_TABREQ;
- if (tSignal->setSignal(GSN_SCAN_TABREQ) == -1) {
- setErrorCode(4001);
- return -1;
- }
Uint32 tupKeyLen = theTupKeyLen;
Uint32 len = theTotalNrOfKeyWordInSignal;
@@ -798,12 +774,16 @@ NdbScanOperation::doSendScan(int aProcessorId)
// we created the ATTRINFO signals after the SCAN_TABREQ signal.
ScanTabReq * const req = CAST_PTR(ScanTabReq, tSignal->getDataPtrSend());
req->attrLenKeyLen = (tupKeyLen << 16) | theTotalCurrAI_Len;
+ Uint32 tmp = req->requestInfo;
+ ScanTabReq::setDistributionKeyFlag(tmp, theDistrKeyIndicator_);
+ req->distributionKey = theDistributionKey;
+ tSignal->setLength(ScanTabReq::StaticLength + theDistrKeyIndicator_);
TransporterFacade *tp = TransporterFacade::instance();
LinearSectionPtr ptr[3];
ptr[0].p = m_prepared_receivers;
ptr[0].sz = theParallelism;
- if (tp->sendFragmentedSignal(tSignal, aProcessorId, ptr, 1) == -1) {
+ if (tp->sendSignal(tSignal, aProcessorId, ptr, 1) == -1) {
setErrorCode(4002);
return -1;
}
@@ -814,8 +794,8 @@ NdbScanOperation::doSendScan(int aProcessorId)
tSignal = theLastKEYINFO;
tSignal->setLength(KeyInfo::HeaderLength + theTotalNrOfKeyWordInSignal);
- assert(theFirstKEYINFO != NULL);
- tSignal = theFirstKEYINFO;
+ assert(theSCAN_TABREQ->next() != NULL);
+ tSignal = theSCAN_TABREQ->next();
NdbApiSignal* last;
do {
@@ -850,6 +830,14 @@ NdbScanOperation::doSendScan(int aProcessorId)
tSignal = tSignal->next();
}
theStatus = WaitResponse;
+
+ m_sent_receivers_count = theParallelism;
+ if(m_ordered)
+ {
+ m_current_api_receiver = theParallelism;
+ m_api_receivers_count = theParallelism;
+ }
+
return tSignalCount;
}//NdbOperation::doSendScan()
@@ -924,11 +912,11 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
const Uint32 * src = (Uint32*)tRecAttr->aRef();
const Uint32 tScanInfo = src[len] & 0x3FFFF;
- const Uint32 tTakeOverNode = src[len] >> 20;
+ const Uint32 tTakeOverFragment = src[len] >> 20;
{
UintR scanInfo = 0;
TcKeyReq::setTakeOverScanFlag(scanInfo, 1);
- TcKeyReq::setTakeOverScanNode(scanInfo, tTakeOverNode);
+ TcKeyReq::setTakeOverScanFragment(scanInfo, tTakeOverFragment);
TcKeyReq::setTakeOverScanInfo(scanInfo, tScanInfo);
newOp->theScanInfo = scanInfo;
}
@@ -942,7 +930,7 @@ NdbScanOperation::takeOverScanOp(OperationType opType, NdbConnection* pTrans){
if(i < len){
NdbApiSignal* tSignal = theNdb->getSignal();
- newOp->theFirstKEYINFO = tSignal;
+ newOp->theTCREQ->next(tSignal);
Uint32 left = len - i;
while(tSignal && left > KeyInfo::DataLength){
@@ -1077,37 +1065,51 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
Uint32 currLen = theTotalNrOfKeyWordInSignal;
Uint32 remaining = KeyInfo::DataLength - currLen;
Uint32 sizeInBytes = tAttrInfo->m_attrSize * tAttrInfo->m_arraySize;
+ bool tDistrKey = tAttrInfo->m_distributionKey;
+ len = aValue != NULL ? sizeInBytes : 0;
+ if (len != sizeInBytes && (len != 0)) {
+ setErrorCodeAbort(4209);
+ return -1;
+ }
+
// normalize char bound
CHARSET_INFO* cs = tAttrInfo->m_cs;
- Uint32 xfrmData[2000];
+ Uint64 xfrmData[1001];
if (cs != NULL && aValue != NULL) {
// current limitation: strxfrm does not increase length
- assert(cs->strxfrm_multiply == 1);
+ assert(cs->strxfrm_multiply <= 1);
+ ((Uint32*)xfrmData)[len >> 2] = 0;
unsigned n =
- (*cs->coll->strnxfrm)(cs,
+ (*cs->coll->strnxfrm)(cs,
(uchar*)xfrmData, sizeof(xfrmData),
- (const uchar*)aValue, sizeInBytes);
- while (n < sizeInBytes)
+ (const uchar*)aValue, len);
+
+ while (n < len)
((uchar*)xfrmData)[n++] = 0x20;
+
+ if(len & 3)
+ {
+ len += (4 - (len & 3));
+ }
+
aValue = (char*)xfrmData;
}
- if (len != sizeInBytes && (len != 0)) {
- setErrorCodeAbort(4209);
- return -1;
- }
+
// insert attribute header
- len = aValue != NULL ? sizeInBytes : 0;
Uint32 tIndexAttrId = tAttrInfo->m_attrId;
Uint32 sizeInWords = (len + 3) / 4;
AttributeHeader ah(tIndexAttrId, sizeInWords);
const Uint32 ahValue = ah.m_value;
- const bool aligned = (UintPtr(aValue) & 3) == 0;
+ const Uint32 align = (UintPtr(aValue) & 7);
+ const bool aligned = (tDistrKey && type == BoundEQ) ?
+ (align == 0) : (align & 3) == 0;
+
const bool nobytes = (len & 0x3) == 0;
const Uint32 totalLen = 2 + sizeInWords;
Uint32 tupKeyLen = theTupKeyLen;
- if(remaining > totalLen && aligned && nobytes){
+ if(remaining > totalLen && aligned && nobytes){
Uint32 * dst = theKEYINFOptr + currLen;
* dst ++ = type;
* dst ++ = ahValue;
@@ -1115,12 +1117,12 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
theTotalNrOfKeyWordInSignal = currLen + totalLen;
} else {
if(!aligned || !nobytes){
- Uint32 tempData[2002];
+ Uint32 *tempData = (Uint32*)xfrmData;
tempData[0] = type;
tempData[1] = ahValue;
+ tempData[2 + (len >> 2)] = 0;
memcpy(tempData+2, aValue, len);
- while ((len & 0x3) != 0)
- ((char*)&tempData[2])[len++] = 0;
+
insertBOUNDS(tempData, 2+sizeInWords);
} else {
Uint32 buf[2] = { type, ahValue };
@@ -1139,11 +1141,11 @@ NdbIndexScanOperation::setBound(const NdbColumnImpl* tAttrInfo,
* so it's safe to use [tIndexAttrId]
* (instead of looping as is NdbOperation::equal_impl)
*/
- if(type == BoundEQ && !theTupleKeyDefined[tIndexAttrId][0]){
- theNoOfTupKeyDefined++;
- theTupleKeyDefined[tIndexAttrId][0] = SETBOUND_EQ;
+ if(type == BoundEQ && tDistrKey)
+ {
+ theNoOfTupKeyLeft--;
+ return handle_distribution_key((Uint64*)aValue, sizeInWords);
}
-
return 0;
} else {
setErrorCodeAbort(4228); // XXX wrong code
@@ -1217,6 +1219,9 @@ NdbIndexScanOperation::readTuples(LockMode lm,
#endif
}
}
+ m_this_bound_start = 0;
+ m_first_bound_word = theKEYINFOptr;
+
return rs;
}
@@ -1285,7 +1290,8 @@ NdbIndexScanOperation::compare(Uint32 skip, Uint32 cols,
}
int
-NdbIndexScanOperation::next_result_ordered(bool fetchAllowed){
+NdbIndexScanOperation::next_result_ordered(bool fetchAllowed,
+ bool forceSend){
Uint32 u_idx = 0, u_last = 0;
Uint32 s_idx = m_current_api_receiver; // first sorted
@@ -1309,9 +1315,12 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed){
if(DEBUG_NEXT_RESULT) ndbout_c("performing fetch...");
TransporterFacade* tp = TransporterFacade::instance();
Guard guard(tp->theMutexPtr);
+ if(theError.code)
+ return -1;
Uint32 seq = theNdbCon->theNodeSequence;
Uint32 nodeId = theNdbCon->theDBnode;
- if(seq == tp->getNodeSequence(nodeId) && !send_next_scan_ordered(s_idx)){
+ if(seq == tp->getNodeSequence(nodeId) &&
+ !send_next_scan_ordered(s_idx, forceSend)){
Uint32 tmp = m_sent_receivers_count;
s_idx = m_current_api_receiver;
while(m_sent_receivers_count > 0 && !theError.code){
@@ -1322,6 +1331,13 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed){
continue;
}
if(DEBUG_NEXT_RESULT) ndbout_c("return -1");
+ setErrorCode(4028);
+ return -1;
+ }
+
+ if(theError.code){
+ setErrorCode(theError.code);
+ if(DEBUG_NEXT_RESULT) ndbout_c("return -1");
return -1;
}
@@ -1331,11 +1347,9 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed){
memcpy(arr, m_conf_receivers, u_last * sizeof(char*));
if(DEBUG_NEXT_RESULT) ndbout_c("sent: %d recv: %d", tmp, u_last);
- if(theError.code){
- setErrorCode(theError.code);
- if(DEBUG_NEXT_RESULT) ndbout_c("return -1");
- return -1;
- }
+ } else {
+ setErrorCode(4028);
+ return -1;
}
} else {
if(DEBUG_NEXT_RESULT) ndbout_c("return 2");
@@ -1400,14 +1414,26 @@ NdbIndexScanOperation::next_result_ordered(bool fetchAllowed){
}
int
-NdbIndexScanOperation::send_next_scan_ordered(Uint32 idx){
+NdbIndexScanOperation::send_next_scan_ordered(Uint32 idx, bool forceSend){
if(idx == theParallelism)
return 0;
+ NdbReceiver* tRec = m_api_receivers[idx];
NdbApiSignal tSignal(theNdb->theMyRef);
tSignal.setSignal(GSN_SCAN_NEXTREQ);
+ Uint32 last = m_sent_receivers_count;
Uint32* theData = tSignal.getDataPtrSend();
+ Uint32* prep_array = theData + 4;
+
+ m_current_api_receiver = idx + 1;
+ if((prep_array[0] = tRec->m_tcPtrI) == RNIL)
+ {
+ if(DEBUG_NEXT_RESULT)
+ ndbout_c("receiver completed, don't send");
+ return 0;
+ }
+
theData[0] = theNdbCon->theTCConPtr;
theData[1] = 0;
Uint64 transId = theNdbCon->theTransactionId;
@@ -1417,35 +1443,35 @@ NdbIndexScanOperation::send_next_scan_ordered(Uint32 idx){
/**
* Prepare ops
*/
- Uint32 last = m_sent_receivers_count;
- Uint32 * prep_array = theData + 4;
-
- NdbReceiver * tRec = m_api_receivers[idx];
m_sent_receivers[last] = tRec;
tRec->m_list_index = last;
- prep_array[0] = tRec->m_tcPtrI;
tRec->prepareSend();
-
m_sent_receivers_count = last + 1;
- m_current_api_receiver = idx + 1;
Uint32 nodeId = theNdbCon->theDBnode;
TransporterFacade * tp = TransporterFacade::instance();
tSignal.setLength(4+1);
- return tp->sendSignal(&tSignal, nodeId);
+ int ret= tp->sendSignal(&tSignal, nodeId);
+ if (!ret) checkForceSend(forceSend);
+ return ret;
}
int
-NdbScanOperation::close_impl(TransporterFacade* tp){
+NdbScanOperation::close_impl(TransporterFacade* tp, bool forceSend){
Uint32 seq = theNdbCon->theNodeSequence;
Uint32 nodeId = theNdbCon->theDBnode;
- if(seq != tp->getNodeSequence(nodeId)){
+ if(seq != tp->getNodeSequence(nodeId))
+ {
theNdbCon->theReleaseOnClose = true;
return -1;
}
- while(theError.code == 0 && m_sent_receivers_count){
+ /**
+ * Wait for outstanding
+ */
+ while(theError.code == 0 && m_sent_receivers_count)
+ {
theNdb->theWaiter.m_node = nodeId;
theNdb->theWaiter.m_state = WAIT_SCAN;
int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT);
@@ -1463,18 +1489,59 @@ NdbScanOperation::close_impl(TransporterFacade* tp){
}
}
- if(m_api_receivers_count+m_conf_receivers_count){
- // Send close scan
- if(send_next_scan(0, true) == -1){ // Close scan
- theNdbCon->theReleaseOnClose = true;
- return -1;
- }
+ if(theError.code)
+ {
+ m_api_receivers_count = 0;
+ m_current_api_receiver = m_ordered ? theParallelism : 0;
+ }
+
+
+ /**
+ * move all conf'ed into api
+ * so that send_next_scan can check if they needs to be closed
+ */
+ Uint32 api = m_api_receivers_count;
+ Uint32 conf = m_conf_receivers_count;
+
+ if(m_ordered)
+ {
+ /**
+ * Ordered scan, keep the m_api_receivers "to the right"
+ */
+ memmove(m_api_receivers, m_api_receivers+m_current_api_receiver,
+ (theParallelism - m_current_api_receiver) * sizeof(char*));
+ api = (theParallelism - m_current_api_receiver);
+ m_api_receivers_count = api;
+ }
+
+ if(DEBUG_NEXT_RESULT)
+ ndbout_c("close_impl: [order api conf sent curr parr] %d %d %d %d %d %d",
+ m_ordered, api, conf,
+ m_sent_receivers_count, m_current_api_receiver, theParallelism);
+
+ if(api+conf)
+ {
+ /**
+ * There's something to close
+ * setup m_api_receivers (for send_next_scan)
+ */
+ memcpy(m_api_receivers+api, m_conf_receivers, conf * sizeof(char*));
+ m_api_receivers_count = api + conf;
+ m_conf_receivers_count = 0;
+ }
+
+ // Send close scan
+ if(send_next_scan(api+conf, true, forceSend) == -1)
+ {
+ theNdbCon->theReleaseOnClose = true;
+ return -1;
}
/**
* wait for close scan conf
*/
- while(m_sent_receivers_count+m_api_receivers_count+m_conf_receivers_count){
+ while(m_sent_receivers_count+m_api_receivers_count+m_conf_receivers_count)
+ {
theNdb->theWaiter.m_node = nodeId;
theNdb->theWaiter.m_state = WAIT_SCAN;
int return_code = theNdb->receiveResponse(WAITFOR_SCAN_TIMEOUT);
@@ -1491,6 +1558,7 @@ NdbScanOperation::close_impl(TransporterFacade* tp){
return -1;
}
}
+
return 0;
}
@@ -1507,17 +1575,12 @@ NdbScanOperation::reset_receivers(Uint32 parallell, Uint32 ordered){
m_api_receivers_count = 0;
m_current_api_receiver = 0;
- m_sent_receivers_count = parallell;
+ m_sent_receivers_count = 0;
m_conf_receivers_count = 0;
-
- if(ordered){
- m_current_api_receiver = parallell;
- m_api_receivers_count = parallell;
- }
}
int
-NdbScanOperation::restart()
+NdbScanOperation::restart(bool forceSend)
{
TransporterFacade* tp = TransporterFacade::instance();
@@ -1526,7 +1589,7 @@ NdbScanOperation::restart()
{
int res;
- if((res= close_impl(tp)))
+ if((res= close_impl(tp, forceSend)))
{
return res;
}
@@ -1545,13 +1608,13 @@ NdbScanOperation::restart()
}
int
-NdbIndexScanOperation::reset_bounds(){
+NdbIndexScanOperation::reset_bounds(bool forceSend){
int res;
{
TransporterFacade* tp = TransporterFacade::instance();
Guard guard(tp->theMutexPtr);
- res= close_impl(tp);
+ res= close_impl(tp, forceSend);
}
if(!res)
@@ -1559,10 +1622,14 @@ NdbIndexScanOperation::reset_bounds(){
theError.code = 0;
reset_receivers(theParallelism, m_ordered);
- theLastKEYINFO = theFirstKEYINFO;
- theKEYINFOptr = ((KeyInfo*)theFirstKEYINFO->getDataPtrSend())->keyData;
+ theLastKEYINFO = theSCAN_TABREQ->next();
+ theKEYINFOptr = ((KeyInfo*)theLastKEYINFO->getDataPtrSend())->keyData;
theTupKeyLen = 0;
theTotalNrOfKeyWordInSignal = 0;
+ theNoOfTupKeyLeft = m_accessTable->m_noOfDistributionKeys;
+ theDistrKeyIndicator_ = 0;
+ m_this_bound_start = 0;
+ m_first_bound_word = theKEYINFOptr;
m_transConnection
->remove_list((NdbOperation*&)m_transConnection->m_firstExecutedScanOp,
this);
@@ -1571,3 +1638,15 @@ NdbIndexScanOperation::reset_bounds(){
}
return res;
}
+
+int
+NdbIndexScanOperation::set_new_bound()
+{
+ Uint32 bound_head = * m_first_bound_word;
+ bound_head |= (theTupKeyLen - m_this_bound_start) << 16;
+ * m_first_bound_word = bound_head;
+
+ m_first_bound_word = theKEYINFOptr + theTotalNrOfKeyWordInSignal;;
+ m_this_bound_start = theTupKeyLen;
+ return 0;
+}
diff --git a/ndb/src/ndbapi/Ndbinit.cpp b/ndb/src/ndbapi/Ndbinit.cpp
index 698bbcde4c6..48e62c36a5f 100644
--- a/ndb/src/ndbapi/Ndbinit.cpp
+++ b/ndb/src/ndbapi/Ndbinit.cpp
@@ -58,7 +58,7 @@ Ndb::Ndb( const char* aDataBase , const char* aSchema) {
theNoOfNdbObjects++;
if (global_ndb_cluster_connection == 0) {
global_ndb_cluster_connection= new Ndb_cluster_connection(ndbConnectString);
- global_ndb_cluster_connection->connect();
+ global_ndb_cluster_connection->connect(12,5,1);
}
setup(global_ndb_cluster_connection, aDataBase, aSchema);
DBUG_VOID_RETURN;
diff --git a/ndb/src/ndbapi/TransporterFacade.cpp b/ndb/src/ndbapi/TransporterFacade.cpp
index bc24110ea14..dfb090c8416 100644
--- a/ndb/src/ndbapi/TransporterFacade.cpp
+++ b/ndb/src/ndbapi/TransporterFacade.cpp
@@ -34,6 +34,7 @@
#include <NdbConfig.h>
#include <ndb_version.h>
#include <SignalLoggerManager.hpp>
+#include <kernel/ndb_limits.h>
//#define REPORT_TRANSPORTER
//#define API_TRACE;
@@ -475,7 +476,8 @@ TransporterFacade::TransporterFacade() :
theTransporterRegistry(0),
theStopReceive(0),
theSendThread(NULL),
- theReceiveThread(NULL)
+ theReceiveThread(NULL),
+ m_fragmented_signal_id(0)
{
theOwnId = 0;
@@ -833,9 +835,129 @@ TransporterFacade::sendSignalUnCond(NdbApiSignal * aSignal, NodeId aNode){
return (ss == SEND_OK ? 0 : -1);
}
+#define CHUNK_SZ NDB_SECTION_SEGMENT_SZ*64 // related to MAX_MESSAGE_SIZE
int
TransporterFacade::sendFragmentedSignal(NdbApiSignal* aSignal, NodeId aNode,
- LinearSectionPtr ptr[3], Uint32 secs){
+ LinearSectionPtr ptr[3], Uint32 secs)
+{
+ if(getIsNodeSendable(aNode) != true)
+ return -1;
+
+#ifdef API_TRACE
+ if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){
+ Uint32 tmp = aSignal->theSendersBlockRef;
+ aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId);
+ signalLogger.sendSignal(* aSignal,
+ 1,
+ aSignal->getDataPtrSend(),
+ aNode,
+ ptr, secs);
+ aSignal->theSendersBlockRef = tmp;
+ }
+#endif
+
+ NdbApiSignal tmp_signal(*(SignalHeader*)aSignal);
+ LinearSectionPtr tmp_ptr[3];
+ Uint32 unique_id= m_fragmented_signal_id++; // next unique id
+ unsigned i;
+ for (i= 0; i < secs; i++)
+ tmp_ptr[i]= ptr[i];
+
+ unsigned start_i= 0;
+ unsigned chunk_sz= 0;
+ unsigned fragment_info= 0;
+ Uint32 *tmp_data= tmp_signal.getDataPtrSend();
+ for (i= 0; i < secs;) {
+ unsigned save_sz= tmp_ptr[i].sz;
+ tmp_data[i-start_i]= i;
+ if (chunk_sz + save_sz > CHUNK_SZ) {
+ // truncate
+ unsigned send_sz= CHUNK_SZ - chunk_sz;
+ if (i != start_i) // first piece of a new section has to be a multiple of NDB_SECTION_SEGMENT_SZ
+ {
+ send_sz=
+ NDB_SECTION_SEGMENT_SZ
+ *(send_sz+NDB_SECTION_SEGMENT_SZ-1)
+ /NDB_SECTION_SEGMENT_SZ;
+ if (send_sz > save_sz)
+ send_sz= save_sz;
+ }
+ tmp_ptr[i].sz= send_sz;
+
+ if (fragment_info < 2) // 1 = first fragment, 2 = middle fragments
+ fragment_info++;
+
+ // send tmp_signal
+ tmp_data[i-start_i+1]= unique_id;
+ tmp_signal.setLength(i-start_i+2);
+ tmp_signal.m_fragmentInfo= fragment_info;
+ tmp_signal.m_noOfSections= i-start_i+1;
+ // do prepare send
+ {
+ SendStatus ss = theTransporterRegistry->prepareSend
+ (&tmp_signal,
+ 1, /*JBB*/
+ tmp_data,
+ aNode,
+ &tmp_ptr[start_i]);
+ assert(ss != SEND_MESSAGE_TOO_BIG);
+ if (ss != SEND_OK) return -1;
+ }
+ // setup variables for next signal
+ start_i= i;
+ chunk_sz= 0;
+ tmp_ptr[i].sz= save_sz-send_sz;
+ tmp_ptr[i].p+= send_sz;
+ if (tmp_ptr[i].sz == 0)
+ i++;
+ }
+ else
+ {
+ chunk_sz+=save_sz;
+ i++;
+ }
+ }
+
+ unsigned a_sz= aSignal->getLength();
+
+ if (fragment_info > 0) {
+ // update the original signal to include section info
+ Uint32 *a_data= aSignal->getDataPtrSend();
+ unsigned tmp_sz= i-start_i;
+ memcpy(a_data+a_sz,
+ tmp_data,
+ tmp_sz*sizeof(Uint32));
+ a_data[a_sz+tmp_sz]= unique_id;
+ aSignal->setLength(a_sz+tmp_sz+1);
+
+ // send last fragment
+ aSignal->m_fragmentInfo= 3; // 3 = last fragment
+ aSignal->m_noOfSections= i-start_i;
+ } else {
+ aSignal->m_noOfSections= secs;
+ }
+
+ // send aSignal
+ int ret;
+ {
+ SendStatus ss = theTransporterRegistry->prepareSend
+ (aSignal,
+ 1/*JBB*/,
+ aSignal->getDataPtrSend(),
+ aNode,
+ &tmp_ptr[start_i]);
+ assert(ss != SEND_MESSAGE_TOO_BIG);
+ ret = (ss == SEND_OK ? 0 : -1);
+ }
+ aSignal->m_noOfSections = 0;
+ aSignal->m_fragmentInfo = 0;
+ aSignal->setLength(a_sz);
+ return ret;
+}
+
+int
+TransporterFacade::sendSignal(NdbApiSignal* aSignal, NodeId aNode,
+ LinearSectionPtr ptr[3], Uint32 secs){
aSignal->m_noOfSections = secs;
if(getIsNodeSendable(aNode) == true){
#ifdef API_TRACE
@@ -865,39 +987,6 @@ TransporterFacade::sendFragmentedSignal(NdbApiSignal* aSignal, NodeId aNode,
return -1;
}
-
-
-int
-TransporterFacade::sendFragmentedSignalUnCond(NdbApiSignal* aSignal,
- NodeId aNode,
- LinearSectionPtr ptr[3],
- Uint32 secs){
- aSignal->m_noOfSections = secs;
-
-#ifdef API_TRACE
- if(setSignalLog() && TRACE_GSN(aSignal->theVerId_signalNumber)){
- Uint32 tmp = aSignal->theSendersBlockRef;
- aSignal->theSendersBlockRef = numberToRef(tmp, theOwnId);
- signalLogger.sendSignal(* aSignal,
- 1,
- aSignal->getDataPtrSend(),
- aNode,
- ptr, secs);
- aSignal->theSendersBlockRef = tmp;
- }
-#endif
- SendStatus ss = theTransporterRegistry->prepareSend(aSignal,
- 1, // JBB
- aSignal->getDataPtrSend(),
- aNode,
- ptr);
- assert(ss != SEND_MESSAGE_TOO_BIG);
- aSignal->m_noOfSections = 0;
- return (ss == SEND_OK ? 0 : -1);
-}
-
-
-
/******************************************************************************
* CONNECTION METHODS Etc
******************************************************************************/
diff --git a/ndb/src/ndbapi/TransporterFacade.hpp b/ndb/src/ndbapi/TransporterFacade.hpp
index 5f473975585..5680e3a6f03 100644
--- a/ndb/src/ndbapi/TransporterFacade.hpp
+++ b/ndb/src/ndbapi/TransporterFacade.hpp
@@ -69,14 +69,11 @@ public:
// Only sends to nodes which are alive
int sendSignal(NdbApiSignal * signal, NodeId nodeId);
+ int sendSignal(NdbApiSignal*, NodeId,
+ LinearSectionPtr ptr[3], Uint32 secs);
int sendFragmentedSignal(NdbApiSignal*, NodeId,
LinearSectionPtr ptr[3], Uint32 secs);
- //Dirrrrty
- int sendFragmentedSignalUnCond(NdbApiSignal*, NodeId,
- LinearSectionPtr ptr[3], Uint32 secs);
-
-
// Is node available for running transactions
bool get_node_alive(NodeId nodeId) const;
bool get_node_stopping(NodeId nodeId) const;
@@ -224,7 +221,8 @@ private:
} m_threads;
Uint32 m_max_trans_id;
-
+ Uint32 m_fragmented_signal_id;
+
/**
* execute function
*/
diff --git a/ndb/src/ndbapi/ndb_cluster_connection.cpp b/ndb/src/ndbapi/ndb_cluster_connection.cpp
index 4c42fe1aeef..f436ee56ede 100644
--- a/ndb/src/ndbapi/ndb_cluster_connection.cpp
+++ b/ndb/src/ndbapi/ndb_cluster_connection.cpp
@@ -40,12 +40,8 @@ Ndb_cluster_connection::Ndb_cluster_connection(const char *connect_string)
DBUG_ENTER("Ndb_cluster_connection");
DBUG_PRINT("enter",("Ndb_cluster_connection this=0x%x", this));
m_facade= TransporterFacade::theFacadeInstance= new TransporterFacade();
- if (connect_string)
- m_connect_string= my_strdup(connect_string,MYF(MY_WME));
- else
- m_connect_string= 0;
+
m_config_retriever= 0;
- m_local_config= 0;
m_connect_thread= 0;
m_connect_callback= 0;
@@ -59,9 +55,39 @@ Ndb_cluster_connection::Ndb_cluster_connection(const char *connect_string)
ndb_print_state_mutex= NdbMutex_Create();
}
#endif
+ m_config_retriever=
+ new ConfigRetriever(connect_string, NDB_VERSION, NODE_TYPE_API);
+ if (m_config_retriever->hasError())
+ {
+ printf("Could not connect initialize handle to management server: %s",
+ m_config_retriever->getErrorString());
+ delete m_config_retriever;
+ m_config_retriever= 0;
+ }
DBUG_VOID_RETURN;
}
+int Ndb_cluster_connection::get_connected_port() const
+{
+ if (m_config_retriever)
+ return m_config_retriever->get_mgmd_port();
+ return -1;
+}
+
+const char *Ndb_cluster_connection::get_connected_host() const
+{
+ if (m_config_retriever)
+ return m_config_retriever->get_mgmd_host();
+ return 0;
+}
+
+const char *Ndb_cluster_connection::get_connectstring(char *buf, int buf_sz) const
+{
+ if (m_config_retriever)
+ return m_config_retriever->get_connectstring(buf,buf_sz);
+ return 0;
+}
+
extern "C" pthread_handler_decl(run_ndb_cluster_connection_connect_thread, me)
{
my_thread_init();
@@ -78,7 +104,7 @@ void Ndb_cluster_connection::connect_thread()
int r;
do {
NdbSleep_SecSleep(1);
- if ((r = connect(1)) == 0)
+ if ((r = connect(0,0,0)) == 0)
break;
if (r == -1) {
printf("Ndb_cluster_connection::connect_thread error\n");
@@ -99,7 +125,7 @@ int Ndb_cluster_connection::start_connect_thread(int (*connect_callback)(void))
int r;
DBUG_ENTER("Ndb_cluster_connection::start_connect_thread");
m_connect_callback= connect_callback;
- if ((r = connect(1)) == 1)
+ if ((r = connect(0,0,0)) == 1)
{
DBUG_PRINT("info",("starting thread"));
m_connect_thread=
@@ -118,45 +144,17 @@ int Ndb_cluster_connection::start_connect_thread(int (*connect_callback)(void))
DBUG_RETURN(0);
}
-int Ndb_cluster_connection::connect(int reconnect)
+int Ndb_cluster_connection::connect(int no_retries, int retry_delay_in_seconds, int verbose)
{
DBUG_ENTER("Ndb_cluster_connection::connect");
const char* error = 0;
do {
if (m_config_retriever == 0)
- {
- if (m_local_config == 0) {
- m_local_config= new LocalConfig();
- if (!m_local_config->init(m_connect_string,0)) {
- ndbout_c("Configuration error: Unable to retrieve local config");
- m_local_config->printError();
- m_local_config->printUsage();
- DBUG_RETURN(-1);
- }
- }
- m_config_retriever=
- new ConfigRetriever(*m_local_config, NDB_VERSION, NODE_TYPE_API);
- }
- else
- if (reconnect == 0)
- DBUG_RETURN(0);
- if (reconnect)
- {
- int r= m_config_retriever->do_connect(1);
- if (r == 1)
- DBUG_RETURN(1); // mgmt server not up yet
- if (r == -1)
- break;
- }
- else
- if(m_config_retriever->do_connect() == -1)
- break;
-
- Uint32 nodeId = m_config_retriever->allocNodeId();
- for(Uint32 i = 0; nodeId == 0 && i<5; i++){
- NdbSleep_SecSleep(3);
- nodeId = m_config_retriever->allocNodeId();
- }
+ DBUG_RETURN(-1);
+ if (m_config_retriever->do_connect(no_retries,retry_delay_in_seconds,verbose))
+ DBUG_RETURN(1); // mgmt server not up yet
+
+ Uint32 nodeId = m_config_retriever->allocNodeId(4/*retries*/,3/*delay*/);
if(nodeId == 0)
break;
ndb_mgm_configuration * props = m_config_retriever->getConfig();
@@ -197,11 +195,8 @@ Ndb_cluster_connection::~Ndb_cluster_connection()
abort();
TransporterFacade::theFacadeInstance= 0;
}
- my_free(m_connect_string,MYF(MY_ALLOW_ZERO_PTR));
if (m_config_retriever)
delete m_config_retriever;
- if (m_local_config)
- delete m_local_config;
DBUG_VOID_RETURN;
}
diff --git a/ndb/src/ndbapi/ndberror.c b/ndb/src/ndbapi/ndberror.c
index 20661b89517..c0a6b6ba122 100644
--- a/ndb/src/ndbapi/ndberror.c
+++ b/ndb/src/ndbapi/ndberror.c
@@ -35,6 +35,7 @@ typedef struct ErrorBundle {
#define NE ndberror_cl_none
#define AE ndberror_cl_application
+#define CE ndberror_cl_configuration
#define ND ndberror_cl_no_data_found
#define CV ndberror_cl_constraint_violation
#define SE ndberror_cl_schema_error
@@ -53,8 +54,32 @@ typedef struct ErrorBundle {
#define NI ndberror_cl_function_not_implemented
#define UE ndberror_cl_unknown_error_code
+static const char REDO_BUFFER_MSG[]=
+"REDO log buffers overloaded, consult online manual (increase RedoBuffer, and|or decrease TimeBetweenLocalCheckpoints, and|or increase NoOfFragmentLogFiles)";
+
static const char* empty_string = "";
+/*
+ * Error code ranges are reserved for respective block
+ *
+ * 200 - TC
+ * 300 - DIH
+ * 400 - LQH
+ * 600 - ACC
+ * 700 - DICT
+ * 800 - TUP
+ * 1200 - LQH
+ * 1300 - BACKUP
+ * 4000 - API
+ * 4100 - ""
+ * 4200 - ""
+ * 4300 - ""
+ * 4400 - ""
+ * 4500 - ""
+ * 4600 - ""
+ * 5000 - Management server
+ */
+
static
const
ErrorBundle ErrorCodes[] = {
@@ -124,7 +149,8 @@ ErrorBundle ErrorCodes[] = {
{ 217, TR, "217" },
{ 218, TR, "218" },
{ 219, TR, "219" },
- { 233, TR, "Out of operation records in transaction coordinator" },
+ { 233, TR,
+ "Out of operation records in transaction coordinator (increase MaxNoOfConcurrentOperations)" },
{ 275, TR, "275" },
{ 279, TR, "Out of transaction markers in transaction coordinator" },
{ 414, TR, "414" },
@@ -136,9 +162,8 @@ ErrorBundle ErrorCodes[] = {
{ 805, TR, "Out of attrinfo records in tuple manager" },
{ 830, TR, "Out of add fragment operation records" },
{ 873, TR, "Out of attrinfo records for scan in tuple manager" },
- { 1217, TR, "1217" },
- { 1219, TR, "Out of operation records in local data manager" },
- { 1220, TR, "1220" },
+ { 1217, TR, "Out of operation records in local data manager (increase MaxNoOfLocalOperations)" },
+ { 1220, TR, REDO_BUFFER_MSG },
{ 1222, TR, "Out of transaction markers in LQH" },
{ 4021, TR, "Out of Send Buffer space in NDB API" },
{ 4022, TR, "Out of Send Buffer space in NDB API" },
@@ -149,9 +174,10 @@ ErrorBundle ErrorCodes[] = {
*/
{ 623, IS, "623" },
{ 624, IS, "624" },
- { 625, IS, "Out of memory in Ndb Kernel, index part" },
- { 826, IS, "826" },
- { 827, IS, "Out of memory in Ndb Kernel, data part" },
+ { 625, IS, "Out of memory in Ndb Kernel, index part (increase IndexMemory)" },
+ { 800, IS, "Too many ordered indexes (increase MaxNoOfOrderedIndexes)" },
+ { 826, IS, "Too many tables and attributes (increase MaxNoOfAttributes or MaxNoOfTables)" },
+ { 827, IS, "Out of memory in Ndb Kernel, data part (increase DataMemory)" },
{ 832, IS, "832" },
/**
@@ -163,15 +189,14 @@ ErrorBundle ErrorCodes[] = {
{ 297, TO, "Time-out in NDB, probably caused by deadlock" }, /* Scan trans timeout, temporary!! */
{ 237, TO, "Transaction had timed out when trying to commit it" },
-
/**
* OverloadError
*/
- { 410, OL, "Out of log file space temporarily" },
- { 677, OL, "Index UNDO buffers overloaded" },
- { 891, OL, "Data UNDO buffers overloaded" },
- { 1221, OL, "REDO log buffers overloaded" },
- { 4006, OL, "Connect failure - out of connection objects" },
+ { 410, OL, REDO_BUFFER_MSG },
+ { 677, OL, "Index UNDO buffers overloaded (increase UndoIndexBuffer)" },
+ { 891, OL, "Data UNDO buffers overloaded (increase UndoDataBuffer)" },
+ { 1221, OL, REDO_BUFFER_MSG },
+ { 4006, OL, "Connect failure - out of connection objects (increase MaxNoOfConcurrentTransactions)" },
@@ -238,12 +263,13 @@ ErrorBundle ErrorCodes[] = {
{ 877, AE, "877" },
{ 878, AE, "878" },
{ 879, AE, "879" },
+ { 880, AE, "Tried to read too much - too many getValue calls" },
{ 884, AE, "Stack overflow in interpreter" },
{ 885, AE, "Stack underflow in interpreter" },
{ 886, AE, "More than 65535 instructions executed in interpreter" },
- { 4256, AE, "Must call Ndb::init() before this function" },
- { 880, AE, "Tried to read too much - too many getValue calls" },
- { 4257, AE, "Tried to read too much - too many getValue calls" },
+ { 897, AE, "Update attempt of primary key via ndbcluster internal api (if this occurs via the MySQL server it is a bug, please report)" },
+ { 4256, AE, "Must call Ndb::init() before this function" },
+ { 4257, AE, "Tried to read too much - too many getValue calls" },
/**
* Scan application errors
@@ -288,7 +314,7 @@ ErrorBundle ErrorCodes[] = {
{ 283, SE, "Table is being dropped" },
{ 284, SE, "Table not defined in transaction coordinator" },
{ 285, SE, "Unknown table error in transaction coordinator" },
- { 881, SE, "Unable to create table, out of data pages" },
+ { 881, SE, "Unable to create table, out of data pages (increase DataMemory) " },
{ 1225, SE, "Table not defined in local query handler" },
{ 1226, SE, "Table is being dropped" },
{ 1228, SE, "Cannot use drop table for drop index" },
@@ -300,6 +326,36 @@ ErrorBundle ErrorCodes[] = {
{ 4003, NI, "Function not implemented yet" },
/**
+ * Backup error codes
+ */
+
+ { 1300, IE, "Undefined error" },
+ { 1301, IE, "Backup issued to not master (reissue command to master)" },
+ { 1302, IE, "Out of backup record" },
+ { 1303, IS, "Out of resources" },
+ { 1304, IE, "Sequence failure" },
+ { 1305, IE, "Backup definition not implemented" },
+ { 1306, AE, "Backup not supported in diskless mode (change Diskless)" },
+
+ { 1321, IE, "Backup aborted by application" },
+ { 1322, IE, "Backup already completed" },
+ { 1323, IE, "1323" },
+ { 1324, IE, "Backup log buffer full" },
+ { 1325, IE, "File or scan error" },
+ { 1326, IE, "Backup abortet due to node failure" },
+ { 1327, IE, "1327" },
+
+ { 1340, IE, "Backup undefined error" },
+ { 1342, AE, "Backup failed to allocate buffers (check configuration)" },
+ { 1343, AE, "Backup failed to setup fs buffers (check configuration)" },
+ { 1344, AE, "Backup failed to allocate tables (check configuration)" },
+ { 1345, AE, "Backup failed to insert file header (check configuration)" },
+ { 1346, AE, "Backup failed to insert table list (check configuration)" },
+ { 1347, AE, "Backup failed to allocate table memory (check configuration)" },
+ { 1348, AE, "Backup failed to allocate file record (check configuration)" },
+ { 1349, AE, "Backup failed to allocate attribute record (check configuration)" },
+
+ /**
* Still uncategorized
*/
{ 720, AE, "Attribute name reused in table definition" },
@@ -344,17 +400,11 @@ ErrorBundle ErrorCodes[] = {
{ 4327, AE, "Distribution Group with 1 byte attribute is not allowed" },
{ 4328, AE, "Disk memory attributes not yet supported" },
{ 4329, AE, "Variable stored attributes not yet supported" },
- { 4330, AE, "Table names limited to 127 bytes" },
- { 4331, AE, "Attribute names limited to 31 bytes" },
- { 4332, AE, "Maximum 2000 attributes in a table" },
- { 4333, AE, "Maximum 4092 bytes long keys allowed" },
- { 4334, AE, "Attribute properties length limited to 127 bytes" },
{ 4400, AE, "Status Error in NdbSchemaCon" },
{ 4401, AE, "Only one schema operation per schema transaction" },
{ 4402, AE, "No schema operation defined before calling execute" },
- { 4500, AE, "Cannot handle more than 2048 tables in NdbApi" },
{ 4501, AE, "Insert in hash table failed when getting table information from Ndb" },
{ 4502, AE, "GetValue not allowed in Update operation" },
{ 4503, AE, "GetValue not allowed in Insert operation" },
@@ -429,7 +479,8 @@ ErrorBundle ErrorCodes[] = {
{ 4267, IE, "Corrupted blob value" },
{ 4268, IE, "Error in blob head update forced rollback of transaction" },
{ 4268, IE, "Unknown blob error" },
- { 4269, IE, "No connection to ndb management server" }
+ { 4269, IE, "No connection to ndb management server" },
+ { 4335, AE, "Only one autoincrement column allowed per table. Having a table without primary key uses an autoincremented hidden key, i.e. a table without a primary key can not have an autoincremented column" }
};
static
@@ -468,6 +519,7 @@ const
ErrorStatusClassification StatusClassificationMapping[] = {
{ ST_S, NE, "No error"},
{ ST_P, AE, "Application error"},
+ { ST_P, CE, "Configuration or application error"},
{ ST_P, ND, "No data found"},
{ ST_P, CV, "Constraint violation"},
{ ST_P, SE, "Schema error"},
diff --git a/ndb/src/mgmclient/CpcClient.hpp b/ndb/test/include/CpcClient.hpp
index 1655bc57b56..1655bc57b56 100644
--- a/ndb/src/mgmclient/CpcClient.hpp
+++ b/ndb/test/include/CpcClient.hpp
diff --git a/ndb/test/include/HugoTransactions.hpp b/ndb/test/include/HugoTransactions.hpp
index 19e4cb43336..b833f2ac629 100644
--- a/ndb/test/include/HugoTransactions.hpp
+++ b/ndb/test/include/HugoTransactions.hpp
@@ -36,15 +36,21 @@ public:
bool allowConstraintViolation = true,
int doSleep = 0,
bool oneTrans = false);
+
int scanReadRecords(Ndb*,
int records,
int abort = 0,
int parallelism = 0,
- bool committed = false);
- int scanReadCommittedRecords(Ndb*,
- int records,
- int abort = 0,
- int parallelism = 0);
+ NdbOperation::LockMode = NdbOperation::LM_Read);
+
+ int scanReadRecords(Ndb*,
+ const NdbDictionary::Index*,
+ int records,
+ int abort = 0,
+ int parallelism = 0,
+ NdbOperation::LockMode = NdbOperation::LM_Read,
+ bool sorted = false);
+
int pkReadRecords(Ndb*,
int records,
int batchsize = 1,
diff --git a/ndb/test/include/NDBT_Tables.hpp b/ndb/test/include/NDBT_Tables.hpp
index aa78f7d4e2c..fb0df8aa35b 100644
--- a/ndb/test/include/NDBT_Tables.hpp
+++ b/ndb/test/include/NDBT_Tables.hpp
@@ -23,11 +23,13 @@
#include <NdbDictionary.hpp>
#include <NDBT_Table.hpp>
+typedef int (* NDBT_CreateTableHook)(Ndb*, NdbDictionary::Table&, int when);
+
class NDBT_Tables {
public:
-
+
static int createTable(Ndb* pNdb, const char* _name, bool _temp = false,
- bool existsOK = false);
+ bool existsOK = false, NDBT_CreateTableHook = 0);
static int createAllTables(Ndb* pNdb, bool _temp, bool existsOK = false);
static int createAllTables(Ndb* pNdb);
diff --git a/ndb/test/include/NDBT_Test.hpp b/ndb/test/include/NDBT_Test.hpp
index b0b5fe15960..8b69faebde8 100644
--- a/ndb/test/include/NDBT_Test.hpp
+++ b/ndb/test/include/NDBT_Test.hpp
@@ -392,10 +392,10 @@ C##suitname():NDBT_TestSuite(#suitname){ \
// Add a number of equal steps to the testcase
#define STEPS(stepfunc, num) \
- for (int i = 0; i < num; i++){ \
+ { int i; for (i = 0; i < num; i++){ \
pts = new NDBT_ParallelStep(pt, #stepfunc, stepfunc); \
pt->addStep(pts);\
- }
+ } }
#define VERIFIER(stepfunc) \
ptv = new NDBT_Verifier(pt, #stepfunc, stepfunc); \
diff --git a/ndb/test/include/NdbRestarter.hpp b/ndb/test/include/NdbRestarter.hpp
index 114726f6a2b..19a88b4f8ad 100644
--- a/ndb/test/include/NdbRestarter.hpp
+++ b/ndb/test/include/NdbRestarter.hpp
@@ -87,8 +87,6 @@ protected:
bool connected;
BaseString addr;
- BaseString host;
- int port;
NdbMgmHandle handle;
ndb_mgm_configuration * m_config;
protected:
diff --git a/ndb/test/include/UtilTransactions.hpp b/ndb/test/include/UtilTransactions.hpp
index 37cd99550a5..23902f3b317 100644
--- a/ndb/test/include/UtilTransactions.hpp
+++ b/ndb/test/include/UtilTransactions.hpp
@@ -53,11 +53,11 @@ public:
int selectCount(Ndb*,
int parallelism = 0,
int* count_rows = NULL,
- ScanLock lock = SL_Read,
+ NdbOperation::LockMode lm = NdbOperation::LM_CommittedRead,
NdbConnection* pTrans = NULL);
int scanReadRecords(Ndb*,
int parallelism,
- bool exclusive,
+ NdbOperation::LockMode lm,
int records,
int noAttribs,
int* attrib_list,
diff --git a/ndb/include/util/getarg.h b/ndb/test/include/getarg.h
index 03ed25f6828..03ed25f6828 100644
--- a/ndb/include/util/getarg.h
+++ b/ndb/test/include/getarg.h
diff --git a/ndb/test/ndbapi/Makefile.am b/ndb/test/ndbapi/Makefile.am
index 787589dd9b6..4c374ec0f13 100644
--- a/ndb/test/ndbapi/Makefile.am
+++ b/ndb/test/ndbapi/Makefile.am
@@ -30,7 +30,8 @@ testSystemRestart \
testTimeout \
testTransactions \
testDeadlock \
-test_event ndbapi_slow_select testReadPerf testLcp
+test_event ndbapi_slow_select testReadPerf testLcp \
+testPartitioning
#flexTimedAsynch
#testBlobs
@@ -69,6 +70,7 @@ test_event_SOURCES = test_event.cpp
ndbapi_slow_select_SOURCES = slow_select.cpp
testReadPerf_SOURCES = testReadPerf.cpp
testLcp_SOURCES = testLcp.cpp
+testPartitioning_SOURCES = testPartitioning.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/include/kernel
diff --git a/ndb/test/ndbapi/Makefile_old b/ndb/test/ndbapi/Makefile_old
deleted file mode 100644
index c3198096ec0..00000000000
--- a/ndb/test/ndbapi/Makefile_old
+++ /dev/null
@@ -1,49 +0,0 @@
-include .defs.mk
-
-
-ifeq ($(NDB_OS), OSE)
-DIRS = basic flexBench flexAsynch
-else
-DIRS = lmc-bench ronja
-BIN_DIRS = \
- flexAsynch \
- flexBench \
- flexHammer \
- flexTT \
- create_tab \
- create_all_tabs \
- drop_all_tabs \
- bulk_copy \
- restarter2 restarter \
- restarts testScan testNdbApi \
- testScanInterpreter testIndex \
- testInterpreter \
- testOIBasic \
- testBackup \
- testBasic \
- basicAsynch \
- testNodeRestart \
- testOperations testTransactions \
- testSystemRestart \
- testTimeout \
- testMgm \
- testRestartGci \
- testDataBuffers \
- testDict \
- acid \
- telco \
- indexTest \
- test_event \
- indexTest2 \
- testGrep \
- testBlobs
-
-ifeq ($(NDB_OS), SOLARIS)
-ifeq ($(NDB_COMPILER), FORTE6)
- DIRS += flexTimedAsynch
-endif
-endif
-endif
-
-include ${NDB_TOP}/Epilogue.mk
-
diff --git a/ndb/test/ndbapi/ScanFunctions.hpp b/ndb/test/ndbapi/ScanFunctions.hpp
index 2ff4b751c33..6964f8c73a8 100644
--- a/ndb/test/ndbapi/ScanFunctions.hpp
+++ b/ndb/test/ndbapi/ScanFunctions.hpp
@@ -286,36 +286,36 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){
attr = new Attrib;
attr->numAttribs = 0;
attriblist.push_back(attr);
-
- for(int i = 1; i < pTab->getNoOfColumns(); i++){
+ int i;
+ for(i = 1; i < pTab->getNoOfColumns(); i++){
attr = new Attrib;
attr->numAttribs = i;
for(int a = 0; a<i; a++)
attr->attribs[a] = a;
attriblist.push_back(attr);
}
- for(int i = pTab->getNoOfColumns()-1; i > 0; i--){
+ for(i = pTab->getNoOfColumns()-1; i > 0; i--){
attr = new Attrib;
attr->numAttribs = i;
for(int a = 0; a<i; a++)
attr->attribs[a] = a;
attriblist.push_back(attr);
}
- for(int i = pTab->getNoOfColumns(); i > 0; i--){
+ for(i = pTab->getNoOfColumns(); i > 0; i--){
attr = new Attrib;
attr->numAttribs = pTab->getNoOfColumns() - i;
for(int a = 0; a<pTab->getNoOfColumns() - i; a++)
attr->attribs[a] = pTab->getNoOfColumns()-a-1;
attriblist.push_back(attr);
}
- for(int i = 1; i < pTab->getNoOfColumns(); i++){
+ for(i = 1; i < pTab->getNoOfColumns(); i++){
attr = new Attrib;
attr->numAttribs = pTab->getNoOfColumns() - i;
for(int a = 0; a<pTab->getNoOfColumns() - i; a++)
attr->attribs[a] = pTab->getNoOfColumns()-a-1;
attriblist.push_back(attr);
}
- for(int i = 1; i < pTab->getNoOfColumns(); i++){
+ for(i = 1; i < pTab->getNoOfColumns(); i++){
attr = new Attrib;
attr->numAttribs = 2;
for(int a = 0; a<2; a++){
@@ -345,11 +345,11 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){
attriblist.push_back(attr);
#if 1
- for(size_t i = 0; i < attriblist.size(); i++){
+ for(size_t j = 0; j < attriblist.size(); j++){
- g_info << attriblist[i]->numAttribs << ": " ;
- for(int a = 0; a < attriblist[i]->numAttribs; a++)
- g_info << attriblist[i]->attribs[a] << ", ";
+ g_info << attriblist[j]->numAttribs << ": " ;
+ for(int a = 0; a < attriblist[j]->numAttribs; a++)
+ g_info << attriblist[j]->attribs[a] << ", ";
g_info << endl;
}
#endif
diff --git a/ndb/test/ndbapi/bank/Makefile_old b/ndb/test/ndbapi/bank/Makefile_old
deleted file mode 100644
index f710f9e6612..00000000000
--- a/ndb/test/ndbapi/bank/Makefile_old
+++ /dev/null
@@ -1,12 +0,0 @@
-include .defs.mk
-
-DIRS = src bankCreator \
- bankSumAccounts \
- bankTransactionMaker \
- bankValidateAllGLs \
- bankMakeGL \
- bankTimer \
- testBank
-
-
-include $(NDB_TOP)/Epilogue.mk
diff --git a/ndb/test/ndbapi/old_dirs/flexBench/Makefile_old b/ndb/test/ndbapi/old_dirs/flexBench/Makefile_old
deleted file mode 100644
index bfff5cd161a..00000000000
--- a/ndb/test/ndbapi/old_dirs/flexBench/Makefile_old
+++ /dev/null
@@ -1,11 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapitest
-
-BIN_TARGET := flexBench
-
-# Source files of non-templated classes (.C files)
-SOURCES = flexBench.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/test/ndbapi/testBlobs.cpp b/ndb/test/ndbapi/testBlobs.cpp
index 41bb82f3e06..4b532856709 100644
--- a/ndb/test/ndbapi/testBlobs.cpp
+++ b/ndb/test/ndbapi/testBlobs.cpp
@@ -22,6 +22,7 @@
#include <NdbMain.h>
#include <NdbOut.hpp>
#include <NdbTest.hpp>
+#include <NdbTick.h>
struct Bcol {
bool m_nullable;
@@ -42,13 +43,14 @@ struct Opt {
bool m_core;
bool m_dbg;
bool m_dbgall;
+ const char* m_dbug;
bool m_full;
unsigned m_loop;
unsigned m_parts;
unsigned m_rows;
unsigned m_seed;
const char* m_skip;
- const char* m_style;
+ const char* m_test;
// metadata
const char* m_tname;
const char* m_x1name; // hash index
@@ -58,6 +60,9 @@ struct Opt {
bool m_oneblob;
Bcol m_blob1;
Bcol m_blob2;
+ // perf
+ const char* m_tnameperf;
+ unsigned m_rowsperf;
// bugs
int m_bug;
int (*m_bugtest)();
@@ -66,13 +71,14 @@ struct Opt {
m_core(false),
m_dbg(false),
m_dbgall(false),
+ m_dbug(0),
m_full(false),
m_loop(1),
m_parts(10),
m_rows(100),
m_seed(0),
- m_skip(""),
- m_style("012"),
+ m_skip(0),
+ m_test(0),
// metadata
m_tname("TBLOB1"),
m_x1name("TBLOB1X1"),
@@ -82,6 +88,9 @@ struct Opt {
m_oneblob(false),
m_blob1(false, 7, 1137, 10),
m_blob2(true, 99, 55, 1),
+ // perf
+ m_tnameperf("TBLOB2"),
+ m_rowsperf(10000),
// bugs
m_bug(0),
m_bugtest(0) {
@@ -100,46 +109,48 @@ printusage()
<< " -core dump core on error" << endl
<< " -dbg print debug" << endl
<< " -dbgall print also NDB API debug (if compiled in)" << endl
+ << " -dbug opt dbug options" << endl
<< " -full read/write only full blob values" << endl
- << " -inline read/write only blobs which fit inline" << endl
<< " -loop N loop N times 0=forever [" << d.m_loop << "]" << endl
<< " -parts N max parts in blob value [" << d.m_parts << "]" << endl
<< " -rows N number of rows [" << d.m_rows << "]" << endl
+ << " -rowsperf N rows for performace test [" << d.m_rowsperf << "]" << endl
<< " -seed N random seed 0=loop number [" << d.m_seed << "]" << endl
- << " -skip xxx skip these tests (see list) [" << d.m_skip << endl
- << " -style xxx access styles to test (see list) [" << d.m_style << "]" << endl
+ << " -skip xxx skip given tests (see list) [no tests]" << endl
+ << " -test xxx only given tests (see list) [all tests]" << endl
<< "metadata" << endl
<< " -pk2len N length of PK2 [" << d.m_pk2len << "/" << g_max_pk2len <<"]" << endl
<< " -oneblob only 1 blob attribute [default 2]" << endl
- << "testcases for -skip" << endl
+ << "testcases for test/skip" << endl
<< " k primary key ops" << endl
<< " i hash index ops" << endl
<< " s table scans" << endl
<< " r ordered index scans" << endl
- << " u update blob value" << endl
- << "access styles for -style" << endl
+ << " p performance test" << endl
+ << "additional flags for test/skip" << endl
+ << " u update existing blob value" << endl
+ << " n normal insert and update" << endl
+ << " w insert and update using writeTuple" << endl
<< " 0 getValue / setValue" << endl
<< " 1 setActiveHook" << endl
<< " 2 readData / writeData" << endl
<< "bug tests (no blob test)" << endl
<< " -bug 4088 ndb api hang with mixed ops on index table" << endl
- << " -bug 2222 delete + write gives 626" << endl
- << " -bug 3333 acc crash on delete and long key" << endl
+ << " -bug nnnn delete + write gives 626" << endl
+ << " -bug nnnn acc crash on delete and long key" << endl
;
}
static Opt g_opt;
static bool
-skipcase(int x)
+testcase(char x)
{
- return strchr(g_opt.m_skip, x) != 0;
-}
-
-static bool
-skipstyle(int x)
-{
- return strchr(g_opt.m_style, '0' + x) == 0;
+ if (x < 10)
+ x += '0';
+ return
+ (g_opt.m_test == 0 || strchr(g_opt.m_test, x) != 0) &&
+ (g_opt.m_skip == 0 || strchr(g_opt.m_skip, x) == 0);
}
static Ndb* g_ndb = 0;
@@ -435,7 +446,9 @@ getBlobLength(NdbBlob* h, unsigned& len)
CHK(h->getLength(len2) == 0);
len = (unsigned)len2;
assert(len == len2);
- DBG("getBlobLength " << h->getColumn()->getName() << " len=" << len);
+ bool isNull;
+ CHK(h->getNull(isNull) == 0);
+ DBG("getBlobLength " << h->getColumn()->getName() << " len=" << len << " null=" << isNull);
return 0;
}
@@ -912,6 +925,41 @@ updatePk(int style)
}
static int
+writePk(int style)
+{
+ DBG("--- writePk " << stylename[style] << " ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("writePk pk1=" << hex << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opr = g_con->getNdbOperation(g_opt.m_tname)) != 0);
+ CHK(g_opr->writeTuple() == 0);
+ CHK(g_opr->equal("PK1", tup.m_pk1) == 0);
+ if (g_opt.m_pk2len != 0)
+ CHK(g_opr->equal("PK2", tup.m_pk2) == 0);
+ CHK(getBlobHandles(g_opr) == 0);
+ if (style == 0) {
+ CHK(setBlobValue(tup) == 0);
+ } else if (style == 1) {
+ // non-nullable must be set
+ CHK(g_bh1->setValue("", 0) == 0);
+ CHK(setBlobWriteHook(tup) == 0);
+ } else {
+ // non-nullable must be set
+ CHK(g_bh1->setValue("", 0) == 0);
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(writeBlobData(tup) == 0);
+ }
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_opr = 0;
+ g_con = 0;
+ tup.m_exists = true;
+ }
+ return 0;
+}
+
+static int
deletePk()
{
DBG("--- deletePk ---");
@@ -996,6 +1044,39 @@ updateIdx(int style)
}
static int
+writeIdx(int style)
+{
+ DBG("--- writeIdx " << stylename[style] << " ---");
+ for (unsigned k = 0; k < g_opt.m_rows; k++) {
+ Tup& tup = g_tups[k];
+ DBG("writeIdx pk1=" << hex << tup.m_pk1);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_opx = g_con->getNdbIndexOperation(g_opt.m_x1name, g_opt.m_tname)) != 0);
+ CHK(g_opx->writeTuple() == 0);
+ CHK(g_opx->equal("PK2", tup.m_pk2) == 0);
+ CHK(getBlobHandles(g_opx) == 0);
+ if (style == 0) {
+ CHK(setBlobValue(tup) == 0);
+ } else if (style == 1) {
+ // non-nullable must be set
+ CHK(g_bh1->setValue("", 0) == 0);
+ CHK(setBlobWriteHook(tup) == 0);
+ } else {
+ // non-nullable must be set
+ CHK(g_bh1->setValue("", 0) == 0);
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(writeBlobData(tup) == 0);
+ }
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ g_opx = 0;
+ g_con = 0;
+ tup.m_exists = true;
+ }
+ return 0;
+}
+
+static int
deleteIdx()
{
DBG("--- deleteIdx ---");
@@ -1167,10 +1248,16 @@ deleteScan(bool idx)
// main
+// from here on print always
+#undef DBG
+#define DBG(x) \
+ do { \
+ ndbout << "line " << __LINE__ << " " << x << endl; \
+ } while (0)
+
static int
testmain()
{
- int style;
g_ndb = new Ndb("TEST_DB");
CHK(g_ndb->init() == 0);
CHK(g_ndb->waitUntilReady() == 0);
@@ -1194,55 +1281,88 @@ testmain()
if (g_opt.m_seed != 0)
srandom(g_opt.m_seed);
for (g_loop = 0; g_opt.m_loop == 0 || g_loop < g_opt.m_loop; g_loop++) {
+ int style;
DBG("=== loop " << g_loop << " ===");
if (g_opt.m_seed == 0)
srandom(g_loop);
// pk
for (style = 0; style <= 2; style++) {
- if (skipcase('k') || skipstyle(style))
+ if (! testcase('k') || ! testcase(style))
continue;
DBG("--- pk ops " << stylename[style] << " ---");
- calcTups(false);
- CHK(insertPk(style) == 0);
- CHK(verifyBlob() == 0);
- CHK(readPk(style) == 0);
- if (! skipcase('u')) {
- calcTups(style);
- CHK(updatePk(style) == 0);
+ if (testcase('n')) {
+ calcTups(false);
+ CHK(insertPk(style) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readPk(style) == 0);
+ if (testcase('u')) {
+ calcTups(style);
+ CHK(updatePk(style) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readPk(style) == 0);
+ }
+ CHK(deletePk() == 0);
+ CHK(verifyBlob() == 0);
+ }
+ if (testcase('w')) {
+ calcTups(false);
+ CHK(writePk(style) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readPk(style) == 0);
+ if (testcase('u')) {
+ calcTups(style);
+ CHK(writePk(style) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readPk(style) == 0);
+ }
+ CHK(deletePk() == 0);
CHK(verifyBlob() == 0);
}
- CHK(readPk(style) == 0);
- CHK(deletePk() == 0);
- CHK(verifyBlob() == 0);
}
// hash index
for (style = 0; style <= 2; style++) {
- if (skipcase('i') || skipstyle(style))
+ if (! testcase('i') || ! testcase(style))
continue;
DBG("--- idx ops " << stylename[style] << " ---");
- calcTups(false);
- CHK(insertPk(style) == 0);
- CHK(verifyBlob() == 0);
- CHK(readIdx(style) == 0);
- calcTups(style);
- if (! skipcase('u')) {
- CHK(updateIdx(style) == 0);
+ if (testcase('n')) {
+ calcTups(false);
+ CHK(insertPk(style) == 0);
CHK(verifyBlob() == 0);
CHK(readIdx(style) == 0);
+ if (testcase('u')) {
+ calcTups(style);
+ CHK(updateIdx(style) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readIdx(style) == 0);
+ }
+ CHK(deleteIdx() == 0);
+ CHK(verifyBlob() == 0);
+ }
+ if (testcase('w')) {
+ calcTups(false);
+ CHK(writePk(style) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readIdx(style) == 0);
+ if (testcase('u')) {
+ calcTups(style);
+ CHK(writeIdx(style) == 0);
+ CHK(verifyBlob() == 0);
+ CHK(readIdx(style) == 0);
+ }
+ CHK(deleteIdx() == 0);
+ CHK(verifyBlob() == 0);
}
- CHK(deleteIdx() == 0);
- CHK(verifyBlob() == 0);
}
// scan table
for (style = 0; style <= 2; style++) {
- if (skipcase('s') || skipstyle(style))
+ if (! testcase('s') || ! testcase(style))
continue;
DBG("--- table scan " << stylename[style] << " ---");
calcTups(false);
CHK(insertPk(style) == 0);
CHK(verifyBlob() == 0);
CHK(readScan(style, false) == 0);
- if (! skipcase('u')) {
+ if (testcase('u')) {
CHK(updateScan(style, false) == 0);
CHK(verifyBlob() == 0);
}
@@ -1251,14 +1371,14 @@ testmain()
}
// scan index
for (style = 0; style <= 2; style++) {
- if (skipcase('r') || skipstyle(style))
+ if (! testcase('r') || ! testcase(style))
continue;
DBG("--- index scan " << stylename[style] << " ---");
calcTups(false);
CHK(insertPk(style) == 0);
CHK(verifyBlob() == 0);
CHK(readScan(style, true) == 0);
- if (! skipcase('u')) {
+ if (testcase('u')) {
CHK(updateScan(style, true) == 0);
CHK(verifyBlob() == 0);
}
@@ -1270,6 +1390,292 @@ testmain()
return 0;
}
+// separate performance test
+
+struct Tmr { // stolen from testOIBasic
+ Tmr() {
+ clr();
+ }
+ void clr() {
+ m_on = m_ms = m_cnt = m_time[0] = m_text[0] = 0;
+ }
+ void on() {
+ assert(m_on == 0);
+ m_on = NdbTick_CurrentMillisecond();
+ }
+ void off(unsigned cnt = 0) {
+ NDB_TICKS off = NdbTick_CurrentMillisecond();
+ assert(m_on != 0 && off >= m_on);
+ m_ms += off - m_on;
+ m_cnt += cnt;
+ m_on = 0;
+ }
+ const char* time() {
+ if (m_cnt == 0)
+ sprintf(m_time, "%u ms", m_ms);
+ else
+ sprintf(m_time, "%u ms per %u ( %u ms per 1000 )", m_ms, m_cnt, (1000 * m_ms) / m_cnt);
+ return m_time;
+ }
+ const char* pct (const Tmr& t1) {
+ if (0 < t1.m_ms)
+ sprintf(m_text, "%u pct", (100 * m_ms) / t1.m_ms);
+ else
+ sprintf(m_text, "[cannot measure]");
+ return m_text;
+ }
+ const char* over(const Tmr& t1) {
+ if (0 < t1.m_ms) {
+ if (t1.m_ms <= m_ms)
+ sprintf(m_text, "%u pct", (100 * (m_ms - t1.m_ms)) / t1.m_ms);
+ else
+ sprintf(m_text, "-%u pct", (100 * (t1.m_ms - m_ms)) / t1.m_ms);
+ } else
+ sprintf(m_text, "[cannot measure]");
+ return m_text;
+ }
+ NDB_TICKS m_on;
+ unsigned m_ms;
+ unsigned m_cnt;
+ char m_time[100];
+ char m_text[100];
+};
+
+static int
+testperf()
+{
+ if (! testcase('p'))
+ return 0;
+ DBG("=== perf test ===");
+ g_ndb = new Ndb("TEST_DB");
+ CHK(g_ndb->init() == 0);
+ CHK(g_ndb->waitUntilReady() == 0);
+ g_dic = g_ndb->getDictionary();
+ NdbDictionary::Table tab(g_opt.m_tnameperf);
+ if (g_dic->getTable(tab.getName()) != 0)
+ CHK(g_dic->dropTable(tab) == 0);
+ // col A - pk
+ { NdbDictionary::Column col("A");
+ col.setType(NdbDictionary::Column::Unsigned);
+ col.setPrimaryKey(true);
+ tab.addColumn(col);
+ }
+ // col B - char 20
+ { NdbDictionary::Column col("B");
+ col.setType(NdbDictionary::Column::Char);
+ col.setLength(20);
+ col.setNullable(true);
+ tab.addColumn(col);
+ }
+ // col C - text
+ { NdbDictionary::Column col("C");
+ col.setType(NdbDictionary::Column::Text);
+ col.setInlineSize(20);
+ col.setPartSize(512);
+ col.setStripeSize(1);
+ col.setNullable(true);
+ tab.addColumn(col);
+ }
+ // create
+ CHK(g_dic->createTable(tab) == 0);
+ Uint32 cA = 0, cB = 1, cC = 2;
+ // timers
+ Tmr t1;
+ Tmr t2;
+ // insert char (one trans)
+ {
+ DBG("--- insert char ---");
+ t1.on();
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+ CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+ CHK(g_opr->insertTuple() == 0);
+ CHK(g_opr->equal(cA, (char*)&k) == 0);
+ CHK(g_opr->setValue(cB, "b") == 0);
+ CHK(g_con->execute(NoCommit) == 0);
+ }
+ t1.off(g_opt.m_rowsperf);
+ CHK(g_con->execute(Rollback) == 0);
+ DBG(t1.time());
+ g_opr = 0;
+ g_con = 0;
+ }
+ // insert text (one trans)
+ {
+ DBG("--- insert text ---");
+ t2.on();
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+ CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+ CHK(g_opr->insertTuple() == 0);
+ CHK(g_opr->equal(cA, (char*)&k) == 0);
+ CHK((g_bh1 = g_opr->getBlobHandle(cC)) != 0);
+ CHK((g_bh1->setValue("c", 1) == 0));
+ CHK(g_con->execute(NoCommit) == 0);
+ }
+ t2.off(g_opt.m_rowsperf);
+ CHK(g_con->execute(Rollback) == 0);
+ DBG(t2.time());
+ g_bh1 = 0;
+ g_opr = 0;
+ g_con = 0;
+ }
+ // insert overhead
+ DBG("insert overhead: " << t2.over(t1));
+ t1.clr();
+ t2.clr();
+ // insert
+ {
+ DBG("--- insert for read test ---");
+ unsigned n = 0;
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+ CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+ CHK(g_opr->insertTuple() == 0);
+ CHK(g_opr->equal(cA, (char*)&k) == 0);
+ CHK(g_opr->setValue(cB, "b") == 0);
+ CHK((g_bh1 = g_opr->getBlobHandle(cC)) != 0);
+ CHK((g_bh1->setValue("c", 1) == 0));
+ if (++n == g_opt.m_batch) {
+ CHK(g_con->execute(Commit) == 0);
+ g_ndb->closeTransaction(g_con);
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ n = 0;
+ }
+ }
+ if (n != 0) {
+ CHK(g_con->execute(Commit) == 0);
+ n = 0;
+ }
+ g_bh1 = 0;
+ g_opr = 0;
+ g_con = 0;
+ }
+ // pk read char (one trans)
+ {
+ DBG("--- pk read char ---");
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ Uint32 a;
+ char b[20];
+ t1.on();
+ for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+ CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+ CHK(g_opr->readTuple() == 0);
+ CHK(g_opr->equal(cA, (char*)&k) == 0);
+ CHK(g_opr->getValue(cA, (char*)&a) != 0);
+ CHK(g_opr->getValue(cB, b) != 0);
+ a = (Uint32)-1;
+ b[0] = 0;
+ CHK(g_con->execute(NoCommit) == 0);
+ CHK(a == k && strcmp(b, "b") == 0);
+ }
+ CHK(g_con->execute(Commit) == 0);
+ t1.off(g_opt.m_rowsperf);
+ DBG(t1.time());
+ g_opr = 0;
+ g_con = 0;
+ }
+ // pk read text (one trans)
+ {
+ DBG("--- pk read text ---");
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ Uint32 a;
+ char c[20];
+ t2.on();
+ for (Uint32 k = 0; k < g_opt.m_rowsperf; k++) {
+ CHK((g_opr = g_con->getNdbOperation(tab.getName())) != 0);
+ CHK(g_opr->readTuple() == 0);
+ CHK(g_opr->equal(cA, (char*)&k) == 0);
+ CHK(g_opr->getValue(cA, (char*)&a) != 0);
+ CHK((g_bh1 = g_opr->getBlobHandle(cC)) != 0);
+ a = (Uint32)-1;
+ c[0] = 0;
+ CHK(g_con->execute(NoCommit) == 0);
+ Uint32 m = 20;
+ CHK(g_bh1->readData(c, m) == 0);
+ CHK(a == k && m == 1 && strcmp(c, "c") == 0);
+ }
+ CHK(g_con->execute(Commit) == 0);
+ t2.off(g_opt.m_rowsperf);
+ DBG(t2.time());
+ g_opr = 0;
+ g_con = 0;
+ }
+ // pk read overhead
+ DBG("pk read overhead: " << t2.over(t1));
+ t1.clr();
+ t2.clr();
+ // scan read char
+ {
+ DBG("--- scan read char ---");
+ NdbResultSet* rs;
+ Uint32 a;
+ char b[20];
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0);
+ CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0);
+ CHK(g_ops->getValue(cA, (char*)&a) != 0);
+ CHK(g_ops->getValue(cB, b) != 0);
+ CHK(g_con->execute(NoCommit) == 0);
+ unsigned n = 0;
+ t1.on();
+ while (1) {
+ a = (Uint32)-1;
+ b[0] = 0;
+ int ret;
+ CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ CHK(a < g_opt.m_rowsperf && strcmp(b, "b") == 0);
+ n++;
+ }
+ CHK(n == g_opt.m_rowsperf);
+ t1.off(g_opt.m_rowsperf);
+ DBG(t1.time());
+ g_ops = 0;
+ g_con = 0;
+ }
+ // scan read text
+ {
+ DBG("--- read text ---");
+ NdbResultSet* rs;
+ Uint32 a;
+ char c[20];
+ CHK((g_con = g_ndb->startTransaction()) != 0);
+ CHK((g_ops = g_con->getNdbScanOperation(tab.getName())) != 0);
+ CHK((rs = g_ops->readTuples(NdbScanOperation::LM_Read)) != 0);
+ CHK(g_ops->getValue(cA, (char*)&a) != 0);
+ CHK((g_bh1 = g_ops->getBlobHandle(cC)) != 0);
+ CHK(g_con->execute(NoCommit) == 0);
+ unsigned n = 0;
+ t2.on();
+ while (1) {
+ a = (Uint32)-1;
+ c[0] = 0;
+ int ret;
+ CHK((ret = rs->nextResult(true)) == 0 || ret == 1);
+ if (ret == 1)
+ break;
+ Uint32 m = 20;
+ CHK(g_bh1->readData(c, m) == 0);
+ CHK(a < g_opt.m_rowsperf && m == 1 && strcmp(c, "c") == 0);
+ n++;
+ }
+ CHK(n == g_opt.m_rowsperf);
+ t2.off(g_opt.m_rowsperf);
+ DBG(t2.time());
+ g_bh1 = 0;
+ g_ops = 0;
+ g_con = 0;
+ }
+ // scan read overhead
+ DBG("scan read overhead: " << t2.over(t1));
+ t1.clr();
+ t2.clr();
+ delete g_ndb;
+ return 0;
+}
+
// bug tests
static int
@@ -1331,9 +1737,7 @@ static struct {
int m_bug;
int (*m_test)();
} g_bugtest[] = {
- { 4088, bugtest_4088 },
- { 2222, bugtest_2222 },
- { 3333, bugtest_3333 }
+ { 4088, bugtest_4088 }
};
NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
@@ -1361,6 +1765,12 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
putenv(strdup("NDB_BLOB_DEBUG=1"));
continue;
}
+ if (strcmp(arg, "-dbug") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_dbug = strdup(argv[0]);
+ continue;
+ }
+ }
if (strcmp(arg, "-full") == 0) {
g_opt.m_full = true;
continue;
@@ -1383,6 +1793,12 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
continue;
}
}
+ if (strcmp(arg, "-rowsperf") == 0) {
+ if (++argv, --argc > 0) {
+ g_opt.m_rowsperf = atoi(argv[0]);
+ continue;
+ }
+ }
if (strcmp(arg, "-seed") == 0) {
if (++argv, --argc > 0) {
g_opt.m_seed = atoi(argv[0]);
@@ -1395,9 +1811,9 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
continue;
}
}
- if (strcmp(arg, "-style") == 0) {
+ if (strcmp(arg, "-test") == 0) {
if (++argv, --argc > 0) {
- g_opt.m_style = strdup(argv[0]);
+ g_opt.m_test = strdup(argv[0]);
continue;
}
}
@@ -1431,14 +1847,19 @@ NDB_COMMAND(testOdbcDriver, "testBlobs", "testBlobs", "testBlobs", 65535)
printusage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
+ if (g_opt.m_dbug != 0) {
+ DBUG_PUSH(g_opt.m_dbug);
+ }
if (g_opt.m_pk2len == 0) {
char b[100];
- strcpy(b, g_opt.m_skip);
+ b[0] = 0;
+ if (g_opt.m_skip != 0)
+ strcpy(b, g_opt.m_skip);
strcat(b, "i");
strcat(b, "r");
g_opt.m_skip = strdup(b);
}
- if (testmain() == -1) {
+ if (testmain() == -1 || testperf() == -1) {
ndbout << "line " << __LINE__ << " FAIL loop=" << g_loop << endl;
return NDBT_ProgramExit(NDBT_FAILED);
}
diff --git a/ndb/test/ndbapi/testDataBuffers.cpp b/ndb/test/ndbapi/testDataBuffers.cpp
index 04602f51d5f..03d52252334 100644
--- a/ndb/test/ndbapi/testDataBuffers.cpp
+++ b/ndb/test/ndbapi/testDataBuffers.cpp
@@ -123,15 +123,15 @@ chkerror(char const* fmt, ...)
// alignment of addresses and data sizes
-static bool isAligned(unsigned x)
+static bool isAligned(UintPtr x)
{
return ((x & 3) == 0);
}
static bool isAligned(char* p)
{
- return isAligned(unsigned(p));
+ return isAligned(UintPtr(p));
}
-static unsigned toAligned(unsigned x)
+static unsigned toAligned(UintPtr x)
{
while (! isAligned(x))
x++;
@@ -223,10 +223,10 @@ testcase(int flag)
noRandom = ! (flag & 8);
ndbout << (noRandom ? "simple sizes" : "randomize sizes") << endl;
- int smax = 0, stot = 0;
+ int smax = 0, stot = 0, i;
if (xverbose)
ndbout << "- define table " << tab << endl;
- for (int i = 0; i < attrcnt; i++) {
+ for (i = 0; i < attrcnt; i++) {
col& c = ccol[i];
memset(&c, 0, sizeof(c));
sprintf(c.aAttrName, "C%d", i);
@@ -266,7 +266,7 @@ testcase(int flag)
return ndberror("getNdbSchemaOp");
if (top->createTable(tab) < 0)
return ndberror("createTable");
- for (int i = 0; i < attrcnt; i++) {
+ for (i = 0; i < attrcnt; i++) {
col& c = ccol[i];
if (top->createAttribute(
c.aAttrName,
@@ -299,7 +299,7 @@ testcase(int flag)
return ndberror("getNdbOperation key=%d", key);
if (op->deleteTuple() < 0)
return ndberror("deleteTuple key=%d", key);
- for (int i = 0; i < attrcnt; i++) {
+ for (i = 0; i < attrcnt; i++) {
col& c = ccol[i];
if (i == 0) {
if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
@@ -329,7 +329,7 @@ testcase(int flag)
return ndberror("getNdbOperation key=%d", key);
if (op->insertTuple() < 0)
return ndberror("insertTuple key=%d", key);
- for (int i = 0; i < attrcnt; i++) {
+ for (i = 0; i < attrcnt; i++) {
col& c = ccol[i];
if (i == 0) {
if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
@@ -362,7 +362,7 @@ testcase(int flag)
return ndberror("getNdbOperation key=%d", key);
if (op->readTuple() < 0)
return ndberror("readTuple key=%d", key);
- for (int i = 0; i < attrcnt; i++) {
+ for (i = 0; i < attrcnt; i++) {
col& c = ccol[i];
if (i == 0) {
if (op->equal(c.aAttrName, (char*)&key, sizeof(key)) < 0)
@@ -371,7 +371,7 @@ testcase(int flag)
if (xverbose) {
char tmp[20];
if (useBuf)
- sprintf(tmp, "0x%x", int(c.buf + off));
+ sprintf(tmp, "0x%p", c.buf + off);
else
strcpy(tmp, "ndbapi");
ndbout << "--- column " << i << " addr=" << tmp << endl;
@@ -388,23 +388,24 @@ testcase(int flag)
}
if (con->execute(Commit) != 0)
return ndberror("execute key=%d", key);
- for (int i = 0; i < attrcnt; i++) {
+ for (i = 0; i < attrcnt; i++) {
col& c = ccol[i];
if (i == 0) {
} else if (useBuf) {
- for (int j = 0; j < off; j++) {
+ int j;
+ for (j = 0; j < off; j++) {
if (c.buf[j] != 'B') {
return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
key, i, j, 'B', c.buf[j]);
}
}
- for (int j = 0; j < c.aArraySize; j++) {
+ for (j = 0; j < c.aArraySize; j++) {
if (c.buf[j + off] != byteVal(key, i, j)) {
return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
key, i, j, byteVal(key, i, j), c.buf[j]);
}
}
- for (int j = c.aArraySize + off; j < c.bufsiz; j++) {
+ for (j = c.aArraySize + off; j < c.bufsiz; j++) {
if (c.buf[j] != 'B') {
return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
key, i, j, 'B', c.buf[j]);
@@ -431,7 +432,8 @@ testcase(int flag)
if (xverbose)
ndbout << "- scan" << endl;
char found[MaxOper];
- for (int k = 0; k < opercnt; k++)
+ int k;
+ for (k = 0; k < opercnt; k++)
found[k] = 0;
for (key = 0; key < opercnt; key++) {
int off = makeOff(key);
@@ -459,7 +461,7 @@ testcase(int flag)
if (op->interpret_exit_ok() < 0)
return ndberror("interpret_exit_ok");
}
- for (int i = 0; i < attrcnt; i++) {
+ for (i = 0; i < attrcnt; i++) {
col& c = ccol[i];
if (i == 0) {
if (op->getValue(c.aAttrName, (char*)&newkey) < 0)
@@ -468,7 +470,7 @@ testcase(int flag)
if (xverbose) {
char tmp[20];
if (useBuf)
- sprintf(tmp, "0x%x", int(c.buf + off));
+ sprintf(tmp, "0x%p", c.buf + off);
else
strcpy(tmp, "ndbapi");
ndbout << "--- column " << i << " addr=" << tmp << endl;
@@ -489,22 +491,23 @@ testcase(int flag)
while ((ret = rs->nextResult()) == 0) {
if (key != newkey)
return ndberror("unexpected key=%d newkey=%d", key, newkey);
- for (int i = 1; i < attrcnt; i++) {
+ for (i = 1; i < attrcnt; i++) {
col& c = ccol[i];
if (useBuf) {
- for (int j = 0; j < off; j++) {
+ int j;
+ for (j = 0; j < off; j++) {
if (c.buf[j] != 'C') {
return chkerror("mismatch before key=%d col=%d pos=%d ok=%02x bad=%02x",
key, i, j, 'C', c.buf[j]);
}
}
- for (int j = 0; j < c.aArraySize; j++) {
+ for (j = 0; j < c.aArraySize; j++) {
if (c.buf[j + off] != byteVal(key, i, j)) {
return chkerror("mismatch key=%d col=%d pos=%d ok=%02x bad=%02x",
key, i, j, byteVal(key, i, j), c.buf[j]);
}
}
- for (int j = c.aArraySize + off; j < c.bufsiz; j++) {
+ for (j = c.aArraySize + off; j < c.bufsiz; j++) {
if (c.buf[j] != 'C') {
return chkerror("mismatch after key=%d col=%d pos=%d ok=%02x bad=%02x",
key, i, j, 'C', c.buf[j]);
@@ -533,7 +536,7 @@ testcase(int flag)
}
con = 0;
op = 0;
- for (int k = 0; k < opercnt; k++)
+ for (k = 0; k < opercnt; k++)
if (! found[k])
return ndberror("key %d not found", k);
ndbout << "scanned " << key << endl;
@@ -545,6 +548,7 @@ testcase(int flag)
NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuffers", 65535)
{
+ int i;
ndb_init();
while (++argv, --argc > 0) {
char const* p = argv[0];
@@ -602,7 +606,7 @@ NDB_COMMAND(testDataBuffers, "testDataBuffers", "testDataBuffers", "testDataBuff
}
}
unsigned ok = true;
- for (int i = 1; 0 == loopcnt || i <= loopcnt; i++) {
+ for (i = 1; 0 == loopcnt || i <= loopcnt; i++) {
ndbout << "=== loop " << i << " ===" << endl;
for (int flag = 0; flag < (1<<testbits); flag++) {
if (testcase(flag) < 0) {
diff --git a/ndb/test/ndbapi/testDeadlock.cpp b/ndb/test/ndbapi/testDeadlock.cpp
index 66fa48173cc..eb985e815ac 100644
--- a/ndb/test/ndbapi/testDeadlock.cpp
+++ b/ndb/test/ndbapi/testDeadlock.cpp
@@ -459,7 +459,8 @@ wl1822_main(char scantx)
static const unsigned thrcount = 2;
// create threads for tx1 and tx2
Thr* thrlist[2];
- for (int n = 0; n < thrcount; n++) {
+ int n;
+ for (n = 0; n < thrcount; n++) {
Thr& thr = *(thrlist[n] = new Thr(1 + n));
CHK(thr.m_ret == 0);
}
@@ -472,7 +473,7 @@ wl1822_main(char scantx)
if (runstep != 0)
thr.start(runstep);
}
- for (int n = 0; n < thrcount; n++) {
+ for (n = 0; n < thrcount; n++) {
Thr& thr = *thrlist[n];
Runstep runstep = wl1822_step[i][n];
if (runstep != 0)
@@ -480,7 +481,7 @@ wl1822_main(char scantx)
}
}
// delete threads
- for (int n = 0; n < thrcount; n++) {
+ for (n = 0; n < thrcount; n++) {
Thr& thr = *thrlist[n];
thr.exit();
thr.join();
diff --git a/ndb/test/ndbapi/testDict.cpp b/ndb/test/ndbapi/testDict.cpp
index 89232de2535..0a43bb02fff 100644
--- a/ndb/test/ndbapi/testDict.cpp
+++ b/ndb/test/ndbapi/testDict.cpp
@@ -1431,11 +1431,12 @@ int
runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
Vector<char*> cols;
Vector<const NdbDictionary::Table*> tabs;
+ int i;
Ndb* pNdb = GETNDB(step);
const Uint32 count = NDBT_Tables::getNumTables();
- for (int i=0; i < count; i++){
+ for (i=0; i < count; i++){
const NdbDictionary::Table * tab = NDBT_Tables::getTable(i);
pNdb->getDictionary()->createTable(* tab);
@@ -1458,7 +1459,7 @@ runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
Uint32 size = cols.size() / 2;
char ** columns = &cols[0];
Uint64 start = NdbTick_CurrentMillisecond();
- for(int i = 0; i<times; i++){
+ for(i = 0; i<times; i++){
int j = 2 * (rand() % size);
const NdbDictionary::Table* tab = (const NdbDictionary::Table*)tcols[j];
const char * col = tcols[j+1];
@@ -1478,6 +1479,84 @@ runTestDictionaryPerf(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK;
}
+int runFailAddFragment(NDBT_Context* ctx, NDBT_Step* step){
+ static int acclst[] = { 3001 };
+ static int tuplst[] = { 4007, 4008, 4009, 4010, 4011, 4012 };
+ static int tuxlst[] = { 12001, 12002, 12003, 12004, 12005, 12006 };
+ static unsigned acccnt = sizeof(acclst)/sizeof(acclst[0]);
+ static unsigned tupcnt = sizeof(tuplst)/sizeof(tuplst[0]);
+ static unsigned tuxcnt = sizeof(tuxlst)/sizeof(tuxlst[0]);
+
+ NdbRestarter restarter;
+ int nodeId = restarter.getMasterNodeId();
+ Ndb* pNdb = GETNDB(step);
+ NdbDictionary::Dictionary* pDic = pNdb->getDictionary();
+ NdbDictionary::Table tab(*ctx->getTab());
+ tab.setFragmentType(NdbDictionary::Object::FragAllLarge);
+
+ // ordered index on first few columns
+ NdbDictionary::Index idx("X");
+ idx.setTable(tab.getName());
+ idx.setType(NdbDictionary::Index::OrderedIndex);
+ idx.setLogging(false);
+ for (int i_hate_broken_compilers = 0;
+ i_hate_broken_compilers < 3 &&
+ i_hate_broken_compilers < tab.getNoOfColumns();
+ i_hate_broken_compilers++) {
+ idx.addColumn(*tab.getColumn(i_hate_broken_compilers));
+ }
+
+ const int loops = ctx->getNumLoops();
+ int result = NDBT_OK;
+ (void)pDic->dropTable(tab.getName());
+
+ for (int l = 0; l < loops; l++) {
+ for (unsigned i0 = 0; i0 < acccnt; i0++) {
+ unsigned j = (l == 0 ? i0 : myRandom48(acccnt));
+ int errval = acclst[j];
+ g_info << "insert error node=" << nodeId << " value=" << errval << endl;
+ CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
+ "failed to set error insert");
+ CHECK2(pDic->createTable(tab) != 0,
+ "failed to fail after error insert " << errval);
+ CHECK2(pDic->createTable(tab) == 0,
+ pDic->getNdbError());
+ CHECK2(pDic->dropTable(tab.getName()) == 0,
+ pDic->getNdbError());
+ }
+ for (unsigned i1 = 0; i1 < tupcnt; i1++) {
+ unsigned j = (l == 0 ? i1 : myRandom48(tupcnt));
+ int errval = tuplst[j];
+ g_info << "insert error node=" << nodeId << " value=" << errval << endl;
+ CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
+ "failed to set error insert");
+ CHECK2(pDic->createTable(tab) != 0,
+ "failed to fail after error insert " << errval);
+ CHECK2(pDic->createTable(tab) == 0,
+ pDic->getNdbError());
+ CHECK2(pDic->dropTable(tab.getName()) == 0,
+ pDic->getNdbError());
+ }
+ for (unsigned i2 = 0; i2 < tuxcnt; i2++) {
+ unsigned j = (l == 0 ? i2 : myRandom48(tuxcnt));
+ int errval = tuxlst[j];
+ g_info << "insert error node=" << nodeId << " value=" << errval << endl;
+ CHECK2(restarter.insertErrorInNode(nodeId, errval) == 0,
+ "failed to set error insert");
+ CHECK2(pDic->createTable(tab) == 0,
+ pDic->getNdbError());
+ CHECK2(pDic->createIndex(idx) != 0,
+ "failed to fail after error insert " << errval);
+ CHECK2(pDic->createIndex(idx) == 0,
+ pDic->getNdbError());
+ CHECK2(pDic->dropTable(tab.getName()) == 0,
+ pDic->getNdbError());
+ }
+ }
+end:
+ return result;
+}
+
NDBT_TESTSUITE(testDict);
TESTCASE("CreateAndDrop",
"Try to create and drop the table loop number of times\n"){
@@ -1573,6 +1652,10 @@ TESTCASE("DictionaryPerf",
""){
INITIALIZER(runTestDictionaryPerf);
}
+TESTCASE("FailAddFragment",
+ "Fail add fragment or attribute in ACC or TUP or TUX\n"){
+ INITIALIZER(runFailAddFragment);
+}
NDBT_TESTSUITE_END(testDict);
int main(int argc, const char** argv){
@@ -1582,5 +1665,3 @@ int main(int argc, const char** argv){
myRandom48Init(NdbTick_CurrentMillisecond());
return testDict.execute(argc, argv);
}
-
-
diff --git a/ndb/test/ndbapi/testIndex.cpp b/ndb/test/ndbapi/testIndex.cpp
index ed9e114fd92..6623ad35a7f 100644
--- a/ndb/test/ndbapi/testIndex.cpp
+++ b/ndb/test/ndbapi/testIndex.cpp
@@ -58,7 +58,9 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){
// Build attrib definitions that describes which attributes to build index
// Try to build strange combinations, not just "all" or all PK's
- for(int i = 1; i <= pTab->getNoOfColumns(); i++){
+ int i;
+
+ for(i = 1; i <= pTab->getNoOfColumns(); i++){
attr = new Attrib;
attr->numAttribs = i;
for(int a = 0; a<i; a++)
@@ -66,7 +68,7 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){
attriblist.push_back(attr);
}
int b = 0;
- for(int i = pTab->getNoOfColumns()-1; i > 0; i--){
+ for(i = pTab->getNoOfColumns()-1; i > 0; i--){
attr = new Attrib;
attr->numAttribs = i;
b++;
@@ -74,21 +76,21 @@ void AttribList::buildAttribList(const NdbDictionary::Table* pTab){
attr->attribs[a] = a+b;
attriblist.push_back(attr);
}
- for(int i = pTab->getNoOfColumns(); i > 0; i--){
+ for(i = pTab->getNoOfColumns(); i > 0; i--){
attr = new Attrib;
attr->numAttribs = pTab->getNoOfColumns() - i;
for(int a = 0; a<pTab->getNoOfColumns() - i; a++)
attr->attribs[a] = pTab->getNoOfColumns()-a-1;
attriblist.push_back(attr);
}
- for(int i = 1; i < pTab->getNoOfColumns(); i++){
+ for(i = 1; i < pTab->getNoOfColumns(); i++){
attr = new Attrib;
attr->numAttribs = pTab->getNoOfColumns() - i;
for(int a = 0; a<pTab->getNoOfColumns() - i; a++)
attr->attribs[a] = pTab->getNoOfColumns()-a-1;
attriblist.push_back(attr);
}
- for(int i = 1; i < pTab->getNoOfColumns(); i++){
+ for(i = 1; i < pTab->getNoOfColumns(); i++){
attr = new Attrib;
attr->numAttribs = 2;
for(int a = 0; a<2; a++){
@@ -226,8 +228,8 @@ int runCreateIndexes(NDBT_Context* ctx, NDBT_Step* step){
while (l < loops && result == NDBT_OK){
-
- for (unsigned int i = 0; i < attrList.attriblist.size(); i++){
+ unsigned int i;
+ for (i = 0; i < attrList.attriblist.size(); i++){
// Try to create index
if (create_index(ctx, i, pTab, pNdb, attrList.attriblist[i], logged) == NDBT_FAILED)
@@ -235,7 +237,7 @@ int runCreateIndexes(NDBT_Context* ctx, NDBT_Step* step){
}
// Now drop all indexes that where created
- for (unsigned int i = 0; i < attrList.attriblist.size(); i++){
+ for (i = 0; i < attrList.attriblist.size(); i++){
// Try to drop index
if (drop_index(i, pNdb, pTab, attrList.attriblist[i]) != NDBT_OK)
@@ -1083,8 +1085,8 @@ runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){
else
pIdx.setType(NdbDictionary::Index::UniqueHashIndex);
pIdx.setStoredIndex(logged);
-
- for (int c = 0; c< pTab->getNoOfColumns(); c++){
+ int c;
+ for (c = 0; c< pTab->getNoOfColumns(); c++){
const NdbDictionary::Column * col = pTab->getColumn(c);
if(col->getPrimaryKey()){
pIdx.addIndexColumn(col->getName());
@@ -1093,7 +1095,7 @@ runUniqueNullTransactions(NDBT_Context* ctx, NDBT_Step* step){
}
int colId = -1;
- for (int c = 0; c< pTab->getNoOfColumns(); c++){
+ for (c = 0; c< pTab->getNoOfColumns(); c++){
const NdbDictionary::Column * col = pTab->getColumn(c);
if(col->getNullable()){
pIdx.addIndexColumn(col->getName());
diff --git a/ndb/test/ndbapi/testLcp.cpp b/ndb/test/ndbapi/testLcp.cpp
index c92be091a97..4304d51596a 100644
--- a/ndb/test/ndbapi/testLcp.cpp
+++ b/ndb/test/ndbapi/testLcp.cpp
@@ -85,7 +85,8 @@ main(int argc, char ** argv){
g_info << " where ZLCP_OP_WRITE_RT_BREAK is finished before SAVE_PAGES"
<< endl;
require(!pause_lcp());
- for(size_t j = 0; j<g_rows; j++){
+ size_t j;
+ for(j = 0; j<g_rows; j++){
require(!do_op(j));
}
require(!continue_lcp(5900));
@@ -98,7 +99,7 @@ main(int argc, char ** argv){
<< endl;
require(!load_table());
require(!pause_lcp());
- for(size_t j = 0; j<g_rows; j++){
+ for(j = 0; j<g_rows; j++){
require(!do_op(j));
}
require(!continue_lcp(5901));
@@ -109,7 +110,7 @@ main(int argc, char ** argv){
g_info << "Testing pre LCP operations, undo-ed at commit" << endl;
require(!load_table());
require(!pause_lcp());
- for(size_t j = 0; j<g_rows; j++){
+ for(j = 0; j<g_rows; j++){
require(!do_op(j));
}
require(!continue_lcp(5902));
@@ -121,6 +122,7 @@ main(int argc, char ** argv){
static int init_ndb(int argc, char** argv)
{
+ ndb_init();
return 0;
}
diff --git a/ndb/test/ndbapi/testNdbApi.cpp b/ndb/test/ndbapi/testNdbApi.cpp
index 74cb1f8bcd0..a1ebac609b6 100644
--- a/ndb/test/ndbapi/testNdbApi.cpp
+++ b/ndb/test/ndbapi/testNdbApi.cpp
@@ -88,10 +88,10 @@ int runTestMaxNdb(NDBT_Context* ctx, NDBT_Step* step){
oldi = i;
- for(size_t i = 0; i < ndbVector.size(); i++){
- delete ndbVector[i];
- if(((i+1) % 250) == 0){
- ndbout << "Deleted " << (Uint64) i << " ndb objects " << endl;
+ for(size_t j = 0; j < ndbVector.size(); j++){
+ delete ndbVector[j];
+ if(((j+1) % 250) == 0){
+ ndbout << "Deleted " << (Uint64) j << " ndb objects " << endl;
}
}
ndbVector.clear();
@@ -178,8 +178,8 @@ int runTestMaxTransaction(NDBT_Context* ctx, NDBT_Step* step){
oldi = i;
- for(size_t i = 0; i < conVector.size(); i++){
- pNdb->closeTransaction(conVector[i]);
+ for(size_t j = 0; j < conVector.size(); j++){
+ pNdb->closeTransaction(conVector[j]);
}
conVector.clear();
l++;
@@ -537,8 +537,8 @@ int runTestDeleteNdb(NDBT_Context* ctx, NDBT_Step* step){
}
// Delete the ndb objects
- for(size_t i = 0; i < ndbVector.size(); i++)
- delete ndbVector[i];
+ for(size_t j = 0; j < ndbVector.size(); j++)
+ delete ndbVector[j];
ndbVector.clear();
l++;
}
diff --git a/ndb/test/ndbapi/testOIBasic.cpp b/ndb/test/ndbapi/testOIBasic.cpp
index 21862e02328..41f0686e63b 100644
--- a/ndb/test/ndbapi/testOIBasic.cpp
+++ b/ndb/test/ndbapi/testOIBasic.cpp
@@ -407,10 +407,11 @@ Col::verify(const void* addr) const
const unsigned char* p = (const unsigned char*)addr;
unsigned n = (p[0] << 8) | p[1];
assert(n <= m_length);
- for (unsigned i = 0; i < n; i++) {
+ unsigned i;
+ for (i = 0; i < n; i++) {
assert(p[2 + i] != 0);
}
- for (unsigned i = n; i < m_length; i++) {
+ for (i = n; i < m_length; i++) {
assert(p[2 + i] == 0);
}
}
@@ -3021,7 +3022,8 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode)
{
LL2(fname);
const int threads = (mode & ST ? 1 : par.m_threads);
- for (int n = 0; n < threads; n++) {
+ int n;
+ for (n = 0; n < threads; n++) {
LL4("start " << n);
Thr& thr = *g_thrlist[n];
thr.m_par.m_tab = par.m_tab;
@@ -3033,7 +3035,7 @@ runstep(Par par, const char* fname, TFunc func, unsigned mode)
thr.start();
}
unsigned errs = 0;
- for (int n = threads - 1; n >= 0; n--) {
+ for (n = threads - 1; n >= 0; n--) {
LL4("stop " << n);
Thr& thr = *g_thrlist[n];
thr.stopped();
@@ -3301,10 +3303,11 @@ runtest(Par par)
CHK(con.connect() == 0);
par.m_con = &con;
g_thrlist = new Thr* [par.m_threads];
- for (unsigned n = 0; n < par.m_threads; n++) {
+ unsigned n;
+ for (n = 0; n < par.m_threads; n++) {
g_thrlist[n] = 0;
}
- for (unsigned n = 0; n < par.m_threads; n++) {
+ for (n = 0; n < par.m_threads; n++) {
g_thrlist[n] = new Thr(par, n);
Thr& thr = *g_thrlist[n];
assert(thr.m_thread != 0);
@@ -3330,11 +3333,11 @@ runtest(Par par)
}
}
}
- for (unsigned n = 0; n < par.m_threads; n++) {
+ for (n = 0; n < par.m_threads; n++) {
Thr& thr = *g_thrlist[n];
thr.exit();
}
- for (unsigned n = 0; n < par.m_threads; n++) {
+ for (n = 0; n < par.m_threads; n++) {
Thr& thr = *g_thrlist[n];
thr.join();
delete &thr;
diff --git a/ndb/test/ndbapi/testPartitioning.cpp b/ndb/test/ndbapi/testPartitioning.cpp
new file mode 100644
index 00000000000..e01e96571c5
--- /dev/null
+++ b/ndb/test/ndbapi/testPartitioning.cpp
@@ -0,0 +1,189 @@
+/* Copyright (C) 2003 MySQL AB
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+#include <NDBT_Test.hpp>
+#include <NDBT_ReturnCodes.h>
+#include <HugoTransactions.hpp>
+#include <UtilTransactions.hpp>
+#include <NdbRestarter.hpp>
+
+#define GETNDB(ps) ((NDBT_NdbApiStep*)ps)->getNdb()
+
+static
+int runLoadTable(NDBT_Context* ctx, NDBT_Step* step)
+{
+ int records = ctx->getNumRecords();
+ HugoTransactions hugoTrans(*ctx->getTab());
+ if (hugoTrans.loadTable(GETNDB(step), records) != 0){
+ return NDBT_FAILED;
+ }
+ return NDBT_OK;
+}
+
+static
+int
+run_drop_table(NDBT_Context* ctx, NDBT_Step* step)
+{
+ NdbDictionary::Dictionary* dict = GETNDB(step)->getDictionary();
+ dict->dropTable(ctx->getTab()->getName());
+ return 0;
+}
+
+static
+int
+add_distribution_key(Ndb*, NdbDictionary::Table& tab, int when)
+{
+ switch(when){
+ case 0: // Before
+ break;
+ case 1: // After
+ return 0;
+ default:
+ return 0;
+ }
+
+ int keys = tab.getNoOfPrimaryKeys();
+ int dks = (2 * keys + 2) / 3;
+ int cnt = 0;
+ ndbout_c("%s pks: %d dks: %d", tab.getName(), keys, dks);
+ for(unsigned i = 0; i<tab.getNoOfColumns(); i++)
+ {
+ NdbDictionary::Column* col = tab.getColumn(i);
+ if(col->getPrimaryKey())
+ {
+ if(dks >= keys || (rand() % 100) > 50)
+ {
+ col->setDistributionKey(true);
+ dks--;
+ }
+ keys--;
+ }
+ }
+ return 0;
+}
+
+int
+run_create_table(NDBT_Context* ctx, NDBT_Step* step)
+{
+ bool dk = ctx->getProperty("distributionkey", (unsigned)0);
+ return NDBT_Tables::createTable(GETNDB(step),
+ ctx->getTab()->getName(),
+ false, false, dk?add_distribution_key:0);
+}
+
+int
+run_pk_dk(NDBT_Context* ctx, NDBT_Step* step)
+{
+ Ndb* p_ndb = GETNDB(step);
+ int records = ctx->getNumRecords();
+ const NdbDictionary::Table *tab =
+ p_ndb->getDictionary()->getTable(ctx->getTab()->getName());
+ HugoTransactions hugoTrans(*tab);
+
+ if (hugoTrans.loadTable(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.pkReadRecords(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.pkUpdateRecords(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.pkDelRecords(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if (hugoTrans.loadTable(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.scanUpdateRecords(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.scanReadRecords(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ if(hugoTrans.clearTable(p_ndb, records) != 0)
+ {
+ return NDBT_FAILED;
+ }
+
+ return 0;
+}
+
+int
+run_hash_dk(NDBT_Context* ctx, NDBT_Step* step)
+{
+ return 0;
+}
+
+int
+run_index_dk(NDBT_Context* ctx, NDBT_Step* step)
+{
+ return 0;
+}
+
+
+NDBT_TESTSUITE(testPartitioning);
+TESTCASE("pk_dk",
+ "Primary key operations with distribution key")
+{
+ TC_PROPERTY("distributionkey", 1);
+ INITIALIZER(run_drop_table);
+ INITIALIZER(run_create_table);
+ INITIALIZER(run_pk_dk);
+ INITIALIZER(run_drop_table);
+}
+TESTCASE("hash_index_dk",
+ "Unique index operatations with distribution key")
+{
+ TC_PROPERTY("distributionkey", 1);
+ INITIALIZER(run_drop_table);
+ INITIALIZER(run_create_table);
+ INITIALIZER(run_hash_dk);
+ INITIALIZER(run_drop_table);
+}
+TESTCASE("ordered_index_dk",
+ "Ordered index operatations with distribution key")
+{
+ TC_PROPERTY("distributionkey", 1);
+ INITIALIZER(run_drop_table);
+ INITIALIZER(run_create_table);
+ INITIALIZER(run_index_dk);
+ INITIALIZER(run_drop_table);
+}
+NDBT_TESTSUITE_END(testPartitioning);
+
+int main(int argc, const char** argv){
+ ndb_init();
+ testPartitioning.setCreateTable(false);
+ return testPartitioning.execute(argc, argv);
+}
+
+
+
diff --git a/ndb/test/ndbapi/testReadPerf.cpp b/ndb/test/ndbapi/testReadPerf.cpp
index 8d0d78cbe8c..3adcb5a2d9b 100644
--- a/ndb/test/ndbapi/testReadPerf.cpp
+++ b/ndb/test/ndbapi/testReadPerf.cpp
@@ -99,7 +99,8 @@ main(int argc, const char** argv){
{ "verbose", 'v', arg_flag, &verbose, "Print verbose status", "verbose" }
};
const int num_args = 1 + P_MAX;
- for(int i = 0; i<P_MAX; i++){
+ int i;
+ for(i = 0; i<P_MAX; i++){
args[i+1].long_name = g_paramters[i].name;
args[i+1].short_name = * g_paramters[i].name;
args[i+1].type = arg_integer;
@@ -127,7 +128,7 @@ main(int argc, const char** argv){
g_err << "Wait until ready failed" << endl;
goto error;
}
- for(int i = optind; i<argc; i++){
+ for(i = optind; i<argc; i++){
const char * T = argv[i];
g_info << "Testing " << T << endl;
BaseString::snprintf(g_table, sizeof(g_table), T);
@@ -390,8 +391,15 @@ run_read(){
void
print_result(){
+ int tmp = 1;
+ tmp *= g_paramters[P_RANGE].value;
+ tmp *= g_paramters[P_LOOPS].value;
+
+ int t, t2;
for(int i = 0; i<P_OP_TYPES; i++){
- g_err.println("%s avg: %u us/row", g_ops[i],
- (1000*g_times[i])/(g_paramters[P_RANGE].value*g_paramters[P_LOOPS].value));
+ g_err << g_ops[i] << " avg: "
+ << (int)((1000*g_times[i])/tmp)
+ << " us/row ("
+ << (1000 * tmp)/g_times[i] << " rows / sec)" << endl;
}
}
diff --git a/ndb/test/ndbapi/testRestartGci.cpp b/ndb/test/ndbapi/testRestartGci.cpp
index e817245af55..4e541d1f38f 100644
--- a/ndb/test/ndbapi/testRestartGci.cpp
+++ b/ndb/test/ndbapi/testRestartGci.cpp
@@ -132,7 +132,8 @@ int runVerifyInserts(NDBT_Context* ctx, NDBT_Step* step){
// RULE1: The vector with saved records should have exactly as many
// records with lower or same gci as there are in DB
int recordsWithLowerOrSameGci = 0;
- for (unsigned i = 0; i < savedRecords.size(); i++){
+ unsigned i;
+ for (i = 0; i < savedRecords.size(); i++){
if (savedRecords[i].m_gci <= restartGCI)
recordsWithLowerOrSameGci++;
}
@@ -144,7 +145,7 @@ int runVerifyInserts(NDBT_Context* ctx, NDBT_Step* step){
// RULE2: The records found in db should have same or lower
// gci as in the vector
- for (unsigned i = 0; i < savedRecords.size(); i++){
+ for (i = 0; i < savedRecords.size(); i++){
CHECK(hugoOps.startTransaction(pNdb) == 0);
CHECK(hugoOps.pkReadRecord(pNdb, i) == 0);
if (hugoOps.execute_Commit(pNdb) != 0){
diff --git a/ndb/test/ndbapi/testScan.cpp b/ndb/test/ndbapi/testScan.cpp
index 0cd30dfefde..22ec3fff327 100644
--- a/ndb/test/ndbapi/testScan.cpp
+++ b/ndb/test/ndbapi/testScan.cpp
@@ -90,11 +90,59 @@ int runLoadAllTables(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK;
}
+char orderedPkIdxName[255];
+
+int createOrderedPkIndex(NDBT_Context* ctx, NDBT_Step* step){
+
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ Ndb* pNdb = GETNDB(step);
+
+ // Create index
+ BaseString::snprintf(orderedPkIdxName, sizeof(orderedPkIdxName),
+ "IDC_O_PK_%s", pTab->getName());
+ NdbDictionary::Index pIdx(orderedPkIdxName);
+ pIdx.setTable(pTab->getName());
+ pIdx.setType(NdbDictionary::Index::OrderedIndex);
+ pIdx.setLogging(false);
+
+ for (int c = 0; c< pTab->getNoOfColumns(); c++){
+ const NdbDictionary::Column * col = pTab->getColumn(c);
+ if(col->getPrimaryKey()){
+ pIdx.addIndexColumn(col->getName());
+ }
+ }
+
+ if (pNdb->getDictionary()->createIndex(pIdx) != 0){
+ ndbout << "FAILED! to create index" << endl;
+ const NdbError err = pNdb->getDictionary()->getNdbError();
+ ERR(err);
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+int createOrderedPkIndex_Drop(NDBT_Context* ctx, NDBT_Step* step){
+ const NdbDictionary::Table* pTab = ctx->getTab();
+ Ndb* pNdb = GETNDB(step);
+
+ // Drop index
+ if (pNdb->getDictionary()->dropIndex(orderedPkIdxName,
+ pTab->getName()) != 0){
+ ndbout << "FAILED! to drop index" << endl;
+ ERR(pNdb->getDictionary()->getNdbError());
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+}
+
+
int runScanReadRandomTable(NDBT_Context* ctx, NDBT_Step* step){
int loops = ctx->getNumLoops();
int records = ctx->getNumRecords();
int parallelism = ctx->getProperty("Parallelism", 240);
- int abort = ctx->getProperty("AbortProb");
+ int abort = ctx->getProperty("AbortProb", 5);
int i = 0;
while (i<loops) {
@@ -218,7 +266,7 @@ int runScanRead(NDBT_Context* ctx, NDBT_Step* step){
int loops = ctx->getNumLoops();
int records = ctx->getNumRecords();
int parallelism = ctx->getProperty("Parallelism", 240);
- int abort = ctx->getProperty("AbortProb");
+ int abort = ctx->getProperty("AbortProb", 5);
int i = 0;
HugoTransactions hugoTrans(*ctx->getTab());
@@ -232,18 +280,66 @@ int runScanRead(NDBT_Context* ctx, NDBT_Step* step){
return NDBT_OK;
}
+int runRandScanRead(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = ctx->getProperty("Parallelism", 240);
+ int abort = ctx->getProperty("AbortProb", 5);
+
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (i<loops && !ctx->isTestStopped()) {
+ g_info << i << ": ";
+ NdbOperation::LockMode lm = (NdbOperation::LockMode)(rand() % 3);
+ if (hugoTrans.scanReadRecords(GETNDB(step),
+ records, abort, parallelism,
+ lm) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
+int runScanReadIndex(NDBT_Context* ctx, NDBT_Step* step){
+ int loops = ctx->getNumLoops();
+ int records = ctx->getNumRecords();
+ int parallelism = ctx->getProperty("Parallelism", 240);
+ int abort = ctx->getProperty("AbortProb", 5);
+ const NdbDictionary::Index * pIdx =
+ GETNDB(step)->getDictionary()->getIndex(orderedPkIdxName,
+ ctx->getTab()->getName());
+
+ int i = 0;
+ HugoTransactions hugoTrans(*ctx->getTab());
+ while (pIdx && i<loops && !ctx->isTestStopped()) {
+ g_info << i << ": ";
+ bool sort = (rand() % 100) > 50 ? true : false;
+ NdbOperation::LockMode lm = (NdbOperation::LockMode)(rand() % 3);
+ if (hugoTrans.scanReadRecords(GETNDB(step), pIdx,
+ records, abort, parallelism,
+ lm,
+ sort) != 0){
+ return NDBT_FAILED;
+ }
+ i++;
+ }
+ return NDBT_OK;
+}
+
int runScanReadCommitted(NDBT_Context* ctx, NDBT_Step* step){
int loops = ctx->getNumLoops();
int records = ctx->getNumRecords();
int parallelism = ctx->getProperty("Parallelism", 240);
- int abort = ctx->getProperty("AbortProb");
+ int abort = ctx->getProperty("AbortProb", 5);
int i = 0;
HugoTransactions hugoTrans(*ctx->getTab());
while (i<loops && !ctx->isTestStopped()) {
g_info << i << ": ";
- if (hugoTrans.scanReadCommittedRecords(GETNDB(step), records,
- abort, parallelism) != 0){
+ if (hugoTrans.scanReadRecords(GETNDB(step), records,
+ abort, parallelism,
+ NdbOperation::LM_CommittedRead) != 0){
return NDBT_FAILED;
}
i++;
@@ -424,7 +520,7 @@ int runScanUpdate(NDBT_Context* ctx, NDBT_Step* step){
int loops = ctx->getNumLoops();
int records = ctx->getNumRecords();
int parallelism = ctx->getProperty("Parallelism", 1);
- int abort = ctx->getProperty("AbortProb");
+ int abort = ctx->getProperty("AbortProb", 5);
int i = 0;
HugoTransactions hugoTrans(*ctx->getTab());
while (i<loops) {
@@ -464,7 +560,7 @@ int runScanUpdate2(NDBT_Context* ctx, NDBT_Step* step){
int loops = ctx->getNumLoops();
int records = ctx->getNumRecords();
int parallelism = ctx->getProperty("Parallelism", 240);
- int abort = ctx->getProperty("AbortProb");
+ int abort = ctx->getProperty("AbortProb", 5);
int i = 0;
HugoTransactions hugoTrans(*ctx->getTab());
while (i<loops) {
@@ -639,7 +735,7 @@ int runCheckGetValue(NDBT_Context* ctx, NDBT_Step* step){
g_info << (unsigned)i << endl;
if(utilTrans.scanReadRecords(GETNDB(step),
parallelism,
- false,
+ NdbOperation::LM_Read,
records,
alist.attriblist[i]->numAttribs,
alist.attriblist[i]->attribs) != 0){
@@ -647,7 +743,7 @@ int runCheckGetValue(NDBT_Context* ctx, NDBT_Step* step){
}
if(utilTrans.scanReadRecords(GETNDB(step),
parallelism,
- true,
+ NdbOperation::LM_Read,
records,
alist.attriblist[i]->numAttribs,
alist.attriblist[i]->attribs) != 0){
@@ -1079,7 +1175,30 @@ TESTCASE("ScanRead488",
"When this limit is exceeded the scan will be aborted with errorcode "\
"488."){
INITIALIZER(runLoadTable);
- STEPS(runScanRead, 70);
+ STEPS(runRandScanRead, 70);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead488O",
+ "Verify scan requirement: It's only possible to have 11 concurrent "\
+ "scans per fragment running in Ndb kernel at the same time. "\
+ "When this limit is exceeded the scan will be aborted with errorcode "\
+ "488."){
+ INITIALIZER(createOrderedPkIndex);
+ INITIALIZER(runLoadTable);
+ STEPS(runScanReadIndex, 70);
+ FINALIZER(createOrderedPkIndex_Drop);
+ FINALIZER(runClearTable);
+}
+TESTCASE("ScanRead488_Mixed",
+ "Verify scan requirement: It's only possible to have 11 concurrent "\
+ "scans per fragment running in Ndb kernel at the same time. "\
+ "When this limit is exceeded the scan will be aborted with errorcode "\
+ "488."){
+ INITIALIZER(createOrderedPkIndex);
+ INITIALIZER(runLoadTable);
+ STEPS(runRandScanRead, 50);
+ STEPS(runScanReadIndex, 50);
+ FINALIZER(createOrderedPkIndex_Drop);
FINALIZER(runClearTable);
}
TESTCASE("ScanRead488Timeout",
diff --git a/ndb/test/ndbapi/testScanPerf.cpp b/ndb/test/ndbapi/testScanPerf.cpp
index c1334125978..d388af9f642 100644
--- a/ndb/test/ndbapi/testScanPerf.cpp
+++ b/ndb/test/ndbapi/testScanPerf.cpp
@@ -38,9 +38,10 @@ struct Parameter {
#define P_ROWS 7
#define P_LOOPS 8
#define P_CREATE 9
-#define P_LOAD 10
+#define P_RESET 11
+#define P_MULTI 12
-#define P_MAX 11
+#define P_MAX 13
static
Parameter
@@ -55,7 +56,9 @@ g_paramters[] = {
{ "size", 1000000, 1, ~0 },
{ "iterations", 3, 1, ~0 },
{ "create_drop", 1, 0, 1 },
- { "data", 1, 0, 1 }
+ { "data", 1, 0, 1 },
+ { "q-reset bounds", 0, 1, 0 },
+ { "multi read range", 1000, 1, ~0 }
};
static Ndb* g_ndb = 0;
@@ -65,10 +68,7 @@ static char g_tablename[256];
static char g_indexname[256];
int create_table();
-int load_table();
int run_scan();
-int clear_table();
-int drop_table();
int
main(int argc, const char** argv){
@@ -80,7 +80,8 @@ main(int argc, const char** argv){
{ "verbose", 'v', arg_flag, &verbose, "Print verbose status", "verbose" }
};
const int num_args = 1 + P_MAX;
- for(int i = 0; i<P_MAX; i++){
+ int i;
+ for(i = 0; i<P_MAX; i++){
args[i+1].long_name = g_paramters[i].name;
args[i+1].short_name = * g_paramters[i].name;
args[i+1].type = arg_integer;
@@ -107,21 +108,15 @@ main(int argc, const char** argv){
g_err << "Wait until ready failed" << endl;
goto error;
}
- for(int i = optind; i<argc; i++){
+ for(i = optind; i<argc; i++){
const char * T = argv[i];
g_info << "Testing " << T << endl;
BaseString::snprintf(g_tablename, sizeof(g_tablename), T);
BaseString::snprintf(g_indexname, sizeof(g_indexname), "IDX_%s", T);
if(create_table())
goto error;
- if(load_table())
- goto error;
if(run_scan())
goto error;
- if(clear_table())
- goto error;
- if(drop_table())
- goto error;
}
if(g_ndb) delete g_ndb;
@@ -136,6 +131,7 @@ create_table(){
NdbDictionary::Dictionary* dict = g_ndb->getDictionary();
assert(dict);
if(g_paramters[P_CREATE].value){
+ g_ndb->getDictionary()->dropTable(g_tablename);
const NdbDictionary::Table * pTab = NDBT_Tables::getTable(g_tablename);
assert(pTab);
NdbDictionary::Table copy = * pTab;
@@ -164,46 +160,18 @@ create_table(){
g_index = dict->getIndex(g_indexname, g_tablename);
assert(g_table);
assert(g_index);
- return 0;
-}
-
-int
-drop_table(){
- if(!g_paramters[P_CREATE].value)
- return 0;
- if(g_ndb->getDictionary()->dropTable(g_table->getName()) != 0){
- g_err << "Failed to drop table: " << g_table->getName() << endl;
- return -1;
- }
- g_table = 0;
- return 0;
-}
-int
-load_table(){
- if(!g_paramters[P_LOAD].value)
- return 0;
-
- int rows = g_paramters[P_ROWS].value;
- HugoTransactions hugoTrans(* g_table);
- if (hugoTrans.loadTable(g_ndb, rows)){
- g_err.println("Failed to load %s with %d rows", g_table->getName(), rows);
- return -1;
+ if(g_paramters[P_CREATE].value)
+ {
+ int rows = g_paramters[P_ROWS].value;
+ HugoTransactions hugoTrans(* g_table);
+ if (hugoTrans.loadTable(g_ndb, rows)){
+ g_err.println("Failed to load %s with %d rows",
+ g_table->getName(), rows);
+ return -1;
+ }
}
- return 0;
-}
-
-int
-clear_table(){
- if(!g_paramters[P_LOAD].value)
- return 0;
- int rows = g_paramters[P_ROWS].value;
- UtilTransactions utilTrans(* g_table);
- if (utilTrans.clearTable(g_ndb, rows) != 0){
- g_err.println("Failed to clear table %s", g_table->getName());
- return -1;
- }
return 0;
}
@@ -218,21 +186,30 @@ run_scan(){
NDB_TICKS start1, stop;
int sum_time= 0;
+ int sample_rows = 0;
+ int tot_rows = 0;
+ NDB_TICKS sample_start = NdbTick_CurrentMillisecond();
+
Uint32 tot = g_paramters[P_ROWS].value;
+ if(g_paramters[P_BOUND].value >= 2 || g_paramters[P_FILT].value == 2)
+ iter *= g_paramters[P_ROWS].value;
+
+ NdbScanOperation * pOp = 0;
+ NdbIndexScanOperation * pIOp = 0;
+ NdbConnection * pTrans = 0;
+ NdbResultSet * rs = 0;
+ int check = 0;
+
for(int i = 0; i<iter; i++){
start1 = NdbTick_CurrentMillisecond();
- NdbConnection * pTrans = g_ndb->startTransaction();
+ pTrans = pTrans ? pTrans : g_ndb->startTransaction();
if(!pTrans){
g_err << "Failed to start transaction" << endl;
err(g_ndb->getNdbError());
return -1;
}
- NdbScanOperation * pOp;
- NdbIndexScanOperation * pIOp;
-
- NdbResultSet * rs;
int par = g_paramters[P_PARRA].value;
int bat = g_paramters[P_BATCH].value;
NdbScanOperation::LockMode lm;
@@ -255,9 +232,17 @@ run_scan(){
assert(pOp);
rs = pOp->readTuples(lm, bat, par);
} else {
- pOp = pIOp = pTrans->getNdbIndexScanOperation(g_indexname, g_tablename);
- bool ord = g_paramters[P_ACCESS].value == 2;
- rs = pIOp->readTuples(lm, bat, par, ord);
+ if(g_paramters[P_RESET].value == 0 || pIOp == 0)
+ {
+ pOp= pIOp= pTrans->getNdbIndexScanOperation(g_indexname, g_tablename);
+ bool ord = g_paramters[P_ACCESS].value == 2;
+ rs = pIOp->readTuples(lm, bat, par, ord);
+ }
+ else
+ {
+ pIOp->reset_bounds();
+ }
+
switch(g_paramters[P_BOUND].value){
case 0: // All
break;
@@ -267,12 +252,28 @@ run_scan(){
case 2: { // 1 row
default:
assert(g_table->getNoOfPrimaryKeys() == 1); // only impl. so far
- abort();
-#if 0
int tot = g_paramters[P_ROWS].value;
int row = rand() % tot;
+#if 0
fix_eq_bound(pIOp, row);
+#else
+ pIOp->setBound((Uint32)0, NdbIndexScanOperation::BoundEQ, &row);
#endif
+ if(g_paramters[P_RESET].value == 2)
+ goto execute;
+ break;
+ }
+ case 3: { // read multi
+ int multi = g_paramters[P_MULTI].value;
+ int tot = g_paramters[P_ROWS].value;
+ for(; multi > 0 && i < iter; --multi, i++)
+ {
+ int row = rand() % tot;
+ pIOp->setBound((Uint32)0, NdbIndexScanOperation::BoundEQ, &row);
+ pIOp->set_new_bound();
+ }
+ if(g_paramters[P_RESET].value == 2)
+ goto execute;
break;
}
}
@@ -280,7 +281,6 @@ run_scan(){
assert(pOp);
assert(rs);
- int check = 0;
switch(g_paramters[P_FILT].value){
case 0: // All
check = pOp->interpret_exit_ok();
@@ -309,10 +309,16 @@ run_scan(){
}
assert(check == 0);
+ if(g_paramters[P_RESET].value == 1)
+ g_paramters[P_RESET].value = 2;
+
for(int i = 0; i<g_table->getNoOfColumns(); i++){
pOp->getValue(i);
}
+ if(g_paramters[P_RESET].value == 1)
+ g_paramters[P_RESET].value = 2;
+execute:
int rows = 0;
check = pTrans->execute(NoCommit);
assert(check == 0);
@@ -333,19 +339,30 @@ run_scan(){
return -1;
}
assert(check == 1);
- g_info << "Found " << rows << " rows" << endl;
-
- pTrans->close();
-
+ if(g_paramters[P_RESET].value == 0)
+ {
+ pTrans->close();
+ pTrans = 0;
+ }
stop = NdbTick_CurrentMillisecond();
+
int time_passed= (int)(stop - start1);
- g_err.println("Time: %d ms = %u rows/sec", time_passed,
- (1000*tot)/time_passed);
+ sample_rows += rows;
sum_time+= time_passed;
+ tot_rows+= rows;
+
+ if(sample_rows >= tot)
+ {
+ int sample_time = (int)(stop - sample_start);
+ g_info << "Found " << sample_rows << " rows" << endl;
+ g_err.println("Time: %d ms = %u rows/sec", sample_time,
+ (1000*sample_rows)/sample_time);
+ sample_rows = 0;
+ sample_start = stop;
+ }
}
- sum_time= sum_time / iter;
- g_err.println("Avg time: %d ms = %u rows/sec", sum_time,
- (1000*tot)/sum_time);
+ g_err.println("Avg time: %d ms = %u rows/sec", sum_time/tot_rows,
+ (1000*tot_rows)/sum_time);
return 0;
}
diff --git a/ndb/test/ndbapi/testSystemRestart.cpp b/ndb/test/ndbapi/testSystemRestart.cpp
index f8f2b84acc4..35016896495 100644
--- a/ndb/test/ndbapi/testSystemRestart.cpp
+++ b/ndb/test/ndbapi/testSystemRestart.cpp
@@ -452,7 +452,7 @@ int runSystemRestart3(NDBT_Context* ctx, NDBT_Step* step){
}
Vector<int> nodeIds;
- for(Uint32 i = 0; i<nodeCount; i++)
+ for(i = 0; i<nodeCount; i++)
nodeIds.push_back(restarter.getDbNodeId(i));
Uint32 currentRestartNodeIndex = 0;
@@ -561,7 +561,7 @@ int runSystemRestart4(NDBT_Context* ctx, NDBT_Step* step){
}
Vector<int> nodeIds;
- for(Uint32 i = 0; i<nodeCount; i++)
+ for(i = 0; i<nodeCount; i++)
nodeIds.push_back(restarter.getDbNodeId(i));
Uint32 currentRestartNodeIndex = 0;
@@ -691,7 +691,7 @@ int runSystemRestart5(NDBT_Context* ctx, NDBT_Step* step){
}
Vector<int> nodeIds;
- for(Uint32 i = 0; i<nodeCount; i++)
+ for(i = 0; i<nodeCount; i++)
nodeIds.push_back(restarter.getDbNodeId(i));
Uint32 currentRestartNodeIndex = 0;
@@ -821,7 +821,7 @@ int runSystemRestart6(NDBT_Context* ctx, NDBT_Step* step){
}
Vector<int> nodeIds;
- for(Uint32 i = 0; i<nodeCount; i++)
+ for(i = 0; i<nodeCount; i++)
nodeIds.push_back(restarter.getDbNodeId(i));
Uint32 currentRestartNodeIndex = 0;
@@ -877,7 +877,7 @@ int runSystemRestart7(NDBT_Context* ctx, NDBT_Step* step){
}
Vector<int> nodeIds;
- for(Uint32 i = 0; i<nodeCount; i++)
+ for(i = 0; i<nodeCount; i++)
nodeIds.push_back(restarter.getDbNodeId(i));
int a_nodeIds[64];
@@ -952,7 +952,7 @@ int runSystemRestart8(NDBT_Context* ctx, NDBT_Step* step){
}
Vector<int> nodeIds;
- for(Uint32 i = 0; i<nodeCount; i++)
+ for(i = 0; i<nodeCount; i++)
nodeIds.push_back(restarter.getDbNodeId(i));
int a_nodeIds[64];
diff --git a/ndb/test/odbc/tpcb/Makefile b/ndb/test/odbc/tpcb/Makefile
deleted file mode 100644
index 8ab429c8ea1..00000000000
--- a/ndb/test/odbc/tpcb/Makefile
+++ /dev/null
@@ -1,30 +0,0 @@
-include .defs.mk
-
-TYPE = *
-
-BIN_TARGET = tpcb
-
-SOURCES = ttTime.c tpcb.cpp
-
-CCFLAGS_LOC += \
- -I$(NDB_TOP)/include \
- -I$(NDB_TOP)/include/ndbapi \
- -I$(NDB_TOP)/include/portlib \
- -I$(NDB_TOP)/include/util \
- -I$(NDB_TOP)/test/include \
- -I/usr/local/include
-
-CCFLAGS_WARNINGS += -Wno-unused -Wno-sign-compare -Wformat
-
-CCFLAGS_TOP += -DndbODBC
-
-BIN_TARGET_LIBS = NDB_API_pic NDB_ODBC_pic NDBT
-
-ifeq ($(NDB_OS),SOLARIS)
-BIN_TARGET_LIBS += dmallocthcxx
-CCFLAGS_TOP += -DDMALLOC
-endif
-
-include $(NDB_TOP)/Epilogue.mk
-
-$(BIN_DIR)$(BIN_TARGET): Makefile
diff --git a/ndb/test/odbc/tpcb/Makefile_mysql b/ndb/test/odbc/tpcb/Makefile_mysql
deleted file mode 100644
index 4e1b9a25fe2..00000000000
--- a/ndb/test/odbc/tpcb/Makefile_mysql
+++ /dev/null
@@ -1,33 +0,0 @@
-include $(NDB_TOP)/Defs.mk
-
-TYPE = odbcclient
-
-BIN_TARGET = tpcb
-
-SOURCES = ttTime.c tpcb.cpp
-
-CCFLAGS_LOC += -I/usr/local/include \
- -I$(NDB_TOP)/test/include \
- -I$(NDB_TOP)/include \
- -I$(NDB_TOP)/include/util \
- -I$(NDB_TOP)/src/client/odbc/common
-
-
-
-
-#CCFLAGS_WARNINGS += -Wno-unused
-
-LIBS_LOC += -L/usr/local/lib
-BIN_TARGET_LIBS_DIRS += /usr/local/lib
-BIN_TARGET_LIBS += odbc odbcinst
-
-#LIBS_SPEC += -pg
-# -lNDBT \
-# -lodbc \
-# -lodbcinst \
-# -lportlib
-
-
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/test/odbc/tpcb/Makefile_ndb b/ndb/test/odbc/tpcb/Makefile_ndb
deleted file mode 100644
index 85960413ef0..00000000000
--- a/ndb/test/odbc/tpcb/Makefile_ndb
+++ /dev/null
@@ -1,30 +0,0 @@
-include $(NDB_TOP)/Defs.mk
-
-TYPE = *
-
-BIN_TARGET = tpcb
-
-SOURCES = ttTime.c tpcb.cpp
-
-CCFLAGS_LOC += \
- -I$(NDB_TOP)/include \
- -I$(NDB_TOP)/include/ndbapi \
- -I$(NDB_TOP)/include/portlib \
- -I$(NDB_TOP)/include/util \
- -I$(NDB_TOP)/test/include \
- -I/usr/local/include
-
-CCFLAGS_WARNINGS += -Wno-unused -Wno-sign-compare -Wformat
-
-CCFLAGS_TOP += -DndbODBC
-
-BIN_TARGET_LIBS = NDB_API_pic NDB_ODBC_pic NDBT
-
-ifeq ($(NDB_OS),SOLARIS)
-BIN_TARGET_LIBS += dmallocthcxx
-CCFLAGS_TOP += -DDMALLOC
-endif
-
-include $(NDB_TOP)/Epilogue.mk
-
-$(BIN_DIR)$(BIN_TARGET): Makefile
diff --git a/ndb/test/odbc/tpcb/readme.txt b/ndb/test/odbc/tpcb/readme.txt
deleted file mode 100644
index 008cafb9d2f..00000000000
--- a/ndb/test/odbc/tpcb/readme.txt
+++ /dev/null
@@ -1,15 +0,0 @@
-'tpcb' requires an .odbc.ini file in
-/etc/
-or in
-/home/user/
-
-The .odbc.ini file must contain a DSN entry called ndb:
-
-#--------- .odbc.ini example --------------------
-
-[ndb]
-Driver = /path_to_installation/lib/libNDB_ODBC.so
-
-#--------- End of example -----------------------
-
-
diff --git a/ndb/test/odbc/tpcb/timesten.h b/ndb/test/odbc/tpcb/timesten.h
deleted file mode 100644
index 45579f9d277..00000000000
--- a/ndb/test/odbc/tpcb/timesten.h
+++ /dev/null
@@ -1,188 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- * $Revision: 1.1 $
- * (c) Copyright 1997-2003, TimesTen, Inc.
- * All rights reserved.
- */
-
-#ifndef TIMESTEN_H_INCLUDED
-#define TIMESTEN_H_INCLUDED
-
-#ifdef _WIN32
-#include <windows.h>
-#endif
-
-#include <sql.h>
-#include <sqltypes.h>
-#include <sqlext.h>
-/*
- * TimesTen extension to application data types; only usable
- * when application directly linked to the TimesTen driver.
- */
-#define SQL_C_ADDR 100
-
-#ifndef SQL_C_SBIGINT
-#if (ODBCVER < 0x0300)
-#define SQL_C_SBIGINT (SQL_BIGINT+SQL_SIGNED_OFFSET)
-#define SQL_C_UBIGINT (SQL_BIGINT+SQL_UNSIGNED_OFFSET)
-#endif
-#endif
-
-#define SQL_C_BIGINT SQL_C_SBIGINT
-
-#if (ODBCVER < 0x0300)
-#ifdef _WIN32
-typedef __int64 SQLBIGINT;
-/* On Unix platforms SQLBIGINT is defined in odbcinclude directory*/
-#endif
-#endif
-
-#define BIGINT SQLBIGINT
-
-#ifdef _WIN32
-#define UBIGINT unsigned __int64
-#else
-#define UBIGINT unsigned long long
-#endif
-
-
-#define SQL_WCHAR (-8)
-#define SQL_WVARCHAR (-9)
-#define SQL_WLONGVARCHAR (-10)
-#define SQL_C_WCHAR SQL_WCHAR
-
-/* SQLGetInfo() InfoTypes */
-#define SQL_CONVERT_WCHAR 122
-#define SQL_CONVERT_WLONGVARCHAR 125
-#define SQL_CONVERT_WVARCHAR 126
-
-/* TimesTen specific SQLGetInfo types */
-#define TT_REPLICATION_INVALID (SQL_INFO_DRIVER_START + 2000)
-
-/* SQLGetInfo() return value bitmasks */
-#ifndef SQL_CVT_WCHAR
-/*
-** These definitions differ from Microsoft in that they are not
-** specified as long (e.g. 0x00200000L), hence they are protected
-** by the ifndef above.
-*/
-#define SQL_CVT_WCHAR 0x00200000
-#define SQL_CVT_WLONGVARCHAR 0x00400000
-#define SQL_CVT_WVARCHAR 0x00800000
-#endif
-
-/*
-** The Microsoft Driver Manager SQLBindParameter() will not pass SQL_WCHAR
-** through. Use this hack to get around it.
-*/
-#define SQL_WCHAR_DM_SQLBINDPARAMETER_BYPASS -888
-
-/* This is an extension to ODBC's isolation levels. It reflects an
- * earlier implementation of read-committed that released locks on
- * next fetch, rather than releasing locks before returning value to
- * application. */
-#define SQL_TXN_CURSOR_STABILITY 0x00001000
-#define SQL_TXN_NOBLOCK_DELETE 0x00002000
-
-/* TimesTen-specific connection option */
-#define TT_PREFETCH_CLOSE 10001
-#define TT_PREFETCH_CLOSE_OFF 0
-#define TT_PREFETCH_CLOSE_ON 1
-
-/* Adding a new sql connection option */
-#define TT_PREFETCH_COUNT 10003
-#define TT_PREFETCH_COUNT_MAX 128
-
-/*
- * Platform specific data types for integers that scale
- * with pointer size
- */
-
-#ifdef _IA64_
-typedef signed __int64 tt_ptrint;
-typedef unsigned __int64 tt_uptrint;
-#else
-#ifdef _WIN32
-typedef signed long tt_ptrint;
-typedef unsigned long tt_uptrint;
-#else
-typedef signed long tt_ptrint;
-typedef unsigned long tt_uptrint;
-#endif
-#endif
-
-#ifdef _WIN32
-typedef signed __int64 tt_int8;
-typedef unsigned __int64 tt_uint8;
-#else
-typedef signed long long tt_int8;
-typedef unsigned long long tt_uint8;
-#endif
-
-/* printf formats for pointer-sized integers */
-#ifdef _IA64_ /* 64-bit NT */
-#define PTRINT_FMT "I64d"
-#define UPTRINT_FMT "I64u"
-#define xPTRINT_FMT "I64x"
-#define XPTRINT_FMT "I64X"
-#else
-#ifdef _WIN32 /* 32-bit NT */
-#define PTRINT_FMT "ld"
-#define UPTRINT_FMT "lu"
-#define xPTRINT_FMT "lx"
-#define XPTRINT_FMT "lX"
-#else /* 32 and 64-bit UNIX */
-#define PTRINT_FMT "ld"
-#define UPTRINT_FMT "lu"
-#define xPTRINT_FMT "lx"
-#define XPTRINT_FMT "lX"
-#endif
-#endif
-
-/* printf formats for 8-byte integers */
-#ifndef INT8_FMT_DEFINED
-#ifdef _WIN32 /* 32 and 64-bit NT */
-#define INT8_FMT "I64d"
-#define UINT8_FMT "I64u"
-#define xINT8_FMT "I64x"
-#define XINT8_FMT "I64X"
-#else /* 32 and 64-bit UNIX */
-#define INT8_FMT "lld"
-#define UINT8_FMT "llu"
-#define xINT8_FMT "llx"
-#define XINT8_FMT "llX"
-#endif
-#define INT8_FMT_DEFINED 1
-#endif
-
-/* The following types are defined in the newer odbc include files
- from Microsoft
-*/
-#if defined (_WIN32) && !defined (_IA64_)
-#ifndef SQLROWSETSIZE
-#define SQLROWSETSIZE SQLUINTEGER
-#define SQLLEN SQLINTEGER
-#define SQLROWOFFSET SQLINTEGER
-#define SQLROWCOUNT SQLUINTEGER
-#define SQLULEN SQLUINTEGER
-#define SQLSETPOSIROW SQLUSMALLINT
-#endif
-#endif
-
-
-#endif
diff --git a/ndb/test/odbc/tpcb/tpcb.cpp b/ndb/test/odbc/tpcb/tpcb.cpp
deleted file mode 100644
index 60d746e7844..00000000000
--- a/ndb/test/odbc/tpcb/tpcb.cpp
+++ /dev/null
@@ -1,1415 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-static const volatile char cvsid[] = "$Id: tpcb.cpp,v 1.4 2003/09/26 09:04:34 johan Exp $";
-/*
- * $Revision: 1.4 $
- * (c) Copyright 1996-2003, TimesTen, Inc.
- * All rights reserved.
- */
-
-/* This source is best displayed with a tabstop of 4 */
-
-#define NDB
-
-//#define MYSQL
-
-#ifdef WIN32
-#include <windows.h>
-#include "ttRand.h"
-#else
-#if !defined NDB && !defined MYSQL
-#include <sqlunix.h>
-#endif
-#include <unistd.h>
-#include <sys/types.h>
-#include <sys/stat.h>
-#ifdef SB_P_OS_CHORUS
-#include "ttRand.h"
-#endif
-#endif
-
-#include <math.h>
-#include <time.h>
-#include <sql.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <ctype.h>
-
-#if !defined NDB && !defined MYSQL
-#include "ttTime.h"
-#include "utils.h"
-#include "tt_version.h"
-#include "timesten.h"
-#endif
-
-#if defined NDB || defined MYSQL
-#include <NdbOut.hpp>
-#include <string.h>
-
-#include <sqlext.h>
-#include <sql.h>
-extern "C" {
-#include "ttTime.h"
-#include "timesten.h"
- void ttGetWallClockTime(ttWallClockTime* timeP);
- void ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
- ttWallClockTime* afterP,
- double* nmillisecondsP);
- void ttGetThreadTimes(ttThreadTimes * endRes);
- void ttCalcElapsedThreadTimes(ttThreadTimes* startRes,
- ttThreadTimes * endRes,
- double * kernel,
- double * user);
-}
-
-#define app_exit exit
-#define status_msg0 ndbout_c
-#define status_msg1 ndbout_c
-#define status_msg2 ndbout_c
-#define err_msg0 ndbout_c
-#define err_msg1 ndbout_c
-#define err_msg3 ndbout_c
-#define out_msg0 ndbout_c
-#define out_msg1 ndbout_c
-#define out_msg3 ndbout_c
-#define CONN_STR_LEN 255
-#define DBMS_TIMESTEN 1
-#define DBMS_MSSQL 2
-#define DBMS_UNKNOWN 3
-#define ABORT_DISCONNECT_EXIT 1
-#define NO_EXIT 0
-#define ERROR_EXIT 1
-#define DISCONNECT_EXIT 2
-#endif
-
-#define VERBOSE_NOMSGS 0
-/* this value is used for results (and err msgs) only */
-#define VERBOSE_RESULTS 1
-/* this value is the default for the cmdline demo */
-#define VERBOSE_DFLT 2
-#define VERBOSE_ALL 3
-
-#ifdef MYSQL
-#define DSNNAME "DSN=myodbc3"
-#elif defined NDB
-#define DSNNAME "DSN=ndb"
-#else
-#define DSNNAME "DSN="
-#endif
-
-/* number of branches, tellers, and accounts */
-
-#define NumBranches 1
-#define TellersPerBranch 10
-#define AccountsPerBranch 10000
-
-/* number of transactions to execute */
-
-#define NumXacts 25000
-
-/* starting seed value for the random number generator */
-
-#define SeedVal 84773
-
-/* for MS SQL, the drop, create and use database statements */
-
-#define DatabaseDropStmt "drop database tpcbDB;"
-#ifdef MYSQL
-#define DatabaseCreateStmt "create database tpcbDB;"
-#else
-#define DatabaseCreateStmt "create database tpcbDB ON DEFAULT = %d;"
-#endif
-#define DatabaseUseStmt "use tpcbDB;"
-
-/*
- * Specifications of table columns.
- * Fillers of 80, 80, 84, and 24 bytes, respectively, are used
- * to ensure that rows are the width required by the benchmark.
- *
- * Note: The TimesTen and MS SQL CREATE TABLE statements for the
- * accounts, tellers and branches tables are different.
- *
- */
-
-#define TuplesPerPage 256
-
-
-#ifdef MYSQL
-
-#define AccountCrTblStmt "create table accounts \
-(number integer not null primary key, \
-branchnum integer not null, \
-balance float not null, \
-filler char(80));"
-
-#define TellerCrTblStmt "create table tellers \
-(number integer not null primary key, \
-branchnum integer not null, \
-balance float not null, \
-filler char(80));"
-
-#define BranchCrTblStmt "create table branches \
-(number integer not null primary key, \
-balance float not null, \
-filler char(84));"
-
-#endif
-
-
-#ifdef NDB
-#define AccountCrTblStmt "create table accounts \
-(number integer not null primary key, \
-branchnum integer not null, \
-balance float not null, \
-filler char(80)) nologging"
-
-#define TellerCrTblStmt "create table tellers \
-(number integer not null primary key, \
-branchnum integer not null, \
-balance float not null, \
-filler char(80)) nologging"
-
-#define BranchCrTblStmt "create table branches \
-(number integer not null primary key, \
-balance float not null, \
-filler char(84)) nologging"
-#endif
-
-#ifdef NDB
-
-#define HistoryCrTblStmt "create table History \
-(tellernum integer not null, \
-branchnum integer not null, \
-accountnum integer not null, \
-delta float not null, \
-createtime integer not null, \
-filler char(24), \
-primary key (tellernum, branchnum, accountnum, delta, createtime)) nologging"
-
-#else
-
-#ifdef MYSQL
-
-#define HistoryCrTblStmt "create table History \
-(tellernum integer not null, \
-branchnum integer not null, \
-accountnum integer not null, \
-delta float(53) not null, \
-createtime integer not null, \
-filler char(24))"
-#endif
-
-#define HistoryCrTblStmt "create table History \
-(tellernum integer not null, \
-branchnum integer not null, \
-accountnum integer not null, \
-delta float(53) not null, \
-createtime integer not null, \
-filler char(24));"
-#endif
-
-#define TTAccountCrTblStmt "create table accounts \
-(number integer not null primary key, \
-branchnum integer not null, \
-balance float(53) not null, \
-filler char(80)) unique hash on (number) pages = %" PTRINT_FMT ";"
-
-#define TTTellerCrTblStmt "create table tellers \
-(number integer not null primary key, \
-branchnum integer not null, \
-balance float(53) not null, \
-filler char(80)) unique hash on (number) pages = %" PTRINT_FMT ";"
-
-#define TTBranchCrTblStmt "create table branches \
-(number integer not null primary key, \
-balance float(53) not null, \
-filler char(84)) unique hash on (number) pages = %" PTRINT_FMT ";"
-
-
-/* Insertion statements used to populate the tables */
-
-#define NumInsStmts 3
-char* insStmt[NumInsStmts] = {
- "insert into branches values (?, 0.0, NULL)",
- "insert into tellers values (?, ?, 0.0, NULL)",
- "insert into accounts values (?, ?, 0.0, NULL)"
-};
-
-/* Transaction statements used to update the tables */
-
-#define NumXactStmts 5
-
-#ifdef NDB
-char* tpcbXactStmt[NumXactStmts] = {
- "update accounts \
-set balance = balance + ? \
-where number = ?",
-
- "select balance \
-from accounts \
-where number = ?",
-
- "update tellers \
-set balance = balance + ? \
-where number = ?",
-
- "update branches \
-set balance = balance + ? \
-where number = ?",
-
- "insert into History(tellernum, branchnum, \
-accountnum, delta, createtime, filler) \
-values (?, ?, ?, ?, ?, NULL)"
-};
-
-#else
-char* tpcbXactStmt[NumXactStmts] = {
- "update accounts \
-set balance = balance + ? \
-where number = ?;",
-
- "select balance \
-from accounts \
-where number = ?;",
-
- "update tellers \
-set balance = balance + ? \
-where number = ?;",
-
- "update branches \
-set balance = balance + ? \
-where number = ?;",
-
- "insert into History \
-values (?, ?, ?, ?, ?, NULL);"
-};
-
-
-#endif
-
-/* Global parameters and flags (typically set by parse_args()) */
-
-int tabFlag = 0; /* Default is NOT tab output mode */
-char szConnStrIn[CONN_STR_LEN]; /* ODBC Connection String */
-int printXactTimes = 0; /* Transaction statistics
- * gathering flag */
-char statFile[FILENAME_MAX]; /* Transaction statistics filename */
-int scaleFactor = 2; /* Default TPS scale factor */
-int numBranchTups; /* Number of branches */
-int numTellerTups; /* Number of tellers */
-int numAccountTups; /* Number of accounts */
-int numNonLocalAccountTups; /* Number of local accounts */
-int numXacts = NumXacts; /* Default number of transactions */
-int verbose = VERBOSE_DFLT; /* Verbose level */
-FILE *statusfp; /* File for status messages */
-
-
-
-int DBMSType; /* DBMS type (DBMS_TIMESTEN, DBMS_MSSQL...) */
-
-
-SQLHENV henv; /* Environment handle */
-
-
-
-
-
-
-
-void handle_errors( SQLHDBC hdbc, SQLHSTMT hstmt, int errcode, int action, char * msg,
- char * file, int line) {
-
- if (errcode == SQL_SUCCESS)
- return;
-
- if(errcode == SQL_ERROR) {
- int ret;
- long diagCount=0;
- short length=0;
- SQLCHAR state[10] = "";
- SQLCHAR message[200] = "";
- long native = 0;
- if(hstmt != 0) {
- ret = SQLGetDiagField(SQL_HANDLE_STMT, hstmt, 0, SQL_DIAG_NUMBER, &diagCount, SQL_IS_INTEGER, 0);
-
- for(long i = 0; i < diagCount; i++) {
- ret = SQLGetDiagRec(SQL_HANDLE_STMT, hstmt, i, (SQLCHAR*)state, &native, (SQLCHAR*)message, 200, &length);
- ndbout_c("GetDiagRec: Message : %s ", message);
- }
- }
- }
-
- if(errcode != SQL_SUCCESS) {
- ndbout_c("Message: %s", msg);
- switch(errcode) {
- case SQL_SUCCESS_WITH_INFO:
- ndbout_c("SQL_SUCCESS_WITH_INFO");
- break;
- case SQL_STILL_EXECUTING:
- ndbout_c("SQL_STILL_EXECUTING");
- break;
- case SQL_ERROR:
- ndbout_c("SQL_ERROR");
- break;
- case SQL_INVALID_HANDLE:
- ndbout_c("SQL_INVALID_HANDLE");
- break;
- default:
- ndbout_c("Some other error");
- }
- exit(1);
- }
-
-
-}
-
-
-
-
-
-/*********************************************************************
- * FUNCTION: usage
- *
- * DESCRIPTION: This function prints a usage message describing
- * the command line options of the program.
- *
- * PARAMETERS: char* prog full program path name
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-static void usage(char *prog)
-{
- char *progname;
-
- /* Get the name of the program (sans path). */
-
-#ifdef WIN32
- progname = strrchr(prog, '\\');
-#else
- progname = strrchr(prog, '/');
-#endif
- if (progname == 0)
- progname = prog;
- else
- ++progname;
-
- /* Print the usage message */
-
- fprintf(stderr,
- "Usage:\t%s [-h] [-help] [-V] [-connStr <string>] [-v <level>]\n"
- "\t\t[-xact <xacts>] [-scale <scale>] [-tabs] [-s <statfile>]\n\n"
- " -h Prints this message and exits.\n"
- " -help Same as -h.\n"
- " -V Prints version number and exits.\n"
- " -connStr <string> Specifies an ODBC connection string to replace the\n"
- " default DSN for the program. The default is\n"
- " \"DSN=TpcbData<version>;OverWrite=1\".\n"
- " -v <level> Verbose level\n"
- " 0 = errors only\n"
- " 1 = results only\n"
- " 2 = results and some status messages (default)\n"
- " 3 = all messages\n"
- " -xact <xacts> Specifies the number of transactions to be run\n"
- " The default is 25000 transactions.\n"
- " -scale <scale> Specifies a scale factor which determines the\n"
- " number of branches (scale), tellers (scale x 10),\n"
- " accounts (scale x 10000) and non-local accounts\n"
- " ((scale-1) x 10000. The default scale factor is 2.\n"
- " -tabs Specifies that the output be a tab-separated\n"
- " format suitable for import into a spreadsheet.\n"
- " Results only go to stdout; status and other\n"
- " messages go to stderr.\n"
- " -s <statfile> Prints individual transaction times to <statfile>.\n",
- progname);
-}
-
-/*********************************************************************
- *
- * FUNCTION: parse_args
- *
- * DESCRIPTION: This function parses the command line arguments
- * passed to main(), setting the appropriate global
- * variables and issuing a usage message for
- * invalid arguments.
- *
- * PARAMETERS: int argc # of arguments from main()
- * char *argv[] arguments from main()
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-void
-parse_args(int argc, char *argv[])
-{
- int i = 1;
-
- *szConnStrIn = 0;
-
- while (i < argc) {
-
- if ( !strcmp(argv[i], "-h") || !strcmp(argv[i], "-help") ) {
- usage(argv[0]);
- app_exit(0);
- }
- /*
- if (!strcmp(argv[i], "-V")) {
- printf("%s\n", TTVERSION_STRING);
- app_exit(0);
- }
- */
- if (strcmp(argv[i], "-s") == 0) {
- if (argc < i+2 ) {
- usage(argv[0]);
- app_exit(1);
- }
- if (sscanf(argv[i+1], "%s", statFile) == 0) {
- usage(argv[0]);
- app_exit(1);
- }
- printXactTimes = 1;
- i += 2;
- }
- else if (!strcmp(argv[i], "-connStr")) {
- if (argc < i+2 ) {
- usage(argv[0]);
- app_exit(1);
- }
- strcpy(szConnStrIn, argv[i+1]);
- i += 2;
- continue;
- }
- else if (strcmp("-v", argv[i]) == 0) {
- if (argc < i+2 ) {
- usage(argv[0]);
- app_exit(1);
- }
- if (sscanf(argv[i+1], "%d", &verbose) == -1 ||
- verbose < 0 || verbose > 3) {
- fprintf(stderr, "-v flag requires an integer parameter (0-3)\n");
- usage(argv[0]);
- app_exit(1);
- }
- i += 2;
- }
- else if (strcmp("-xact",argv[i]) == 0) {
- if (argc < i+2 ) {
- usage(argv[0]);
- app_exit(1);
- }
-
- if (sscanf(argv[i+1], "%" PTRINT_FMT, &numXacts) == -1 || numXacts < 0) {
- fprintf(stderr, "-xact flag requires a non-negative integer argument\n");
- usage(argv[0]);
- app_exit(1);
- }
-
- i += 2;
- }
- else if (strcmp("-scale",argv[i]) == 0) {
- if (argc < i+2 ) {
- usage(argv[0]);
- app_exit(1);
- }
- if (sscanf(argv[i+1], "%d", &scaleFactor) == -1 || scaleFactor < 1) {
- fprintf(stderr, "-scale flag requires an integer argument >= 1\n");
- usage(argv[0]);
- app_exit(1);
- }
- /* Calculate tuple sizes */
- numBranchTups = NumBranches * scaleFactor;
- numTellerTups = TellersPerBranch * scaleFactor;
- numAccountTups = AccountsPerBranch * scaleFactor;
- numNonLocalAccountTups = AccountsPerBranch * (scaleFactor-1);
- i += 2;
- }
- else if (strcmp("-tabs",argv[i]) == 0) {
- tabFlag = 1;
- statusfp = stderr;
- i += 1;
- }
- else {
- usage(argv[0]);
- app_exit(1);
- }
- }
-}
-
-/*********************************************************************
- *
- * FUNCTION: doImmed
- *
- * DESCRIPTION: This function executes and frees the specified
- * statement. It is used as a direct means to
- * create the tables used by this benchmark,
- *
- * PARAMETERS: SQLHDBC hdbc SQL Connection handle
- * SQLHSTMT hs SQL Statement handle
- * char* cmd SQL Statement text
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-void
-doImmed(SQLHDBC hdbc, SQLHSTMT hs, char* cmd)
-{
- SQLRETURN rc;
-
- /* Execute the command */
-
- rc = SQLExecDirect(hs, (SQLCHAR *) cmd, SQL_NTS);
- handle_errors(hdbc, hs, rc, ABORT_DISCONNECT_EXIT,
- "Error executing statement", __FILE__, __LINE__);
-
- /* Close associated cursor and drop pending results */
-
- rc = SQLFreeStmt(hs, SQL_CLOSE);
- handle_errors(hdbc, hs, rc, ABORT_DISCONNECT_EXIT,
- "closing statement handle",
- __FILE__, __LINE__);
-
-}
-
-
-/*********************************************************************
- *
- * FUNCTION: main
- *
- * DESCRIPTION: This is the main function of the tpcb benchmark.
- * It connects to an ODBC data source, creates and
- * populates tables, updates the tables in a user-
- * specified number of transactions and reports on
- * on the transaction times.
- *
- * PARAMETERS: int argc # of command line arguments
- * char *argv[] command line arguments
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-int
-main(int argc, char *argv[])
-{
-
- /* variables used for setting up the tables */
-
- char cmdStr[1024];
- char errstr[4096];
-
- /* variables used during transactions */
-
- int accountNum;
- int tellerNum;
- int branchNum;
- int timeStamp;
- double delta;
- unsigned int lrand;
- unsigned short *srands, localLimit;
- int lp64;
-
- /* variables used for timing and statistics */
-
- int warmup;
- double kernel, user, real;
- ttThreadTimes startRes, endRes;
- ttWallClockTime startT, endT;
- ttWallClockTime** rtStart;
- ttWallClockTime** rtEnd;
- double** resTime;
- double maxTime, totTime;
- int i;
- int j;
- int numLocalXacts=0, numRemoteXacts=0;
-
- /* variables for ODBC */
-
- SQLHDBC hdbc;
- SQLHSTMT hstmt;
- SQLHSTMT txstmt[NumXactStmts];
- SQLRETURN rc;
- char DBMSName[32];
- char DBMSVersion[32];
- int databaseSize;
-
- int fThreadTime = 1;
-
-#ifdef WIN32
- OSVERSIONINFO sysInfo;
-
- sysInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
- GetVersionEx (&sysInfo);
-
- /* GetThreadTimes is not supported on 95/98. Hence,
- we do not support Resource/User/System times */
- if (sysInfo.dwPlatformId != VER_PLATFORM_WIN32_NT)
- fThreadTime = 0;
-#endif
-#if defined(TTCLIENTSERVER) && defined(__hpux) && !defined(__LP64__)
- /* HP requires this for C main programs that call aC++ shared libs */
- _main();
-#endif /* hpux32 */
-
- /* Set up default signal handlers */
-
-#ifndef NDB
- /* StopRequestClear();
- if (HandleSignals() != 0) {
- err_msg0("Unable to set signal handlers\n");
- return 1;
- }
- */
-#endif
- /* set IO mode for demo */
- /* set_io_mode(); */
-
- /* initialize the file for status messages */
- statusfp = stdout;
-
- /* set variable for 8-byte longs */
- lp64 = (sizeof(lrand) == 8);
-
- /* set the default tuple sizes */
-
- numBranchTups = NumBranches * scaleFactor;
- numTellerTups = TellersPerBranch * scaleFactor;
- numAccountTups = AccountsPerBranch * scaleFactor;
- numNonLocalAccountTups = AccountsPerBranch * (scaleFactor-1);
-
- /* parse the command arguments */
- parse_args(argc, argv);
-
- /* allocate the transaction-based variables */
-
- rtStart = (ttWallClockTime**) malloc(numXacts * sizeof(ttWallClockTime*));
- if (!rtStart) {
- err_msg0("Cannot allocate the transaction timing structures");
- app_exit(1);
- }
- for (i = 0; i < numXacts; i++) {
- rtStart[i] = (ttWallClockTime*) malloc(sizeof(ttWallClockTime));
- if (!rtStart[i]) {
- err_msg0("Cannot allocate the transaction timing structures");
- app_exit(1);
- }
- }
-
- rtEnd = (ttWallClockTime**) malloc(numXacts * sizeof(ttWallClockTime*));
- if (!rtEnd) {
- err_msg0("Cannot allocate the transaction timing structures");
- app_exit(1);
- }
- for (i = 0; i < numXacts; i++) {
- rtEnd[i] = (ttWallClockTime*) malloc(sizeof(ttWallClockTime));
- if (!rtEnd[i]) {
- err_msg0("Cannot allocate the transaction timing structures");
- app_exit(1);
- }
- }
-
- resTime = (double**) malloc(numXacts * sizeof(double*));
- if (!resTime) {
- err_msg0("Cannot allocate the transaction timing structures");
- app_exit(1);
- }
- for (i = 0; i < numXacts; i++) {
- resTime[i] = (double*) malloc(sizeof(double));
- if (!resTime[i]) {
- err_msg0("Cannot allocate the transaction timing structures");
- app_exit(1);
- }
- }
-
- /* ODBC initialization */
-
- rc = SQLAllocEnv(&henv);
- if (rc != SQL_SUCCESS && rc != SQL_SUCCESS_WITH_INFO) {
- /* error occurred -- don't bother calling handle_errors, since handle
- * is not valid so SQLError won't work */
- err_msg3("ERROR in %s, line %d: %s\n",
- __FILE__, __LINE__, "allocating an environment handle");
- app_exit(1);
- }
- SQLSetEnvAttr(henv, SQL_ATTR_ODBC_VERSION, (SQLPOINTER)SQL_OV_ODBC3, SQL_IS_INTEGER);
-
- /* call this in case of warning */
- handle_errors(NULL, NULL, rc, NO_EXIT,
- "allocating execution environment",
- __FILE__, __LINE__);
-
- rc = SQLAllocConnect(henv, &hdbc);
- handle_errors(NULL, NULL, rc, ERROR_EXIT,
- "allocating connection handle",
- __FILE__, __LINE__);
-
- /* Connect to data store */
-
- status_msg0("Connecting to the data source...\n");
-
- /* Set up the connection options if not specified on the command line
- * (default to TimesTen settings).
- */
-
- if ( !*szConnStrIn ) {
- /* Running the benchmark with a scale factor creates (scale) branches,
- * (scale x 10) tellers, (scale x 10000) accounts and ((scale-1) x 10000)
- * non-local accounts. The size of the table rows are branches (141)
- * tellers (141) and accounts (141). Therefore the data size requirements
- * of this benchmark is:
- * size ~= 141 * ((scale * 20011) - 10000) (bytes)
- *
- * Multiply data size by 20% to account for additional DB overhead (e.g.
- * indexes), and round up the nearest 10Mb for safety.
- */
-
- int est_size = (int) (3.6 * scaleFactor + 10.0);
- est_size = est_size - (est_size % 10);
-
- sprintf(szConnStrIn,"OverWrite=1;PermSize=%d;%s",
- est_size, DSNNAME);
- status_msg0("Connecting to the data source... %s \n", szConnStrIn);
- }
-
- rc = SQLDriverConnect(hdbc, NULL, (SQLCHAR *) szConnStrIn, SQL_NTS,
- NULL, 0, NULL,
- SQL_DRIVER_NOPROMPT);
-
- status_msg0("Connected to the data source...\n");
- sprintf(errstr, "connecting to driver (connect string %s)\n",
- szConnStrIn);
- handle_errors(hdbc, NULL, rc, ERROR_EXIT,
- errstr, __FILE__, __LINE__);
-
- /* Turn auto-commit off */
-
- rc = SQLSetConnectOption(hdbc, SQL_AUTOCOMMIT, SQL_AUTOCOMMIT_OFF);
- handle_errors(hdbc, NULL, rc, DISCONNECT_EXIT,
- "switching off the AUTO_COMMIT option",
- __FILE__, __LINE__);
-
- /* Allocate a statement handle */
-
- rc = SQLAllocStmt(hdbc, &hstmt);
- handle_errors(hdbc, NULL, rc, DISCONNECT_EXIT,
- "allocating a statement handle",
- __FILE__, __LINE__);
-
- /* (Implicit) Transaction begin */
-
- /* Determine the DBMS Type*/
-
- DBMSName[0] = '\0';
- rc = SQLGetInfo(hdbc, SQL_DBMS_NAME, (PTR) &DBMSName,
- sizeof(DBMSName), NULL);
- rc = SQLGetInfo(hdbc, SQL_DRIVER_VER, (PTR) &DBMSVersion,
- sizeof(DBMSVersion), NULL);
-
- if (strcmp(DBMSName, "TimesTen") == 0)
- DBMSType = DBMS_TIMESTEN;
- else if (strcmp(DBMSName, "Microsoft SQL Server") == 0)
- DBMSType = DBMS_MSSQL;
- else DBMSType = DBMS_UNKNOWN;
-
- /* if not TimesTen: delete (if it exists), create & use the new database */
-
- if (DBMSType != DBMS_TIMESTEN) {
- status_msg0("Deleting the database...\n");
- rc = SQLExecDirect(hstmt, (SQLCHAR *) DatabaseDropStmt, SQL_NTS);
-
- /* estimate database size, size = data space + log space
- * data space = (#tuples)/(tuples per page) * 2K bytes/page
- * tuples per page = useable page size / row size (no index) = 2016/(96+2)
- * log space = #transactions * average log size for the program transaction mix
- * database size is in MB
- */
-
- databaseSize = (int) ceil((((numBranchTups + numTellerTups + numAccountTups)/
- (2016/98)) * 2048 + (numXacts * 600)) / 1000000.0);
-
- status_msg1("Creating the database (%dMB)...\n", databaseSize);
-#ifndef NDB
- sprintf(cmdStr, DatabaseCreateStmt, databaseSize);
- doImmed(hdbc, hstmt, cmdStr);
- strcpy(cmdStr, DatabaseUseStmt);
- doImmed(hdbc, hstmt, cmdStr);
-#endif
- }
-
- status_msg2("Connected to '%s' version '%s'...\n", DBMSName, DBMSVersion);
-
- /* create branches table */
- status_msg0("Creating tasddbles...\n");
-#ifndef NDB
- if (DBMSType == DBMS_TIMESTEN)
- sprintf(cmdStr, TTBranchCrTblStmt, numBranchTups/TuplesPerPage + 1);
- else
-#endif
- sprintf(cmdStr, BranchCrTblStmt);
- doImmed(hdbc, hstmt, cmdStr);
-
- /* create tellers table */
-#ifndef NDB
- if (DBMSType == DBMS_TIMESTEN)
- sprintf(cmdStr, TTTellerCrTblStmt, numTellerTups/TuplesPerPage + 1);
-
- else
-#endif
- sprintf(cmdStr, TellerCrTblStmt);
- doImmed(hdbc, hstmt, cmdStr);
-
- /* create accounts table */
-#ifndef NDB
- if (DBMSType == DBMS_TIMESTEN)
- sprintf(cmdStr, TTAccountCrTblStmt, numAccountTups/TuplesPerPage + 1);
- else
-#endif
- sprintf(cmdStr, AccountCrTblStmt);
- doImmed(hdbc, hstmt, cmdStr);
-
- /* create History table */
-
- doImmed(hdbc, hstmt, HistoryCrTblStmt);
-
- /* lock the database during population */
-#ifndef NDB
- if ( DBMSType == DBMS_TIMESTEN ) {
- rc = SQLExecDirect(hstmt, (SQLCHAR *)"call ttlocklevel('DS')", SQL_NTS);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "specifying dbs lock usage",
- __FILE__, __LINE__);
- /* make sure dbs lock take effect in next transaction */
- rc = SQLTransact(henv,hdbc,SQL_COMMIT);
- if ( rc != SQL_SUCCESS) {
- handle_errors(hdbc, SQL_NULL_HSTMT, rc, ERROR_EXIT,
- "committing transaction",
- __FILE__, __LINE__);
- }
- }
-#endif
- /* populate branches table */
-
-
- rc = SQLPrepare(hstmt, (SQLCHAR *) insStmt[0], SQL_NTS);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "preparing statement",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER, 10, 0, &branchNum, sizeof branchNum, NULL);
-
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
-
- status_msg1("Populating branches table (%" PTRINT_FMT " rows)...\n",
- numBranchTups);
-
-
- for (i=0; i<numBranchTups; i++) {
- branchNum = i;
- rc = SQLExecute(hstmt);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "Error executing statement",
- __FILE__, __LINE__);
- }
-
- /* Reset all bind-parameters for the statement handle. */
- rc = SQLFreeStmt(hstmt, SQL_RESET_PARAMS);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "resetting parms on statement handle",
- __FILE__, __LINE__);
-
- /* populate tellers table */
-
- status_msg1("Populating tellers table (%" PTRINT_FMT " rows)...\n",
- numTellerTups);
-
-
- rc = SQLPrepare(hstmt, (SQLCHAR *) insStmt[1], SQL_NTS);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "preparing statement",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
- 10, 0, &tellerNum, sizeof tellerNum, NULL);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
- 10, 0, &branchNum, sizeof branchNum, NULL);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- for (i=0; i<numTellerTups; i++) {
- tellerNum = i;
- branchNum = i/TellersPerBranch;
- rc = SQLExecute(hstmt);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "Error executing statement",
- __FILE__, __LINE__);
- }
-
- /* Reset all bind-parameters for the statement handle. */
-
- rc = SQLFreeStmt(hstmt, SQL_RESET_PARAMS);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "resetting parms on statement handle",
- __FILE__, __LINE__);
-
- /* populate accounts table */
-
- status_msg1("Populating accounts table (%" PTRINT_FMT " rows)...\n",
- numAccountTups);
-
- rc = SQLPrepare(hstmt, (SQLCHAR *) insStmt[2], SQL_NTS);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "preparing statement",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(hstmt, 1, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
- 10, 0, &accountNum, sizeof accountNum, NULL);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(hstmt, 2, SQL_PARAM_INPUT, SQL_C_SLONG, SQL_INTEGER,
- 10, 0, &branchNum, sizeof branchNum, NULL);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- for (i=0; i<numAccountTups; i++) {
- accountNum = i;
- branchNum = i/AccountsPerBranch;
- rc = SQLExecute(hstmt);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "Error executing statement",
- __FILE__, __LINE__);
- }
- status_msg0("Commit...\n");
- rc = SQLTransact(henv, hdbc, SQL_COMMIT);
- status_msg0("Commit done...\n");
- handle_errors(hdbc, NULL, rc, ERROR_EXIT,
- "committing transaction",
- __FILE__, __LINE__);
-
- /* compile SQL statements of transaction */
-
- status_msg0("Compiling statements of transaction...\n");
- for (i=0; i<NumXactStmts; i++) {
-#ifndef NDB
- rc = SQLAllocStmt(hdbc, &txstmt[i]);
- handle_errors(hdbc, NULL, rc, ABORT_DISCONNECT_EXIT,
- "allocating a statement handle",
- __FILE__, __LINE__);
-#else
- rc = SQLAllocHandle(SQL_HANDLE_STMT, hdbc, &txstmt[i]);
- handle_errors(hdbc, NULL, rc, ABORT_DISCONNECT_EXIT,
- "allocating a statement handle",
- __FILE__, __LINE__);
-
-#endif
-
- rc = SQLPrepare(txstmt[i], (SQLCHAR *) tpcbXactStmt[i], SQL_NTS);
- handle_errors(hdbc, txstmt[i], rc, ABORT_DISCONNECT_EXIT,
- "preparing statement",
- __FILE__, __LINE__);
- }
-
- /* unuse dbs lock */
-#ifndef NDB
- if ( DBMSType == DBMS_TIMESTEN ) {
- rc = SQLExecDirect(hstmt, (SQLCHAR *)"call ttlocklevel('Row')", SQL_NTS);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "specifying row lock usage",
- __FILE__, __LINE__);
- }
-#endif
-
- /* commit transaction */
-
- rc = SQLTransact(henv, hdbc, SQL_COMMIT);
- handle_errors(hdbc, NULL, rc, ERROR_EXIT,
- "committing transaction",
- __FILE__, __LINE__);
-
-
- /* Initialize random seed and timers */
-
- srand48(SeedVal);
- localLimit = (unsigned short)((1<<16) * 0.85);
-
- /* Initialize parameter lists for each of the transactions */
-
- rc = SQLBindParameter(txstmt[0], 1, SQL_PARAM_INPUT, SQL_C_DOUBLE,
- SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
- handle_errors(hdbc, txstmt[0], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[0], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
- SQL_INTEGER, 10, 0, &accountNum, sizeof accountNum,
- NULL);
- handle_errors(hdbc, txstmt[0], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[1], 1, SQL_PARAM_INPUT, SQL_C_SLONG,
- SQL_INTEGER, 10, 0, &accountNum, sizeof accountNum,
- NULL);
- handle_errors(hdbc, txstmt[1], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[2], 1, SQL_PARAM_INPUT, SQL_C_DOUBLE,
- SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
- handle_errors(hdbc, txstmt[2], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[2], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
- SQL_INTEGER, 10, 0, &tellerNum, sizeof tellerNum,
- NULL);
- handle_errors(hdbc, txstmt[2], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[3], 1, SQL_PARAM_INPUT, SQL_C_DOUBLE,
- SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
- handle_errors(hdbc, txstmt[3], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[3], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
- SQL_INTEGER, 10, 0, &branchNum, sizeof branchNum,
- NULL);
- handle_errors(hdbc, txstmt[3], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[4], 1, SQL_PARAM_INPUT, SQL_C_SLONG,
- SQL_INTEGER, 10, 0, &tellerNum, sizeof tellerNum,
- NULL);
- handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[4], 2, SQL_PARAM_INPUT, SQL_C_SLONG,
- SQL_INTEGER, 10, 0, &branchNum, sizeof branchNum,
- NULL);
- handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[4], 3, SQL_PARAM_INPUT, SQL_C_SLONG,
- SQL_INTEGER, 10, 0, &accountNum, sizeof accountNum,
- NULL);
- handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[4], 4, SQL_PARAM_INPUT, SQL_C_DOUBLE,
- SQL_DOUBLE, 15, 0, &delta, sizeof delta, NULL);
- handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- rc = SQLBindParameter(txstmt[4], 5, SQL_PARAM_INPUT, SQL_C_SLONG,
- SQL_INTEGER, 10, 0, &timeStamp, sizeof timeStamp,
- NULL);
- handle_errors(hdbc, txstmt[4], rc, ABORT_DISCONNECT_EXIT,
- "binding parameter",
- __FILE__, __LINE__);
-
- /* Execute transaction loop.
- * Do it twice, once briefly as a warm-up. */
-
-
-
- for (warmup = 1; warmup >= 0; warmup--) {
-
- int max_i = (warmup ? numXacts/10 : numXacts);
-
- /* Execute tpcb transaction max_i times.*/
-
- if (warmup) {
- status_msg1("\nWarming up with %d tpcb transactions...\n", max_i);
- }
- else {
- status_msg1("Executing and timing %d tpcb transactions...\n", max_i);
- }
-
- ttGetWallClockTime(&startT);
- ttGetThreadTimes(&startRes);
-
- for (i = 0; i < max_i; i++) {
-
- lrand = lrand48();
- srands = (unsigned short *)(&lrand);
- if (lp64) srands += 2; /* skip high half -- all zero */
-
- /* randomly choose a teller */
-
- tellerNum = srands[0] % numTellerTups;
-
- /* compute branch */
-
- branchNum = (tellerNum / TellersPerBranch);
-
- /* randomly choose an account */
-
- if (srands[1] < localLimit || numBranchTups == 1) {
-
- /* choose account local to selected branch */
-
- accountNum = branchNum * AccountsPerBranch +
- (lrand48() % AccountsPerBranch);
-
- ++numLocalXacts;
-
- }
- else {
- /* choose account not local to selected branch */
-
- /* first select account in range [0,numNonLocalAccountTups) */
-
- accountNum = lrand48() % numNonLocalAccountTups;
-
- /* if branch number of selected account is at least as big
- * as local branch number, then increment account number
- * by AccountsPerBranch to skip over local accounts
- */
-
- if ((accountNum/AccountsPerBranch) >= branchNum)
- accountNum += AccountsPerBranch;
-
- ++numRemoteXacts;
- }
-
- /* select delta amount, -999,999 to +999,999 */
-
- delta = ((lrand48() % 1999999) - 999999);
-
-
- /* begin timing the "residence time" */
-
- ttGetWallClockTime(rtStart[i]);
-
- for ( j = 0; j < NumXactStmts - 2; j++) {
- rc = SQLExecute(txstmt[j]);
- handle_errors(hdbc, txstmt[j], rc, ABORT_DISCONNECT_EXIT,
- "Error executing statement1",
- __FILE__, __LINE__);
-
- /* Close the handle after the SELECT statement
- * (txstmt[1]) for non TimesTen DBMS' */
-
- if ((DBMSType != DBMS_TIMESTEN) && (j == 1)) {
- SQLFreeStmt(txstmt[1], SQL_CLOSE);
- }
-
-
- }
-
- /* note that time must be taken within the */
- timeStamp = time(NULL);
-
- rc = SQLExecute(txstmt[NumXactStmts - 1]);
- handle_errors(hdbc, txstmt[NumXactStmts - 1], rc,
- ABORT_DISCONNECT_EXIT, "Error executing statement2",
- __FILE__, __LINE__);
-
- rc = SQLTransact(henv, hdbc, SQL_COMMIT);
- handle_errors(hdbc, NULL, rc, ERROR_EXIT,
- "Error committing transaction",
- __FILE__, __LINE__);
-
- ttGetWallClockTime(rtEnd[i]);
-
- } /* end fortransaction loop */
-
-
-
-
- ttGetThreadTimes(&endRes);
- ttGetWallClockTime(&endT);
- ttCalcElapsedThreadTimes(&startRes, &endRes, &kernel, &user);
- ttCalcElapsedWallClockTime(&startT, &endT, &real);
-
- if (warmup) {
- if (!tabFlag) {
- if (verbose) {
- if (fThreadTime) {
- out_msg0(" time user system\n");
-
- out_msg3("Warmup time (sec): %12.3f %12.3f %12.3f\n\n",
- real/1000.0, user, kernel);
- } else {
- out_msg1("Warmup time (sec): %12.3f\n\n", real/1000.0);
- }
- }
- } else {
- if (verbose) {
- if (fThreadTime) {
- out_msg0("\ttime\tuser\tsystem\n");
-
- out_msg3("Warmup time (sec):\t%12.3f\t%12.3f\t%12.3f\n",
- real/1000.0, user, kernel);
- } else {
- out_msg1("Warmup time (sec):\t%12.3f\n", real/1000.0);
- }
- }
- }
- }
- }
-
- status_msg0("\nExecution completed...\n");
-
- /* Compute and report timing statistics */
-
- maxTime = 0.0;
- totTime = 0.0;
-
- for (i = 0; i < numXacts; i++) {
- ttCalcElapsedWallClockTime(rtStart[i], rtEnd[i], resTime[i]);
- totTime += *(resTime[i]);
-
- if (*(resTime[i]) > maxTime) maxTime = *(resTime[i]);
- }
-
- if (!tabFlag) {
- if (verbose) {
- if (fThreadTime) {
- out_msg0(" time user system\n");
- out_msg3("Total time (sec): %12.3f %12.3f %12.3f\n",
- real/1000.0, user, kernel);
- } else {
- out_msg1("Total time (sec): %12.3f\n", real/1000.0);
- }
- }
-
- if (verbose)
- out_msg1("\nAverage transaction time (msec):%12.3f\n",
- totTime/numXacts);
- if (verbose)
- out_msg1("Maximum transaction time (msec):%12.3f\n", maxTime);
- if (verbose)
- out_msg1("\nLocal transactions: %7" PTRINT_FMT "\n", numLocalXacts);
- if (verbose)
- out_msg1("Remote transactions: %7" PTRINT_FMT "\n", numRemoteXacts);
-
- } else {
- if (verbose) {
- if (fThreadTime) {
- out_msg0("\ttime\tuser\tsystem\n");
- out_msg3("Total time (sec):\t%12.3f\t%12.3f\t%12.3f\n",
- real/1000.0, user, kernel);
- } else {
- out_msg1("Total time (sec):\t%12.3f\n", real/1000.0);
- }
- }
-
- if (verbose)
- out_msg1("\nAverage transaction time (msec):\t%12.3f\n",
- totTime/numXacts);
- if (verbose)
- out_msg1("Maximum transaction time (msec):\t%12.3f\n", maxTime);
- if (verbose)
- out_msg1("Local transactions:\t%7" PTRINT_FMT "\n", numLocalXacts);
-
- if (verbose)
- out_msg1("Remote transactions:\t%7" PTRINT_FMT "\n", numRemoteXacts);
-
-
-
- }
-
- /* If the statfile option is selected, print each transaction's time */
-
- if (printXactTimes) {
- FILE * fp;
- if ( (fp = fopen (statFile, "w")) == NULL ) {
- err_msg1("Unable to open stat file %s for writing\n\n", statFile);
- } else {
- for (int i = 0; i < numXacts; i++)
- fprintf(fp,"%6d: %12.3f\n", i, *(resTime[i]));
- fclose(fp);
- }
- }
-
- /* Disconnect and return */
-
- rc = SQLFreeStmt(hstmt, SQL_DROP);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "dropping the statement handle",
- __FILE__, __LINE__);
-
- for (int i=0; i<NumXactStmts; i++) {
- rc = SQLFreeStmt(txstmt[i], SQL_DROP);
- handle_errors(hdbc, hstmt, rc, ABORT_DISCONNECT_EXIT,
- "dropping the statement handle",
- __FILE__, __LINE__);
- }
-
- if (verbose >= VERBOSE_DFLT)
- status_msg0("Disconnecting from the data source...\n");
-
- rc = SQLDisconnect(hdbc);
- handle_errors(hdbc, NULL, rc, ERROR_EXIT,
- "disconnecting",
- __FILE__, __LINE__);
-
- rc = SQLFreeConnect(hdbc);
- handle_errors(hdbc, NULL, rc, ERROR_EXIT,
- "freeing connection handle",
- __FILE__, __LINE__);
-
- rc = SQLFreeEnv(henv);
- handle_errors(NULL, NULL, rc, ERROR_EXIT,
- "freeing environment handle",
- __FILE__, __LINE__);
-
- app_exit(0);
- return 0;
-}
-
-
-
-
-
-/* Emacs variable settings */
-/* Local Variables: */
-/* tab-width:8 */
-/* indent-tabs-mode:nil */
-/* c-basic-offset:2 */
-/* End: */
-
-
-
diff --git a/ndb/test/odbc/tpcb/ttTime.c b/ndb/test/odbc/tpcb/ttTime.c
deleted file mode 100644
index 8f10b0c6b91..00000000000
--- a/ndb/test/odbc/tpcb/ttTime.c
+++ /dev/null
@@ -1,366 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-static const volatile char cvsid[] = "$Id: ttTime.c,v 1.1 2003/09/23 12:43:46 johan Exp $";
-/*
- * $Revision: 1.1 $
- * (c) Copyright 1996-2003, TimesTen, Inc.
- * All rights reserved.
- *
- */
-
-
-/* Contains functions for performing elapsed-time calculations
- in a portable manner */
-
-#include "ttTime.h"
-
-#ifdef WIN32
-
-#include <stdio.h>
-#include <mapiutil.h>
-
-/*------------*/
-/* NT VERSION */
-/*------------*/
-
-/*********************************************************************
- *
- * FUNCTION: ttGetThreadTimes
- *
- * DESCRIPTION: This function sets the supplied parameter's
- * user and kernel time for the current thread.
- *
- * PARAMETERS: ttThreadTimes* timesP thread time structure
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-void
-ttGetThreadTimes(ttThreadTimes* timesP)
-{
- BOOL rc;
- HANDLE curThread;
- FILETIME creationTime;
- FILETIME exitTime;
- FILETIME kTime;
- FILETIME uTime;
-
- memset (&kTime, 0, sizeof (FILETIME));
- memset (&uTime, 0, sizeof (FILETIME));
-
- curThread = GetCurrentThread();
- rc = GetThreadTimes(curThread,
- &creationTime,
- &exitTime,
- &kTime,
- &uTime);
-
- timesP->kernelTime = kTime;
- timesP->userTime = uTime;
-
-}
-
-/*********************************************************************
- *
- * FUNCTION: ttCalcElapsedThreadTimes
- *
- * DESCRIPTION: This function calculates the user and kernel
- * time deltas.
- *
- * PARAMETERS: ttThreadTimes* beforeP beginning timestamp (IN)
- * ttThreadTimes* afterP ending timestamp (IN)
- * double* kernelDeltaP kernel time delta (OUT)
- * double* userDeltaP user time delta (OUT)
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-void
-ttCalcElapsedThreadTimes(ttThreadTimes* beforeP,
- ttThreadTimes* afterP,
- double* kernelDeltaP,
- double* userDeltaP)
-{
- static const double secPerHi = (double) 4.294967296; /* 2**32 * 10**-9 */
- FILETIME *before, *after;
-
- before = &beforeP->kernelTime;
- after = &afterP->kernelTime;
- *kernelDeltaP = (double) ((after->dwHighDateTime - before->dwHighDateTime) * secPerHi
- + (after->dwLowDateTime - before->dwLowDateTime) * 100e-9);
- before = &beforeP->userTime;
- after = &afterP->userTime;
- *userDeltaP = (double) ((after->dwHighDateTime - before->dwHighDateTime) * secPerHi
- + (after->dwLowDateTime - before->dwLowDateTime) * 100e-9);
-}
-
-/*********************************************************************
- *
- * FUNCTION: ttGetWallClockTime
- *
- * DESCRIPTION: This function gets the current wall-clock time.
- *
- * PARAMETERS: ttWallClockTime* timeP tms time structure (OUT)
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-void
-ttGetWallClockTime(ttWallClockTime* timeP)
-{
- LARGE_INTEGER frequency;
- if ( QueryPerformanceFrequency(&frequency) ) {
- QueryPerformanceCounter(&(timeP->time64));
- }
- else {
- _ftime(&(timeP->notSoLargeTime));
- }
-}
-
-/*********************************************************************
- *
- * FUNCTION: ttCalcElapsedWallClockTime
- *
- * DESCRIPTION: This function calculates the elapsed wall-clock
- * time in msec.
- *
- * PARAMETERS: ttWallClockTime* beforeP starting timestamp
- * ttWallClockTime* afterP ending timestamp
- * double* nmillisecondsP elapsed time (OUT)
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-void
-ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
- ttWallClockTime* afterP,
- double* nmillisecondsP)
-{
- LARGE_INTEGER frequency;
-
- if ( QueryPerformanceFrequency(&frequency) ) {
- *nmillisecondsP = 1000 * ((double) (afterP->time64.QuadPart
- - beforeP->time64.QuadPart))
- / frequency.QuadPart;
-
- }
- else {
- double start;
- double end;
-
- start = (double) beforeP->notSoLargeTime.time * 1000. +
- (double) beforeP->notSoLargeTime.millitm;
- end = (double) afterP->notSoLargeTime.time * 1000. +
- (double) afterP->notSoLargeTime.millitm;
-
- *nmillisecondsP = (double) (end - start);
- }
-}
-
-#elif defined (RTSYS_VXWORKS)
-
-/*-----------------*/
-/* VxWorks VERSION */
-/*-----------------*/
-
-/*
- * The TimeBase registers have a period of 60ns, i.e.
- * 0.00000006 or (6e-8) seconds.
- */
-#define TIMER_MSEC_PER_CYC (6e-5)
-
-void
-ttGetWallClockTime(ttWallClockTime* timeP)
-{
- vxTimeBaseGet(&timeP->sep.upper32, &timeP->sep.lower32);
-}
-
-
-void
-ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
- ttWallClockTime* afterP,
- double* nmillisecondsP)
-{
- *nmillisecondsP = (double)(afterP->val - beforeP->val) * TIMER_MSEC_PER_CYC;
-}
-
-
-#else
-
-/*--------------*/
-/* UNIX VERSION */
-/*--------------*/
-
-#include <unistd.h>
-
-/*********************************************************************
- *
- * FUNCTION: ttGetThreadTimes
- *
- * DESCRIPTION: This function sets the supplied parameter's
- * tms structure.
- *
- * PARAMETERS: ttThreadTimes* timesP tms time structure
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-#ifdef SB_P_OS_CHORUS
-void ttGetThreadTimes(ttThreadTimes* timesP)
-{
- KnCap actorCap;
-
- if (acap (agetId(), &actorCap) == -1) {
- timesP->ins.tmSec = 0;
- timesP->ins.tmNSec = 0;
- timesP->ext.tmSec = 0;
- timesP->ext.tmNSec = 0;
- }
- else {
- (void) threadTimes (&actorCap, K_ALLACTORTHREADS,
- &timesP->ins, &timesP->ext);
- }
-}
-#else
-void ttGetThreadTimes(ttThreadTimes* timesP)
-{
- (void) times(timesP);
-}
-#endif
-
-/*********************************************************************
- *
- * FUNCTION: ttCalcElapsedThreadTimes
- *
- * DESCRIPTION: This function calculates the user and kernel
- * time deltas.
- *
- * PARAMETERS: ttThreadTimes* beforeP beginning timestamp (IN)
- * ttThreadTimes* afterP ending timestamp (IN)
- * double* kernelDeltaP kernel time delta (OUT)
- * double* userDeltaP user time delta (OUT)
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-#ifdef SB_P_OS_CHORUS
-void
-ttCalcElapsedThreadTimes(ttThreadTimes* beforeP,
- ttThreadTimes* afterP,
- double* kernelDeltaP,
- double* userDeltaP)
-{
- double kernelBefore;
- double kernelAfter;
- double userBefore;
- double userAfter;
-
- kernelBefore = (beforeP->ext.tmSec) + (beforeP->ext.tmNSec / 1e9);
- kernelAfter = (afterP->ext.tmSec) + (afterP->ext.tmNSec / 1e9);
- *kernelDeltaP = kernelAfter - kernelBefore;
-
- userBefore = (beforeP->ins.tmSec) + (beforeP->ins.tmNSec / 1e9);
- userAfter = (afterP->ins.tmSec) + (afterP->ins.tmNSec / 1e9);
- *userDeltaP = userAfter - userBefore;
-
-}
-#else
-void
-ttCalcElapsedThreadTimes(ttThreadTimes* beforeP,
- ttThreadTimes* afterP,
- double* kernelDeltaP,
- double* userDeltaP)
-{
- double ticks = (double)sysconf(_SC_CLK_TCK);
-
- *kernelDeltaP = (afterP->tms_stime - beforeP->tms_stime) / ticks;
- *userDeltaP = (afterP->tms_utime - beforeP->tms_utime) / ticks;
-}
-#endif
-
-/*********************************************************************
- *
- * FUNCTION: ttGetWallClockTime
- *
- * DESCRIPTION: This function gets the current wall-clock time.
- *
- * PARAMETERS: ttWallClockTime* timeP tms time structure (OUT)
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-void
-ttGetWallClockTime(ttWallClockTime* timeP)
-{
- gettimeofday(timeP, NULL);
-}
-
-/*********************************************************************
- *
- * FUNCTION: ttCalcElapsedWallClockTime
- *
- * DESCRIPTION: This function calculates the elapsed wall-clock
- * time is msec.
- *
- * PARAMETERS: ttWallClockTime* beforeP starting timestamp
- * ttWallClockTime* afterP ending timestamp
- * double* nmillisecondsP elapsed time (OUT)
- *
- * RETURNS: void
- *
- * NOTES: NONE
- *
- *********************************************************************/
-
-void
-ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
- ttWallClockTime* afterP,
- double* nmillisP)
-{
- *nmillisP = (afterP->tv_sec - beforeP->tv_sec)*1000.0 +
- (afterP->tv_usec - beforeP->tv_usec)/1000.0;
-}
-
-#endif
-
-/* Emacs variable settings */
-/* Local Variables: */
-/* tab-width:8 */
-/* indent-tabs-mode:nil */
-/* c-basic-offset:2 */
-/* End: */
diff --git a/ndb/test/odbc/tpcb/ttTime.h b/ndb/test/odbc/tpcb/ttTime.h
deleted file mode 100644
index f78b71667fe..00000000000
--- a/ndb/test/odbc/tpcb/ttTime.h
+++ /dev/null
@@ -1,125 +0,0 @@
-/* Copyright (C) 2003 MySQL AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-/*
- * $Revision: 1.1 $
- * (c) Copyright 1996-2003, TimesTen, Inc.
- * All rights reserved.
- *
- */
-
-#ifndef __TT_TIME
-#define __TT_TIME
-
-
-#ifdef WIN32
-
-#include <windows.h>
-#include <sys/types.h>
-#include <sys/timeb.h>
-
-typedef struct {
- FILETIME kernelTime;
- FILETIME userTime;
-} ttThreadTimes;
-
-
-typedef union {
- LARGE_INTEGER time64;
- struct _timeb notSoLargeTime;
-} ttWallClockTime;
-
-#elif defined(RTSYS_VXWORKS)
-
-#define srand48(x) sb_srand48((x))
-#define drand48() sb_drand48()
-
-#ifdef SB_P_OS_VXPPC
-/* For little-endian switch the lower, upper fields */
-typedef union {
- struct {
- unsigned int upper32;
- unsigned int lower32;
- } sep;
- long long val;
-} ttWallClockTime;
-
-/*
- * This is a VxWorks private function to read the PPC's 64 bit Time Base
- * Register. This is the assembler dump of this function.
- 001126e4 7cad42e6 mftb r5, TBU
- 001126e8 7ccc42e6 mftb r6, TBL
- 001126ec 7ced42e6 mftb r7, TBU
- 001126f0 7c053800 cmp crf0, 0, r5, r7
- 001126f4 4082fff0 bc 0x4, 0x2, vxTimeBaseGet
- 001126f8 90a30000 stw r5, 0x0(r3)
- 001126fc 90c40000 stw r6, 0x0(r4)
- 00112700 4e800020 blr
- * This is a fine grained timer with a period of 60ns.
- */
-void vxTimeBaseGet(unsigned int* pUpper32, unsigned int* pLower32);
-#endif /* SB_P_OS_VXPPC */
-
-#elif defined(SB_P_OS_CHORUS)
-#include <sys/types.h>
-#include <sys/times.h>
-#include <sys/time.h>
-
-#include <vtimer/chVtimer.h>
-
-struct chrTimes {
- KnTimeVal ins;
- KnTimeVal ext;
-};
-typedef struct chrTimes ttThreadTimes;
-
-typedef struct timeval ttWallClockTime;
-
-#else
-/* UNIX version */
-
-#include <sys/times.h>
-#include <sys/time.h>
-
-typedef struct tms ttThreadTimes;
-
-typedef struct timeval ttWallClockTime;
-
-#endif /* NT, VxWorks, Chorus, Unix */
-
-
-#ifndef RTSYS_VXWORKS
-void ttGetThreadTimes(ttThreadTimes* timesP);
-void ttCalcElapsedThreadTimes(ttThreadTimes* beforeP, ttThreadTimes* afterP,
- double* kernelDeltaP, double* userDeltaP);
-#endif /* ! VXWORKS */
-void ttGetWallClockTime(ttWallClockTime* timeP);
-void ttCalcElapsedWallClockTime(ttWallClockTime* beforeP,
- ttWallClockTime* afterP,
- double* nmillisecondsP);
-
-
-
-
-
-#endif /* __TT_TIME */
-
-/* Emacs variable settings */
-/* Local Variables: */
-/* tab-width:8 */
-/* indent-tabs-mode:nil */
-/* c-basic-offset:2 */
-/* End: */
diff --git a/ndb/test/run-test/Makefile.am b/ndb/test/run-test/Makefile.am
index 3bf2edde47a..c890536dcc6 100644
--- a/ndb/test/run-test/Makefile.am
+++ b/ndb/test/run-test/Makefile.am
@@ -11,8 +11,8 @@ test_SCRIPTS=atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \
atrt-clear-result.sh make-config.sh make-index.sh make-html-reports.sh
atrt_SOURCES = main.cpp
-INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmclient
-LDADD_LOC = $(top_builddir)/ndb/src/mgmclient/CpcClient.o \
+INCLUDES_LOC = -I$(top_srcdir)/ndb/test/include
+LDADD_LOC = $(top_builddir)/ndb/test/src/libNDBT.a \
$(top_builddir)/ndb/src/libndbclient.la \
$(top_builddir)/dbug/libdbug.a \
$(top_builddir)/mysys/libmysys.a \
diff --git a/ndb/test/run-test/Makefile_old b/ndb/test/run-test/Makefile_old
deleted file mode 100644
index 6b4689b2dbb..00000000000
--- a/ndb/test/run-test/Makefile_old
+++ /dev/null
@@ -1,22 +0,0 @@
-include .defs.mk
-
-TYPE := util
-
-BIN_TARGET := atrt
-BIN_TARGET_LIBS := mgmapi
-
-SOURCES = main.cpp
-SCRIPTS = atrt-analyze-result.sh atrt-gather-result.sh atrt-setup.sh \
- atrt-clear-result.sh make-config.sh
-
-OBJECTS_LOC = $(call fixpath,$(NDB_TOP)/src/mgmclient/CpcClient.o)
-
-CFLAGS_main.cpp := -I$(call fixpath,$(NDB_TOP)/src/mgmclient)
-CCFLAGS_LOC += -I$(call fixpath,$(NDB_TOP)/include/mgmapi)
-
-include $(NDB_TOP)/Epilogue.mk
-
-_bins::
- -rm -f $(SCRIPTS:%=$(NDB_TOP)/bin/%)
- cp $(SCRIPTS) $(NDB_TOP)/bin
-
diff --git a/ndb/test/run-test/daily-basic-tests.txt b/ndb/test/run-test/daily-basic-tests.txt
index 8d7e8a06c72..8a927b88194 100644
--- a/ndb/test/run-test/daily-basic-tests.txt
+++ b/ndb/test/run-test/daily-basic-tests.txt
@@ -222,6 +222,18 @@ max-time: 500
cmd: testScan
args: -n ScanRead488 -l 10 T6
+max-time: 500
+cmd: testScan
+args: -n ScanRead488O -l 10 T6
+
+max-time: 1000
+cmd: testScan
+args: -n ScanRead488_Mixed -l 10 T6
+
+max-time: 500
+cmd: testScan
+args: -n ScanRead488Timeout -l 10 T6
+
max-time: 600
cmd: testScan
args: -n ScanRead40 -l 100 T2
@@ -474,493 +486,13 @@ args: -n UpdateWithoutValues T6
#cmd: testInterpreter
#args: T1
#
-max-time: 1500
-cmd: testOperations
-args: -n ReadRead
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadReadEx
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadInsert
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadUpdate
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadDelete
-
-max-time: 1500
-cmd: testOperations
-args: -n FReadRead
-
-max-time: 1500
-cmd: testOperations
-args: -n FReadReadEx
-
-max-time: 1500
-cmd: testOperations
-args: -n FReadInsert
-
-max-time: 1500
-cmd: testOperations
-args: -n FReadUpdate
-
-max-time: 1500
-cmd: testOperations
-args: -n FReadDelete
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadExRead
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadExReadEx
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadExInsert
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadExUpdate
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadExDelete
-
-max-time: 1500
-cmd: testOperations
-args: -n InsertRead
-
-max-time: 1500
-cmd: testOperations
-args: -n InsertReadEx
-
-max-time: 1500
-cmd: testOperations
-args: -n InsertInsert
-
-max-time: 1500
-cmd: testOperations
-args: -n InsertUpdate
-
-max-time: 1500
-cmd: testOperations
-args: -n InsertDelete
-
-max-time: 1500
-cmd: testOperations
-args: -n UpdateRead
-
-max-time: 1500
-cmd: testOperations
-args: -n UpdateReadEx
-
-max-time: 1500
-cmd: testOperations
-args: -n UpdateInsert
-
-max-time: 1500
-cmd: testOperations
-args: -n UpdateUpdate
-
-max-time: 1500
-cmd: testOperations
-args: -n UpdateDelete
-
-max-time: 1500
-cmd: testOperations
-args: -n DeleteRead
-
-max-time: 1500
-cmd: testOperations
-args: -n DeleteReadEx
-
-max-time: 1500
-cmd: testOperations
-args: -n DeleteInsert
-
-max-time: 1500
+max-time: 150000
cmd: testOperations
-args: -n DeleteUpdate
-
-max-time: 1500
-cmd: testOperations
-args: -n DeleteDelete
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadSimpleRead
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadDirtyRead
-
-max-time: 1500
-cmd: testOperations
-args: -n FReadSimpleRead
-
-max-time: 1500
-cmd: testOperations
-args: -n FReadDirtyRead
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadExSimpleRead
-
-max-time: 1500
-cmd: testOperations
-args: -n ReadExDirtyRead
-
-max-time: 1500
-cmd: testOperations
-args: -n InsertSimpleRead
-
-max-time: 1500
-cmd: testOperations
-args: -n InsertDirtyRead
-
-max-time: 1500
-cmd: testOperations
-args: -n UpdateSimpleRead
-
-max-time: 1500
-cmd: testOperations
-args: -n UpdateDirtyRead
-
-max-time: 1500
-cmd: testOperations
-args: -n DeleteSimpleRead
-
-max-time: 1500
-cmd: testOperations
-args: -n DeleteDirtyRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadReadEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadInsert
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadUpdate
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadDelete
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExReadEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExInsert
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExUpdate
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExDelete
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertReadEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertInsert
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertUpdate
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertDelete
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateReadEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateInsert
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateUpdate
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateDelete
-
-max-time: 1500
-cmd: testTransactions
-args: -n DeleteRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n DeleteReadEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n DeleteInsert
-
-max-time: 1500
-cmd: testTransactions
-args: -n DeleteUpdate
-
-max-time: 1500
-cmd: testTransactions
-args: -n DeleteDelete
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadSimpleRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadDirtyRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExSimpleRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExDirtyRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertSimpleRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertDirtyRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateSimpleRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateDirtyRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n DeleteSimpleRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n DeleteDirtyRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadScan
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadScanHl
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadScanEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanReadEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanSimpleRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanDirtyRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanInsert
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanUpdate
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanDelete
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanScan
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanScanHl
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanScanEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlReadEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlSimpleRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlDirtyRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlInsert
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlUpdate
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlDelete
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlScan
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlScanHl
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanHlScanEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExReadEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExSimpleRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExDirtyRead
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExInsert
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExUpdate
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExDelete
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExScan
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExScanHl
-
-max-time: 1500
-cmd: testTransactions
-args: -n ScanExScanEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExScan
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExScanHl
-
-max-time: 1500
-cmd: testTransactions
-args: -n ReadExScanEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertScan
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertScanHl
-
-max-time: 1500
-cmd: testTransactions
-args: -n InsertScanEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateScan
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateScanHl
-
-max-time: 1500
-cmd: testTransactions
-args: -n UpdateScanEx
-
-max-time: 1500
-cmd: testTransactions
-args: -n DeleteScan
-
-max-time: 1500
-cmd: testTransactions
-args: -n DeleteScanHl
+args:
-max-time: 1500
+max-time: 150000
cmd: testTransactions
-args: -n DeleteScanEx
+args:
max-time: 1500
cmd: testRestartGci
diff --git a/ndb/test/run-test/main.cpp b/ndb/test/run-test/main.cpp
index 22799a9a1b2..ac7710d9546 100644
--- a/ndb/test/run-test/main.cpp
+++ b/ndb/test/run-test/main.cpp
@@ -459,7 +459,7 @@ setup_config(atrt_config& config){
proc.m_type = atrt_process::NDB_MGM;
proc.m_proc.m_name.assfmt("%d-%s", index, "ndb_mgmd");
proc.m_proc.m_path.assign(dir).append("/libexec/ndb_mgmd");
- proc.m_proc.m_args = "--nodaemon -c initconfig.txt";
+ proc.m_proc.m_args = "--nodaemon -f config.ini";
proc.m_proc.m_cwd.appfmt("%d.ndb_mgmd", index);
connect_string.appfmt("host=%s:%d;",
proc.m_hostname.c_str(), proc.m_ndb_mgm_port);
@@ -538,15 +538,19 @@ connect_ndb_mgm(atrt_process & proc){
}
BaseString tmp = proc.m_hostname;
tmp.appfmt(":%d", proc.m_ndb_mgm_port);
- time_t start = time(0);
- const time_t max_connect_time = 30;
- do {
- if(ndb_mgm_connect(handle, tmp.c_str()) != -1){
- proc.m_ndb_mgm_handle = handle;
- return true;
- }
- sleep(1);
- } while(time(0) < (start + max_connect_time));
+
+ if (ndb_mgm_set_connectstring(handle,tmp.c_str()))
+ {
+ g_logger.critical("Unable to create parse connectstring");
+ return false;
+ }
+
+ if(ndb_mgm_connect(handle, 30, 1, 0) != -1)
+ {
+ proc.m_ndb_mgm_handle = handle;
+ return true;
+ }
+
g_logger.critical("Unable to connect to ndb mgm %s", tmp.c_str());
return false;
}
diff --git a/ndb/src/mgmclient/CpcClient.cpp b/ndb/test/src/CpcClient.cpp
index d407ba65312..d407ba65312 100644
--- a/ndb/src/mgmclient/CpcClient.cpp
+++ b/ndb/test/src/CpcClient.cpp
diff --git a/ndb/test/src/HugoOperations.cpp b/ndb/test/src/HugoOperations.cpp
index e8e2d992345..d3da8ae4ba2 100644
--- a/ndb/test/src/HugoOperations.cpp
+++ b/ndb/test/src/HugoOperations.cpp
@@ -456,11 +456,6 @@ int HugoOperations::setValueForAttr(NdbOperation* pOp,
int check = 0;
const NdbDictionary::Column* attr = tab.getColumn(attrId);
- if (attr->getTupleKey()){
- // Don't set values for TupleId PKs
- return check;
- }
-
switch (attr->getType()){
case NdbDictionary::Column::Char:
case NdbDictionary::Column::Varchar:
diff --git a/ndb/test/src/HugoTransactions.cpp b/ndb/test/src/HugoTransactions.cpp
index 456bfffbb77..096f5406bbf 100644
--- a/ndb/test/src/HugoTransactions.cpp
+++ b/ndb/test/src/HugoTransactions.cpp
@@ -29,26 +29,175 @@ HugoTransactions::~HugoTransactions(){
deallocRows();
}
-
-int HugoTransactions::scanReadCommittedRecords(Ndb* pNdb,
+int
+HugoTransactions::scanReadRecords(Ndb* pNdb,
int records,
int abortPercent,
- int parallelism){
- return scanReadRecords(pNdb, records, abortPercent, parallelism, true);
+ int parallelism,
+ NdbOperation::LockMode lm)
+{
+
+ int retryAttempt = 0;
+ const int retryMax = 100;
+ int check, a;
+ NdbConnection *pTrans;
+ NdbScanOperation *pOp;
+
+ while (true){
+
+ if (retryAttempt >= retryMax){
+ g_err << "ERROR: has retried this operation " << retryAttempt
+ << " times, failing!" << endl;
+ return NDBT_FAILED;
+ }
+
+ pTrans = pNdb->startTransaction();
+ if (pTrans == NULL) {
+ const NdbError err = pNdb->getNdbError();
+
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ continue;
+ }
+ ERR(err);
+ return NDBT_FAILED;
+ }
+
+ pOp = pTrans->getNdbScanOperation(tab.getName());
+ if (pOp == NULL) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ NdbResultSet * rs;
+ rs = pOp ->readTuples(lm);
+
+ if( rs == 0 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ check = pOp->interpret_exit_ok();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ for(a = 0; a<tab.getNoOfColumns(); a++){
+ if((row.attributeStore(a) =
+ pOp->getValue(tab.getColumn(a)->getName())) == 0) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+ }
+
+ check = pTrans->execute(NoCommit);
+ if( check == -1 ) {
+ const NdbError err = pTrans->getNdbError();
+ if (err.status == NdbError::TemporaryError){
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ NdbSleep_MilliSleep(50);
+ retryAttempt++;
+ continue;
+ }
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ // Abort after 1-100 or 1-records rows
+ int ranVal = rand();
+ int abortCount = ranVal % (records == 0 ? 100 : records);
+ bool abortTrans = false;
+ if (abort > 0){
+ // Abort if abortCount is less then abortPercent
+ if (abortCount < abortPercent)
+ abortTrans = true;
+ }
+
+ int eof;
+ int rows = 0;
+ while((eof = rs->nextResult(true)) == 0){
+ rows++;
+ if (calc.verifyRowValues(&row) != 0){
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ if (abortCount == rows && abortTrans == true){
+ ndbout << "Scan is aborted" << endl;
+ g_info << "Scan is aborted" << endl;
+ rs->close();
+ if( check == -1 ) {
+ ERR(pTrans->getNdbError());
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ pNdb->closeTransaction(pTrans);
+ return NDBT_OK;
+ }
+ }
+ if (eof == -1) {
+ const NdbError err = pTrans->getNdbError();
+
+ if (err.status == NdbError::TemporaryError){
+ ERR_INFO(err);
+ pNdb->closeTransaction(pTrans);
+ NdbSleep_MilliSleep(50);
+ switch (err.code){
+ case 488:
+ case 245:
+ case 490:
+ // Too many active scans, no limit on number of retry attempts
+ break;
+ default:
+ retryAttempt++;
+ }
+ continue;
+ }
+ ERR(err);
+ pNdb->closeTransaction(pTrans);
+ return NDBT_FAILED;
+ }
+
+ pNdb->closeTransaction(pTrans);
+
+ g_info << rows << " rows have been read" << endl;
+ if (records != 0 && rows != records){
+ g_err << "Check expected number of records failed" << endl
+ << " expected=" << records <<", " << endl
+ << " read=" << rows << endl;
+ return NDBT_FAILED;
+ }
+
+ return NDBT_OK;
+ }
+ return NDBT_FAILED;
}
int
HugoTransactions::scanReadRecords(Ndb* pNdb,
+ const NdbDictionary::Index * pIdx,
int records,
int abortPercent,
int parallelism,
- bool committed){
+ NdbOperation::LockMode lm,
+ bool sorted)
+{
int retryAttempt = 0;
const int retryMax = 100;
int check, a;
NdbConnection *pTrans;
- NdbScanOperation *pOp;
+ NdbIndexScanOperation *pOp;
while (true){
@@ -72,7 +221,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- pOp = pTrans->getNdbScanOperation(tab.getName());
+ pOp = pTrans->getNdbIndexScanOperation(pIdx->getName(), tab.getName());
if (pOp == NULL) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -80,8 +229,7 @@ HugoTransactions::scanReadRecords(Ndb* pNdb,
}
NdbResultSet * rs;
- rs = pOp ->readTuples(committed ? NdbScanOperation::LM_CommittedRead :
- NdbScanOperation::LM_Read);
+ rs = pOp ->readTuples(lm, 0, parallelism, sorted);
if( rs == 0 ) {
ERR(pTrans->getNdbError());
diff --git a/ndb/test/src/Makefile.am b/ndb/test/src/Makefile.am
index a513086dc33..56f3d6a1ec6 100644
--- a/ndb/test/src/Makefile.am
+++ b/ndb/test/src/Makefile.am
@@ -9,7 +9,8 @@ libNDBT_a_SOURCES = \
HugoAsynchTransactions.cpp UtilTransactions.cpp \
NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \
NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp \
- NdbSchemaCon.cpp NdbSchemaOp.cpp
+ NdbSchemaCon.cpp NdbSchemaOp.cpp getarg.c \
+ CpcClient.cpp
INCLUDES_LOC = -I$(top_srcdir)/ndb/src/common/mgmcommon -I$(top_srcdir)/ndb/include/mgmcommon -I$(top_srcdir)/ndb/include/kernel -I$(top_srcdir)/ndb/src/mgmapi
diff --git a/ndb/test/src/Makefile_old b/ndb/test/src/Makefile_old
deleted file mode 100644
index 2738ce1aba2..00000000000
--- a/ndb/test/src/Makefile_old
+++ /dev/null
@@ -1,33 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapitest
-
-ARCHIVE_TARGET := NDBT
-
-SOURCES = NDBT_ReturnCodes.cpp \
- NDBT_Error.cpp NDBT_Tables.cpp NDBT_ResultRow.cpp \
- NDBT_Test.cpp HugoCalculator.cpp \
- HugoOperations.cpp HugoTransactions.cpp \
- HugoAsynchTransactions.cpp UtilTransactions.cpp \
- NdbRestarter.cpp NdbRestarts.cpp NDBT_Output.cpp \
- NdbBackup.cpp NdbConfig.cpp NdbGrep.cpp NDBT_Table.cpp
-
-SOURCES.c =
-
-CFLAGS_NdbRestarter.cpp := -I$(call fixpath,$(NDB_TOP)/src/common/mgmcommon)
-CFLAGS_NdbConfig.cpp := -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \
- -I$(call fixpath,$(NDB_TOP)/src/mgmapi)
-CFLAGS_NdbRestarts.cpp := -I$(call fixpath,$(NDB_TOP)/include/kernel)
-CFLAGS_NdbBackup.cpp := -I$(call fixpath,$(NDB_TOP)/include/mgmcommon) \
- -I$(call fixpath,$(NDB_TOP)/src/mgmapi) \
- -I$(call fixpath,$(NDB_TOP)/include/kernel)
-CFLAGS_NdbGrep.cpp += -I$(call fixpath,$(NDB_TOP)/include/kernel) -I$(call fixpath,$(NDB_TOP)/include/mgmcommon)
-
-include $(NDB_TOP)/Epilogue.mk
-
-
-
-
-
-
-
diff --git a/ndb/test/src/NDBT_Tables.cpp b/ndb/test/src/NDBT_Tables.cpp
index ff6db3e892c..b61d48b216c 100644
--- a/ndb/test/src/NDBT_Tables.cpp
+++ b/ndb/test/src/NDBT_Tables.cpp
@@ -820,21 +820,25 @@ NDBT_Tables::createAllTables(Ndb* pNdb){
int
NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp,
- bool existsOk){
+ bool existsOk, NDBT_CreateTableHook f){
const NdbDictionary::Table* tab = NDBT_Tables::getTable(_name);
if (tab == NULL){
ndbout << "Could not create table " << _name
<< ", it doesn't exist in list of tables "\
- "that NDBT_Tables can create!" << endl;
+ "that NDBT_Tables can create!" << endl;
return NDBT_WRONGARGS;
}
-
+
int r = 0;
do {
NdbDictionary::Table tmpTab(* tab);
tmpTab.setStoredTable(_temp ? 0 : 1);
-
+ if(f != 0 && f(pNdb, tmpTab, 0))
+ {
+ ndbout << "Failed to create table" << endl;
+ return NDBT_FAILED;
+ }
r = pNdb->getDictionary()->createTable(tmpTab);
if(r == -1){
if(!existsOk){
@@ -883,6 +887,11 @@ NDBT_Tables::createTable(Ndb* pNdb, const char* _name, bool _temp,
}
}
}
+ if(f != 0 && f(pNdb, tmpTab, 1))
+ {
+ ndbout << "Failed to create table" << endl;
+ return NDBT_FAILED;
+ }
} while(false);
return r;
diff --git a/ndb/test/src/NDBT_Test.cpp b/ndb/test/src/NDBT_Test.cpp
index 367223f8c98..bbbde008938 100644
--- a/ndb/test/src/NDBT_Test.cpp
+++ b/ndb/test/src/NDBT_Test.cpp
@@ -519,6 +519,7 @@ void NDBT_TestCaseImpl1::waitSteps(){
NdbThread_WaitFor(threads[i], &status);
NdbThread_Destroy(&threads[i]);
}
+ threads.clear();
}
@@ -839,9 +840,9 @@ void NDBT_TestSuite::execute(Ndb* ndb, const NdbDictionary::Table* pTab,
continue;
}
pTab2 = pDict->getTable(pTab->getName());
- } else {
+ } else if(!pTab2) {
pTab2 = pTab;
- }
+ }
ctx = new NDBT_Context();
ctx->setTab(pTab2);
diff --git a/ndb/test/src/NdbBackup.cpp b/ndb/test/src/NdbBackup.cpp
index 1ce48d495a5..09f52bf0bed 100644
--- a/ndb/test/src/NdbBackup.cpp
+++ b/ndb/test/src/NdbBackup.cpp
@@ -69,28 +69,19 @@ NdbBackup::getBackupDataDirForNode(int _node_id){
/**
* Fetch configuration from management server
*/
- LocalConfig lc;
- if (!lc.init(0,0)) {
- abort();
- }
- ConfigRetriever cr(lc, 0, NODE_TYPE_API);
- ndb_mgm_configuration * p = 0;
+ ndb_mgm_configuration *p;
+ if (connect())
+ return NULL;
- BaseString tmp; tmp.assfmt("%s:%d", host.c_str(), port);
- NdbMgmHandle handle = ndb_mgm_create_handle();
- if(handle == 0 || ndb_mgm_connect(handle, tmp.c_str()) != 0 ||
- (p = ndb_mgm_get_configuration(handle, 0)) == 0){
-
- const char * s = 0;
- if(p == 0 && handle != 0){
- s = ndb_mgm_get_latest_error_msg(handle);
- if(s == 0)
- s = "No error given!";
+ if ((p = ndb_mgm_get_configuration(handle, 0)) == 0)
+ {
+ const char * s= ndb_mgm_get_latest_error_msg(handle);
+ if(s == 0)
+ s = "No error given!";
- ndbout << "Could not fetch configuration" << endl;
- ndbout << s << endl;
- return NULL;
- }
+ ndbout << "Could not fetch configuration" << endl;
+ ndbout << s << endl;
+ return NULL;
}
/**
@@ -155,13 +146,14 @@ NdbBackup::execRestore(bool _restore_data,
ndbout << "scp res: " << res << endl;
- BaseString::snprintf(buf, 255, "%sndb_restore -c \"host=%s\" -n %d -b %d %s %s .",
+ BaseString::snprintf(buf, 255, "%sndb_restore -c \"%s:%d\" -n %d -b %d %s %s .",
#if 1
"",
#else
"valgrind --leak-check=yes -v "
#endif
- addr.c_str(),
+ ndb_mgm_get_connected_host(handle),
+ ndb_mgm_get_connected_port(handle),
_node_id,
_backup_id,
_restore_data?"-r":"",
diff --git a/ndb/test/src/NdbRestarter.cpp b/ndb/test/src/NdbRestarter.cpp
index 4d6d3ddc001..91c0963feae 100644
--- a/ndb/test/src/NdbRestarter.cpp
+++ b/ndb/test/src/NdbRestarter.cpp
@@ -18,7 +18,6 @@
#include <NdbOut.hpp>
#include <NdbSleep.h>
#include <NdbTick.h>
-#include <LocalConfig.hpp>
#include <mgmapi_debug.h>
#include <NDBT_Output.hpp>
#include <random.h>
@@ -33,42 +32,11 @@
NdbRestarter::NdbRestarter(const char* _addr):
connected(false),
- port(-1),
handle(NULL),
m_config(0)
{
if (_addr == NULL){
- LocalConfig lcfg;
- if(!lcfg.init()){
- lcfg.printError();
- lcfg.printUsage();
- g_err << "NdbRestarter - Error parsing local config file" << endl;
- return;
- }
-
- if (lcfg.ids.size() == 0){
- g_err << "NdbRestarter - No management servers configured in local config file" << endl;
- return;
- }
-
- for (int i = 0; i<lcfg.ids.size(); i++){
- MgmtSrvrId * m = &lcfg.ids[i];
-
- switch(m->type){
- case MgmId_TCP:
- char buf[255];
- snprintf(buf, 255, "%s:%d", m->name.c_str(), m->port);
- addr.assign(buf);
- host.assign(m->name.c_str());
- port = m->port;
- return;
- break;
- case MgmId_File:
- break;
- default:
- break;
- }
- }
+ addr.assign("");
} else {
addr.assign(_addr);
}
@@ -391,13 +359,22 @@ NdbRestarter::isConnected(){
int
NdbRestarter::connect(){
+ disconnect();
handle = ndb_mgm_create_handle();
if (handle == NULL){
g_err << "handle == NULL" << endl;
return -1;
}
g_info << "Connecting to mgmsrv at " << addr.c_str() << endl;
- if (ndb_mgm_connect(handle, addr.c_str()) == -1) {
+ if (ndb_mgm_set_connectstring(handle,addr.c_str()))
+ {
+ MGMERR(handle);
+ g_err << "Connection to " << addr.c_str() << " failed" << endl;
+ return -1;
+ }
+
+ if (ndb_mgm_connect(handle, 0, 0, 0) == -1)
+ {
MGMERR(handle);
g_err << "Connection to " << addr.c_str() << " failed" << endl;
return -1;
diff --git a/ndb/test/src/NdbSchemaOp.cpp b/ndb/test/src/NdbSchemaOp.cpp
index a296094ea9d..9bce0b10fc3 100644
--- a/ndb/test/src/NdbSchemaOp.cpp
+++ b/ndb/test/src/NdbSchemaOp.cpp
@@ -158,7 +158,6 @@ NdbSchemaOp::createAttribute( const char* anAttrName,
col.setPrimaryKey(false);
col.setDistributionKey(aDistributionKeyFlag);
- col.setDistributionGroup(aDistributionGroupFlag,aDistributionGroupNoOfBits);
col.setAutoIncrement(aAutoIncrement);
col.setDefaultValue(aDefaultValue != 0 ? aDefaultValue : "");
diff --git a/ndb/test/src/UtilTransactions.cpp b/ndb/test/src/UtilTransactions.cpp
index c0e6effd244..869f7fc76cb 100644
--- a/ndb/test/src/UtilTransactions.cpp
+++ b/ndb/test/src/UtilTransactions.cpp
@@ -619,7 +619,7 @@ UtilTransactions::addRowToInsert(Ndb* pNdb,
int
UtilTransactions::scanReadRecords(Ndb* pNdb,
int parallelism,
- bool exclusive,
+ NdbOperation::LockMode lm,
int records,
int noAttribs,
int *attrib_list,
@@ -669,10 +669,7 @@ UtilTransactions::scanReadRecords(Ndb* pNdb,
return NDBT_FAILED;
}
- NdbResultSet * rs = pOp->readTuples(exclusive ?
- NdbScanOperation::LM_Exclusive :
- NdbScanOperation::LM_Read,
- 0, parallelism);
+ NdbResultSet * rs = pOp->readTuples(lm, 0, parallelism);
if( rs == 0 ) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
@@ -761,7 +758,7 @@ int
UtilTransactions::selectCount(Ndb* pNdb,
int parallelism,
int* count_rows,
- ScanLock lock,
+ NdbOperation::LockMode lm,
NdbConnection* pTrans){
int retryAttempt = 0;
@@ -785,19 +782,7 @@ UtilTransactions::selectCount(Ndb* pNdb,
return NDBT_FAILED;
}
- NdbResultSet * rs;
- switch(lock){
- case SL_ReadHold:
- rs = pOp->readTuples(NdbScanOperation::LM_Read);
- break;
- case SL_Exclusive:
- rs = pOp->readTuples(NdbScanOperation::LM_Exclusive);
- break;
- case SL_Read:
- default:
- rs = pOp->readTuples(NdbScanOperation::LM_CommittedRead);
- }
-
+ NdbResultSet * rs = pOp->readTuples(lm);
if( rs == 0) {
ERR(pTrans->getNdbError());
pNdb->closeTransaction(pTrans);
diff --git a/ndb/src/common/util/getarg.c b/ndb/test/src/getarg.c
index 99b2840a5a6..9f03af69824 100644
--- a/ndb/src/common/util/getarg.c
+++ b/ndb/test/src/getarg.c
@@ -36,15 +36,33 @@
#include "getarg.h"
-#define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag)
-
#ifndef HAVE_STRLCPY
-extern size_t strlcpy (char *dst, const char *src, size_t dst_sz);
-#endif /* !HAVE_STRLCPY */
-
+static size_t
+strlcpy (char *dst, const char *src, size_t dst_sz)
+{
+ size_t n;
+ char *p;
+ for (p = dst, n = 0;
+ n + 1 < dst_sz && *src != '\0';
+ ++p, ++src, ++n)
+ *p = *src;
+ *p = '\0';
+ if (*src == '\0')
+ return n;
+ else
+ return n + strlen (src);
+}
+#endif
#ifndef HAVE_STRLCAT
-extern size_t strlcat (char *dst, const char *src, size_t dst_sz);
-#endif /* !HAVE_STRLCAT */
+static size_t
+strlcat (char *dst, const char *src, size_t dst_sz)
+{
+ size_t len = strlen(dst);
+ return len + strlcpy (dst + len, src, dst_sz - len);
+}
+#endif
+
+#define ISFLAG(X) ((X).type == arg_flag || (X).type == arg_negative_flag)
#ifndef max
#define max(a, b) (a) > (b) ? (a) : (b)
diff --git a/ndb/test/tools/Makefile.am b/ndb/test/tools/Makefile.am
index 8d94c21b721..3255267b636 100644
--- a/ndb/test/tools/Makefile.am
+++ b/ndb/test/tools/Makefile.am
@@ -20,12 +20,10 @@ copy_tab_SOURCES = copy_tab.cpp
create_index_SOURCES = create_index.cpp
ndb_cpcc_SOURCES = cpcc.cpp
-INCLUDES_LOC = -I$(top_srcdir)/ndb/src/mgmclient
-
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_ndbapitest.mk.am
-ndb_cpcc_LDADD = $(LDADD) $(top_builddir)/ndb/src/mgmclient/CpcClient.o
+ndb_cpcc_LDADD = $(LDADD)
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/ndb/test/tools/Makefile_old b/ndb/test/tools/Makefile_old
deleted file mode 100644
index b8e90ae207f..00000000000
--- a/ndb/test/tools/Makefile_old
+++ /dev/null
@@ -1,9 +0,0 @@
-include .defs.mk
-
-DIRS := hugoCalculator hugoFill hugoLoad hugoLockRecords \
- hugoPkDelete hugoPkRead hugoPkReadRecord hugoPkUpdate \
- hugoScanRead hugoScanUpdate restart waiter
-
-include $(NDB_TOP)/Epilogue.mk
-
-_bins_ndbapi : _libs_src
diff --git a/ndb/test/tools/create_index.cpp b/ndb/test/tools/create_index.cpp
index 75a657522f6..6e4c5377f4a 100644
--- a/ndb/test/tools/create_index.cpp
+++ b/ndb/test/tools/create_index.cpp
@@ -30,7 +30,7 @@ main(int argc, const char** argv){
const char* _dbname = "TEST_DB";
int _help = 0;
- int _ordered, _pk;
+ int _ordered = 0, _pk = 1;
struct getargs args[] = {
{ "database", 'd', arg_string, &_dbname, "dbname",
diff --git a/ndb/test/tools/hugoScanRead.cpp b/ndb/test/tools/hugoScanRead.cpp
index cdfdcea4654..42180207a8a 100644
--- a/ndb/test/tools/hugoScanRead.cpp
+++ b/ndb/test/tools/hugoScanRead.cpp
@@ -35,13 +35,17 @@ int main(int argc, const char** argv){
int _parallelism = 1;
const char* _tabname = NULL;
int _help = 0;
-
+ int lock = NdbOperation::LM_Read;
+ int sorted = 0;
+
struct getargs args[] = {
{ "aborts", 'a', arg_integer, &_abort, "percent of transactions that are aborted", "abort%" },
{ "loops", 'l', arg_integer, &_loops, "number of times to run this program(0=infinite loop)", "loops" },
{ "parallelism", 'p', arg_integer, &_parallelism, "parallelism(1-240)", "para" },
{ "records", 'r', arg_integer, &_records, "Number of records", "recs" },
- { "usage", '?', arg_flag, &_help, "Print help", "" }
+ { "usage", '?', arg_flag, &_help, "Print help", "" },
+ { "lock", 'm', arg_integer, &lock, "lock mode", "" },
+ { "sorted", 's', arg_flag, &sorted, "sorted", "" }
};
int num_args = sizeof(args) / sizeof(args[0]);
int optind = 0;
@@ -73,16 +77,48 @@ int main(int argc, const char** argv){
ndbout << " Table " << _tabname << " does not exist!" << endl;
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
+
+ const NdbDictionary::Index * pIdx = 0;
+ if(optind+1 < argc)
+ {
+ pIdx = MyNdb.getDictionary()->getIndex(argv[optind+1], _tabname);
+ if(!pIdx)
+ ndbout << " Index " << argv[optind+1] << " not found" << endl;
+ else
+ if(pIdx->getType() != NdbDictionary::Index::UniqueOrderedIndex &&
+ pIdx->getType() != NdbDictionary::Index::OrderedIndex)
+ {
+ ndbout << " Index " << argv[optind+1] << " is not scannable" << endl;
+ pIdx = 0;
+ }
+ }
HugoTransactions hugoTrans(*pTab);
int i = 0;
while (i<_loops || _loops==0) {
ndbout << i << ": ";
- if(hugoTrans.scanReadRecords(&MyNdb,
- 0,
- _abort,
- _parallelism) != 0){
- return NDBT_ProgramExit(NDBT_FAILED);
+ if(!pIdx)
+ {
+ if(hugoTrans.scanReadRecords(&MyNdb,
+ 0,
+ _abort,
+ _parallelism,
+ (NdbOperation::LockMode)lock) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
+ }
+ else
+ {
+ if(hugoTrans.scanReadRecords(&MyNdb, pIdx,
+ 0,
+ _abort,
+ _parallelism,
+ (NdbOperation::LockMode)lock,
+ sorted) != 0)
+ {
+ return NDBT_ProgramExit(NDBT_FAILED);
+ }
}
i++;
}
diff --git a/ndb/test/tools/old_dirs/waiter/Makefile_old b/ndb/test/tools/old_dirs/waiter/Makefile_old
deleted file mode 100644
index da2c9daff00..00000000000
--- a/ndb/test/tools/old_dirs/waiter/Makefile_old
+++ /dev/null
@@ -1,11 +0,0 @@
-include .defs.mk
-
-TYPE := ndbapitest
-
-BIN_TARGET := waiter
-
-# Source files of non-templated classes (.C files)
-SOURCES = waiter.cpp
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/tools/Makefile.am b/ndb/tools/Makefile.am
index 64625f69ea2..7a61a9b1be5 100644
--- a/ndb/tools/Makefile.am
+++ b/ndb/tools/Makefile.am
@@ -1,5 +1,6 @@
ndbtools_PROGRAMS = \
+ ndb_test_platform \
ndb_waiter \
ndb_drop_table \
ndb_delete_all \
@@ -7,22 +8,34 @@ ndbtools_PROGRAMS = \
ndb_drop_index \
ndb_show_tables \
ndb_select_all \
- ndb_select_count
+ ndb_select_count \
+ ndb_restore
-tools_common_sources = ../test/src/NDBT_ReturnCodes.cpp ../test/src/NDBT_Table.cpp ../test/src/NDBT_Output.cpp
+tools_common_sources = ../test/src/NDBT_ReturnCodes.cpp \
+ ../test/src/NDBT_Table.cpp \
+ ../test/src/NDBT_Output.cpp
+ndb_test_platform_SOURCES = ndb_test_platform.cpp
ndb_waiter_SOURCES = waiter.cpp $(tools_common_sources)
ndb_delete_all_SOURCES = delete_all.cpp $(tools_common_sources)
ndb_desc_SOURCES = desc.cpp $(tools_common_sources)
ndb_drop_index_SOURCES = drop_index.cpp $(tools_common_sources)
ndb_drop_table_SOURCES = drop_tab.cpp $(tools_common_sources)
ndb_show_tables_SOURCES = listTables.cpp $(tools_common_sources)
-ndb_select_all_SOURCES = select_all.cpp ../test/src/NDBT_ResultRow.cpp $(tools_common_sources)
+ndb_select_all_SOURCES = select_all.cpp \
+ ../test/src/NDBT_ResultRow.cpp \
+ $(tools_common_sources)
ndb_select_count_SOURCES = select_count.cpp $(tools_common_sources)
+ndb_restore_SOURCES = restore/restore_main.cpp \
+ restore/consumer.cpp \
+ restore/consumer_restore.cpp \
+ restore/consumer_printer.cpp \
+ restore/Restore.cpp
include $(top_srcdir)/ndb/config/common.mk.am
include $(top_srcdir)/ndb/config/type_ndbapitools.mk.am
+ndb_test_platform_LDFLAGS = @ndb_bin_am_ldflags@
ndb_waiter_LDFLAGS = @ndb_bin_am_ldflags@
ndb_drop_table_LDFLAGS = @ndb_bin_am_ldflags@
ndb_delete_all_LDFLAGS = @ndb_bin_am_ldflags@
@@ -31,6 +44,7 @@ ndb_drop_index_LDFLAGS = @ndb_bin_am_ldflags@
ndb_show_tables_LDFLAGS = @ndb_bin_am_ldflags@
ndb_select_all_LDFLAGS = @ndb_bin_am_ldflags@
ndb_select_count_LDFLAGS = @ndb_bin_am_ldflags@
+ndb_restore_LDFLAGS = @ndb_bin_am_ldflags@
# Don't update the files from bitkeeper
%::SCCS/s.%
diff --git a/ndb/tools/Makefile_old b/ndb/tools/Makefile_old
deleted file mode 100644
index b9dc6883e18..00000000000
--- a/ndb/tools/Makefile_old
+++ /dev/null
@@ -1,12 +0,0 @@
-include .defs.mk
-
-BIN_DIRS = select_all select_count desc list_tables \
- drop_tab delete_all copy_tab \
- create_index drop_index verify_index cpcc
-
-ifneq ($(NDB_ODBC),N)
-BIN_DIRS += ndbsql
-endif
-
-include $(NDB_TOP)/Epilogue.mk
-
diff --git a/ndb/tools/delete_all.cpp b/ndb/tools/delete_all.cpp
index aa5798376ae..046ac8005d2 100644
--- a/ndb/tools/delete_all.cpp
+++ b/ndb/tools/delete_all.cpp
@@ -15,41 +15,65 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <ndb_opts.h>
#include <NdbOut.hpp>
#include <NdbApi.hpp>
#include <NdbSleep.h>
#include <NDBT.hpp>
-#include <getarg.h>
-
static int clear_table(Ndb* pNdb, const NdbDictionary::Table* pTab, int parallelism=240);
-int main(int argc, const char** argv){
- ndb_init();
-
- const char* _tabname = NULL;
- const char* _dbname = "TEST_DB";
- int _help = 0;
-
- struct getargs args[] = {
- { "usage", '?', arg_flag, &_help, "Print help", "" },
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"}
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
+static const char* opt_connect_str= 0;
+static const char* _dbname = "TEST_DB";
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_desc"),
+ { "database", 'd', "Name of database table is in",
+ (gptr*) &_dbname, (gptr*) &_dbname, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
char desc[] =
"tabname\n"\
"This program will delete all records in the specified table using scan delete.\n";
-
- if(getarg(args, num_args, argc, argv, &optind) ||
- argv[optind] == NULL || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_delete_all.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
}
- _tabname = argv[optind];
+ return 0;
+}
+int main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+
+ Ndb::setConnectString(opt_connect_str);
// Connect to Ndb
Ndb MyNdb(_dbname);
@@ -64,13 +88,12 @@ int main(int argc, const char** argv){
// Check if table exists in db
int res = NDBT_OK;
- for(int i = optind; i<argc; i++){
+ for(int i = 0; i<argc; i++){
const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]);
if(pTab == NULL){
- ndbout << " Table " << _tabname << " does not exist!" << endl;
+ ndbout << " Table " << argv[i] << " does not exist!" << endl;
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
-
ndbout << "Deleting all from " << argv[i] << "...";
if(clear_table(&MyNdb, pTab) == NDBT_FAILED){
res = NDBT_FAILED;
diff --git a/ndb/tools/desc.cpp b/ndb/tools/desc.cpp
index 9eed1485a6d..c5e9efdfa8a 100644
--- a/ndb/tools/desc.cpp
+++ b/ndb/tools/desc.cpp
@@ -14,40 +14,66 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <getarg.h>
+#include <ndb_global.h>
+#include <ndb_opts.h>
#include <NDBT.hpp>
#include <NdbApi.hpp>
-
-
-
-int main(int argc, const char** argv){
- ndb_init();
- const char* _tabname = NULL;
- const char* _dbname = "TEST_DB";
- int _unqualified = 0;
- int _help = 0;
-
- struct getargs args[] = {
- { "unqualified", 'u', arg_flag, &_unqualified, "unqualified",
- "Use unqualified table names"},
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"},
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
+static const char* opt_connect_str= 0;
+static const char* _dbname = "TEST_DB";
+static int _unqualified = 0;
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_desc"),
+ { "database", 'd', "Name of database table is in",
+ (gptr*) &_dbname, (gptr*) &_dbname, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "unqualified", 'u', "Use unqualified table names",
+ (gptr*) &_unqualified, (gptr*) &_unqualified, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
char desc[] =
"tabname\n"\
"This program list all properties of table(s) in NDB Cluster.\n"\
- " ex: desc T1 T2 T4\n";
-
- if(getarg(args, num_args, argc, argv, &optind) ||
- argv[optind] == NULL ||_help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
+ " ex: desc T1 T2 T4\n";
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_desc.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
}
- _tabname = argv[optind];
+ return 0;
+}
+
+int main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+
+ Ndb::setConnectString(opt_connect_str);
Ndb* pMyNdb;
pMyNdb = new Ndb(_dbname);
@@ -60,7 +86,7 @@ int main(int argc, const char** argv){
ndbout << endl;
NdbDictionary::Dictionary * dict = pMyNdb->getDictionary();
- for (int i = optind; i < argc; i++) {
+ for (int i = 0; i < argc; i++) {
NDBT_Table* pTab = (NDBT_Table*)dict->getTable(argv[i]);
if (pTab != 0){
ndbout << (* pTab) << endl;
diff --git a/ndb/tools/drop_index.cpp b/ndb/tools/drop_index.cpp
index 70c29461c23..6600811e0c4 100644
--- a/ndb/tools/drop_index.cpp
+++ b/ndb/tools/drop_index.cpp
@@ -15,38 +15,66 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <ndb_opts.h>
#include <NdbOut.hpp>
#include <NdbApi.hpp>
#include <NDBT.hpp>
-#include <getarg.h>
-
-int main(int argc, const char** argv){
- ndb_init();
-
- const char* _tabname = NULL;
- const char* _dbname = "TEST_DB";
- int _help = 0;
-
- struct getargs args[] = {
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"},
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
+static const char* opt_connect_str= 0;
+static const char* _dbname = "TEST_DB";
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_desc"),
+ { "database", 'd', "Name of database table is in",
+ (gptr*) &_dbname, (gptr*) &_dbname, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
char desc[] =
"<indexname>+\n"\
"This program will drop index(es) in Ndb\n";
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_drop_index.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ }
+ return 0;
+}
- if(getarg(args, num_args, argc, argv, &optind) ||
- argv[optind] == NULL || _help){
- arg_printusage(args, num_args, argv[0], desc);
+int main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ if (argc < 1) {
+ usage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- _tabname = argv[optind];
+ Ndb::setConnectString(opt_connect_str);
// Connect to Ndb
Ndb MyNdb(_dbname);
if(MyNdb.init() != 0){
@@ -58,7 +86,7 @@ int main(int argc, const char** argv){
ndbout << "Waiting for ndb to become ready..." << endl;
int res = 0;
- for(int i = optind; i<argc; i++){
+ for(int i = 0; i<argc; i++){
ndbout << "Dropping index " << argv[i] << "...";
int tmp;
if((tmp = MyNdb.getDictionary()->dropIndex(argv[i], 0)) != 0){
diff --git a/ndb/tools/drop_tab.cpp b/ndb/tools/drop_tab.cpp
index 15c229cb0fb..0661a8c599b 100644
--- a/ndb/tools/drop_tab.cpp
+++ b/ndb/tools/drop_tab.cpp
@@ -15,43 +15,66 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include <ndb_global.h>
+#include <ndb_opts.h>
#include <NdbOut.hpp>
#include <NdbApi.hpp>
#include <NDBT.hpp>
-#include <getarg.h>
-
-int main(int argc, const char** argv){
- ndb_init();
-
- const char* _tabname = NULL;
- const char* _dbname = "TEST_DB";
- const char* _connectstr = NULL;
- int _help = 0;
-
- struct getargs args[] = {
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"},
- { "connstr", 'c', arg_string, &_connectstr, "connect string",
- "How to connect to NDB"},
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
+static const char* opt_connect_str= 0;
+static const char* _dbname = "TEST_DB";
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_desc"),
+ { "database", 'd', "Name of database table is in",
+ (gptr*) &_dbname, (gptr*) &_dbname, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
char desc[] =
"tabname\n"\
"This program will drop one table in Ndb\n";
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_drop_table.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ }
+ return 0;
+}
- if(getarg(args, num_args, argc, argv, &optind) ||
- argv[optind] == NULL || _help){
- arg_printusage(args, num_args, argv[0], desc);
+int main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ if (argc < 1) {
+ usage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
- _tabname = argv[optind];
-
- if (_connectstr)
- Ndb::setConnectString(_connectstr);
+
+ Ndb::setConnectString(opt_connect_str);
Ndb MyNdb(_dbname);
if(MyNdb.init() != 0){
ERR(MyNdb.getNdbError());
@@ -62,7 +85,7 @@ int main(int argc, const char** argv){
ndbout << "Waiting for ndb to become ready..." << endl;
int res = 0;
- for(int i = optind; i<argc; i++){
+ for(int i = 0; i<argc; i++){
ndbout << "Dropping table " << argv[i] << "...";
int tmp;
if((tmp = MyNdb.getDictionary()->dropTable(argv[i])) != 0){
diff --git a/ndb/tools/listTables.cpp b/ndb/tools/listTables.cpp
index 4fc5bcd7f21..ccb6967e2dc 100644
--- a/ndb/tools/listTables.cpp
+++ b/ndb/tools/listTables.cpp
@@ -22,7 +22,7 @@
*/
#include <ndb_global.h>
-#include <getarg.h>
+#include <ndb_opts.h>
#include <NdbApi.hpp>
#include <NDBT.hpp>
@@ -161,39 +161,33 @@ list(const char * tabname,
}
}
-#ifndef DBUG_OFF
-const char *debug_option= 0;
-#endif
-
-int main(int argc, const char** argv){
- ndb_init();
- int _loops = 1;
- const char* _tabname = NULL;
- const char* _dbname = "TEST_DB";
- int _type = 0;
- int _help = 0;
- const char* _connect_str = NULL;
-
- struct getargs args[] = {
- { "loops", 'l', arg_integer, &_loops, "loops",
- "Number of times to run(default = 1)" },
- { "unqualified", 'u', arg_flag, &_unqualified, "unqualified",
- "Use unqualified table names"},
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"},
- { "type", 't', arg_integer, &_type, "type",
- "Type of objects to show, see NdbDictionary.hpp for numbers(default = 0)" },
- { "connect-string", 'c', arg_string, &_connect_str,
- "Set connect string for connecting to ndb_mgmd. <constr>=\"host=<hostname:port>[;nodeid=<id>]\". Overides specifying entries in NDB_CONNECTSTRING and config file",
- "<constr>" },
-#ifndef DBUG_OFF
- { "debug", 0, arg_string, &debug_option,
- "Specify debug options e.g. d:t:i:o,out.trace", "options" },
-#endif
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
+static const char* opt_connect_str= 0;
+static const char* _dbname = "TEST_DB";
+static int _loops;
+static int _type;
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_desc"),
+ { "database", 'd', "Name of database table is in",
+ (gptr*) &_dbname, (gptr*) &_dbname, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "loops", 'l', "loops",
+ (gptr*) &_loops, (gptr*) &_loops, 0,
+ GET_INT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0 },
+ { "type", 't', "type",
+ (gptr*) &_type, (gptr*) &_type, 0,
+ GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "unqualified", 'u', "Use unqualified table names",
+ (gptr*) &_unqualified, (gptr*) &_unqualified, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
char desc[] =
"tabname\n"\
"This program list all system objects in NDB Cluster.\n"\
@@ -201,23 +195,44 @@ int main(int argc, const char** argv){
" ex: list_tables -t 2 would show all UserTables\n"\
"To show all indexes for a table write table name as final argument\n"\
" ex: list_tables T1\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_show_tables.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
}
- _tabname = argv[optind];
-
-#ifndef DBUG_OFF
- if (debug_option)
- DBUG_PUSH(debug_option);
-#endif
+ return 0;
+}
+
+int main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char* _tabname;
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ _tabname = argv[0];
- ndb_cluster_connection = new Ndb_cluster_connection(_connect_str);
+ ndb_cluster_connection = new Ndb_cluster_connection(opt_connect_str);
+ if (ndb_cluster_connection->connect(12,5,1))
+ fatal("unable to connect");
ndb = new Ndb(ndb_cluster_connection, _dbname);
if (ndb->init() != 0)
fatal("init");
- ndb_cluster_connection->connect();
if (ndb->waitUntilReady(30) < 0)
fatal("waitUntilReady");
dic = ndb->getDictionary();
diff --git a/ndb/tools/ndb_test_platform.cpp b/ndb/tools/ndb_test_platform.cpp
new file mode 100644
index 00000000000..72dd146dacd
--- /dev/null
+++ b/ndb/tools/ndb_test_platform.cpp
@@ -0,0 +1,95 @@
+/* Copyright (C) 2003 MySQL AB
+
+ 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; either version 2 of the License, or
+ (at your option) any later version.
+
+ 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
+
+
+#include <ndb_global.h>
+#include <my_sys.h>
+#include <BaseString.hpp>
+
+/*
+ * Test BaseString::snprintf
+ */
+
+static
+int test_snprintf(const char * fmt, int buf_sz, int result)
+{
+ int ret;
+ char buf[100];
+ ret = BaseString::snprintf(buf, buf_sz, fmt);
+
+ if(ret < 0)
+ {
+ printf("BaseString::snprint returns %d with size=%d and strlen(fmt)=%d\n",
+ ret, buf_sz, strlen(fmt));
+ return -1;
+ }
+
+ if(ret+1 == buf_sz)
+ {
+ printf("BaseString::snprint truncates returns %d with size=%d and strlen(fmt)=%d\n",
+ ret, buf_sz, strlen(fmt));
+ return -1;
+ }
+
+ if(ret != result)
+ {
+ printf("BaseString::snprint returns incorrect value: returned=%d != expected=%d\n",
+ ret, result);
+ return -1;
+ }
+
+ for(ret = 0; ret+1 < buf_sz && ret < result; ret++)
+ {
+ if(buf[ret] != fmt[ret])
+ {
+ printf("BaseString::snprint Incorrect value in output buffer: "
+ "size=%d returned=expected=%d at pos=%d result=%d != expected=%d\n",
+ buf_sz, result, ret, buf[ret], fmt[ret]);
+ return -1;
+ }
+ }
+ return 0;
+}
+
+int
+main(void)
+{
+ /*
+ * Test BaseString::snprintf
+ */
+
+ if(test_snprintf("test", 1, 4))
+ return -1;
+
+ if(test_snprintf("test", 0, 4))
+ return -1;
+
+ if(test_snprintf("test", 100, 4))
+ return -1;
+
+ /*
+ * Test UintPtr
+ */
+
+ if (sizeof(UintPtr) != sizeof(Uint32*))
+ {
+ printf("sizeof(UintPtr)=%d != sizeof(Uint32*)=%d\n",
+ sizeof(UintPtr), sizeof(Uint32*));
+ return -1;
+ }
+
+ return 0;
+}
diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.cpp b/ndb/tools/restore/Restore.cpp
index fb3bde6bdef..6e2fcaed3af 100644
--- a/ndb/src/kernel/blocks/backup/restore/Restore.cpp
+++ b/ndb/tools/restore/Restore.cpp
@@ -15,7 +15,6 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
#include "Restore.hpp"
-#include "BackupFormat.hpp"
#include <NdbTCP.h>
#include <OutputStream.hpp>
#include <Bitmask.hpp>
@@ -25,9 +24,6 @@
#include <SimpleProperties.hpp>
#include <signaldata/DictTabInfo.hpp>
-// from src/ndbapi
-#include <NdbDictionaryImpl.hpp>
-
Uint16 Twiddle16(Uint16 in); // Byte shift 16-bit data
Uint32 Twiddle32(Uint32 in); // Byte shift 32-bit data
Uint64 Twiddle64(Uint64 in); // Byte shift 64-bit data
diff --git a/ndb/src/kernel/blocks/backup/restore/Restore.hpp b/ndb/tools/restore/Restore.hpp
index 0ec1ab852e9..82fcdcdb183 100644
--- a/ndb/src/kernel/blocks/backup/restore/Restore.hpp
+++ b/ndb/tools/restore/Restore.hpp
@@ -19,7 +19,8 @@
#include <ndb_global.h>
#include <NdbOut.hpp>
-#include <BackupFormat.hpp>
+#include "../src/kernel/blocks/backup/BackupFormat.hpp"
+#include "../src/ndbapi/NdbDictionaryImpl.hpp"
#include <NdbApi.hpp>
#include <ndb_version.h>
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer.cpp b/ndb/tools/restore/consumer.cpp
index e94c31b2666..e94c31b2666 100644
--- a/ndb/src/kernel/blocks/backup/restore/consumer.cpp
+++ b/ndb/tools/restore/consumer.cpp
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer.hpp b/ndb/tools/restore/consumer.hpp
index 692c814159f..692c814159f 100644
--- a/ndb/src/kernel/blocks/backup/restore/consumer.hpp
+++ b/ndb/tools/restore/consumer.hpp
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_printer.cpp b/ndb/tools/restore/consumer_printer.cpp
index 0aa5b521d29..0aa5b521d29 100644
--- a/ndb/src/kernel/blocks/backup/restore/consumer_printer.cpp
+++ b/ndb/tools/restore/consumer_printer.cpp
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_printer.hpp b/ndb/tools/restore/consumer_printer.hpp
index 7cbc924e364..7cbc924e364 100644
--- a/ndb/src/kernel/blocks/backup/restore/consumer_printer.hpp
+++ b/ndb/tools/restore/consumer_printer.hpp
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp b/ndb/tools/restore/consumer_restore.cpp
index a35d9d22c65..e2c55e5a0b1 100644
--- a/ndb/src/kernel/blocks/backup/restore/consumer_restore.cpp
+++ b/ndb/tools/restore/consumer_restore.cpp
@@ -16,7 +16,6 @@
#include "consumer_restore.hpp"
#include <NdbSleep.h>
-#include <NdbDictionaryImpl.hpp>
extern FilteredNdbOut err;
extern FilteredNdbOut info;
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_restore.hpp b/ndb/tools/restore/consumer_restore.hpp
index 59e2734ea1f..59e2734ea1f 100644
--- a/ndb/src/kernel/blocks/backup/restore/consumer_restore.hpp
+++ b/ndb/tools/restore/consumer_restore.hpp
diff --git a/ndb/src/kernel/blocks/backup/restore/consumer_restorem.cpp b/ndb/tools/restore/consumer_restorem.cpp
index 6a9ec07148a..6a9ec07148a 100644
--- a/ndb/src/kernel/blocks/backup/restore/consumer_restorem.cpp
+++ b/ndb/tools/restore/consumer_restorem.cpp
diff --git a/ndb/src/kernel/blocks/backup/restore/main.cpp b/ndb/tools/restore/restore_main.cpp
index f7b1479cc93..409ebd54764 100644
--- a/ndb/src/kernel/blocks/backup/restore/main.cpp
+++ b/ndb/tools/restore/restore_main.cpp
@@ -14,7 +14,8 @@
along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-#include <getarg.h>
+#include <ndb_global.h>
+#include <ndb_opts.h>
#include <Vector.hpp>
#include <ndb_limits.h>
#include <NdbTCP.h>
@@ -35,80 +36,118 @@ static Vector<class BackupConsumer *> g_consumers;
static const char* ga_backupPath = "." DIR_SEPARATOR;
-static const char* ga_connect_NDB = NULL;
+static const char* opt_connect_str= NULL;
/**
* print and restore flags
*/
static bool ga_restore = false;
static bool ga_print = false;
+static int _print = 0;
+static int _print_meta = 0;
+static int _print_data = 0;
+static int _print_log = 0;
+static int _restore_data = 0;
+static int _restore_meta = 0;
+
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_restore"),
+ { "connect", 'c', "same as --connect-string",
+ (gptr*) &opt_connect_str, (gptr*) &opt_connect_str, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "nodeid", 'n', "Backup files from node with id",
+ (gptr*) &ga_nodeId, (gptr*) &ga_nodeId, 0,
+ GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "backupid", 'b', "Backup id",
+ (gptr*) &ga_backupId, (gptr*) &ga_backupId, 0,
+ GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "restore_data", 'r',
+ "Restore table data/logs into NDB Cluster using NDBAPI",
+ (gptr*) &_restore_data, (gptr*) &_restore_data, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "restore_meta", 'm',
+ "Restore meta data into NDB Cluster using NDBAPI",
+ (gptr*) &_restore_meta, (gptr*) &_restore_meta, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "parallelism", 'p',
+ "No of parallel transactions during restore of data."
+ "(parallelism can be 1 to 1024)",
+ (gptr*) &ga_nParallelism, (gptr*) &ga_nParallelism, 0,
+ GET_INT, REQUIRED_ARG, 128, 1, 1024, 0, 1, 0 },
+ { "print", 256, "Print data and log to stdout",
+ (gptr*) &_print, (gptr*) &_print, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "print_data", 257, "Print data to stdout",
+ (gptr*) &_print_data, (gptr*) &_print_data, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "print_meta", 258, "Print meta data to stdout",
+ (gptr*) &_print_meta, (gptr*) &_print_meta, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "print_log", 259, "Print log to stdout",
+ (gptr*) &_print_log, (gptr*) &_print_log, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "dont_ignore_systab_0", 'f',
+ "Experimental. Do not ignore system table during restore.",
+ (gptr*) &ga_dont_ignore_systab_0, (gptr*) &ga_dont_ignore_systab_0, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+
+static void short_usage_sub(void)
+{
+ printf("Usage: %s [OPTIONS] [<path to backup files>]\n", my_progname);
+}
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
+ short_usage_sub();
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_restore.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case 'n':
+ if (ga_nodeId == 0)
+ {
+ printf("Error in --nodeid,-n setting, see --help\n");
+ exit(1);
+ }
+ break;
+ case 'b':
+ if (ga_backupId == 0)
+ {
+ printf("Error in --backupid,-b setting, see --help\n");
+ exit(1);
+ }
+ break;
+ case '?':
+ usage();
+ exit(0);
+ }
+ return 0;
+}
bool
-readArguments(const int argc, const char** argv)
+readArguments(int *pargc, char*** pargv)
{
-
- int _print = 0;
- int _print_meta = 0;
- int _print_data = 0;
- int _print_log = 0;
- int _restore_data = 0;
- int _restore_meta = 0;
-
-
- struct getargs args[] =
- {
- { "connect", 'c', arg_string, &ga_connect_NDB,
- "NDB Cluster connection", "\"nodeid=<api id>;host=<hostname:port>\""},
- { "nodeid", 'n', arg_integer, &ga_nodeId,
- "Backup files from node", "db node id"},
- { "backupid", 'b',arg_integer, &ga_backupId, "Backup id", "backup id"},
- { "print", '\0', arg_flag, &_print,
- "Print data and log to stdout", "print data and log"},
- { "print_data", '\0', arg_flag, &_print_data,
- "Print data to stdout", "print data"},
- { "print_meta", '\0', arg_flag, &_print_meta,
- "Print meta data to stdout", "print meta data"},
- { "print_log", '\0', arg_flag, &_print_log,
- "Print log to stdout", "print log"},
- { "restore_data", 'r', arg_flag, &_restore_data,
- "Restore table data/logs into NDB Cluster using NDBAPI",
- "Restore table data/log"},
- { "restore_meta", 'm', arg_flag, &_restore_meta,
- "Restore meta data into NDB Cluster using NDBAPI", "Restore meta data"},
- { "parallelism", 'p', arg_integer, &ga_nParallelism,
- "No of parallel transactions during restore of data."
- "(parallelism can be 1 to 1024)",
- "Parallelism"},
-#ifdef USE_MYSQL
- { "use_mysql", '\0', arg_flag, &use_mysql,
- "Restore meta data via mysql. Systab will be ignored. Data is restored "
- "using NDBAPI.", "use mysql"},
- { "user", '\0', arg_string, &ga_user, "MySQL user", "Default: root"},
- { "password", '\0', arg_string, &ga_password, "MySQL user's password",
- "Default: \"\" "},
- { "host", '\0', arg_string, &ga_host, "Hostname of MySQL server",
- "Default: localhost"},
- { "socket", '\0', arg_string, &ga_socket, "Path to MySQL server socket file",
- "Default: /tmp/mysql.sock"},
- { "port", '\0', arg_integer, &ga_port, "Port number of MySQL server",
- "Default: 3306"},
-#endif
- { "dont_ignore_systab_0", 'f', arg_flag, &ga_dont_ignore_systab_0,
- "Experimental. Do not ignore system table during restore.",
- "dont_ignore_systab_0"}
-
- };
-
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
-
- if (getarg(args, num_args, argc, argv, &optind) ||
- ga_nodeId == 0 ||
- ga_backupId == 0 ||
- ga_nParallelism < 1 ||
- ga_nParallelism >1024)
+ const char *load_default_groups[]= { "mysql_cluster","ndb_restore",0 };
+ load_defaults("my",load_default_groups,pargc,pargv);
+ if (handle_options(pargc, pargv, my_long_options, get_one_option))
{
- arg_printusage(args, num_args, argv[0], "<path to backup files>\n");
- return false;
+ exit(1);
}
BackupPrinter* printer = new BackupPrinter();
@@ -122,10 +161,6 @@ readArguments(const int argc, const char** argv)
return false;
}
- /**
- * Got segmentation fault when using the printer's attributes directly
- * in getargs... Do not have the time to found out why... this is faster...
- */
if (_print)
{
ga_print = true;
@@ -169,15 +204,14 @@ readArguments(const int argc, const char** argv)
g_consumers.push_back(c);
}
// Set backup file path
- if (argv[optind] != NULL)
+ if (*pargv[0] != NULL)
{
- ga_backupPath = argv[optind];
+ ga_backupPath = *pargv[0];
}
return true;
}
-
void
clearConsumers()
{
@@ -204,19 +238,16 @@ free_data_callback()
}
int
-main(int argc, const char** argv)
+main(int argc, char** argv)
{
- ndb_init();
- if (!readArguments(argc, argv))
+ NDB_INIT(argv[0]);
+
+ if (!readArguments(&argc, &argv))
{
return -1;
}
- if (ga_connect_NDB != NULL)
- {
- // Use connection string
- Ndb::setConnectString(ga_connect_NDB);
- }
+ Ndb::setConnectString(opt_connect_str);
/**
* we must always load meta data, even if we will only print it to stdout
@@ -323,7 +354,8 @@ main(int argc, const char** argv)
if (res < 0)
{
- err << "Restore: An error occured while restoring data. Exiting... res=" << res << endl;
+ err << "Restore: An error occured while restoring data. Exiting... "
+ << "res=" << res << endl;
return -1;
}
@@ -349,7 +381,8 @@ main(int argc, const char** argv)
}
if (res < 0)
{
- err << "Restore: An restoring the data log. Exiting... res=" << res << endl;
+ err << "Restore: An restoring the data log. Exiting... res="
+ << res << endl;
return -1;
}
logIter.validateFooter(); //not implemented
diff --git a/ndb/tools/select_all.cpp b/ndb/tools/select_all.cpp
index 9f8108d9f32..5efeed485a4 100644
--- a/ndb/tools/select_all.cpp
+++ b/ndb/tools/select_all.cpp
@@ -16,6 +16,7 @@
#include <ndb_global.h>
+#include <ndb_opts.h>
#include <NdbOut.hpp>
@@ -23,13 +24,8 @@
#include <NdbMain.h>
#include <NDBT.hpp>
#include <NdbSleep.h>
-#include <getarg.h>
#include <NdbScanFilter.hpp>
-#ifndef DBUG_OFF
-const char *debug_option= 0;
-#endif
-
int scanReadRecords(Ndb*,
const NdbDictionary::Table*,
const NdbDictionary::Index*,
@@ -40,39 +36,44 @@ int scanReadRecords(Ndb*,
char delim,
bool orderby);
-int main(int argc, const char** argv){
- ndb_init();
- int _parallelism = 240;
- const char* _delimiter = "\t";
- int _header = true;
- int _useHexFormat = false;
- const char* _tabname = NULL;
- const char* _dbname = "TEST_DB";
- int _help = 0;
- int _lock = 0;
- int _order = 0;
-
- struct getargs args[] = {
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"},
- { "parallelism", 'p', arg_integer, &_parallelism, "parallelism",
- "parallelism" },
- { "header", 'h', arg_flag, &_header, "Print header", "header" },
- { "useHexFormat", 'x', arg_flag, &_useHexFormat,
- "Output numbers in hexadecimal format", "useHexFormat" },
- { "delimiter", 'd', arg_string, &_delimiter, "Column delimiter",
- "delimiter" },
-#ifndef DBUG_OFF
- { "debug", 0, arg_string, &debug_option,
- "Specify debug options e.g. d:t:i:o,out.trace", "options" },
-#endif
- { "usage", '?', arg_flag, &_help, "Print help", "" },
- { "lock", 'l', arg_integer, &_lock,
- "Read(0), Read-hold(1), Exclusive(2)", "lock"},
- { "order", 'o', arg_flag, &_order, "Sort resultset according to index", ""}
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
+static const char* opt_connect_str= 0;
+static const char* _dbname = "TEST_DB";
+static const char* _delimiter = "\t";
+static int _unqualified, _header, _parallelism, _useHexFormat, _lock,
+ _order;
+
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_desc"),
+ { "database", 'd', "Name of database table is in",
+ (gptr*) &_dbname, (gptr*) &_dbname, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "parallelism", 'p', "parallelism",
+ (gptr*) &_parallelism, (gptr*) &_parallelism, 0,
+ GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "lock", 'l', "Read(0), Read-hold(1), Exclusive(2)",
+ (gptr*) &_lock, (gptr*) &_lock, 0,
+ GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "order", 'o', "Sort resultset according to index",
+ (gptr*) &_order, (gptr*) &_order, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "header", 'h', "Print header",
+ (gptr*) &_header, (gptr*) &_header, 0,
+ GET_BOOL, NO_ARG, 1, 0, 0, 0, 0, 0 },
+ { "useHexFormat", 'x', "Output numbers in hexadecimal format",
+ (gptr*) &_useHexFormat, (gptr*) &_useHexFormat, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "delimiter", 'D', "Column delimiter",
+ (gptr*) &_delimiter, (gptr*) &_delimiter, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
char desc[] =
"tabname\n"\
"This program reads all records from one table in NDB Cluster\n"\
@@ -80,19 +81,42 @@ int main(int argc, const char** argv){
"(It only print error messages if it encounters a permanent error.)\n"\
"It can also be used to dump the content of a table to file \n"\
" ex: select_all --no-header --delimiter=';' T4 > T4.data\n";
-
- if(getarg(args, num_args, argc, argv, &optind) ||
- argv[optind] == NULL || _help) {
- arg_printusage(args, num_args, argv[0], desc);
- return NDBT_ProgramExit(NDBT_WRONGARGS);
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_select_all.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
}
- _tabname = argv[optind];
+ return 0;
+}
-#ifndef DBUG_OFF
- if (debug_option)
- DBUG_PUSH(debug_option);
-#endif
+int main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+ const char* _tabname;
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ if ((_tabname = argv[0]) == 0) {
+ usage();
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ }
+ Ndb::setConnectString(opt_connect_str);
// Connect to Ndb
Ndb MyNdb(_dbname);
@@ -108,14 +132,19 @@ int main(int argc, const char** argv){
// Check if table exists in db
const NdbDictionary::Table* pTab = NDBT_Table::discoverTableFromDb(&MyNdb, _tabname);
const NdbDictionary::Index * pIdx = 0;
- if(optind+1 < argc){
- pIdx = MyNdb.getDictionary()->getIndex(argv[optind+1], _tabname);
+ if(argc > 1){
+ pIdx = MyNdb.getDictionary()->getIndex(argv[1], _tabname);
}
if(pTab == NULL){
ndbout << " Table " << _tabname << " does not exist!" << endl;
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
+
+ if(argc > 1 && pIdx == 0)
+ {
+ ndbout << " Index " << argv[1] << " does not exists" << endl;
+ }
if(_order && pIdx == NULL){
ndbout << " Order flag given without an index" << endl;
diff --git a/ndb/tools/select_count.cpp b/ndb/tools/select_count.cpp
index 6650421e637..c3491f842d8 100644
--- a/ndb/tools/select_count.cpp
+++ b/ndb/tools/select_count.cpp
@@ -16,6 +16,7 @@
#include <ndb_global.h>
+#include <ndb_opts.h>
#include <NdbOut.hpp>
@@ -23,7 +24,6 @@
#include <NdbMain.h>
#include <NDBT.hpp>
#include <NdbSleep.h>
-#include <getarg.h>
#include <UtilTransactions.hpp>
static int
@@ -32,34 +32,68 @@ select_count(Ndb* pNdb, const NdbDictionary::Table* pTab,
int* count_rows,
UtilTransactions::ScanLock lock);
-int main(int argc, const char** argv){
- ndb_init();
- const char* _dbname = "TEST_DB";
- int _parallelism = 240;
- int _help = 0;
- int _lock = 0;
-
- struct getargs args[] = {
- { "database", 'd', arg_string, &_dbname, "dbname",
- "Name of database table is in"},
- { "parallelism", 's', arg_integer, &_parallelism, "parallelism", "parallelism" },
- { "usage", '?', arg_flag, &_help, "Print help", "" },
- { "lock", 'l', arg_integer, &_lock,
- "Read(0), Read-hold(1), Exclusive(2)", "lock"}
-
- };
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
+static const char* opt_connect_str= 0;
+static const char* _dbname = "TEST_DB";
+static int _parallelism = 240;
+static int _lock = 0;
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_desc"),
+ { "database", 'd', "Name of database table is in",
+ (gptr*) &_dbname, (gptr*) &_dbname, 0,
+ GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { "parallelism", 'p', "parallelism",
+ (gptr*) &_parallelism, (gptr*) &_parallelism, 0,
+ GET_INT, REQUIRED_ARG, 240, 0, 0, 0, 0, 0 },
+ { "lock", 'l', "Read(0), Read-hold(1), Exclusive(2)",
+ (gptr*) &_lock, (gptr*) &_lock, 0,
+ GET_INT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
char desc[] =
"tabname1 ... tabnameN\n"\
"This program will count the number of records in tables\n";
-
- if(getarg(args, num_args, argc, argv, &optind) ||
- argv[optind] == NULL || _help) {
- arg_printusage(args, num_args, argv[0], desc);
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_select_count.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ }
+ return 0;
+}
+
+int main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
+ return NDBT_ProgramExit(NDBT_WRONGARGS);
+ if (argc < 1) {
+ usage();
return NDBT_ProgramExit(NDBT_WRONGARGS);
}
+ Ndb::setConnectString(opt_connect_str);
// Connect to Ndb
Ndb MyNdb(_dbname);
@@ -72,7 +106,7 @@ int main(int argc, const char** argv){
while(MyNdb.waitUntilReady() != 0)
ndbout << "Waiting for ndb to become ready..." << endl;
- for(int i = optind; i<argc; i++){
+ for(int i = 0; i<argc; i++){
// Check if table exists in db
const NdbDictionary::Table * pTab = NDBT_Table::discoverTableFromDb(&MyNdb, argv[i]);
if(pTab == NULL){
diff --git a/ndb/tools/waiter.cpp b/ndb/tools/waiter.cpp
index c01a3f9192e..5973b046f8f 100644
--- a/ndb/tools/waiter.cpp
+++ b/ndb/tools/waiter.cpp
@@ -16,81 +16,76 @@
#include <ndb_global.h>
+#include <ndb_opts.h>
+
#include <mgmapi.h>
#include <NdbMain.h>
#include <NdbOut.hpp>
#include <NdbSleep.h>
-#include <getarg.h>
#include <kernel/ndb_limits.h>
-#include "../include/mgmcommon/LocalConfig.hpp"
#include <NDBT.hpp>
int
-waitClusterStatus(const char* _addr, ndb_mgm_node_status _status, unsigned int _timeout);
+waitClusterStatus(const char* _addr, ndb_mgm_node_status _status,
+ unsigned int _timeout);
-int main(int argc, const char** argv){
- ndb_init();
+static const char* opt_connect_str= 0;
+static int _no_contact = 0;
+static int _timeout = 120;
+static struct my_option my_long_options[] =
+{
+ NDB_STD_OPTS("ndb_desc"),
+ { "no-contact", 'n', "Wait for cluster no contact",
+ (gptr*) &_no_contact, (gptr*) &_no_contact, 0,
+ GET_BOOL, NO_ARG, 0, 0, 0, 0, 0, 0 },
+ { "timeout", 't', "Timeout to wait",
+ (gptr*) &_timeout, (gptr*) &_timeout, 0,
+ GET_INT, REQUIRED_ARG, 120, 0, 0, 0, 0, 0 },
+ { 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
+};
+static void print_version()
+{
+ printf("MySQL distrib %s, for %s (%s)\n",MYSQL_SERVER_VERSION,SYSTEM_TYPE,MACHINE_TYPE);
+}
+static void usage()
+{
+ print_version();
+ my_print_help(my_long_options);
+ my_print_variables(my_long_options);
+}
+static my_bool
+get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
+ char *argument)
+{
+ switch (optid) {
+ case '#':
+ DBUG_PUSH(argument ? argument : "d:t:O,/tmp/ndb_drop_table.trace");
+ break;
+ case 'V':
+ print_version();
+ exit(0);
+ case '?':
+ usage();
+ exit(0);
+ }
+ return 0;
+}
+int main(int argc, char** argv){
+ NDB_INIT(argv[0]);
+ const char *load_default_groups[]= { "mysql_cluster",0 };
+ load_defaults("my",load_default_groups,&argc,&argv);
const char* _hostName = NULL;
- int _no_contact = 0;
- int _help = 0;
- int _timeout = 120;
-
- struct getargs args[] = {
- { "timeout", 0, arg_integer, &_timeout, "Timeout to wait", "#" },
- { "no-contact", 0, arg_flag, &_no_contact, "Wait for cluster no contact", "" },
- { "usage", '?', arg_flag, &_help, "Print help", "" }
- };
-
- int num_args = sizeof(args) / sizeof(args[0]);
- int optind = 0;
- char desc[] =
- "hostname:port\n"\
- "This program will connect to the mgmsrv of a NDB cluster.\n"\
- "It will then wait for all nodes to be started\n";
-
- if(getarg(args, num_args, argc, argv, &optind) || _help) {
- arg_printusage(args, num_args, argv[0], desc);
+ int ho_error;
+ if ((ho_error=handle_options(&argc, &argv, my_long_options, get_one_option)))
return NDBT_ProgramExit(NDBT_WRONGARGS);
- }
char buf[255];
- _hostName = argv[optind];
-
- if (_hostName == NULL){
- LocalConfig lcfg;
- if(!lcfg.init())
- {
- lcfg.printError();
- lcfg.printUsage();
- g_err << "Error parsing local config file" << endl;
- return NDBT_ProgramExit(NDBT_FAILED);
- }
+ _hostName = argv[0];
- for (unsigned i = 0; i<lcfg.ids.size();i++)
- {
- MgmtSrvrId * m = &lcfg.ids[i];
-
- switch(m->type){
- case MgmId_TCP:
- snprintf(buf, 255, "%s:%d", m->name.c_str(), m->port);
- _hostName = buf;
- break;
- case MgmId_File:
- break;
- default:
- break;
- }
- if (_hostName != NULL)
- break;
- }
- if (_hostName == NULL)
- {
- g_err << "No management servers configured in local config file" << endl;
- return NDBT_ProgramExit(NDBT_FAILED);
- }
- }
+ if (_hostName == 0)
+ _hostName= opt_connect_str;
if (_no_contact) {
if (waitClusterStatus(_hostName, NDB_MGM_NODE_STATUS_NO_CONTACT, _timeout) != 0)
@@ -183,13 +178,19 @@ waitClusterStatus(const char* _addr,
int _nodes[MAX_NDB_NODES];
int _num_nodes = 0;
- handle = ndb_mgm_create_handle();
+ handle = ndb_mgm_create_handle();
if (handle == NULL){
g_err << "handle == NULL" << endl;
return -1;
}
g_info << "Connecting to mgmsrv at " << _addr << endl;
- if (ndb_mgm_connect(handle, _addr) == -1) {
+ if (ndb_mgm_set_connectstring(handle, _addr))
+ {
+ MGMERR(handle);
+ g_err << "Connectstring " << _addr << " invalid" << endl;
+ return -1;
+ }
+ if (ndb_mgm_connect(handle,0,0,1)) {
MGMERR(handle);
g_err << "Connection to " << _addr << " failed" << endl;
return -1;
diff --git a/netware/comp_err.def b/netware/comp_err.def
index d694c07174a..f27b40c7b78 100644
--- a/netware/comp_err.def
+++ b/netware/comp_err.def
@@ -2,7 +2,7 @@
# MySQL Error File Compiler
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Error File Compiler"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/isamchk.def b/netware/isamchk.def
index 69e8ac0405b..31cf3fc569a 100644
--- a/netware/isamchk.def
+++ b/netware/isamchk.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL ISAM Table Check Tool"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL ISAM Table Check Tool"
VERSION 4, 0
STACKSIZE 65536
diff --git a/netware/isamlog.def b/netware/isamlog.def
index bb8312066ef..52f9de0d928 100644
--- a/netware/isamlog.def
+++ b/netware/isamlog.def
@@ -2,7 +2,7 @@
# ISAM Log
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL ISAM Table Log Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/libmysql.def b/netware/libmysql.def
index 7804c4468a5..fea117dedd1 100644
--- a/netware/libmysql.def
+++ b/netware/libmysql.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
EXPORT @libmysql.imp
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Client Library"
VERSION 4, 0
AUTOUNLOAD
diff --git a/netware/my_print_defaults.def b/netware/my_print_defaults.def
index 49f167341ae..826981256b5 100644
--- a/netware/my_print_defaults.def
+++ b/netware/my_print_defaults.def
@@ -2,7 +2,7 @@
# My Print Defaults
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Print Defaults Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/myisam_ftdump.def b/netware/myisam_ftdump.def
index 259d6617445..9639404b53b 100644
--- a/netware/myisam_ftdump.def
+++ b/netware/myisam_ftdump.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL MyISAM Table Dump Tool"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL MyISAM Table Dump Tool"
VERSION 4, 0
STACKSIZE 65536
diff --git a/netware/myisamchk.def b/netware/myisamchk.def
index cdfe186058f..eaa01730872 100644
--- a/netware/myisamchk.def
+++ b/netware/myisamchk.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL MyISAM Table Check Tool"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL MyISAM Table Check Tool"
VERSION 4, 0
STACKSIZE 65536
diff --git a/netware/myisamlog.def b/netware/myisamlog.def
index 5c4cbb23361..3580c870c10 100644
--- a/netware/myisamlog.def
+++ b/netware/myisamlog.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL MyISAM Table Log Tool"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL MyISAM Table Log Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/myisampack.def b/netware/myisampack.def
index 9111538c2c0..a6946982236 100644
--- a/netware/myisampack.def
+++ b/netware/myisampack.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL MyISAM Table Pack Tool"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL MyISAM Table Pack Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysql.def b/netware/mysql.def
index 9b4424ed4fb..5ae8dc102a0 100644
--- a/netware/mysql.def
+++ b/netware/mysql.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL Monitor"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Monitor"
VERSION 4, 0
MULTIPLE
diff --git a/netware/mysql_install.def b/netware/mysql_install.def
index 87fc76919f9..3392afb7298 100644
--- a/netware/mysql_install.def
+++ b/netware/mysql_install.def
@@ -2,7 +2,7 @@
# My Print Defaults
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Install Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysql_install_db.def b/netware/mysql_install_db.def
index 4653638b5ad..1657b7c17af 100644
--- a/netware/mysql_install_db.def
+++ b/netware/mysql_install_db.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL Install"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Initial Database Installer"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysql_test_run.def b/netware/mysql_test_run.def
index b34f62a1f91..d4d4baee168 100644
--- a/netware/mysql_test_run.def
+++ b/netware/mysql_test_run.def
@@ -4,7 +4,7 @@
MODULE libc.nlm
STACKSIZE 65536
SCREENNAME "MySQL Test Run"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Test Run"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysql_waitpid.def b/netware/mysql_waitpid.def
index 4d56d29c42f..da0884ccba3 100644
--- a/netware/mysql_waitpid.def
+++ b/netware/mysql_waitpid.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
#SCREENNAME "MySQL Tool - Wait for a Program to Terminate"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Tool - Wait for a Program to Terminate"
VERSION 4, 0
STACKSIZE 65536
diff --git a/netware/mysqladmin.def b/netware/mysqladmin.def
index 0ace36992b1..46f90d531fa 100644
--- a/netware/mysqladmin.def
+++ b/netware/mysqladmin.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL Admin"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Admin Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysqlbinlog.def b/netware/mysqlbinlog.def
index 89677b4a353..25a470e7353 100644
--- a/netware/mysqlbinlog.def
+++ b/netware/mysqlbinlog.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL Binary Log Dump Tool"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Binary Log Dump Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysqlcheck.def b/netware/mysqlcheck.def
index 8820e9aae8e..7067b1d1729 100644
--- a/netware/mysqlcheck.def
+++ b/netware/mysqlcheck.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL Check Tool"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Check Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysqld.def b/netware/mysqld.def
index 6856aefe56c..42c2d176a1b 100644
--- a/netware/mysqld.def
+++ b/netware/mysqld.def
@@ -2,7 +2,7 @@
# MySQL Server
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Database Server"
VERSION 4, 0
MULTIPLE
diff --git a/netware/mysqld_safe.def b/netware/mysqld_safe.def
index 9080ef783c9..2a9ef04b47d 100644
--- a/netware/mysqld_safe.def
+++ b/netware/mysqld_safe.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL Database Server"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Database Server Monitor"
VERSION 4, 0
MULTIPLE
diff --git a/netware/mysqldump.def b/netware/mysqldump.def
index 901c9b262dc..ddacf7bc0d5 100644
--- a/netware/mysqldump.def
+++ b/netware/mysqldump.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL Dump Tool"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Dump Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysqlimport.def b/netware/mysqlimport.def
index d6f7fcb6bbd..5253da42567 100644
--- a/netware/mysqlimport.def
+++ b/netware/mysqlimport.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL Import"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Import Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysqlshow.def b/netware/mysqlshow.def
index 2b41386f643..0b61b81dcf9 100644
--- a/netware/mysqlshow.def
+++ b/netware/mysqlshow.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
SCREENNAME "MySQL Show"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Show Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/mysqltest.def b/netware/mysqltest.def
index d98f6436a4a..e134acede07 100644
--- a/netware/mysqltest.def
+++ b/netware/mysqltest.def
@@ -2,7 +2,7 @@
# MySQL Admin
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Test Case Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/pack_isam.def b/netware/pack_isam.def
index f0f5a7e328a..b93cfdffbeb 100644
--- a/netware/pack_isam.def
+++ b/netware/pack_isam.def
@@ -2,7 +2,7 @@
# Pack ISAM
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL ISAM Table Pack Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/perror.def b/netware/perror.def
index f1d23715f55..18c95d8b236 100644
--- a/netware/perror.def
+++ b/netware/perror.def
@@ -2,7 +2,7 @@
# PERROR
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Error Code Description Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/replace.def b/netware/replace.def
index b55690152b9..19348ee4245 100644
--- a/netware/replace.def
+++ b/netware/replace.def
@@ -2,7 +2,7 @@
# Replace
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Text Replacement Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/netware/resolve_stack_dump.def b/netware/resolve_stack_dump.def
index 21fd177fbc7..01042699d61 100644
--- a/netware/resolve_stack_dump.def
+++ b/netware/resolve_stack_dump.def
@@ -3,7 +3,7 @@
#------------------------------------------------------------------------------
MODULE libc.nlm
#SCREENNAME "MySQL Stack Dump Resolve Tool"
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL Stack Dump Resolve Tool"
VERSION 4, 0
STACKSIZE 65536
diff --git a/netware/resolveip.def b/netware/resolveip.def
index 10b99304e22..244f52bb969 100644
--- a/netware/resolveip.def
+++ b/netware/resolveip.def
@@ -2,7 +2,7 @@
# Resolve IP
#------------------------------------------------------------------------------
MODULE libc.nlm
-COPYRIGHT "(c) 2003 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
+COPYRIGHT "(c) 2003-2005 Novell, Inc. Portions (c) 2003 MySQL AB. All Rights Reserved."
DESCRIPTION "MySQL IP/Hostname Resolve Tool"
VERSION 4, 0
XDCDATA ../netware/mysql.xdc
diff --git a/scripts/fill_help_tables.sh b/scripts/fill_help_tables.sh
index cb5437f7178..78dfe7b6088 100644
--- a/scripts/fill_help_tables.sh
+++ b/scripts/fill_help_tables.sh
@@ -197,6 +197,10 @@ sub prepare_name
$a =~ s/(\@node(.*?)\n)/ /g;
$a =~ s/(\@tab)/\t/g;
$a =~ s/\@item/ /g;
+ $a =~ s/\@minus\{\}/-/g;
+ $a =~ s/\@dots\{\}/.../g;
+ $a =~ s/\@var\{((.|\n)+?)\}/$1/go;
+ $a =~ s/\@command\{((.|\n)+?)\}/$1/go;
$a =~ s/\@code\{((.|\n)+?)\}/$1/go;
$a =~ s/\@strong\{(.+?)\}/$1/go;
$a =~ s/\@samp\{(.+?)\}/$1/go;
@@ -244,6 +248,10 @@ sub prepare_description
$a =~ s/(\@item)/ /g;
$a =~ s/(\@tindex\s(.*?)\n)//g;
$a =~ s/(\@c\s(.*?)\n)//g;
+ $a =~ s/\@minus\{\}/-/g;
+ $a =~ s/\@dots\{\}/.../g;
+ $a =~ s/\@var\{((.|\n)+?)\}/$1/go;
+ $a =~ s/\@command\{((.|\n)+?)\}/$1/go;
$a =~ s/\@code\{((.|\n)+?)\}/$1/go;
$a =~ s/\@strong\{(.+?)\}/$1/go;
$a =~ s/\@samp\{(.+?)\}/$1/go;
@@ -273,6 +281,8 @@ sub prepare_example
$a =~ s/(^\@c for_help_topic(.*?)\n)//g;
+ $a =~ s/\@var\{((.|\n)+?)\}/$1/go;
+ $a =~ s/\@dots\{\}/.../g;
$a =~ s/\\/\\\\/g;
$a =~ s/(\@{)/{/g;
$a =~ s/(\@})/}/g;
diff --git a/scripts/mysql_fix_privilege_tables.sh b/scripts/mysql_fix_privilege_tables.sh
index 2d6434a0eb5..6790ebbffa6 100644
--- a/scripts/mysql_fix_privilege_tables.sh
+++ b/scripts/mysql_fix_privilege_tables.sh
@@ -13,7 +13,7 @@ args=""
port=""
socket=""
database="mysql"
-bindir=""
+bindir="."
pkgdatadir="@pkgdatadir@"
file=mysql_fix_privilege_tables.sql
@@ -74,6 +74,7 @@ parse_arguments() {
# Get first arguments from the my.cfg file, groups [mysqld] and
# [mysql_install_db], and then merge with the command line arguments
+print_defaults=my_print_defaults
for dir in ./bin @bindir@ @bindir@ extra $bindir/../bin $bindir/../extra
do
if test -x $dir/my_print_defaults
@@ -105,7 +106,7 @@ then
done
fi
-cmd="$bindir/mysql -f --user=$user --host=$host"
+cmd="$bindir/mysql --no-defaults --force --user=$user --host=$host"
if test ! -z "$password" ; then
cmd="$cmd --password=$password"
fi
diff --git a/scripts/mysqld_safe.sh b/scripts/mysqld_safe.sh
index b9e7ce21f79..1f4d17f8885 100644
--- a/scripts/mysqld_safe.sh
+++ b/scripts/mysqld_safe.sh
@@ -141,12 +141,12 @@ fi
args=
SET_USER=2
-parse_arguments `$print_defaults --loose-verbose $defaults mysqld server`
+parse_arguments `$print_defaults $defaults --loose-verbose mysqld server`
if test $SET_USER -eq 2
then
SET_USER=0
fi
-parse_arguments `$print_defaults --loose-verbose $defaults mysqld_safe safe_mysqld`
+parse_arguments `$print_defaults $defaults --loose-verbose mysqld_safe safe_mysqld`
parse_arguments PICK-ARGS-FROM-ARGV "$@"
safe_mysql_unix_port=${mysql_unix_port:-${MYSQL_UNIX_PORT:-@MYSQL_UNIX_ADDR@}}
@@ -315,7 +315,7 @@ do
break
fi
- if test @IS_LINUX@ -a $KILL_MYSQLD -eq 1
+ if @IS_LINUX@ && test $KILL_MYSQLD -eq 1
then
# Test if one process was hanging.
# This is only a fix for Linux (running as base 3 mysqld processes)
diff --git a/server-tools/instance-manager/mysqlmanager.cc b/server-tools/instance-manager/mysqlmanager.cc
index 78fa3ac565b..9ad8ce2c858 100644
--- a/server-tools/instance-manager/mysqlmanager.cc
+++ b/server-tools/instance-manager/mysqlmanager.cc
@@ -233,8 +233,7 @@ spawn:
sigsuspend(&zeromask);
if (is_terminated)
- log_info("angel got signal %d (%s), exiting",
- is_terminated, sys_siglist[is_terminated]);
+ log_info("angel got signal %d, exiting", is_terminated);
else if (child_status == CHILD_NEED_RESPAWN)
{
child_status= CHILD_OK;
diff --git a/server-tools/instance-manager/thread_repository.cc b/server-tools/instance-manager/thread_repository.cc
index 0a46f61c831..d0b302d29fb 100644
--- a/server-tools/instance-manager/thread_repository.cc
+++ b/server-tools/instance-manager/thread_repository.cc
@@ -148,10 +148,11 @@ void Thread_repository::deliver_shutdown()
{
struct timespec shutdown_time;
set_timespec(shutdown_time, 1);
+ Thread_info *info;
pthread_mutex_lock(&LOCK_thread_repository);
shutdown_in_progress= true;
- for (Thread_info *info= head.next; info != &head; info= info->next)
+ for (info= head.next; info != &head; info= info->next)
{
pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL);
/*
@@ -173,7 +174,7 @@ void Thread_repository::deliver_shutdown()
so this time everybody should be informed (presumably each worker can
get CPU during shutdown_time.)
*/
- for (Thread_info *info= head.next; info != &head; info= info->next)
+ for (info= head.next; info != &head; info= info->next)
{
pthread_kill(info->thread_id, THREAD_KICK_OFF_SIGNAL);
if (info->current_cond)
diff --git a/sql-common/client.c b/sql-common/client.c
index fa1488f4f11..aa50b9fe27b 100644
--- a/sql-common/client.c
+++ b/sql-common/client.c
@@ -1512,6 +1512,7 @@ static MYSQL_METHODS client_methods=
#endif
};
+
MYSQL *
CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
const char *passwd, const char *db,
@@ -1534,7 +1535,6 @@ CLI_MYSQL_REAL_CONNECT(MYSQL *mysql,const char *host, const char *user,
#ifdef HAVE_SYS_UN_H
struct sockaddr_un UNIXaddr;
#endif
-
init_sigpipe_variables
DBUG_ENTER("mysql_real_connect");
LINT_INIT(host_info);
diff --git a/sql-common/my_time.c b/sql-common/my_time.c
index dc997921f74..4c5dd361061 100644
--- a/sql-common/my_time.c
+++ b/sql-common/my_time.c
@@ -395,7 +395,8 @@ str_to_datetime(const char *str, uint length, MYSQL_TIME *l_time,
goto err;
}
- if (number_of_fields < 3 || l_time->month > 12 ||
+ if (number_of_fields < 3 ||
+ l_time->year > 9999 || l_time->month > 12 ||
l_time->day > 31 || l_time->hour > 23 ||
l_time->minute > 59 || l_time->second > 59 ||
(!(flags & TIME_FUZZY_DATE) && (l_time->month == 0 ||
@@ -723,6 +724,10 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
I couldn't come up with a better way to get a repeatable result :(
We can't use mktime() as it's buggy on many platforms and not thread safe.
+
+ Note: this code assumes that our time_t estimation is not too far away
+ from real value (we assume that localtime_r(tmp) will return something
+ within 24 hrs from t) which is probably true for all current time zones.
*/
tmp=(time_t) (((calc_daynr((uint) t->year,(uint) t->month,(uint) t->day) -
(long) days_at_timestart)*86400L + (long) t->hour*3600L +
@@ -735,7 +740,8 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
for (loop=0;
loop < 2 &&
(t->hour != (uint) l_time->tm_hour ||
- t->minute != (uint) l_time->tm_min);
+ t->minute != (uint) l_time->tm_min ||
+ t->second != (uint) l_time->tm_sec);
loop++)
{ /* One check should be enough ? */
/* Get difference in days */
@@ -745,15 +751,22 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
else if (days > 1)
days= -1;
diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour)) +
- (long) (60*((int) t->minute - (int) l_time->tm_min)));
+ (long) (60*((int) t->minute - (int) l_time->tm_min)) +
+ (long) ((int) t->second - (int) l_time->tm_sec));
current_timezone+= diff+3600; /* Compensate for -3600 above */
tmp+= (time_t) diff;
localtime_r(&tmp,&tm_tmp);
l_time=&tm_tmp;
}
/*
- Fix that if we are in the not existing daylight saving time hour
- we move the start of the next real hour
+ Fix that if we are in the non existing daylight saving time hour
+ we move the start of the next real hour.
+
+ This code doesn't handle such exotical thing as time-gaps whose length
+ is more than one hour or non-integer (latter can theoretically happen
+ if one of seconds will be removed due leap correction, or because of
+ general time correction like it happened for Africa/Monrovia time zone
+ in year 1972).
*/
if (loop == 2 && t->hour != (uint) l_time->tm_hour)
{
@@ -763,7 +776,8 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
else if (days > 1)
days= -1;
diff=(3600L*(long) (days*24+((int) t->hour - (int) l_time->tm_hour))+
- (long) (60*((int) t->minute - (int) l_time->tm_min)));
+ (long) (60*((int) t->minute - (int) l_time->tm_min)) +
+ (long) ((int) t->second - (int) l_time->tm_sec));
if (diff == 3600)
tmp+=3600 - t->minute*60 - t->second; /* Move to next hour */
else if (diff == -3600)
@@ -779,10 +793,10 @@ my_system_gmt_sec(const MYSQL_TIME *t, long *my_timezone, bool *in_dst_time_gap)
/* Set MYSQL_TIME structure to 0000-00-00 00:00:00.000000 */
-void set_zero_time(MYSQL_TIME *tm)
+void set_zero_time(MYSQL_TIME *tm, enum enum_mysql_timestamp_type time_type)
{
bzero((void*) tm, sizeof(*tm));
- tm->time_type= MYSQL_TIMESTAMP_NONE;
+ tm->time_type= time_type;
}
diff --git a/sql/Makefile.am b/sql/Makefile.am
index a3935835a2d..7d2eda1e222 100644
--- a/sql/Makefile.am
+++ b/sql/Makefile.am
@@ -29,8 +29,7 @@ libexec_PROGRAMS = mysqld
noinst_PROGRAMS = gen_lex_hash
bin_PROGRAMS = mysql_tzinfo_to_sql
gen_lex_hash_LDFLAGS = @NOINST_LDFLAGS@
-LDADD = @isam_libs@ \
- $(top_builddir)/myisam/libmyisam.a \
+LDADD = $(top_builddir)/myisam/libmyisam.a \
$(top_builddir)/myisammrg/libmyisammrg.a \
$(top_builddir)/heap/libheap.a \
$(top_builddir)/vio/libvio.a \
@@ -51,7 +50,7 @@ noinst_HEADERS = item.h item_func.h item_sum.h item_cmpfunc.h \
procedure.h sql_class.h sql_lex.h sql_list.h \
sql_manager.h sql_map.h sql_string.h unireg.h \
field.h handler.h mysqld_suffix.h \
- ha_isammrg.h ha_isam.h ha_myisammrg.h\
+ ha_myisammrg.h\
ha_heap.h ha_myisam.h ha_berkeley.h ha_innodb.h \
ha_ndbcluster.h opt_range.h protocol.h \
sql_select.h structs.h table.h sql_udf.h hash_filo.h\
@@ -86,7 +85,7 @@ mysqld_SOURCES = sql_lex.cc sql_handler.cc \
records.cc filesort.cc handler.cc \
ha_heap.cc ha_myisam.cc ha_myisammrg.cc \
ha_berkeley.cc ha_innodb.cc \
- ha_isam.cc ha_isammrg.cc ha_ndbcluster.cc \
+ ha_ndbcluster.cc \
sql_db.cc sql_table.cc sql_rename.cc sql_crypt.cc \
sql_load.cc mf_iocache.cc field_conv.cc sql_show.cc \
sql_udf.cc sql_analyse.cc sql_analyse.h sql_cache.cc \
diff --git a/sql/examples/ha_archive.cc b/sql/examples/ha_archive.cc
index 6fbfb3f9f9d..3f176da1c7f 100644
--- a/sql/examples/ha_archive.cc
+++ b/sql/examples/ha_archive.cc
@@ -530,13 +530,15 @@ int ha_archive::write_row(byte * buf)
z_off_t written;
DBUG_ENTER("ha_archive::write_row");
- statistic_increment(ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
pthread_mutex_lock(&share->mutex);
written= gzwrite(share->archive_write, buf, table->reclength);
- DBUG_PRINT("ha_archive::get_row", ("Wrote %d bytes expected %d", written, table->reclength));
- share->dirty= TRUE;
+ DBUG_PRINT("ha_archive::write_row", ("Wrote %d bytes expected %d", written, table->reclength));
+ if (!delayed_insert || !bulk_insert)
+ share->dirty= TRUE;
+
if (written != table->reclength)
goto error;
/*
@@ -628,9 +630,12 @@ int ha_archive::get_row(gzFile file_to_read, byte *buf)
if (read == 0)
DBUG_RETURN(HA_ERR_END_OF_FILE);
- /* If the record is the wrong size, the file is probably damaged */
+ /*
+ If the record is the wrong size, the file is probably damaged, unless
+ we are dealing with a delayed insert or a bulk insert.
+ */
if ((ulong) read != table->reclength)
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
/* Calculate blob length, we use this for our buffer */
for (field=table->blob_field; *field ; field++)
@@ -648,7 +653,7 @@ int ha_archive::get_row(gzFile file_to_read, byte *buf)
{
read= gzread(file_to_read, last, size);
if ((size_t) read != size)
- DBUG_RETURN(HA_ERR_CRASHED_ON_USAGE);
+ DBUG_RETURN(HA_ERR_END_OF_FILE);
(*field)->set_ptr(size, last);
last += size;
}
@@ -671,7 +676,8 @@ int ha_archive::rnd_next(byte *buf)
DBUG_RETURN(HA_ERR_END_OF_FILE);
scan_rows--;
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
current_position= gztell(archive);
rc= get_row(archive, buf);
@@ -707,7 +713,8 @@ void ha_archive::position(const byte *record)
int ha_archive::rnd_pos(byte * buf, byte *pos)
{
DBUG_ENTER("ha_archive::rnd_pos");
- statistic_increment(ha_read_rnd_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
current_position= ha_get_ptr(pos, ref_length);
z_off_t seek= gzseek(archive, current_position, SEEK_SET);
@@ -821,15 +828,6 @@ int ha_archive::optimize(THD* thd, HA_CHECK_OPT* check_opt)
}
-/*
- No transactions yet, so this is pretty dull.
-*/
-int ha_archive::external_lock(THD *thd, int lock_type)
-{
- DBUG_ENTER("ha_archive::external_lock");
- DBUG_RETURN(0);
-}
-
/*
Below is an example of how to setup row level locking.
*/
@@ -837,6 +835,11 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
THR_LOCK_DATA **to,
enum thr_lock_type lock_type)
{
+ if (lock_type == TL_WRITE_DELAYED)
+ delayed_insert= TRUE;
+ else
+ delayed_insert= FALSE;
+
if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK)
{
/*
@@ -871,97 +874,46 @@ THR_LOCK_DATA **ha_archive::store_lock(THD *thd,
}
-/******************************************************************************
-
- Everything below here is default, please look at ha_example.cc for
- descriptions.
-
- ******************************************************************************/
-
-int ha_archive::update_row(const byte * old_data, byte * new_data)
-{
-
- DBUG_ENTER("ha_archive::update_row");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-int ha_archive::delete_row(const byte * buf)
-{
- DBUG_ENTER("ha_archive::delete_row");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-int ha_archive::index_read(byte * buf, const byte * key,
- uint key_len __attribute__((unused)),
- enum ha_rkey_function find_flag
- __attribute__((unused)))
-{
- DBUG_ENTER("ha_archive::index_read");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-int ha_archive::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len __attribute__((unused)),
- enum ha_rkey_function find_flag
- __attribute__((unused)))
-{
- DBUG_ENTER("ha_archive::index_read_idx");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
-int ha_archive::index_next(byte * buf)
-{
- DBUG_ENTER("ha_archive::index_next");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-int ha_archive::index_prev(byte * buf)
-{
- DBUG_ENTER("ha_archive::index_prev");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-int ha_archive::index_first(byte * buf)
-{
- DBUG_ENTER("ha_archive::index_first");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-int ha_archive::index_last(byte * buf)
-{
- DBUG_ENTER("ha_archive::index_last");
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
-}
-
-
+/*
+ Hints for optimizer, see ha_tina for more information
+*/
void ha_archive::info(uint flag)
{
DBUG_ENTER("ha_archive::info");
- /* This is a lie, but you don't want the optimizer to see zero or 1 */
+ /*
+ This should be an accurate number now, though bulk and delayed inserts can
+ cause the number to be inaccurate.
+ */
records= share->rows_recorded;
deleted= 0;
DBUG_VOID_RETURN;
}
-int ha_archive::extra(enum ha_extra_function operation)
-{
- DBUG_ENTER("ha_archive::extra");
- DBUG_RETURN(0);
-}
-int ha_archive::reset(void)
+/*
+ This method tells us that a bulk insert operation is about to occur. We set
+ a flag which will keep write_row from saying that its data is dirty. This in
+ turn will keep selects from causing a sync to occur.
+ Basically, yet another optimizations to keep compression working well.
+*/
+void ha_archive::start_bulk_insert(ha_rows rows)
{
- DBUG_ENTER("ha_archive::reset");
- DBUG_RETURN(0);
+ DBUG_ENTER("ha_archive::info");
+ bulk_insert= TRUE;
+ DBUG_VOID_RETURN;
}
-ha_rows ha_archive::records_in_range(uint inx, key_range *min_key,
- key_range *max_key)
+
+/*
+ Other side of start_bulk_insert, is end_bulk_insert. Here we turn off the bulk insert
+ flag, and set the share dirty so that the next select will call sync for us.
+*/
+int ha_archive::end_bulk_insert()
{
- DBUG_ENTER("ha_archive::records_in_range ");
- DBUG_RETURN(records); // HA_ERR_WRONG_COMMAND
+ bulk_insert= FALSE;
+ share->dirty= TRUE;
+ DBUG_RETURN(0);
}
#endif /* HAVE_ARCHIVE_DB */
diff --git a/sql/examples/ha_archive.h b/sql/examples/ha_archive.h
index b619de5f6c1..809f52a883b 100644
--- a/sql/examples/ha_archive.h
+++ b/sql/examples/ha_archive.h
@@ -32,10 +32,10 @@ typedef struct st_archive_share {
uint table_name_length,use_count;
pthread_mutex_t mutex;
THR_LOCK lock;
- File meta_file; /* Meta file we use */
- gzFile archive_write; /* Archive file we are working with */
- bool dirty; /* Flag for if a flush should occur */
- ulonglong rows_recorded; /* Number of rows in tables */
+ File meta_file; /* Meta file we use */
+ gzFile archive_write; /* Archive file we are working with */
+ bool dirty; /* Flag for if a flush should occur */
+ ulonglong rows_recorded; /* Number of rows in tables */
} ARCHIVE_SHARE;
/*
@@ -53,9 +53,11 @@ class ha_archive: public handler
byte byte_buffer[IO_SIZE]; /* Initial buffer for our string */
String buffer; /* Buffer used for blob storage */
ulonglong scan_rows; /* Number of rows left in scan */
+ bool delayed_insert; /* If the insert is delayed */
+ bool bulk_insert; /* If we are performing a bulk insert */
public:
- ha_archive(TABLE *table): handler(table)
+ ha_archive(TABLE *table): handler(table), delayed_insert(0), bulk_insert(0)
{
/* Set our original buffer from pre-allocated memory */
buffer.set(byte_buffer, IO_SIZE, system_charset_info);
@@ -72,37 +74,15 @@ public:
ulong table_flags() const
{
return (HA_REC_NOT_IN_SEQ | HA_NOT_EXACT_COUNT | HA_NO_AUTO_INCREMENT |
- HA_FILE_BASED);
+ HA_FILE_BASED | HA_CAN_INSERT_DELAYED);
}
ulong index_flags(uint idx, uint part, bool all_parts) const
{
return 0;
}
- /*
- Have to put something here, there is no real limit as far as
- archive is concerned.
- */
- uint max_supported_record_length() const { return UINT_MAX; }
- /*
- Called in test_quick_select to determine if indexes should be used.
- */
- virtual double scan_time() { return (double) (records) / 20.0+10; }
- /* The next method will never be called */
- virtual double read_time(uint index, uint ranges, ha_rows rows)
- { return (double) rows / 20.0+1; }
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 delete_row(const byte * buf);
- int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_idx(byte * buf, uint idx, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_next(byte * buf);
- int index_prev(byte * buf);
- int index_first(byte * buf);
- int index_last(byte * buf);
int rnd_init(bool scan=1);
int rnd_next(byte *buf);
int rnd_pos(byte * buf, byte *pos);
@@ -116,12 +96,10 @@ public:
int write_data_header(gzFile file_to_write);
void position(const byte *record);
void info(uint);
- int extra(enum ha_extra_function operation);
- int reset(void);
- int external_lock(THD *thd, int lock_type);
- ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
int optimize(THD* thd, HA_CHECK_OPT* check_opt);
+ void start_bulk_insert(ha_rows rows);
+ int end_bulk_insert();
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
};
diff --git a/sql/examples/ha_tina.cc b/sql/examples/ha_tina.cc
index 0345a170c3c..39573a8f54c 100644
--- a/sql/examples/ha_tina.cc
+++ b/sql/examples/ha_tina.cc
@@ -426,7 +426,7 @@ int ha_tina::write_row(byte * buf)
int size;
DBUG_ENTER("ha_tina::write_row");
- statistic_increment(ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count, &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
@@ -462,7 +462,8 @@ int ha_tina::update_row(const byte * old_data, byte * new_data)
int size;
DBUG_ENTER("ha_tina::update_row");
- statistic_increment(ha_update_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
@@ -489,7 +490,7 @@ int ha_tina::update_row(const byte * old_data, byte * new_data)
int ha_tina::delete_row(const byte * buf)
{
DBUG_ENTER("ha_tina::delete_row");
- statistic_increment(ha_delete_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
if (chain_append())
DBUG_RETURN(-1);
@@ -629,7 +630,8 @@ int ha_tina::rnd_next(byte *buf)
{
DBUG_ENTER("ha_tina::rnd_next");
- statistic_increment(ha_read_rnd_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
current_position= next_position;
if (!share->mapped_file)
@@ -666,7 +668,8 @@ void ha_tina::position(const byte *record)
int ha_tina::rnd_pos(byte * buf, byte *pos)
{
DBUG_ENTER("ha_tina::rnd_pos");
- statistic_increment(ha_read_rnd_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
+ &LOCK_status);
current_position= ha_get_ptr(pos,ref_length);
DBUG_RETURN(find_current_row(buf));
}
diff --git a/sql/field.cc b/sql/field.cc
index 7a8f59c25fe..73f442a868e 100644
--- a/sql/field.cc
+++ b/sql/field.cc
@@ -429,8 +429,9 @@ uint Field::fill_cache_field(CACHE_FIELD *copy)
copy->length-=table->blob_ptr_size;
return copy->length;
}
- else if (!zero_pack() && (type() == FIELD_TYPE_STRING && copy->length > 4 ||
- type() == FIELD_TYPE_VAR_STRING))
+ else if (!zero_pack() &&
+ (type() == MYSQL_TYPE_STRING && copy->length >= 4 &&
+ copy->length < 256))
copy->strip=1; /* Remove end space */
else
copy->strip=0;
@@ -479,6 +480,26 @@ bool Field::optimize_range(uint idx, uint part)
return test(table->file->index_flags(idx, part, 1) & HA_READ_RANGE);
}
+
+Field *Field::new_field(MEM_ROOT *root, struct st_table *new_table)
+{
+ Field *tmp;
+ if (!(tmp= (Field*) memdup_root(root,(char*) this,size_of())))
+ return 0;
+
+ if (tmp->table->maybe_null)
+ tmp->flags&= ~NOT_NULL_FLAG;
+ tmp->table= new_table;
+ tmp->key_start.init(0);
+ tmp->part_of_key.init(0);
+ tmp->part_of_sortkey.init(0);
+ tmp->unireg_check=Field::NONE;
+ tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
+ ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
+ tmp->reset_fields();
+ return tmp;
+}
+
/****************************************************************************
Field_null, a field that always return NULL
****************************************************************************/
@@ -547,7 +568,8 @@ int Field_decimal::store(const char *from, uint len, CHARSET_INFO *cs)
/* Convert character set if the old one is multi byte */
if (cs->mbmaxlen > 1)
{
- tmp.copy(from, len, cs, &my_charset_bin);
+ uint dummy_errors;
+ tmp.copy(from, len, cs, &my_charset_bin, &dummy_errors);
from= tmp.ptr();
len= tmp.length();
}
@@ -1181,7 +1203,7 @@ int Field_tiny::store(double nr)
error= 1;
}
else
- *ptr=(char) nr;
+ *ptr=(char) (int) nr;
}
return error;
}
@@ -1312,9 +1334,9 @@ int Field_short::store(const char *from,uint len,CHARSET_INFO *cs)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (tmp > (uint16) ~0)
+ else if (tmp > UINT_MAX16)
{
- tmp=(uint16) ~0;
+ tmp=UINT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
@@ -1363,9 +1385,9 @@ int Field_short::store(double nr)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr > (double) (uint16) ~0)
+ else if (nr > (double) UINT_MAX16)
{
- res=(int16) (uint16) ~0;
+ res=(int16) UINT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
@@ -1387,7 +1409,7 @@ int Field_short::store(double nr)
error= 1;
}
else
- res=(int16) nr;
+ res=(int16) (int) nr;
}
#ifdef WORDS_BIGENDIAN
if (table->db_low_byte_first)
@@ -1412,9 +1434,9 @@ int Field_short::store(longlong nr)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
- else if (nr > (longlong) (uint16) ~0)
+ else if (nr > (longlong) UINT_MAX16)
{
- res=(int16) (uint16) ~0;
+ res=(int16) UINT_MAX16;
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
@@ -1784,7 +1806,6 @@ int Field_long::store(const char *from,uint len,CHARSET_INFO *cs)
longlong tmp;
long store_tmp;
int error;
- bool warning_given= 0;
char *end;
tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES);
@@ -1863,9 +1884,10 @@ int Field_long::store(double nr)
res=0;
error= 1;
}
- else if (nr > (double) (ulong) ~0L)
+ else if (nr > (double) UINT_MAX32)
{
- res=(int32) (uint32) ~0L;
+ res= UINT_MAX32;
+ set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
error= 1;
}
else
@@ -1884,7 +1906,7 @@ int Field_long::store(double nr)
error= 1;
}
else
- res=(int32) nr;
+ res=(int32) (longlong) nr;
}
if (error)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_OUT_OF_RANGE, 1);
@@ -2074,8 +2096,7 @@ int Field_longlong::store(const char *from,uint len,CHARSET_INFO *cs)
longlong tmp;
int error= 0;
char *end;
- bool warning_given;
-
+
tmp= cs->cset->scan(cs, from, from+len, MY_SEQ_SPACES);
len-= (uint)tmp;
from+= tmp;
@@ -2124,7 +2145,7 @@ int Field_longlong::store(double nr)
res=0;
error= 1;
}
- else if (nr >= (double) ~ (ulonglong) 0)
+ else if (nr >= (double) ULONGLONG_MAX)
{
res= ~(longlong) 0;
error= 1;
@@ -2134,15 +2155,15 @@ int Field_longlong::store(double nr)
}
else
{
- if (nr < (double) LONGLONG_MIN)
+ if (nr <= (double) LONGLONG_MIN)
{
res= LONGLONG_MIN;
- error= 1;
+ error= (nr < (double) LONGLONG_MIN);
}
- else if (nr > (double) LONGLONG_MAX)
+ else if (nr >= (double) LONGLONG_MAX)
{
res= LONGLONG_MAX;
- error= 1;
+ error= (nr > (double) LONGLONG_MAX);
}
else
res=(longlong) nr;
@@ -4113,6 +4134,10 @@ int Field_datetime::store(longlong nr)
void Field_datetime::store_time(TIME *ltime,timestamp_type type)
{
longlong tmp;
+ /*
+ We don't perform range checking here since values stored in TIME
+ structure always fit into DATETIME range.
+ */
if (type == MYSQL_TIMESTAMP_DATE || type == MYSQL_TIMESTAMP_DATETIME)
tmp=((ltime->year*10000L+ltime->month*100+ltime->day)*LL(1000000)+
(ltime->hour*10000L+ltime->minute*100+ltime->second));
@@ -4417,6 +4442,8 @@ String *Field_string::val_str(String *val_buffer __attribute__((unused)),
int Field_string::cmp(const char *a_ptr, const char *b_ptr)
{
+ uint a_len, b_len;
+
if (field_charset->strxfrm_multiply > 1)
{
/*
@@ -4426,12 +4453,21 @@ int Field_string::cmp(const char *a_ptr, const char *b_ptr)
return field_charset->coll->strnncollsp(field_charset,
(const uchar*) a_ptr, field_length,
(const uchar*) b_ptr,
- field_length);
+ field_length, 0);
+ }
+ if (field_charset->mbmaxlen != 1)
+ {
+ uint char_len= field_length/field_charset->mbmaxlen;
+ a_len= my_charpos(field_charset, a_ptr, a_ptr + field_length, char_len);
+ b_len= my_charpos(field_charset, b_ptr, b_ptr + field_length, char_len);
}
- return my_strnncoll(field_charset,(const uchar*) a_ptr, field_length,
- (const uchar*) b_ptr, field_length);
+ else
+ a_len= b_len= field_length;
+ return my_strnncoll(field_charset,(const uchar*) a_ptr, a_len,
+ (const uchar*) b_ptr, b_len);
}
+
void Field_string::sort_string(char *to,uint length)
{
uint tmp=my_strnxfrm(field_charset,
@@ -4444,18 +4480,24 @@ void Field_string::sort_string(char *to,uint length)
void Field_string::sql_type(String &res) const
{
+ THD *thd= table->in_use;
CHARSET_INFO *cs=res.charset();
- ulong length= cs->cset->snprintf(cs,(char*) res.ptr(),
- res.alloced_length(), "%s(%d)",
- (field_length > 3 &&
- (table->db_options_in_use &
- HA_OPTION_PACK_RECORD) ?
- (has_charset() ? "varchar" : "varbinary") :
+ ulong length;
+
+ length= cs->cset->snprintf(cs,(char*) res.ptr(),
+ res.alloced_length(), "%s(%d)",
+ ((type() == MYSQL_TYPE_VAR_STRING &&
+ !thd->variables.new_mode) ?
+ (has_charset() ? "varchar" : "varbinary") :
(has_charset() ? "char" : "binary")),
- (int) field_length / charset()->mbmaxlen);
+ (int) field_length / charset()->mbmaxlen);
res.length(length);
+ if ((thd->variables.sql_mode & (MODE_MYSQL323 | MODE_MYSQL40)) &&
+ has_charset() && (charset()->state & MY_CS_BINSORT))
+ res.append(" binary");
}
+
char *Field_string::pack(char *to, const char *from, uint max_length)
{
uint length= min(field_length,max_length);
@@ -4489,10 +4531,27 @@ const char *Field_string::unpack(char *to, const char *from)
}
-int Field_string::pack_cmp(const char *a, const char *b, uint length)
+/*
+ Compare two packed keys
+
+ SYNOPSIS
+ pack_cmp()
+ a New key
+ b Original key
+ length Key length
+ insert_or_update 1 if this is an insert or update
+
+ RETURN
+ < 0 a < b
+ 0 a = b
+ > 0 a > b
+*/
+
+int Field_string::pack_cmp(const char *a, const char *b, uint length,
+ my_bool insert_or_update)
{
uint a_length, b_length;
- if (field_length > 255)
+ if (length > 255)
{
a_length= uint2korr(a);
b_length= uint2korr(b);
@@ -4504,29 +4563,51 @@ int Field_string::pack_cmp(const char *a, const char *b, uint length)
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- return my_strnncoll(field_charset,
- (const uchar*)a,a_length,
- (const uchar*)b,b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
-int Field_string::pack_cmp(const char *b, uint length)
+/*
+ Compare a packed key against row
+
+ SYNOPSIS
+ pack_cmp()
+ key Original key
+ length Key length. (May be less than field length)
+ insert_or_update 1 if this is an insert or update
+
+ RETURN
+ < 0 row < key
+ 0 row = key
+ > 0 row > key
+*/
+
+int Field_string::pack_cmp(const char *key, uint length,
+ my_bool insert_or_update)
{
- uint b_length;
- if (field_length > 255)
+ uint row_length, key_length;
+ char *end;
+ if (length > 255)
{
- b_length= uint2korr(b);
- b+= 2;
+ key_length= uint2korr(key);
+ key+= 2;
}
else
- b_length= (uint) (uchar) *b++;
- char *end= ptr + field_length;
+ key_length= (uint) (uchar) *key++;
+
+ /* Only use 'length' of key, not field_length */
+ end= ptr + length;
while (end > ptr && end[-1] == ' ')
end--;
- uint a_length = (uint) (end - ptr);
- return my_strnncoll(field_charset,
- (const uchar*)ptr,a_length,
- (const uchar*)b, b_length);
+ row_length= (uint) (end - ptr);
+
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) ptr, row_length,
+ (const uchar*) key, key_length,
+ insert_or_update);
}
@@ -4534,16 +4615,31 @@ uint Field_string::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+2;
- else
- return (uint) ((uchar) *data_ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
+
uint Field_string::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
}
+Field *Field_string::new_field(MEM_ROOT *root, struct st_table *new_table)
+{
+ if (type() != MYSQL_TYPE_VAR_STRING || table == new_table)
+ return Field::new_field(root, new_table);
+
+ /*
+ Old VARCHAR field which should be modified to a VARCHAR on copy
+ This is done to ensure that ALTER TABLE will convert old VARCHAR fields
+ to now VARCHAR fields.
+ */
+ return new Field_varstring(field_length, maybe_null(),
+ field_name, new_table,
+ charset());
+}
+
/****************************************************************************
** VARCHAR type (Not available for the end user yet)
****************************************************************************/
@@ -4552,7 +4648,7 @@ uint Field_string::max_packed_col_length(uint max_length)
int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
{
int error= 0;
- uint32 not_used;
+ uint32 not_used, copy_length;
char buff[80];
String tmpstr(buff,sizeof(buff), &my_charset_bin);
@@ -4566,15 +4662,21 @@ int Field_varstring::store(const char *from,uint length,CHARSET_INFO *cs)
if (conv_errors)
error= 1;
}
- if (length > field_length)
- {
- length=field_length;
+ /*
+ Make sure we don't break a multibyte sequence
+ as well as don't copy a malformed data.
+ */
+ copy_length= field_charset->cset->well_formed_len(field_charset,
+ from,from+length,
+ field_length/
+ field_charset->mbmaxlen);
+ memcpy(ptr + HA_KEY_BLOB_LENGTH, from, copy_length);
+ int2store(ptr, copy_length);
+
+ if (copy_length < length)
error= 1;
- }
if (error)
set_warning(MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_DATA_TRUNCATED, 1);
- memcpy(ptr+HA_KEY_BLOB_LENGTH,from,length);
- int2store(ptr, length);
return error;
}
@@ -4621,17 +4723,49 @@ int Field_varstring::cmp(const char *a_ptr, const char *b_ptr)
uint a_length=uint2korr(a_ptr);
uint b_length=uint2korr(b_ptr);
int diff;
- diff= my_strnncoll(field_charset,
- (const uchar*) a_ptr+HA_KEY_BLOB_LENGTH,
- min(a_length,b_length),
- (const uchar*) b_ptr+HA_KEY_BLOB_LENGTH,
- min(a_length,b_length));
- return diff ? diff : (int) (a_length - b_length);
+ diff= field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a_ptr+
+ HA_KEY_BLOB_LENGTH,
+ a_length,
+ (const uchar*) b_ptr+
+ HA_KEY_BLOB_LENGTH,
+ b_length,0);
+ return diff;
}
+
+int Field_varstring::key_cmp(const byte *key_ptr, uint max_key_length)
+{
+ char *blob1;
+ uint length= uint2korr(ptr);
+ CHARSET_INFO *cs= charset();
+ uint char_length= max_key_length / cs->mbmaxlen;
+
+ char_length= my_charpos(cs, ptr + HA_KEY_BLOB_LENGTH,
+ ptr + HA_KEY_BLOB_LENGTH + length, char_length);
+ set_if_smaller(length, char_length);
+ return cs->coll->strnncollsp(cs,
+ (const uchar*) ptr+2, length,
+ (const uchar*) key_ptr+HA_KEY_BLOB_LENGTH,
+ uint2korr(key_ptr), 0);
+}
+
+
+int Field_varstring::key_cmp(const byte *a,const byte *b)
+{
+ CHARSET_INFO *cs= charset();
+ return cs->coll->strnncollsp(cs,
+ (const uchar*) a + HA_KEY_BLOB_LENGTH,
+ uint2korr(a),
+ (const uchar*) b + HA_KEY_BLOB_LENGTH,
+ uint2korr(b),
+ 0);
+}
+
+
void Field_varstring::sort_string(char *to,uint length)
{
- uint tot_length=uint2korr(ptr);
+ uint tot_length= uint2korr(ptr);
tot_length= my_strnxfrm(field_charset,
(uchar*) to, length,
(uchar*) ptr+HA_KEY_BLOB_LENGTH,
@@ -4651,9 +4785,11 @@ void Field_varstring::sql_type(String &res) const
res.length(length);
}
+
char *Field_varstring::pack(char *to, const char *from, uint max_length)
{
uint length=uint2korr(from);
+ set_if_smaller(max_length, field_length);
if (length > max_length)
length=max_length;
*to++= (char) (length & 255);
@@ -4668,12 +4804,14 @@ char *Field_varstring::pack(char *to, const char *from, uint max_length)
char *Field_varstring::pack_key(char *to, const char *from, uint max_length)
{
uint length=uint2korr(from);
- uint char_length= (field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length;
- from+=HA_KEY_BLOB_LENGTH;
+ uint char_length= ((field_charset->mbmaxlen > 1) ?
+ max_length/field_charset->mbmaxlen : max_length);
+ from+= HA_KEY_BLOB_LENGTH;
if (length > char_length)
+ {
char_length= my_charpos(field_charset, from, from+length, char_length);
- set_if_smaller(length, char_length);
+ set_if_smaller(length, char_length);
+ }
*to++= (char) (length & 255);
if (max_length > 255)
*to++= (char) (length >> 8);
@@ -4686,16 +4824,16 @@ char *Field_varstring::pack_key(char *to, const char *from, uint max_length)
const char *Field_varstring::unpack(char *to, const char *from)
{
uint length;
- if (field_length > 255)
+ if (field_length <= 255)
{
length= (uint) (uchar) (*to= *from++);
to[1]=0;
}
else
{
- length=uint2korr(from);
- to[0] = *from++;
- to[1] = *from++;
+ length= uint2korr(from);
+ to[0]= *from++;
+ to[1]= *from++;
}
if (length)
memcpy(to+HA_KEY_BLOB_LENGTH, from, length);
@@ -4703,77 +4841,122 @@ const char *Field_varstring::unpack(char *to, const char *from)
}
-int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length)
+int Field_varstring::pack_cmp(const char *a, const char *b, uint key_length,
+ my_bool insert_or_update)
{
uint a_length;
uint b_length;
if (key_length > 255)
{
- a_length=uint2korr(a); a+= 2;
- b_length=uint2korr(b); b+= 2;
+ a_length=uint2korr(a); a+= HA_KEY_BLOB_LENGTH;
+ b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
}
else
{
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
-int Field_varstring::pack_cmp(const char *b, uint key_length)
+
+int Field_varstring::pack_cmp(const char *b, uint key_length,
+ my_bool insert_or_update)
{
char *a= ptr+HA_KEY_BLOB_LENGTH;
uint a_length= uint2korr(ptr);
uint b_length;
+ uint char_length= ((field_charset->mbmaxlen > 1) ?
+ key_length / field_charset->mbmaxlen : key_length);
+
if (key_length > 255)
{
- b_length=uint2korr(b); b+= 2;
+ b_length=uint2korr(b); b+= HA_KEY_BLOB_LENGTH;
}
else
- {
b_length= (uint) (uchar) *b++;
+
+ if (a_length > char_length)
+ {
+ char_length= my_charpos(field_charset, a, a+a_length, char_length);
+ set_if_smaller(a_length, char_length);
}
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a,
+ a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
+
uint Field_varstring::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+HA_KEY_BLOB_LENGTH;
- else
- return (uint) ((uchar) *data_ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
+
uint Field_varstring::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
}
-void Field_varstring::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
- imagetype type)
+
+void Field_varstring::get_key_image(char *buff, uint length, imagetype type)
{
- uint f_length=uint2korr(ptr);
- if (f_length > length)
- f_length= length;
- int2store(buff,length);
- memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+HA_KEY_BLOB_LENGTH, length);
-#ifdef HAVE_purify
+ uint f_length= uint2korr(ptr);
+ uint char_length= length / field_charset->mbmaxlen;
+ char_length= my_charpos(field_charset, ptr, ptr + HA_KEY_BLOB_LENGTH,
+ char_length);
+ set_if_smaller(f_length, char_length);
+ int2store(buff,f_length);
+ memcpy(buff+HA_KEY_BLOB_LENGTH, ptr+HA_KEY_BLOB_LENGTH, f_length);
if (f_length < length)
+ {
+ /*
+ Must clear this as we do a memcmp in opt_range.cc to detect
+ identical keys
+ */
bzero(buff+HA_KEY_BLOB_LENGTH+f_length, (length-f_length));
-#endif
+ }
}
-void Field_varstring::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+
+void Field_varstring::set_key_image(char *buff,uint length)
{
length=uint2korr(buff); // Real length is here
- (void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
+ (void) Field_varstring::store(buff+HA_KEY_BLOB_LENGTH, length,
+ field_charset);
}
+int Field_varstring::cmp_binary_offset(uint row_offset)
+{
+ return cmp_binary(ptr, ptr+row_offset);
+}
+
+
+int Field_varstring::cmp_binary(const char *a_ptr, const char *b_ptr,
+ uint32 max_length)
+{
+ char *a,*b;
+ uint diff;
+ uint32 a_length,b_length;
+
+ a_length= uint2korr(a_ptr);
+ b_length= uint2korr(b_ptr);
+ set_if_smaller(a_length, max_length);
+ set_if_smaller(b_length, max_length);
+ if (a_length != b_length)
+ return 1;
+ return memcmp(a_ptr+2, b_ptr+2, a_length);
+}
+
/****************************************************************************
** blob type
@@ -5011,10 +5194,10 @@ String *Field_blob::val_str(String *val_buffer __attribute__((unused)),
int Field_blob::cmp(const char *a,uint32 a_length, const char *b,
uint32 b_length)
{
- return field_charset->coll->strnncoll(field_charset,
- (const uchar*)a, a_length,
- (const uchar*)b, b_length,
- 0);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*)a, a_length,
+ (const uchar*)b, b_length,
+ 0);
}
@@ -5061,8 +5244,7 @@ int Field_blob::cmp_binary(const char *a_ptr, const char *b_ptr,
/* The following is used only when comparing a key */
-void Field_blob::get_key_image(char *buff,uint length,
- CHARSET_INFO *cs, imagetype type)
+void Field_blob::get_key_image(char *buff, uint length, imagetype type)
{
uint32 blob_length= get_length(ptr);
char *blob;
@@ -5097,8 +5279,9 @@ void Field_blob::get_key_image(char *buff,uint length,
#endif /*HAVE_SPATIAL*/
get_ptr(&blob);
- uint char_length= length / cs->mbmaxlen;
- char_length= my_charpos(cs, blob, blob + blob_length, char_length);
+ uint char_length= length / field_charset->mbmaxlen;
+ char_length= my_charpos(field_charset, blob, blob + blob_length,
+ char_length);
set_if_smaller(blob_length, char_length);
if ((uint32) length > blob_length)
@@ -5114,10 +5297,11 @@ void Field_blob::get_key_image(char *buff,uint length,
memcpy(buff+HA_KEY_BLOB_LENGTH, blob, length);
}
-void Field_blob::set_key_image(char *buff,uint length, CHARSET_INFO *cs)
+
+void Field_blob::set_key_image(char *buff,uint length)
{
length= uint2korr(buff);
- (void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, cs);
+ (void) Field_blob::store(buff+HA_KEY_BLOB_LENGTH, length, field_charset);
}
@@ -5130,7 +5314,7 @@ int Field_blob::key_cmp(const byte *key_ptr, uint max_key_length)
uint char_length= max_key_length / cs->mbmaxlen;
char_length= my_charpos(cs, blob1, blob1+blob_length, char_length);
set_if_smaller(blob_length, char_length);
- return Field_blob::cmp(blob1,min(blob_length, max_key_length),
+ return Field_blob::cmp(blob1, blob_length,
(char*) key_ptr+HA_KEY_BLOB_LENGTH,
uint2korr(key_ptr));
}
@@ -5222,7 +5406,8 @@ const char *Field_blob::unpack(char *to, const char *from)
/* Keys for blobs are like keys on varchars */
-int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
+int Field_blob::pack_cmp(const char *a, const char *b, uint key_length,
+ my_bool insert_or_update)
{
uint a_length;
uint b_length;
@@ -5236,13 +5421,15 @@ int Field_blob::pack_cmp(const char *a, const char *b, uint key_length)
a_length= (uint) (uchar) *a++;
b_length= (uint) (uchar) *b++;
}
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
-int Field_blob::pack_cmp(const char *b, uint key_length)
+int Field_blob::pack_cmp(const char *b, uint key_length,
+ my_bool insert_or_update)
{
char *a;
memcpy_fixed(&a,ptr+packlength,sizeof(char*));
@@ -5256,12 +5443,11 @@ int Field_blob::pack_cmp(const char *b, uint key_length)
b_length=uint2korr(b); b+=2;
}
else
- {
b_length= (uint) (uchar) *b++;
- }
- return my_strnncoll(field_charset,
- (const uchar*) a, a_length,
- (const uchar*) b, b_length);
+ return field_charset->coll->strnncollsp(field_charset,
+ (const uchar*) a, a_length,
+ (const uchar*) b, b_length,
+ insert_or_update);
}
/* Create a packed key that will be used for storage from a MySQL row */
@@ -5271,8 +5457,8 @@ char *Field_blob::pack_key(char *to, const char *from, uint max_length)
char *save=ptr;
ptr=(char*) from;
uint32 length=get_length(); // Length of from string
- uint char_length= (field_charset->mbmaxlen > 1) ?
- max_length/field_charset->mbmaxlen : max_length;
+ uint char_length= ((field_charset->mbmaxlen > 1) ?
+ max_length/field_charset->mbmaxlen : max_length);
if (length)
get_ptr((char**) &from);
if (length > char_length)
@@ -5346,14 +5532,15 @@ char *Field_blob::pack_key_from_key_image(char *to, const char *from,
return to+length;
}
+
uint Field_blob::packed_col_length(const char *data_ptr, uint length)
{
if (length > 255)
return uint2korr(data_ptr)+2;
- else
- return (uint) ((uchar) *data_ptr)+1;
+ return (uint) ((uchar) *data_ptr)+1;
}
+
uint Field_blob::max_packed_col_length(uint max_length)
{
return (max_length > 255 ? 2 : 1)+max_length;
@@ -5362,8 +5549,7 @@ uint Field_blob::max_packed_col_length(uint max_length)
#ifdef HAVE_SPATIAL
-void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
- imagetype type)
+void Field_geom::get_key_image(char *buff, uint length, imagetype type)
{
char *blob;
const char *dummy;
@@ -5392,11 +5578,6 @@ void Field_geom::get_key_image(char *buff, uint length, CHARSET_INFO *cs,
}
-void Field_geom::set_key_image(char *buff, uint length, CHARSET_INFO *cs)
-{
- Field_blob::set_key_image(buff, length, cs);
-}
-
void Field_geom::sql_type(String &res) const
{
CHARSET_INFO *cs= &my_charset_latin1;
@@ -5530,7 +5711,8 @@ int Field_enum::store(const char *from,uint length,CHARSET_INFO *cs)
/* Convert character set if nesessary */
if (String::needs_conversion(length, cs, field_charset, &not_used))
{
- tmpstr.copy(from, length, cs, field_charset);
+ uint dummy_errors;
+ tmpstr.copy(from, length, cs, field_charset, &dummy_errors);
from= tmpstr.ptr();
length= tmpstr.length();
}
@@ -5678,10 +5860,11 @@ void Field_enum::sql_type(String &res) const
bool flag=0;
for (const char **pos= typelib->type_names; *pos; pos++)
{
+ uint dummy_errors;
if (flag)
res.append(',');
/* convert to res.charset() == utf8, then quote */
- enum_item.copy(*pos, strlen(*pos), charset(), res.charset());
+ enum_item.copy(*pos, strlen(*pos), charset(), res.charset(), &dummy_errors);
append_unescaped(&res, enum_item.ptr(), enum_item.length());
flag= 1;
}
@@ -5712,7 +5895,8 @@ int Field_set::store(const char *from,uint length,CHARSET_INFO *cs)
/* Convert character set if nesessary */
if (String::needs_conversion(length, cs, field_charset, &not_used_offset))
{
- tmpstr.copy(from, length, cs, field_charset);
+ uint dummy_errors;
+ tmpstr.copy(from, length, cs, field_charset, &dummy_errors);
from= tmpstr.ptr();
length= tmpstr.length();
}
@@ -5788,10 +5972,11 @@ void Field_set::sql_type(String &res) const
bool flag=0;
for (const char **pos= typelib->type_names; *pos; pos++)
{
+ uint dummy_errors;
if (flag)
res.append(',');
/* convert to res.charset() == utf8, then quote */
- set_item.copy(*pos, strlen(*pos), charset(), res.charset());
+ set_item.copy(*pos, strlen(*pos), charset(), res.charset(), &dummy_errors);
append_unescaped(&res, set_item.ptr(), set_item.length());
flag= 1;
}
@@ -5841,33 +6026,49 @@ bool Field_num::eq_def(Field *field)
/*****************************************************************************
-** Handling of field and create_field
+ Handling of field and create_field
*****************************************************************************/
void create_field::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_VAR_STRING:
- case MYSQL_TYPE_STRING:
- length*= charset->mbmaxlen;
- pack_length= calc_pack_length(sql_type == FIELD_TYPE_VAR_STRING ?
- FIELD_TYPE_STRING : sql_type, length);
- break;
- case MYSQL_TYPE_ENUM:
- case MYSQL_TYPE_SET:
- length*= charset->mbmaxlen;
- break;
- default:
- /* do nothing */
- break;
+ 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_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VARCHAR:
+ length*= charset->mbmaxlen;
+ key_length*= charset->mbmaxlen;
+ pack_length= calc_pack_length(sql_type, length);
+ break;
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ length*= charset->mbmaxlen;
+ break;
+ default:
+ /* do nothing */
+ break;
}
}
+
+enum_field_types get_blob_type_from_length(ulong length)
+{
+ enum_field_types type;
+ if (length < 256)
+ type= FIELD_TYPE_TINY_BLOB;
+ else if (length < 65536)
+ type= FIELD_TYPE_BLOB;
+ else if (length < 256L*256L*256L)
+ type= FIELD_TYPE_MEDIUM_BLOB;
+ else
+ type= FIELD_TYPE_LONG_BLOB;
+ return type;
+}
+
+
/*
Make a field from the .frm file info
*/
@@ -5875,9 +6076,10 @@ void create_field::create_length_to_internal_length(void)
uint32 calc_pack_length(enum_field_types type,uint32 length)
{
switch (type) {
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_DECIMAL: return (length);
- case FIELD_TYPE_VAR_STRING: return (length+HA_KEY_BLOB_LENGTH);
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case FIELD_TYPE_DECIMAL: return (length);
+ case MYSQL_TYPE_VARCHAR: return (length+HA_KEY_BLOB_LENGTH);
case FIELD_TYPE_YEAR:
case FIELD_TYPE_TINY : return 1;
case FIELD_TYPE_SHORT : return 2;
@@ -5949,8 +6151,19 @@ Field *make_field(char *ptr, uint32 field_length,
if (f_is_alpha(pack_flag))
{
if (!f_is_packed(pack_flag))
- return new Field_string(ptr,field_length,null_pos,null_bit,
- unireg_check, field_name, table, field_charset);
+ {
+ if (field_type == MYSQL_TYPE_STRING ||
+ field_type == FIELD_TYPE_DECIMAL || // 3.23 or 4.0 string
+ field_type == MYSQL_TYPE_VAR_STRING)
+ return new Field_string(ptr,field_length,null_pos,null_bit,
+ unireg_check, field_name, table,
+ field_charset);
+ if (field_type == MYSQL_TYPE_VARCHAR)
+ return new Field_varstring(ptr,field_length,null_pos,null_bit,
+ unireg_check, field_name, table,
+ field_charset);
+ return 0; // Error
+ }
uint pack_length=calc_pack_length((enum_field_types)
f_packtype(pack_flag),
@@ -6061,42 +6274,51 @@ create_field::create_field(Field *old_field,Field *orig_field)
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();
charset= old_field->charset(); // May be NULL ptr
comment= old_field->comment;
+ decimals= old_field->decimals();
/* Fix if the original table had 4 byte pointer blobs */
if (flags & BLOB_FLAG)
pack_length= (pack_length- old_field->table->blob_ptr_size +
portable_sizeof_char_ptr);
- switch (sql_type)
- {
- case FIELD_TYPE_BLOB:
- switch (pack_length - portable_sizeof_char_ptr)
- {
- case 1: sql_type= FIELD_TYPE_TINY_BLOB; break;
- case 2: sql_type= FIELD_TYPE_BLOB; break;
- case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
- default: sql_type= FIELD_TYPE_LONG_BLOB; break;
- }
- length=(length+charset->mbmaxlen-1)/charset->mbmaxlen; // QQ: Probably not needed
- break;
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
- length=(length+charset->mbmaxlen-1)/charset->mbmaxlen;
- break;
- default:
- break;
- }
-
- decimals= old_field->decimals();
- if (sql_type == FIELD_TYPE_STRING)
- {
+ switch (sql_type) {
+ case FIELD_TYPE_BLOB:
+ switch (pack_length - portable_sizeof_char_ptr) {
+ case 1: sql_type= FIELD_TYPE_TINY_BLOB; break;
+ case 2: sql_type= FIELD_TYPE_BLOB; break;
+ case 3: sql_type= FIELD_TYPE_MEDIUM_BLOB; break;
+ default: sql_type= FIELD_TYPE_LONG_BLOB; break;
+ }
+ length=(length+charset->mbmaxlen-1) / charset->mbmaxlen;
+ key_length/= charset->mbmaxlen;
+ break;
+ case MYSQL_TYPE_STRING:
/* Change CHAR -> VARCHAR if dynamic record length */
- sql_type=old_field->type();
- decimals=0;
+ if (old_field->type() == MYSQL_TYPE_VAR_STRING)
+ sql_type= MYSQL_TYPE_VARCHAR;
+ /* fall through */
+
+ case MYSQL_TYPE_ENUM:
+ case MYSQL_TYPE_SET:
+ case MYSQL_TYPE_VARCHAR:
+ case MYSQL_TYPE_VAR_STRING:
+ /* These are corrected in create_length_to_internal_length */
+ length= (length+charset->mbmaxlen-1) / charset->mbmaxlen;
+ key_length/= charset->mbmaxlen;
+ break;
+#ifdef HAVE_SPATIAL
+ case FIELD_TYPE_GEOMETRY:
+ geom_type= ((Field_geom*)old_field)->geom_type;
+ break;
+#endif
+ default:
+ break;
}
+
if (flags & (ENUM_FLAG | SET_FLAG))
interval= ((Field_enum*) old_field)->typelib;
else
@@ -6121,12 +6343,6 @@ create_field::create_field(Field *old_field,Field *orig_field)
def= new Item_string(pos, tmp.length(), charset);
}
}
-#ifdef HAVE_SPATIAL
- if (sql_type == FIELD_TYPE_GEOMETRY)
- {
- geom_type= ((Field_geom*)old_field)->geom_type;
- }
-#endif
}
diff --git a/sql/field.h b/sql/field.h
index 50ea1450085..4353780f9a4 100644
--- a/sql/field.h
+++ b/sql/field.h
@@ -37,11 +37,7 @@ class Field
void operator=(Field &);
public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
- static void operator delete(void *ptr_arg, size_t size) {
-#ifdef SAFEMALLOC
- bfill(ptr_arg, size, 0x8F);
-#endif
- }
+ static void operator delete(void *ptr_arg, size_t size) { TRASH(ptr_arg, size); }
char *ptr; // Position to field in record
uchar *null_ptr; // Byte where null_bit is
@@ -188,27 +184,7 @@ public:
*/
virtual bool can_be_compared_as_longlong() const { return FALSE; }
virtual void free() {}
- Field *new_field(MEM_ROOT *root, struct st_table *new_table)
- {
- Field *tmp= (Field*) memdup_root(root,(char*) this,size_of());
- if (tmp)
- {
- if (tmp->table->maybe_null)
- tmp->flags&= ~NOT_NULL_FLAG;
- tmp->table= new_table;
- tmp->key_start.init(0);
- tmp->part_of_key.init(0);
- tmp->part_of_sortkey.init(0);
- tmp->unireg_check=Field::NONE;
- tmp->flags&= (NOT_NULL_FLAG | BLOB_FLAG | UNSIGNED_FLAG |
- ZEROFILL_FLAG | BINARY_FLAG | ENUM_FLAG | SET_FLAG);
-#ifdef PROBABLY_WRONG
- tmp->table_name= new_table->table_name;
-#endif
- tmp->reset_fields();
- }
- return tmp;
- }
+ virtual Field *new_field(MEM_ROOT *root, struct st_table *new_table);
inline void move_field(char *ptr_arg,uchar *null_ptr_arg,uchar null_bit_arg)
{
ptr=ptr_arg; null_ptr=null_ptr_arg; null_bit=null_bit_arg;
@@ -224,11 +200,10 @@ public:
{ memcpy(buff,ptr,length); }
inline void set_image(char *buff,uint length, CHARSET_INFO *cs)
{ memcpy(ptr,buff,length); }
- virtual void get_key_image(char *buff,uint length, CHARSET_INFO *cs,
- imagetype type)
- { get_image(buff,length,cs); }
- virtual void set_key_image(char *buff,uint length, CHARSET_INFO *cs)
- { set_image(buff,length,cs); }
+ virtual void get_key_image(char *buff, uint length, imagetype type)
+ { get_image(buff,length, &my_charset_bin); }
+ virtual void set_key_image(char *buff,uint length)
+ { set_image(buff,length, &my_charset_bin); }
inline longlong val_int_offset(uint row_offset)
{
ptr+=row_offset;
@@ -267,9 +242,11 @@ public:
virtual uint max_packed_col_length(uint max_length)
{ return max_length;}
- virtual int pack_cmp(const char *a,const char *b, uint key_length_arg)
+ virtual int pack_cmp(const char *a,const char *b, uint key_length_arg,
+ my_bool insert_or_update)
{ return cmp(a,b); }
- virtual int pack_cmp(const char *b, uint key_length_arg)
+ virtual int pack_cmp(const char *b, uint key_length_arg,
+ my_bool insert_or_update)
{ return cmp(ptr,b); }
uint offset(); // Should be inline ...
void copy_from_tmp(int offset);
@@ -911,9 +888,11 @@ public:
enum_field_types type() const
{
- return ((table && table->db_create_options & HA_OPTION_PACK_RECORD &&
- field_length >= 4) ?
- FIELD_TYPE_VAR_STRING : FIELD_TYPE_STRING);
+ return ((orig_table &&
+ orig_table->db_create_options & HA_OPTION_PACK_RECORD &&
+ field_length >= 4) &&
+ orig_table->frm_version < FRM_VER_TRUE_VARCHAR ?
+ MYSQL_TYPE_VAR_STRING : MYSQL_TYPE_STRING);
}
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT; }
@@ -930,8 +909,9 @@ public:
void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
const char *unpack(char* to, const char *from);
- int pack_cmp(const char *a,const char *b,uint key_length);
- int pack_cmp(const char *b,uint key_length);
+ int pack_cmp(const char *a,const char *b,uint key_length,
+ my_bool insert_or_update);
+ int pack_cmp(const char *b,uint key_length,my_bool insert_or_update);
uint packed_col_length(const char *to, uint length);
uint max_packed_col_length(uint max_length);
uint size_of() const { return sizeof(*this); }
@@ -939,6 +919,7 @@ public:
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
field_cast_enum field_cast_type() { return FIELD_CAST_STRING; }
+ Field *new_field(MEM_ROOT *root, struct st_table *new_table);
};
@@ -958,7 +939,7 @@ public:
NONE, field_name_arg, table_arg, cs)
{}
- enum_field_types type() const { return FIELD_TYPE_VAR_STRING; }
+ enum_field_types type() const { return MYSQL_TYPE_VARCHAR; }
enum ha_base_keytype key_type() const
{ return binary() ? HA_KEYTYPE_VARBINARY : HA_KEYTYPE_VARTEXT; }
bool zero_pack() const { return 0; }
@@ -973,18 +954,23 @@ public:
String *val_str(String*,String *);
int cmp(const char *,const char*);
void sort_string(char *buff,uint length);
- void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
- void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+ void get_key_image(char *buff,uint length, imagetype type);
+ void set_key_image(char *buff,uint length);
void sql_type(String &str) const;
char *pack(char *to, const char *from, uint max_length=~(uint) 0);
char *pack_key(char *to, const char *from, uint max_length);
const char *unpack(char* to, const char *from);
- int pack_cmp(const char *a, const char *b, uint key_length);
- int pack_cmp(const char *b, uint key_length);
+ int pack_cmp(const char *a, const char *b, uint key_length,
+ my_bool insert_or_update);
+ int pack_cmp(const char *b, uint key_length,my_bool insert_or_update);
+ int cmp_binary(const char *a,const char *b, uint32 max_length=~0L);
+ int cmp_binary_offset(uint row_offset);
+ int key_cmp(const byte *,const byte*);
+ int key_cmp(const byte *str, uint length);
uint packed_col_length(const char *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 FIELD_TYPE_VAR_STRING; }
+ enum_field_types real_type() const { return MYSQL_TYPE_VARCHAR; }
bool has_charset(void) const
{ return charset() == &my_charset_bin ? FALSE : TRUE; }
field_cast_enum field_cast_type() { return FIELD_CAST_VARSTRING; }
@@ -1053,8 +1039,8 @@ public:
store_length(length);
memcpy_fixed(ptr+packlength,&data,sizeof(char*));
}
- void get_key_image(char *buff,uint length, CHARSET_INFO *cs, imagetype type);
- void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+ void get_key_image(char *buff,uint length, imagetype type);
+ void set_key_image(char *buff,uint length);
void sql_type(String &str) const;
inline bool copy()
{ char *tmp;
@@ -1072,8 +1058,9 @@ public:
char *pack_key(char *to, const char *from, uint max_length);
char *pack_key_from_key_image(char* to, const char *from, uint max_length);
const char *unpack_key(char* to, const char *from, uint max_length);
- int pack_cmp(const char *a, const char *b, uint key_length);
- int pack_cmp(const char *b, uint key_length);
+ int pack_cmp(const char *a, const char *b, uint key_length,
+ my_bool insert_or_update);
+ int pack_cmp(const char *b, uint key_length,my_bool insert_or_update);
uint packed_col_length(const char *col_ptr, uint length);
uint max_packed_col_length(uint max_length);
void free() { value.free(); }
@@ -1086,6 +1073,7 @@ public:
uint32 max_length();
};
+
#ifdef HAVE_SPATIAL
class Field_geom :public Field_blob {
public:
@@ -1110,12 +1098,12 @@ public:
int store(double nr) { return 1; }
int store(longlong nr) { return 1; }
- void get_key_image(char *buff,uint length, CHARSET_INFO *cs,imagetype type);
- void set_key_image(char *buff,uint length, CHARSET_INFO *cs);
+ void get_key_image(char *buff,uint length,imagetype type);
field_cast_enum field_cast_type() { return FIELD_CAST_GEOM; }
};
#endif /*HAVE_SPATIAL*/
+
class Field_enum :public Field_str {
protected:
uint packlength;
@@ -1196,10 +1184,11 @@ public:
LEX_STRING comment; // Comment for field
Item *def; // Default value
enum enum_field_types sql_type;
- uint32 length;
- uint decimals,flags,pack_length;
+ ulong length;
+ uint decimals, flags, pack_length, key_length;
Field::utype unireg_check;
TYPELIB *interval; // Which interval to use
+ List<String> interval_list;
CHARSET_INFO *charset;
Field::geometry_type geom_type;
Field *field; // For alter table
@@ -1261,6 +1250,7 @@ Field *make_field(char *ptr, uint32 field_length,
TYPELIB *interval, const char *field_name,
struct st_table *table);
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);
diff --git a/sql/field_conv.cc b/sql/field_conv.cc
index 890687fc925..f6cc851639a 100644
--- a/sql/field_conv.cc
+++ b/sql/field_conv.cc
@@ -126,8 +126,7 @@ set_field_to_null(Field *field)
return 0;
}
if (!current_thd->no_errors)
- my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
- field->field_name);
+ my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
return -1;
}
@@ -185,8 +184,7 @@ set_field_to_null_with_conversions(Field *field, bool no_conversions)
return 0;
}
if (!current_thd->no_errors)
- my_printf_error(ER_BAD_NULL_ERROR,ER(ER_BAD_NULL_ERROR),MYF(0),
- field->field_name);
+ my_error(ER_BAD_NULL_ERROR, MYF(0), field->field_name);
return -1;
}
@@ -355,15 +353,16 @@ static void do_expand_string(Copy_field *copy)
static void do_varstring(Copy_field *copy)
{
uint length=uint2korr(copy->from_ptr);
- if (length > copy->to_length-2)
+ if (length > copy->to_length- HA_KEY_BLOB_LENGTH)
{
- length=copy->to_length-2;
+ length=copy->to_length-HA_KEY_BLOB_LENGTH;
if (current_thd->count_cuted_fields)
copy->to_field->set_warning(MYSQL_ERROR::WARN_LEVEL_WARN,
ER_WARN_DATA_TRUNCATED, 1);
}
int2store(copy->to_ptr,length);
- memcpy(copy->to_ptr+2, copy->from_ptr,length);
+ memcpy(copy->to_ptr+HA_KEY_BLOB_LENGTH, copy->from_ptr + HA_KEY_BLOB_LENGTH,
+ length);
}
/***************************************************************************
@@ -473,7 +472,7 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
{
if (to->flags & BLOB_FLAG)
{
- if (!(from->flags & BLOB_FLAG))
+ if (!(from->flags & BLOB_FLAG) || from->charset() != to->charset())
return do_conv_blob;
if (from_length != to_length ||
to->table->db_low_byte_first != from->table->db_low_byte_first)
@@ -506,7 +505,7 @@ void (*Copy_field::get_copy_func(Field *to,Field *from))(Copy_field*)
}
else if (to->charset() != from->charset())
return do_field_string;
- else if (to->real_type() == FIELD_TYPE_VAR_STRING && to_length !=
+ else if (to->real_type() == MYSQL_TYPE_VARCHAR && to_length !=
from_length)
return do_varstring;
else if (to_length < from_length)
@@ -573,7 +572,8 @@ void field_conv(Field *to,Field *from)
Field_blob *blob=(Field_blob*) to;
from->val_str(&blob->value);
if (!blob->value.is_alloced() &&
- from->real_type() != FIELD_TYPE_STRING)
+ from->real_type() != MYSQL_TYPE_STRING &&
+ from->real_type() != MYSQL_TYPE_VARCHAR)
blob->value.copy();
blob->store(blob->value.ptr(),blob->value.length(),from->charset());
return;
diff --git a/sql/filesort.cc b/sql/filesort.cc
index 3e56acefea9..569ae3da357 100644
--- a/sql/filesort.cc
+++ b/sql/filesort.cc
@@ -284,7 +284,8 @@ ha_rows filesort(THD *thd, TABLE *table, SORT_FIELD *sortorder, uint s_length,
}
}
if (error)
- my_error(ER_FILSORT_ABORT,MYF(ME_ERROR+ME_WAITTANG));
+ my_message(ER_FILSORT_ABORT, ER(ER_FILSORT_ABORT),
+ MYF(ME_ERROR+ME_WAITTANG));
else
statistic_add(thd->status_var.filesort_rows,
(ulong) records, &LOCK_status);
@@ -464,7 +465,7 @@ static ha_rows find_all_keys(SORTPARAM *param, SQL_SELECT *select,
error=file->rnd_next(sort_form->record[0]);
if (!flag)
{
- ha_store_ptr(ref_pos,ref_length,record); // Position to row
+ my_store_ptr(ref_pos,ref_length,record); // Position to row
record+=sort_form->db_record_offset;
}
else
@@ -707,7 +708,7 @@ static void make_sortkey(register SORTPARAM *param,
}
case REAL_RESULT:
{
- double value=item->val();
+ double value= item->val_real();
if ((maybe_null=item->null_value))
{
bzero((char*) to,sort_field->length+1);
diff --git a/sql/ha_berkeley.cc b/sql/ha_berkeley.cc
index a5d0023b875..6cb83624eff 100644
--- a/sql/ha_berkeley.cc
+++ b/sql/ha_berkeley.cc
@@ -234,13 +234,13 @@ int berkeley_show_logs(Protocol *protocol)
{
char **all_logs, **free_logs, **a, **f;
int error=1;
- MEM_ROOT show_logs_root;
- MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
+ MEM_ROOT **root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**,THR_MALLOC);
+ MEM_ROOT show_logs_root, *old_mem_root= *root_ptr;
DBUG_ENTER("berkeley_show_logs");
init_sql_alloc(&show_logs_root, BDB_LOG_ALLOC_BLOCK_SIZE,
BDB_LOG_ALLOC_BLOCK_SIZE);
- my_pthread_setspecific_ptr(THR_MALLOC,&show_logs_root);
+ *root_ptr= &show_logs_root;
if ((error= db_env->log_archive(db_env, &all_logs,
DB_ARCH_ABS | DB_ARCH_LOG)) ||
@@ -277,15 +277,17 @@ int berkeley_show_logs(Protocol *protocol)
}
err:
free_root(&show_logs_root,MYF(0));
- my_pthread_setspecific_ptr(THR_MALLOC,old_root);
+ *root_ptr= old_mem_root;
DBUG_RETURN(error);
}
+
static void berkeley_print_error(const char *db_errpfx, char *buffer)
{
sql_print_error("%s: %s",db_errpfx,buffer); /* purecov: tested */
}
+
static void berkeley_noticecall(DB_ENV *db_env, db_notices notice)
{
switch (notice)
@@ -392,6 +394,7 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key)
for (; key_part != end && (int) key_length > 0; key_part++)
{
int cmp;
+ uint length;
if (key_part->null_bit)
{
if (*new_key_ptr != *saved_key_ptr++)
@@ -400,11 +403,12 @@ berkeley_cmp_packed_key(DB *file, const DBT *new_key, const DBT *saved_key)
if (!*new_key_ptr++)
continue;
}
- if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,
- key_part->length)))
+ if ((cmp= key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,
+ key_part->length,
+ key->table->insert_or_update)))
return cmp;
- uint length=key_part->field->packed_col_length(new_key_ptr,
- key_part->length);
+ length= key_part->field->packed_col_length(new_key_ptr,
+ key_part->length);
new_key_ptr+=length;
key_length-=length;
saved_key_ptr+=key_part->field->packed_col_length(saved_key_ptr,
@@ -430,7 +434,7 @@ berkeley_cmp_fix_length_key(DB *file, const DBT *new_key, const DBT *saved_key)
for (; key_part != end && (int) key_length > 0 ; key_part++)
{
int cmp;
- if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,0)))
+ if ((cmp=key_part->field->pack_cmp(new_key_ptr,saved_key_ptr,0,0)))
return cmp;
new_key_ptr+=key_part->length;
key_length-= key_part->length;
@@ -440,6 +444,7 @@ berkeley_cmp_fix_length_key(DB *file, const DBT *new_key, const DBT *saved_key)
}
#endif
+
/* Compare key against row */
static bool
@@ -451,6 +456,7 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
for (; key_part != end && (int) key_length > 0; key_part++)
{
int cmp;
+ uint length;
if (key_part->null_bit)
{
key_length--;
@@ -464,15 +470,20 @@ berkeley_key_cmp(TABLE *table, KEY *key_info, const char *key, uint key_length)
if (!*key++) // Null value
continue;
}
- if ((cmp=key_part->field->pack_cmp(key,key_part->length)))
+ /*
+ Last argument has to be 0 as we are also using this to function to see
+ if a key like 'a ' matched a row with 'a'
+ */
+ if ((cmp= key_part->field->pack_cmp(key, key_part->length, 0)))
return cmp;
- uint length=key_part->field->packed_col_length(key,key_part->length);
- key+=length;
- key_length-=length;
+ length= key_part->field->packed_col_length(key,key_part->length);
+ key+= length;
+ key_length-= length;
}
return 0; // Identical keys
}
+
int ha_berkeley::open(const char *name, int mode, uint test_if_locked)
{
char name_buff[FN_REFLEN];
@@ -863,6 +874,7 @@ int ha_berkeley::write_row(byte * record)
if ((error=pack_row(&row, record,1)))
DBUG_RETURN(error); /* purecov: inspected */
+ table->insert_or_update= 1; // For handling of VARCHAR
if (table->keys + test(hidden_primary_key) == 1)
{
error=file->put(file, transaction, create_key(&prim_key, primary_key,
@@ -948,6 +960,7 @@ int ha_berkeley::write_row(byte * record)
break;
}
}
+ table->insert_or_update= 0;
if (error == DB_KEYEXIST)
error=HA_ERR_FOUND_DUPP_KEY;
else if (!error)
@@ -972,7 +985,7 @@ int ha_berkeley::key_cmp(uint keynr, const byte * old_row,
(new_row[key_part->null_offset] & key_part->null_bit))
return 1;
}
- if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
if (key_part->field->cmp_binary((char*) (old_row + key_part->offset),
@@ -1107,6 +1120,7 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
+ table->insert_or_update= 1; // For handling of VARCHAR
if (hidden_primary_key)
{
primary_key_changed=0;
@@ -1159,6 +1173,7 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
if (new_error)
error = new_error;
}
+ table->insert_or_update= 0;
DBUG_RETURN(error); // Fatal error /* purecov: inspected */
}
changed_keys.set_bit(keynr);
@@ -1191,8 +1206,9 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
thd_options);
if (new_error)
{
- error=new_error; // This shouldn't happen /* purecov: inspected */
- break; /* purecov: inspected */
+ /* This shouldn't happen */
+ error=new_error; /* purecov: inspected */
+ break; /* purecov: inspected */
}
}
}
@@ -1204,6 +1220,7 @@ int ha_berkeley::update_row(const byte * old_row, byte * new_row)
if (error != DB_LOCK_DEADLOCK)
break;
}
+ table->insert_or_update= 0;
if (error == DB_KEYEXIST)
error=HA_ERR_FOUND_DUPP_KEY;
DBUG_RETURN(error);
@@ -1474,7 +1491,8 @@ int ha_berkeley::index_read(byte * buf, const byte * key,
find_flag= HA_READ_AFTER_KEY;
do_prev= 1;
}
- if (key_len == key_info->key_length)
+ if (key_len == key_info->key_length &&
+ !table->key_info[active_index].flags & HA_END_SPACE_KEY)
{
if (find_flag == HA_READ_AFTER_KEY)
key_info->handler.bdb_return_if_eq= 1;
@@ -1571,7 +1589,8 @@ int ha_berkeley::index_next_same(byte * buf, const byte *key, uint keylen)
statistic_increment(table->in_use->status_var.ha_read_next_count,
&LOCK_status);
bzero((char*) &row,sizeof(row));
- if (keylen == table->key_info[active_index].key_length)
+ if (keylen == table->key_info[active_index].key_length &&
+ !table->key_info[active_index].flags & HA_END_SPACE_KEY)
error=read_row(cursor->c_get(cursor, &last_key, &row, DB_NEXT_DUP),
(char*) buf, active_index, &row, &last_key, 1);
else
@@ -1812,7 +1831,8 @@ int ha_berkeley::external_lock(THD *thd, int lock_type)
!thd->transaction.all.bdb_tid)
{
/* We have to start a master transaction */
- DBUG_PRINT("trans",("starting transaction all"));
+ DBUG_PRINT("trans",("starting transaction all: options: 0x%lx",
+ (ulong) thd->options));
if ((error=txn_begin(db_env, 0,
(DB_TXN**) &thd->transaction.all.bdb_tid,
0)))
@@ -2066,19 +2086,35 @@ ha_rows ha_berkeley::records_in_range(uint keynr, key_range *start_key,
DB_KEY_RANGE start_range, end_range;
DB *kfile=key_file[keynr];
double start_pos,end_pos,rows;
- DBUG_ENTER("records_in_range");
-
- if ((start_key && kfile->key_range(kfile,transaction,
- pack_key(&key, keynr, key_buff,
- start_key->key,
- start_key->length),
- &start_range,0)) ||
- (end_key && kfile->key_range(kfile,transaction,
- pack_key(&key, keynr, key_buff,
- end_key->key,
- end_key->length),
- &end_range,0)))
- DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); // Better than returning an error /* purecov: inspected */
+ bool error;
+ KEY *key_info= &table->key_info[keynr];
+ DBUG_ENTER("ha_berkeley::records_in_range");
+
+ /* Ensure we get maximum range, even for varchar keys with different space */
+ key_info->handler.bdb_return_if_eq= -1;
+ error= ((start_key && kfile->key_range(kfile,transaction,
+ pack_key(&key, keynr, key_buff,
+ start_key->key,
+ start_key->length),
+ &start_range,0)));
+ if (error)
+ {
+ key_info->handler.bdb_return_if_eq= 0;
+ // Better than returning an error
+ DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); /* purecov: inspected */
+ }
+ key_info->handler.bdb_return_if_eq= 1;
+ error= (end_key && kfile->key_range(kfile,transaction,
+ pack_key(&key, keynr, key_buff,
+ end_key->key,
+ end_key->length),
+ &end_range,0));
+ key_info->handler.bdb_return_if_eq= 0;
+ if (error)
+ {
+ // Better than returning an error
+ DBUG_RETURN(HA_BERKELEY_RANGE_COUNT); /* purecov: inspected */
+ }
if (!start_key)
start_pos= 0.0;
@@ -2561,6 +2597,7 @@ end:
DBUG_VOID_RETURN;
}
+
/*
Return an estimated of the number of rows in the table.
Used when sorting to allocate buffers and by the optimizer.
@@ -2586,11 +2623,11 @@ int ha_berkeley::cmp_ref(const byte *ref1, const byte *ref2)
{
field= key_part->field;
result= field->pack_cmp((const char*)ref1, (const char*)ref2,
- key_part->length);
+ key_part->length, 0);
if (result)
return result;
- ref1 += field->packed_col_length((const char*)ref1, key_part->length);
- ref2 += field->packed_col_length((const char*)ref2, key_part->length);
+ ref1+= field->packed_col_length((const char*)ref1, key_part->length);
+ ref2+= field->packed_col_length((const char*)ref2, key_part->length);
}
return 0;
diff --git a/sql/ha_heap.cc b/sql/ha_heap.cc
index 3bb8383e488..60555d51402 100644
--- a/sql/ha_heap.cc
+++ b/sql/ha_heap.cc
@@ -30,6 +30,18 @@
const char **ha_heap::bas_ext() const
{ static const char *ext[1]= { NullS }; return ext; }
+/*
+ Hash index statistics is updated (copied from HP_KEYDEF::hash_buckets to
+ rec_per_key) after 1/HEAP_STATS_UPDATE_THRESHOLD fraction of table records
+ have been inserted/updated/deleted. delete_all_rows() and table flush cause
+ immediate update.
+
+ NOTE
+ hash index statistics must be updated when number of table records changes
+ from 0 to non-zero value and vice versa. Otherwise records_in_range may
+ erroneously return 0 and 'range' may miss records.
+*/
+#define HEAP_STATS_UPDATE_THRESHOLD 10
int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
@@ -48,6 +60,8 @@ int ha_heap::open(const char *name, int mode, uint test_if_locked)
{
/* Initialize variables for the opened table */
set_keys_for_scanning();
+ if (table->tmp_table == NO_TMP_TABLE)
+ update_key_stats();
}
return (file ? 0 : 1);
}
@@ -84,35 +98,68 @@ void ha_heap::set_keys_for_scanning(void)
}
}
+
+void ha_heap::update_key_stats()
+{
+ for (uint i= 0; i < table->keys; i++)
+ {
+ KEY *key=table->key_info+i;
+ if (key->algorithm != HA_KEY_ALG_BTREE)
+ {
+ ha_rows hash_buckets= file->s->keydef[i].hash_buckets;
+ key->rec_per_key[key->key_parts-1]=
+ hash_buckets ? file->s->records/hash_buckets : 0;
+ }
+ }
+ records_changed= 0;
+}
+
+
int ha_heap::write_row(byte * buf)
{
- statistic_increment(current_thd->status_var.ha_write_count,&LOCK_status);
+ int res;
+ statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])
update_auto_increment();
- return heap_write(file,buf);
+ res= heap_write(file,buf);
+ if (!res && table->tmp_table == NO_TMP_TABLE &&
+ ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
+ update_key_stats();
+ return res;
}
int ha_heap::update_row(const byte * old_data, byte * new_data)
{
- statistic_increment(current_thd->status_var.ha_update_count,&LOCK_status);
+ int res;
+ statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
- return heap_update(file,old_data,new_data);
+ res= heap_update(file,old_data,new_data);
+ if (!res && table->tmp_table == NO_TMP_TABLE &&
+ ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
+ update_key_stats();
+ return res;
}
int ha_heap::delete_row(const byte * buf)
{
- statistic_increment(current_thd->status_var.ha_delete_count,&LOCK_status);
- return heap_delete(file,buf);
+ int res;
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
+ res= heap_delete(file,buf);
+ if (!res && table->tmp_table == NO_TMP_TABLE &&
+ ++records_changed*HEAP_STATS_UPDATE_THRESHOLD > file->s->records)
+ update_key_stats();
+ return res;
}
int ha_heap::index_read(byte * buf, const byte * key, uint key_len,
enum ha_rkey_function find_flag)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error = heap_rkey(file,buf,active_index, key, key_len, find_flag);
table->status = error ? STATUS_NOT_FOUND : 0;
return error;
@@ -121,7 +168,8 @@ int ha_heap::index_read(byte * buf, const byte * key, uint key_len,
int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error= heap_rkey(file, buf, active_index, key, key_len,
HA_READ_PREFIX_LAST);
table->status= error ? STATUS_NOT_FOUND : 0;
@@ -131,7 +179,8 @@ int ha_heap::index_read_last(byte *buf, const byte *key, uint key_len)
int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error = heap_rkey(file, buf, index, key, key_len, find_flag);
table->status = error ? STATUS_NOT_FOUND : 0;
return error;
@@ -140,7 +189,8 @@ int ha_heap::index_read_idx(byte * buf, uint index, const byte * key,
int ha_heap::index_next(byte * buf)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=heap_rnext(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -149,7 +199,8 @@ int ha_heap::index_next(byte * buf)
int ha_heap::index_prev(byte * buf)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_prev_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_prev_count,
+ &LOCK_status);
int error=heap_rprev(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -158,7 +209,7 @@ int ha_heap::index_prev(byte * buf)
int ha_heap::index_first(byte * buf)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_first_count,
+ statistic_increment(table->in_use->status_var.ha_read_first_count,
&LOCK_status);
int error=heap_rfirst(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -168,7 +219,8 @@ int ha_heap::index_first(byte * buf)
int ha_heap::index_last(byte * buf)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_last_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_last_count,
+ &LOCK_status);
int error=heap_rlast(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -181,7 +233,7 @@ int ha_heap::rnd_init(bool scan)
int ha_heap::rnd_next(byte *buf)
{
- statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
&LOCK_status);
int error=heap_scan(file, buf);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -192,7 +244,8 @@ int ha_heap::rnd_pos(byte * buf, byte *pos)
{
int error;
HEAP_PTR position;
- statistic_increment(current_thd->status_var.ha_read_rnd_count, &LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+ &LOCK_status);
memcpy_fixed((char*) &position,pos,sizeof(HEAP_PTR));
error=heap_rrnd(file, buf, position);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -229,6 +282,8 @@ int ha_heap::extra(enum ha_extra_function operation)
int ha_heap::delete_all_rows()
{
heap_clear(file);
+ if (table->tmp_table == NO_TMP_TABLE)
+ update_key_stats();
return 0;
}
@@ -386,7 +441,7 @@ ha_rows ha_heap::records_in_range(uint inx, key_range *min_key,
min_key->flag != HA_READ_KEY_EXACT ||
max_key->flag != HA_READ_AFTER_KEY)
return HA_POS_ERROR; // Can only use exact keys
- return 10; // Good guess
+ return key->rec_per_key[key->key_parts-1];
}
@@ -427,16 +482,20 @@ int ha_heap::create(const char *name, TABLE *table_arg,
{
uint flag= key_part->key_type;
Field *field= key_part->field;
+
if (pos->algorithm == HA_KEY_ALG_BTREE)
seg->type= field->key_type();
else
{
- if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT)
+ if ((seg->type = field->key_type()) != (int) HA_KEYTYPE_TEXT &&
+ seg->type != HA_KEYTYPE_VARTEXT &&
+ seg->type != HA_KEYTYPE_VARBINARY)
seg->type= HA_KEYTYPE_BINARY;
}
seg->start= (uint) key_part->offset;
seg->length= (uint) key_part->length;
- seg->flag = 0;
+ seg->flag= key_part->key_part_flag;
+
seg->charset= field->charset();
if (field->null_ptr)
{
@@ -456,7 +515,7 @@ int ha_heap::create(const char *name, TABLE *table_arg,
}
}
mem_per_row+= MY_ALIGN(table_arg->reclength + 1, sizeof(char*));
- max_rows = (ha_rows) (current_thd->variables.max_heap_table_size /
+ max_rows = (ha_rows) (table->in_use->variables.max_heap_table_size /
mem_per_row);
HP_CREATE_INFO hp_create_info;
hp_create_info.auto_key= auto_key;
diff --git a/sql/ha_heap.h b/sql/ha_heap.h
index e469a676b65..8b44695df07 100644
--- a/sql/ha_heap.h
+++ b/sql/ha_heap.h
@@ -27,9 +27,10 @@ class ha_heap: public handler
{
HP_INFO *file;
key_map btree_keys;
-
- public:
- ha_heap(TABLE *table): handler(table), file(0) {}
+ /* number of records changed since last statistics update */
+ uint records_changed;
+public:
+ ha_heap(TABLE *table): handler(table), file(0), records_changed(0) {}
~ha_heap() {}
const char *table_type() const { return "HEAP"; }
const char *index_type(uint inx)
@@ -97,4 +98,6 @@ class ha_heap: public handler
HEAP_PTR ptr2=*(HEAP_PTR*)ref2;
return ptr1 < ptr2? -1 : (ptr1 > ptr2? 1 : 0);
}
+private:
+ void update_key_stats();
};
diff --git a/sql/ha_innodb.cc b/sql/ha_innodb.cc
index efd74a543c2..0c7fc23ee49 100644
--- a/sql/ha_innodb.cc
+++ b/sql/ha_innodb.cc
@@ -80,6 +80,7 @@ extern "C" {
#include "../innobase/include/fsp0fsp.h"
#include "../innobase/include/sync0sync.h"
#include "../innobase/include/fil0fil.h"
+#include "../innobase/include/trx0xa.h"
}
#define HA_INNOBASE_ROWS_IN_TABLE 10000 /* to get optimization right */
@@ -149,6 +150,93 @@ static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
static INNOBASE_SHARE *get_share(const char *table_name);
static void free_share(INNOBASE_SHARE *share);
+/*********************************************************************
+Commits a transaction in an InnoDB database. */
+
+void
+innobase_commit_low(
+/*================*/
+ trx_t* trx); /* in: transaction handle */
+
+struct show_var_st innodb_status_variables[]= {
+ {"buffer_pool_pages_data",
+ (char*) &export_vars.innodb_buffer_pool_pages_data, SHOW_LONG},
+ {"buffer_pool_pages_dirty",
+ (char*) &export_vars.innodb_buffer_pool_pages_dirty, SHOW_LONG},
+ {"buffer_pool_pages_flushed",
+ (char*) &export_vars.innodb_buffer_pool_pages_flushed, SHOW_LONG},
+ {"buffer_pool_pages_free",
+ (char*) &export_vars.innodb_buffer_pool_pages_free, SHOW_LONG},
+ {"buffer_pool_pages_latched",
+ (char*) &export_vars.innodb_buffer_pool_pages_latched, SHOW_LONG},
+ {"buffer_pool_pages_misc",
+ (char*) &export_vars.innodb_buffer_pool_pages_misc, SHOW_LONG},
+ {"buffer_pool_pages_total",
+ (char*) &export_vars.innodb_buffer_pool_pages_total, SHOW_LONG},
+ {"buffer_pool_read_ahead_rnd",
+ (char*) &export_vars.innodb_buffer_pool_read_ahead_rnd, SHOW_LONG},
+ {"buffer_pool_read_ahead_seq",
+ (char*) &export_vars.innodb_buffer_pool_read_ahead_seq, SHOW_LONG},
+ {"buffer_pool_read_requests",
+ (char*) &export_vars.innodb_buffer_pool_read_requests, SHOW_LONG},
+ {"buffer_pool_reads",
+ (char*) &export_vars.innodb_buffer_pool_reads, SHOW_LONG},
+ {"buffer_pool_wait_free",
+ (char*) &export_vars.innodb_buffer_pool_wait_free, SHOW_LONG},
+ {"buffer_pool_write_requests",
+ (char*) &export_vars.innodb_buffer_pool_write_requests, SHOW_LONG},
+ {"data_fsyncs",
+ (char*) &export_vars.innodb_data_fsyncs, SHOW_LONG},
+ {"data_pending_fsyncs",
+ (char*) &export_vars.innodb_data_pending_fsyncs, SHOW_LONG},
+ {"data_pending_reads",
+ (char*) &export_vars.innodb_data_pending_reads, SHOW_LONG},
+ {"data_pending_writes",
+ (char*) &export_vars.innodb_data_pending_writes, SHOW_LONG},
+ {"data_read",
+ (char*) &export_vars.innodb_data_read, SHOW_LONG},
+ {"data_reads",
+ (char*) &export_vars.innodb_data_reads, SHOW_LONG},
+ {"data_writes",
+ (char*) &export_vars.innodb_data_writes, SHOW_LONG},
+ {"data_written",
+ (char*) &export_vars.innodb_data_written, SHOW_LONG},
+ {"dblwr_pages_written",
+ (char*) &export_vars.innodb_dblwr_pages_written, SHOW_LONG},
+ {"dblwr_writes",
+ (char*) &export_vars.innodb_dblwr_writes, SHOW_LONG},
+ {"log_waits",
+ (char*) &export_vars.innodb_log_waits, SHOW_LONG},
+ {"log_write_requests",
+ (char*) &export_vars.innodb_log_write_requests, SHOW_LONG},
+ {"log_writes",
+ (char*) &export_vars.innodb_log_writes, SHOW_LONG},
+ {"os_log_fsyncs",
+ (char*) &export_vars.innodb_os_log_fsyncs, SHOW_LONG},
+ {"os_log_pending_fsyncs",
+ (char*) &export_vars.innodb_os_log_pending_fsyncs, SHOW_LONG},
+ {"os_log_pending_writes",
+ (char*) &export_vars.innodb_os_log_pending_writes, SHOW_LONG},
+ {"os_log_written",
+ (char*) &export_vars.innodb_os_log_written, SHOW_LONG},
+ {"page_size",
+ (char*) &export_vars.innodb_page_size, SHOW_LONG},
+ {"pages_created",
+ (char*) &export_vars.innodb_pages_created, SHOW_LONG},
+ {"pages_read",
+ (char*) &export_vars.innodb_pages_read, SHOW_LONG},
+ {"pages_written",
+ (char*) &export_vars.innodb_pages_written, SHOW_LONG},
+ {"rows_deleted",
+ (char*) &export_vars.innodb_rows_deleted, SHOW_LONG},
+ {"rows_inserted",
+ (char*) &export_vars.innodb_rows_inserted, SHOW_LONG},
+ {"rows_read",
+ (char*) &export_vars.innodb_rows_read, SHOW_LONG},
+ {"rows_updated",
+ (char*) &export_vars.innodb_rows_updated, SHOW_LONG},
+ {NullS, NullS, SHOW_LONG}};
+
/* General functions */
/**********************************************************************
@@ -331,6 +419,9 @@ convert_error_code_to_mysql(
} else if (error == (int) DB_NO_SAVEPOINT) {
return(HA_ERR_NO_SAVEPOINT);
+ } else if (error == (int) DB_LOCK_TABLE_FULL) {
+
+ return(HA_ERR_LOCK_TABLE_FULL);
} else {
return(-1); // Unknown error
}
@@ -430,6 +521,25 @@ innobase_mysql_print_thd(
}
/**********************************************************************
+Determines whether the given character set is of variable length.
+
+NOTE that the exact prototype of this function has to be in
+/innobase/data/data0type.ic! */
+extern "C"
+ibool
+innobase_is_mb_cset(
+/*================*/
+ ulint cset) /* in: MySQL charset-collation code */
+{
+ CHARSET_INFO* cs;
+ ut_ad(cset < 256);
+
+ cs = all_charsets[cset];
+
+ return(cs && cs->mbminlen != cs->mbmaxlen);
+}
+
+/**********************************************************************
Compares NUL-terminated UTF-8 strings case insensitively.
NOTE that the exact prototype of this function has to be in
@@ -495,9 +605,10 @@ innobase_mysql_tmpfile(void)
if (fd2 < 0) {
DBUG_PRINT("error",("Got error %d on dup",fd2));
my_errno=errno;
- my_error(EE_OUT_OF_FILERESOURCES,
- MYF(ME_BELL+ME_WAITTANG), filename, my_errno);
- }
+ my_error(EE_OUT_OF_FILERESOURCES,
+ MYF(ME_BELL+ME_WAITTANG),
+ filename, my_errno);
+ }
my_close(fd, MYF(MY_WME));
}
return(fd2);
@@ -1253,7 +1364,7 @@ innobase_commit(
if (trx_handle != (void*)&innodb_dummy_stmt_trx_handle
|| (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
- /* We were instructed to commit the whole transaction, or
+ /* We were instructed to commit the whole transaction, or
this is an SQL statement end and autocommit is on */
innobase_commit_low(trx);
@@ -1395,6 +1506,39 @@ innobase_rollback(
}
/*********************************************************************
+Rolls back a transaction */
+
+int
+innobase_rollback_trx(
+/*==================*/
+ /* out: 0 or error number */
+ trx_t* trx) /* in: transaction */
+{
+ int error = 0;
+
+ DBUG_ENTER("innobase_rollback_trx");
+ DBUG_PRINT("trans", ("aborting transaction"));
+
+ /* Release a possible FIFO ticket and search latch. Since we will
+ reserve the kernel mutex, we have to release the search system latch
+ first to obey the latching order. */
+
+ innobase_release_stat_resources(trx);
+
+ if (trx->auto_inc_lock) {
+ /* If we had reserved the auto-inc lock for some table (if
+ we come here to roll back the latest SQL statement) we
+ release it now before a possibly lengthy rollback */
+
+ row_unlock_table_autoinc_for_mysql(trx);
+ }
+
+ error = trx_rollback_for_mysql(trx);
+
+ DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
+}
+
+/*********************************************************************
Rolls back a transaction to a savepoint. */
int
@@ -1507,17 +1651,14 @@ innobase_close_connection(
*****************************************************************************/
/********************************************************************
-This function is not relevant since we store the tables and indexes
-into our own tablespace, not as files, whose extension this function would
-give. */
+Gives the file extension of an InnoDB single-table tablespace. */
const char**
ha_innobase::bas_ext() const
/*========================*/
- /* out: file extension strings, currently not
- used */
+ /* out: file extension string */
{
- static const char* ext[] = {".InnoDB", NullS};
+ static const char* ext[] = {".ibd", NullS};
return(ext);
}
@@ -1868,12 +2009,13 @@ innobase_mysql_cmp(
switch (mysql_tp) {
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_BLOB:
case FIELD_TYPE_LONG_BLOB:
+ case MYSQL_TYPE_VARCHAR:
/* Use the charset number to pick the right charset struct for
the comparison. Since the MySQL function get_charset may be
slow before Bar removes the mutex operation there, we first
@@ -1901,7 +2043,7 @@ innobase_mysql_cmp(
ret = charset->coll->strnncollsp(charset,
a, a_length,
- b, b_length);
+ b, b_length, 0);
if (ret < 0) {
return(-1);
} else if (ret > 0) {
@@ -1930,17 +2072,11 @@ get_innobase_type_from_mysql_type(
8 bits: this is used in ibuf and also when DATA_NOT_NULL is ORed to
the type */
- DBUG_ASSERT((ulint)FIELD_TYPE_STRING < 256);
- DBUG_ASSERT((ulint)FIELD_TYPE_VAR_STRING < 256);
- DBUG_ASSERT((ulint)FIELD_TYPE_DOUBLE < 256);
- DBUG_ASSERT((ulint)FIELD_TYPE_FLOAT < 256);
- DBUG_ASSERT((ulint)FIELD_TYPE_DECIMAL < 256);
-
switch (field->type()) {
/* NOTE that we only allow string types in DATA_MYSQL
and DATA_VARMYSQL */
- case FIELD_TYPE_VAR_STRING: if (field->binary()) {
-
+ case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_VARCHAR: if (field->binary()) {
return(DATA_BINARY);
} else if (strcmp(
field->charset()->name,
@@ -1949,7 +2085,7 @@ get_innobase_type_from_mysql_type(
} else {
return(DATA_VARMYSQL);
}
- case FIELD_TYPE_STRING: if (field->binary()) {
+ case MYSQL_TYPE_STRING: if (field->binary()) {
return(DATA_FIXBINARY);
} else if (strcmp(
@@ -2128,7 +2264,13 @@ build_template(
ulint n_fields;
ulint n_requested_fields = 0;
ibool fetch_all_in_key = FALSE;
- ibool fetch_primary_key_cols = FALSE;
+ ibool fetch_primary_key_cols = TRUE; /* The ROR code in
+ opt_range.cc assumes that the
+ primary key cols are always
+ retrieved. Starting from
+ MySQL-5.0.2, let us always
+ fetch them, even though it
+ wastes some CPU. */
ulint i;
if (prebuilt->select_lock_type == LOCK_X) {
@@ -2318,6 +2460,72 @@ ha_innobase::write_row(
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
+ if (user_thd->lex->sql_command == SQLCOM_ALTER_TABLE
+ && num_write_row >= 10000) {
+ /* ALTER TABLE is COMMITted at every 10000 copied rows.
+ The IX table lock for the original table has to be re-issued.
+ As this method will be called on a temporary table where the
+ contents of the original table is being copied to, it is
+ a bit tricky to determine the source table. The cursor
+ position in the source table need not be adjusted after the
+ intermediate COMMIT, since writes by other transactions are
+ being blocked by a MySQL table lock TL_WRITE_ALLOW_READ. */
+
+ dict_table_t* src_table;
+ ibool mode;
+
+ num_write_row = 0;
+
+ /* Commit the transaction. This will release the table
+ locks, so they have to be acquired again. */
+
+ /* Altering an InnoDB table */
+ /* Get the source table. */
+ src_table = lock_get_src_table(
+ prebuilt->trx, prebuilt->table, &mode);
+ if (!src_table) {
+ no_commit:
+ /* Unknown situation: do not commit */
+ /*
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+ " InnoDB error: ALTER TABLE is holding lock"
+ " on %lu tables!\n",
+ prebuilt->trx->mysql_n_tables_locked);
+ */
+ ;
+ } else if (src_table == prebuilt->table) {
+ /* Source table is not in InnoDB format:
+ no need to re-acquire locks on it. */
+
+ /* Altering to InnoDB format */
+ innobase_commit(user_thd, prebuilt->trx);
+ /* Note that this transaction is still active. */
+ user_thd->transaction.all.innodb_active_trans = 1;
+ /* We will need an IX lock on the destination table. */
+ prebuilt->sql_stat_start = TRUE;
+ } else {
+ /* Ensure that there are no other table locks than
+ LOCK_IX and LOCK_AUTO_INC on the destination table. */
+ if (!lock_is_table_exclusive(prebuilt->table,
+ prebuilt->trx)) {
+ goto no_commit;
+ }
+
+ /* Commit the transaction. This will release the table
+ locks, so they have to be acquired again. */
+ innobase_commit(user_thd, prebuilt->trx);
+ /* Note that this transaction is still active. */
+ user_thd->transaction.all.innodb_active_trans = 1;
+ /* Re-acquire the table lock on the source table. */
+ row_lock_table_for_mysql(prebuilt, src_table, mode);
+ /* We will need an IX lock on the destination table. */
+ prebuilt->sql_stat_start = TRUE;
+ }
+ }
+
+ num_write_row++;
+
if (last_query_id != user_thd->query_id) {
prebuilt->sql_stat_start = TRUE;
last_query_id = user_thd->query_id;
@@ -2435,12 +2643,12 @@ innobase_convert_and_store_changed_col(
if (len == UNIV_SQL_NULL) {
data = NULL;
- } else if (col_type == DATA_VARCHAR || col_type == DATA_BINARY
- || col_type == DATA_VARMYSQL) {
- /* Remove trailing spaces */
- while (len > 0 && data[len - 1] == ' ') {
- len--;
- }
+ } else if (col_type == DATA_VARCHAR || col_type == DATA_BINARY
+ || col_type == DATA_VARMYSQL) {
+ /* Remove trailing spaces */
+ while (len > 0 && data[len - 1] == ' ') {
+ len--;
+ }
} else if (col_type == DATA_INT) {
/* Store integer data in InnoDB in a big-endian
format, sign bit negated, if signed */
@@ -2690,6 +2898,32 @@ ha_innobase::delete_row(
DBUG_RETURN(error);
}
+/**************************************************************************
+Deletes a lock set to a row */
+
+void
+ha_innobase::unlock_row(void)
+/*=========================*/
+{
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
+
+ DBUG_ENTER("ha_innobase::unlock_row");
+
+ ut_ad(prebuilt->trx ==
+ (trx_t*) current_thd->transaction.all.innobase_tid);
+
+ if (last_query_id != user_thd->query_id) {
+ ut_print_timestamp(stderr);
+ fprintf(stderr,
+" InnoDB: Error: last_query_id is %lu != user_thd_query_id is %lu\n",
+ (ulong)last_query_id, (ulong)user_thd->query_id);
+ mem_analyze_corruption((byte *) prebuilt->trx);
+ ut_error;
+ }
+
+ row_unlock_for_mysql(prebuilt);
+}
+
/**********************************************************************
Initializes a handle to use an index. */
@@ -3356,7 +3590,7 @@ create_table_def(
TABLE* form, /* in: information on table
columns and indexes */
const char* table_name, /* in: table name */
- const char* path_of_temp_table)/* in: if this is a table explicitly
+ const char* path_of_temp_table,/* in: if this is a table explicitly
created by the user with the
TEMPORARY keyword, then this
parameter is the dir path where the
@@ -3364,6 +3598,7 @@ create_table_def(
an .ibd file for it (no .ibd extension
in the path, though); otherwise this
is NULL */
+ ibool comp) /* in: TRUE=compact record format */
{
Field* field;
dict_table_t* table;
@@ -3384,7 +3619,7 @@ create_table_def(
/* We pass 0 as the space id, and determine at a lower level the space
id where to store the table */
- table = dict_mem_table_create((char*) table_name, 0, n_cols);
+ table = dict_mem_table_create(table_name, 0, n_cols, comp);
if (path_of_temp_table) {
table->dir_path_of_temp_table =
@@ -3648,12 +3883,9 @@ ha_innobase::create(
/* Create the table definition in InnoDB */
- if (create_info->options & HA_LEX_CREATE_TMP_TABLE) {
-
- error = create_table_def(trx, form, norm_name, name2);
- } else {
- error = create_table_def(trx, form, norm_name, NULL);
- }
+ error = create_table_def(trx, form, norm_name,
+ create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
+ !(form->db_options_in_use & HA_OPTION_PACK_RECORD));
if (error) {
innobase_commit_low(trx);
@@ -4620,6 +4852,104 @@ ha_innobase::get_foreign_key_create_info(void)
return(str);
}
+
+int
+ha_innobase::get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
+{
+ dict_foreign_t* foreign;
+
+ DBUG_ENTER("get_foreign_key_list");
+ row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
+ ut_a(prebuilt != NULL);
+ update_thd(current_thd);
+ prebuilt->trx->op_info = (char*)"getting list of foreign keys";
+ trx_search_latch_release_if_reserved(prebuilt->trx);
+ mutex_enter_noninline(&(dict_sys->mutex));
+ foreign = UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
+
+ while (foreign != NULL)
+ {
+ uint i;
+ FOREIGN_KEY_INFO f_key_info;
+ LEX_STRING *name= 0;
+ const char *tmp_buff;
+
+ tmp_buff= foreign->id;
+ i= 0;
+ while (tmp_buff[i] != '/')
+ i++;
+ tmp_buff+= i + 1;
+ f_key_info.forein_id= make_lex_string(thd, f_key_info.forein_id,
+ tmp_buff, strlen(tmp_buff), 1);
+ tmp_buff= foreign->referenced_table_name;
+ i= 0;
+ while (tmp_buff[i] != '/')
+ i++;
+ f_key_info.referenced_db= make_lex_string(thd, f_key_info.referenced_db,
+ tmp_buff, i, 1);
+ tmp_buff+= i + 1;
+ f_key_info.referenced_table= make_lex_string(thd,
+ f_key_info.referenced_table,
+ tmp_buff, strlen(tmp_buff), 1);
+
+ for (i= 0;;)
+ {
+ tmp_buff= foreign->foreign_col_names[i];
+ name= make_lex_string(thd, name, tmp_buff, strlen(tmp_buff), 1);
+ f_key_info.foreign_fields.push_back(name);
+ tmp_buff= foreign->referenced_col_names[i];
+ name= make_lex_string(thd, name, tmp_buff, strlen(tmp_buff), 1);
+ f_key_info.referenced_fields.push_back(name);
+ if (++i >= foreign->n_fields)
+ break;
+ }
+
+ ulong length= 0;
+ if (foreign->type == DICT_FOREIGN_ON_DELETE_CASCADE)
+ {
+ length=17;
+ tmp_buff= "ON DELETE CASCADE";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_DELETE_SET_NULL)
+ {
+ length=18;
+ tmp_buff= "ON DELETE SET NULL";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_DELETE_NO_ACTION)
+ {
+ length=19;
+ tmp_buff= "ON DELETE NO ACTION";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_UPDATE_CASCADE)
+ {
+ length=17;
+ tmp_buff= "ON UPDATE CASCADE";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_UPDATE_SET_NULL)
+ {
+ length=18;
+ tmp_buff= "ON UPDATE SET NULL";
+ }
+ else if (foreign->type == DICT_FOREIGN_ON_UPDATE_NO_ACTION)
+ {
+ length=19;
+ tmp_buff= "ON UPDATE NO ACTION";
+ }
+ f_key_info.constraint_method= make_lex_string(thd,
+ f_key_info.constraint_method,
+ tmp_buff, length, 1);
+
+ FOREIGN_KEY_INFO *pf_key_info= ((FOREIGN_KEY_INFO *)
+ thd->memdup((gptr) &f_key_info,
+ sizeof(FOREIGN_KEY_INFO)));
+ f_key_list->push_back(pf_key_info);
+ foreign = UT_LIST_GET_NEXT(foreign_list, foreign);
+ }
+ mutex_exit_noninline(&(dict_sys->mutex));
+ prebuilt->trx->op_info = (char*)"";
+ DBUG_RETURN(0);
+}
+
/***********************************************************************
Checks if a table is referenced by a foreign key. The MySQL manual states that
a REPLACE is either equivalent to an INSERT, or DELETE(s) + INSERT. Only a
@@ -4913,7 +5243,8 @@ ha_innobase::external_lock(
if (thd->in_lock_tables &&
thd->variables.innodb_table_locks) {
ulint error;
- error = row_lock_table_for_mysql(prebuilt);
+ error = row_lock_table_for_mysql(prebuilt,
+ NULL, LOCK_TABLE_EXP);
if (error != DB_SUCCESS) {
error = convert_error_code_to_mysql(
@@ -4971,10 +5302,21 @@ ha_innobase::external_lock(
}
/****************************************************************************
+Here we export InnoDB status variables to MySQL. */
+
+void
+innodb_export_status(void)
+/*======================*/
+{
+ srv_export_innodb_status();
+}
+
+
+/****************************************************************************
Implements the SHOW INNODB STATUS command. Sends the output of the InnoDB
Monitor to the client. */
-int
+bool
innodb_show_status(
/*===============*/
THD* thd) /* in: the MySQL query thread of the caller */
@@ -4988,7 +5330,7 @@ innodb_show_status(
my_message(ER_NOT_SUPPORTED_YET,
"Cannot call SHOW INNODB STATUS because skip-innodb is defined",
MYF(0));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
trx = check_trx_exists(thd);
@@ -5017,7 +5359,7 @@ innodb_show_status(
if (!(str = my_malloc(flen + 1, MYF(0))))
{
mutex_exit_noninline(&srv_monitor_file_mutex);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
rewind(srv_monitor_file);
@@ -5034,7 +5376,7 @@ innodb_show_status(
my_free(str, MYF(0));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
protocol->prepare_for_resend();
@@ -5042,10 +5384,10 @@ innodb_show_status(
my_free(str, MYF(0));
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
/****************************************************************************
@@ -5513,4 +5855,158 @@ innobase_query_is_replace(void)
}
}
+/***********************************************************************
+This function is used to prepare X/Open XA distributed transaction */
+
+int innobase_xa_prepare(
+/*====================*/
+ /* out: 0 or error number */
+ THD* thd, /* in: handle to the MySQL thread of the user
+ whose XA transaction should be prepared */
+ bool all) /* in: TRUE - commit transaction
+ FALSE - the current SQL statement ended */
+{
+ int error = 0;
+ trx_t* trx;
+
+ trx = check_trx_exists(thd);
+
+ /* TODO: Get X/Open XA Transaction Identification from MySQL*/
+ memset(&trx->xid, 0, sizeof(trx->xid));
+ trx->xid.formatID = -1;
+
+ /* Release a possible FIFO ticket and search latch. Since we will
+ reserve the kernel mutex, we have to release the search system latch
+ first to obey the latching order. */
+
+ innobase_release_stat_resources(trx);
+
+ if (trx->active_trans == 0 && trx->conc_state != TRX_NOT_STARTED) {
+
+ fprintf(stderr,
+"InnoDB: Error: thd->transaction.all.innodb_active_trans == 0\n"
+"InnoDB: but trx->conc_state != TRX_NOT_STARTED\n");
+ }
+
+ if (all || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
+
+ /* We were instructed to prepare the whole transaction, or
+ this is an SQL statement end and autocommit is on */
+
+ error = trx_prepare_for_mysql(trx);
+ } else {
+ /* We just mark the SQL statement ended and do not do a
+ transaction prepare */
+
+ if (trx->auto_inc_lock) {
+ /* If we had reserved the auto-inc lock for some
+ table in this SQL statement we release it now */
+
+ row_unlock_table_autoinc_for_mysql(trx);
+ }
+ /* Store the current undo_no of the transaction so that we
+ know where to roll back if we have to roll back the next
+ SQL statement */
+
+ trx_mark_sql_stat_end(trx);
+ }
+
+ /* Tell the InnoDB server that there might be work for utility
+ threads: */
+
+ srv_active_wake_master_thread();
+
+ return error;
+}
+
+/***********************************************************************
+This function is used to recover X/Open XA distributed transactions */
+
+int innobase_xa_recover(
+ /* out: number of prepared transactions
+ stored in xid_list */
+ XID* xid_list, /* in/out: prepared transactions */
+ uint len) /* in: number of slots in xid_list */
+/*====================*/
+{
+ if (len == 0 || xid_list == NULL) {
+ return 0;
+ }
+
+ return (trx_recover_for_mysql(xid_list, len));
+}
+
+/***********************************************************************
+This function is used to commit one X/Open XA distributed transaction
+which is in the prepared state */
+
+int innobase_commit_by_xid(
+/*=======================*/
+ /* out: 0 or error number */
+ XID* xid) /* in: X/Open XA Transaction Identification */
+{
+ trx_t* trx;
+
+ trx = trx_get_trx_by_xid(xid);
+
+ if (trx) {
+ innobase_commit_low(trx);
+
+ return(XA_OK);
+ } else {
+ return(XAER_NOTA);
+ }
+}
+
+/***********************************************************************
+This function is used to rollback one X/Open XA distributed transaction
+which is in the prepared state */
+
+int innobase_rollback_by_xid(
+ /* out: 0 or error number */
+ XID *xid) /* in : X/Open XA Transaction Idenfification */
+{
+ trx_t* trx;
+
+ trx = trx_get_trx_by_xid(xid);
+
+ if (trx) {
+ return(innobase_rollback_trx(trx));
+ } else {
+ return(XAER_NOTA);
+ }
+}
+
+/***********************************************************************
+This function is used to test commit/rollback of XA transactions */
+
+int innobase_xa_end(
+/*================*/
+ THD* thd) /* in: MySQL thread handle of the user for whom
+ transactions should be recovered */
+{
+ DBUG_ENTER("innobase_xa_end");
+
+ XID trx_list[100];
+ int trx_num, trx_num_max = 100;
+ int i;
+ XID xid;
+
+ while((trx_num = innobase_xa_recover(trx_list, trx_num_max))) {
+
+ for(i=0;i < trx_num; i++) {
+ xid = trx_list[i];
+
+ if ( i % 2) {
+ innobase_commit_by_xid(&xid);
+ } else {
+ innobase_rollback_by_xid(&xid);
+ }
+ }
+ }
+
+ free(trx_list);
+
+ DBUG_RETURN(0);
+}
#endif /* HAVE_INNOBASE_DB */
diff --git a/sql/ha_innodb.h b/sql/ha_innodb.h
index 57e136a8fba..b3b8d1a29e8 100644
--- a/sql/ha_innodb.h
+++ b/sql/ha_innodb.h
@@ -64,6 +64,7 @@ class ha_innobase: public handler
uint last_match_mode;/* match mode of the latest search:
ROW_SEL_EXACT, ROW_SEL_EXACT_PREFIX,
or undefined */
+ uint num_write_row; /* number of write_row() calls */
longlong auto_inc_counter_for_this_stat;
ulong max_supported_row_length(const byte *buf);
@@ -83,9 +84,11 @@ class ha_innobase: public handler
HA_CAN_SQL_HANDLER |
HA_NOT_EXACT_COUNT |
HA_PRIMARY_KEY_IN_READ_INDEX |
+ HA_NO_VARCHAR |
HA_TABLE_SCAN_ON_INDEX),
last_dup_key((uint) -1),
- start_of_scan(0)
+ start_of_scan(0),
+ num_write_row(0)
{
}
~ha_innobase() {}
@@ -120,6 +123,7 @@ class ha_innobase: public handler
int write_row(byte * buf);
int update_row(const byte * old_data, byte * new_data);
int delete_row(const byte * buf);
+ void unlock_row();
int index_init(uint index);
int index_end();
@@ -159,6 +163,7 @@ class ha_innobase: public handler
int check(THD* thd, HA_CHECK_OPT* check_opt);
char* update_table_comment(const char* comment);
char* get_foreign_key_create_info();
+ int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list);
uint referenced_by_foreign_key();
void free_foreign_key_create_info(char* str);
THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
@@ -172,6 +177,7 @@ class ha_innobase: public handler
int cmp_ref(const byte *ref1, const byte *ref2);
};
+extern struct show_var_st innodb_status_variables[];
extern uint innobase_init_flags, innobase_lock_type;
extern uint innobase_flush_log_at_trx_commit;
extern ulong innobase_cache_size;
@@ -230,7 +236,8 @@ int innobase_savepoint(
my_off_t binlog_cache_pos);
int innobase_close_connection(THD *thd);
int innobase_drop_database(char *path);
-int innodb_show_status(THD* thd);
+bool innodb_show_status(THD* thd);
+void innodb_export_status(void);
my_bool innobase_query_caching_of_table_permitted(THD* thd, char* full_name,
uint full_name_len);
@@ -239,3 +246,46 @@ void innobase_release_temporary_latches(void* innobase_tid);
void innobase_store_binlog_offset_and_flush_log(char *binlog_name,longlong offset);
int innobase_start_trx_and_assign_read_view(THD* thd);
+
+/***********************************************************************
+This function is used to prepare X/Open XA distributed transaction */
+
+int innobase_xa_prepare(
+/*====================*/
+ /* out: 0 or error number */
+ THD* thd, /* in: handle to the MySQL thread of the user
+ whose XA transaction should be prepared */
+ bool all); /* in: TRUE - commit transaction
+ FALSE - the current SQL statement ended */
+
+/***********************************************************************
+This function is used to recover X/Open XA distributed transactions */
+
+int innobase_xa_recover(
+/*====================*/
+ /* out: number of prepared transactions
+ stored in xid_list */
+ XID* xid_list, /* in/out: prepared transactions */
+ uint len); /* in: number of slots in xid_list */
+
+/***********************************************************************
+This function is used to commit one X/Open XA distributed transaction
+which is in the prepared state */
+
+int innobase_commit_by_xid(
+/*=======================*/
+ /* out: 0 or error number */
+ XID* xid); /* in : X/Open XA Transaction Identification */
+
+/***********************************************************************
+This function is used to rollback one X/Open XA distributed transaction
+which is in the prepared state */
+
+int innobase_rollback_by_xid(
+ /* out: 0 or error number */
+ XID *xid); /* in : X/Open XA Transaction Idenfification */
+
+
+int innobase_xa_end(THD *thd);
+
+
diff --git a/sql/ha_isam.cc b/sql/ha_isam.cc
deleted file mode 100644
index d703df7d2e3..00000000000
--- a/sql/ha_isam.cc
+++ /dev/null
@@ -1,408 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-
-#include "mysql_priv.h"
-#ifdef HAVE_ISAM
-#include <m_ctype.h>
-#include <myisampack.h>
-#include "ha_isam.h"
-#ifndef MASTER
-#include "../srclib/isam/isamdef.h"
-#else
-#include "../isam/isamdef.h"
-#endif
-
-/*****************************************************************************
-** isam tables
-*****************************************************************************/
-
-
-const char **ha_isam::bas_ext() const
-{ static const char *ext[]= { ".ISM",".ISD", NullS }; return ext; }
-
-int ha_isam::open(const char *name, int mode, uint test_if_locked)
-{
- char name_buff[FN_REFLEN];
- if (!(file=nisam_open(fn_format(name_buff,name,"","",2 | 4), mode,
- test_if_locked)))
- return (my_errno ? my_errno : -1);
-
- if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
- test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
- (void) nisam_extra(file,HA_EXTRA_NO_WAIT_LOCK);
- info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
- if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
- (void) nisam_extra(file,HA_EXTRA_WAIT_LOCK);
- if (!table->db_record_offset)
- int_table_flags|=HA_REC_NOT_IN_SEQ;
- return (0);
-}
-
-int ha_isam::close(void)
-{
- return !nisam_close(file) ? 0 : my_errno ? my_errno : -1;
-}
-
-uint ha_isam::min_record_length(uint options) const
-{
- return (options & HA_OPTION_PACK_RECORD) ? 1 : 5;
-}
-
-
-int ha_isam::write_row(byte * buf)
-{
- statistic_increment(current_thd->status_var.ha_write_count, &LOCK_status);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
- table->timestamp_field->set_time();
- if (table->next_number_field && buf == table->record[0])
- update_auto_increment();
- return !nisam_write(file,buf) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::update_row(const byte * old_data, byte * new_data)
-{
- statistic_increment(current_thd->status_var.ha_update_count, &LOCK_status);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
- return !nisam_update(file,old_data,new_data) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::delete_row(const byte * buf)
-{
- statistic_increment(current_thd->status_var.ha_delete_count, &LOCK_status);
- return !nisam_delete(file,buf) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
- int error=nisam_rkey(file, buf, active_index, key, key_len, find_flag);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
- int error=nisam_rkey(file, buf, index, key, key_len, find_flag);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::index_read_last(byte * buf, const byte * key, uint key_len)
-{
- statistic_increment(current_thd->status_var.ha_read_key_count, &LOCK_status);
- int error=nisam_rkey(file, buf, active_index, key, key_len,
- HA_READ_PREFIX_LAST);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::index_next(byte * buf)
-{
- statistic_increment(current_thd->status_var.ha_read_next_count,
- &LOCK_status);
- int error=nisam_rnext(file,buf,active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
-}
-
-int ha_isam::index_prev(byte * buf)
-{
- statistic_increment(current_thd->status_var.ha_read_prev_count,
- &LOCK_status);
- int error=nisam_rprev(file,buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
-}
-
-int ha_isam::index_first(byte * buf)
-{
- statistic_increment(current_thd->status_var.ha_read_first_count,
- &LOCK_status);
- int error=nisam_rfirst(file, buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
-}
-
-int ha_isam::index_last(byte * buf)
-{
- statistic_increment(current_thd->status_var.ha_read_last_count,
- &LOCK_status);
- int error=nisam_rlast(file, buf, active_index);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : HA_ERR_END_OF_FILE;
-}
-
-int ha_isam::rnd_init(bool scan)
-{
- return nisam_extra(file,HA_EXTRA_RESET) ? 0 : my_errno ? my_errno : -1;;
-}
-
-int ha_isam::rnd_next(byte *buf)
-{
- statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
- &LOCK_status);
- int error=nisam_rrnd(file, buf, NI_POS_ERROR);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isam::rnd_pos(byte * buf, byte *pos)
-{
- statistic_increment(current_thd->status_var.ha_read_rnd_count,
- &LOCK_status);
- int error=nisam_rrnd(file, buf, (ulong) ha_get_ptr(pos,ref_length));
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-void ha_isam::position(const byte *record)
-{
- my_off_t position=nisam_position(file);
- if (position == (my_off_t) ~ (ulong) 0)
- position=HA_OFFSET_ERROR;
- ha_store_ptr(ref, ref_length, position);
-}
-
-void ha_isam::info(uint flag)
-{
- N_ISAMINFO info;
- (void) nisam_info(file,&info,flag);
- if (flag & HA_STATUS_VARIABLE)
- {
- records = info.records;
- deleted = info.deleted;
- data_file_length=info.data_file_length;
- index_file_length=info.index_file_length;
- delete_length = info.delete_length;
- check_time = info.isamchk_time;
- mean_rec_length=info.mean_reclength;
- }
- if (flag & HA_STATUS_CONST)
- {
- max_data_file_length=info.max_data_file_length;
- max_index_file_length=info.max_index_file_length;
- create_time = info.create_time;
- sortkey = info.sortkey;
- block_size=nisam_block_size;
- table->keys = min(table->keys,info.keys);
- table->keys_in_use.set_prefix(table->keys);
- table->db_options_in_use= info.options;
- table->db_record_offset=
- (table->db_options_in_use &
- (HA_OPTION_PACK_RECORD | HA_OPTION_COMPRESS_RECORD)) ? 0 :
- table->reclength;
- if (!table->tmp_table)
- {
- ulong *rec_per_key=info.rec_per_key;
- for (uint i=0 ; i < table->keys ; i++)
- {
- table->key_info[i].rec_per_key[table->key_info[i].key_parts-1]=
- *(rec_per_key++);
- }
- }
- ref_length=4;
- }
- if (flag & HA_STATUS_ERRKEY)
- {
- errkey = info.errkey;
- ha_store_ptr(dupp_ref, ref_length, info.dupp_key_pos);
- }
- if (flag & HA_STATUS_TIME)
- update_time = info.update_time;
-}
-
-
-int ha_isam::extra(enum ha_extra_function operation)
-{
- if ((specialflag & SPECIAL_SAFE_MODE || test_flags & TEST_NO_EXTRA) &&
- (operation == HA_EXTRA_WRITE_CACHE ||
- operation == HA_EXTRA_KEYREAD))
- return 0;
- return nisam_extra(file,operation);
-}
-
-int ha_isam::external_lock(THD *thd, int lock_type)
-{
- if (!table->tmp_table)
- return nisam_lock_database(file,lock_type);
- return 0;
-}
-
-
-THR_LOCK_DATA **ha_isam::store_lock(THD *thd,
- THR_LOCK_DATA **to,
- enum thr_lock_type lock_type)
-{
- if (lock_type != TL_IGNORE && file->lock.type == TL_UNLOCK)
- file->lock.type=lock_type;
- *to++= &file->lock;
- return to;
-}
-
-
-int ha_isam::create(const char *name, register TABLE *form,
- HA_CREATE_INFO *create_info)
-
-{
- uint options=form->db_options_in_use;
- int error;
- uint i,j,recpos,minpos,fieldpos,temp_length,length;
- enum ha_base_keytype type;
- char buff[FN_REFLEN];
- KEY *pos;
- N_KEYDEF keydef[MAX_KEY];
- N_RECINFO *recinfo,*recinfo_pos;
- DBUG_ENTER("ha_isam::create");
-
- type=HA_KEYTYPE_BINARY; // Keep compiler happy
- if (!(recinfo= (N_RECINFO*) my_malloc((form->fields*2+2)*sizeof(N_RECINFO),
- MYF(MY_WME))))
- DBUG_RETURN(HA_ERR_OUT_OF_MEM);
-
- pos=form->key_info;
- for (i=0; i < form->keys ; i++, pos++)
- {
- keydef[i].base.flag= (pos->flags & HA_NOSAME);
- for (j=0 ; (int7) j < pos->key_parts ; j++)
- {
- keydef[i].seg[j].base.flag=pos->key_part[j].key_part_flag;
- Field *field=pos->key_part[j].field;
- type=field->key_type();
-
- if ((options & HA_OPTION_PACK_KEYS ||
- (pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
- HA_SPACE_PACK_USED))) &&
- pos->key_part[j].length > 8 &&
- (type == HA_KEYTYPE_TEXT ||
- type == HA_KEYTYPE_NUM ||
- (type == HA_KEYTYPE_BINARY && !field->zero_pack())))
- {
- if (j == 0)
- keydef[i].base.flag|=HA_PACK_KEY;
- if (!(field->flags & ZEROFILL_FLAG) &&
- (field->type() == FIELD_TYPE_STRING ||
- field->type() == FIELD_TYPE_VAR_STRING ||
- ((int) (pos->key_part[j].length - field->decimals()))
- >= 4))
- keydef[i].seg[j].base.flag|=HA_SPACE_PACK;
- }
- keydef[i].seg[j].base.type=(int) type;
- keydef[i].seg[j].base.start= pos->key_part[j].offset;
- keydef[i].seg[j].base.length= pos->key_part[j].length;
- }
- keydef[i].seg[j].base.type=(int) HA_KEYTYPE_END; /* End of key-parts */
- }
-
- recpos=0; recinfo_pos=recinfo;
- while (recpos < (uint) form->reclength)
- {
- Field **field,*found=0;
- minpos=form->reclength; length=0;
-
- for (field=form->field ; *field ; field++)
- {
- if ((fieldpos=(*field)->offset()) >= recpos &&
- fieldpos <= minpos)
- {
- /* skip null fields */
- if (!(temp_length= (*field)->pack_length()))
- continue; /* Skip null-fields */
- if (! found || fieldpos < minpos ||
- (fieldpos == minpos && temp_length < length))
- {
- minpos=fieldpos; found= *field; length=temp_length;
- }
- }
- }
- DBUG_PRINT("loop",("found: 0x%lx recpos: %d minpos: %d length: %d",
- found,recpos,minpos,length));
- if (recpos != minpos)
- { // Reserved space (Null bits?)
- recinfo_pos->base.type=(int) FIELD_NORMAL;
- recinfo_pos++->base.length= (uint16) (minpos-recpos);
- }
- if (! found)
- break;
-
- if (found->flags & BLOB_FLAG)
- {
- /* ISAM can only handle blob pointers of sizeof(char(*)) */
- recinfo_pos->base.type= (int) FIELD_BLOB;
- if (options & HA_OPTION_LONG_BLOB_PTR)
- length= length-portable_sizeof_char_ptr+sizeof(char*);
- }
- else if (!(options & HA_OPTION_PACK_RECORD))
- recinfo_pos->base.type= (int) FIELD_NORMAL;
- else if (found->zero_pack())
- recinfo_pos->base.type= (int) FIELD_SKIP_ZERO;
- else
- recinfo_pos->base.type= (int) ((length <= 3 ||
- (found->flags & ZEROFILL_FLAG)) ?
- FIELD_NORMAL :
- found->type() == FIELD_TYPE_STRING ||
- found->type() == FIELD_TYPE_VAR_STRING ?
- FIELD_SKIP_ENDSPACE :
- FIELD_SKIP_PRESPACE);
- recinfo_pos++ ->base.length=(uint16) length;
- recpos=minpos+length;
- DBUG_PRINT("loop",("length: %d type: %d",
- recinfo_pos[-1].base.length,recinfo_pos[-1].base.type));
-
- if ((found->flags & BLOB_FLAG) && (options & HA_OPTION_LONG_BLOB_PTR) &&
- sizeof(char*) != portable_sizeof_char_ptr)
- { // Not used space
- recinfo_pos->base.type=(int) FIELD_ZERO;
- recinfo_pos++->base.length=
- (uint16) (portable_sizeof_char_ptr-sizeof(char*));
- recpos+= (portable_sizeof_char_ptr-sizeof(char*));
- }
- }
- recinfo_pos->base.type= (int) FIELD_LAST; /* End of fieldinfo */
- error=nisam_create(fn_format(buff,name,"","",2+4+16),form->keys,keydef,
- recinfo,(ulong) form->max_rows, (ulong) form->min_rows,
- 0, 0, 0L);
- my_free((gptr) recinfo,MYF(0));
- DBUG_RETURN(error);
-
-}
-
-static key_range no_range= { (byte*) 0, 0, HA_READ_KEY_EXACT };
-
-ha_rows ha_isam::records_in_range(uint inx, key_range *min_key,
- key_range *max_key)
-{
- /* ISAM checks if 'key' pointer <> 0 to know if there is no range */
- if (!min_key)
- min_key= &no_range;
- if (!max_key)
- max_key= &no_range;
- return (ha_rows) nisam_records_in_range(file,
- (int) inx,
- min_key->key, min_key->length,
- min_key->flag,
- max_key->key, max_key->length,
- max_key->flag);
-}
-#endif /* HAVE_ISAM */
diff --git a/sql/ha_isam.h b/sql/ha_isam.h
deleted file mode 100644
index b3e932696cb..00000000000
--- a/sql/ha_isam.h
+++ /dev/null
@@ -1,79 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-/* class for the the myisam handler */
-
-#include <nisam.h>
-
-class ha_isam: public handler
-{
- N_INFO *file;
- /* We need this as table_flags() may change after open() */
- ulong int_table_flags;
-
- public:
- ha_isam(TABLE *table)
- :handler(table), file(0),
- int_table_flags(HA_READ_RND_SAME |
- HA_DUPP_POS | HA_NOT_DELETE_WITH_CACHE | HA_FILE_BASED)
- {}
- ~ha_isam() {}
- ulong index_flags(uint idx, uint part, bool all_parts) const
- { return HA_READ_NEXT; } // but no HA_READ_PREV here!!!
- const char *table_type() const { return "ISAM"; }
- const char *index_type(uint key_number) { return "BTREE"; }
- const char **bas_ext() const;
- ulong table_flags() const { return int_table_flags; }
- uint max_supported_record_length() const { return HA_MAX_REC_LENGTH; }
- uint max_supported_keys() const { return N_MAXKEY; }
- uint max_supported_key_parts() const { return N_MAXKEY_SEG; }
- uint max_supported_key_length() const { return N_MAX_KEY_LENGTH; }
- uint min_record_length(uint options) const;
- bool low_byte_first() const { return 0; }
-
- 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 delete_row(const byte * buf);
- int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_idx(byte * buf, uint idx, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_last(byte * buf, const byte * key, uint key_len);
- int index_next(byte * buf);
- int index_prev(byte * buf);
- int index_first(byte * buf);
- int index_last(byte * buf);
- int rnd_init(bool scan);
- int rnd_next(byte *buf);
- int rnd_pos(byte * buf, byte *pos);
- void position(const byte *record);
- void info(uint);
- int extra(enum ha_extra_function operation);
- int external_lock(THD *thd, int lock_type);
- ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
-
- int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
- THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
- enum thr_lock_type lock_type);
-};
-
diff --git a/sql/ha_isammrg.cc b/sql/ha_isammrg.cc
deleted file mode 100644
index 5a070087724..00000000000
--- a/sql/ha_isammrg.cc
+++ /dev/null
@@ -1,210 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#ifdef __GNUC__
-#pragma implementation // gcc: Class implementation
-#endif
-
-#include "mysql_priv.h"
-#ifdef HAVE_ISAM
-#include <m_ctype.h>
-#ifndef MASTER
-#include "../srclib/merge/mrg_def.h"
-#else
-#include "../merge/mrg_def.h"
-#endif
-#include "ha_isammrg.h"
-
-/*****************************************************************************
-** ISAM MERGE tables
-*****************************************************************************/
-
-const char **ha_isammrg::bas_ext() const
-{ static const char *ext[]= { ".MRG", NullS }; return ext; }
-
-int ha_isammrg::open(const char *name, int mode, uint test_if_locked)
-{
- char name_buff[FN_REFLEN];
- if (!(file=mrg_open(fn_format(name_buff,name,"","",2 | 4), mode,
- test_if_locked)))
- return (my_errno ? my_errno : -1);
-
- if (!(test_if_locked == HA_OPEN_WAIT_IF_LOCKED ||
- test_if_locked == HA_OPEN_ABORT_IF_LOCKED))
- mrg_extra(file,HA_EXTRA_NO_WAIT_LOCK);
- info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
- if (!(test_if_locked & HA_OPEN_WAIT_IF_LOCKED))
- mrg_extra(file,HA_EXTRA_WAIT_LOCK);
- if (table->reclength != mean_rec_length)
- {
- DBUG_PRINT("error",("reclength: %d mean_rec_length: %d",
- table->reclength, mean_rec_length));
- mrg_close(file);
- file=0;
- return ER_WRONG_MRG_TABLE;
- }
- return (0);
-}
-
-int ha_isammrg::close(void)
-{
- return !mrg_close(file) ? 0 : my_errno ? my_errno : -1;
-}
-
-uint ha_isammrg::min_record_length(uint options) const
-{
- return (options & HA_OPTION_PACK_RECORD) ? 1 : 5;
-}
-
-int ha_isammrg::write_row(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::update_row(const byte * old_data, byte * new_data)
-{
- statistic_increment(current_thd->status_var.ha_update_count, &LOCK_status);
- if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
- table->timestamp_field->set_time();
- return !mrg_update(file,old_data,new_data) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::delete_row(const byte * buf)
-{
- statistic_increment(current_thd->status_var.ha_delete_count, &LOCK_status);
- return !mrg_delete(file,buf) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_read_idx(byte * buf, uint index, const byte * key,
- uint key_len, enum ha_rkey_function find_flag)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_next(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_prev(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_first(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::index_last(byte * buf)
-{
- return (my_errno=HA_ERR_WRONG_COMMAND);
-}
-
-int ha_isammrg::rnd_init(bool scan)
-{
- return !mrg_extra(file,HA_EXTRA_RESET) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::rnd_next(byte *buf)
-{
- statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
- &LOCK_status);
- int error=mrg_rrnd(file, buf, ~(mrg_off_t) 0);
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::rnd_pos(byte * buf, byte *pos)
-{
- statistic_increment(current_thd->status_var.ha_read_rnd_count, &LOCK_status);
- int error=mrg_rrnd(file, buf, (ulong) ha_get_ptr(pos,ref_length));
- table->status=error ? STATUS_NOT_FOUND: 0;
- return !error ? 0 : my_errno ? my_errno : -1;
-}
-
-void ha_isammrg::position(const byte *record)
-{
- ulong position= mrg_position(file);
- ha_store_ptr(ref, ref_length, (my_off_t) position);
-}
-
-
-void ha_isammrg::info(uint flag)
-{
- MERGE_INFO info;
- (void) mrg_info(file,&info,flag);
- records = (ha_rows) info.records;
- deleted = (ha_rows) info.deleted;
- data_file_length=info.data_file_length;
- errkey = info.errkey;
- table->keys_in_use.clear_all(); // No keys yet
- table->db_options_in_use = info.options;
- mean_rec_length=info.reclength;
- block_size=0;
- update_time=0;
- ref_length=4; // Should be big enough
-}
-
-
-int ha_isammrg::extra(enum ha_extra_function operation)
-{
- return !mrg_extra(file,operation) ? 0 : my_errno ? my_errno : -1;
-}
-
-int ha_isammrg::external_lock(THD *thd, int lock_type)
-{
- return !mrg_lock_database(file,lock_type) ? 0 : my_errno ? my_errno : -1;
-}
-
-uint ha_isammrg::lock_count(void) const
-{
- return file->tables;
-}
-
-THR_LOCK_DATA **ha_isammrg::store_lock(THD *thd,
- THR_LOCK_DATA **to,
- enum thr_lock_type lock_type)
-{
- MRG_TABLE *open_table;
-
- for (open_table=file->open_tables ;
- open_table != file->end_table ;
- open_table++)
- {
- *(to++)= &open_table->table->lock;
- if (lock_type != TL_IGNORE && open_table->table->lock.type == TL_UNLOCK)
- open_table->table->lock.type=lock_type;
- }
- return to;
-}
-
-
-int ha_isammrg::create(const char *name, register TABLE *form,
- HA_CREATE_INFO *create_info)
-
-{
- char buff[FN_REFLEN];
- return mrg_create(fn_format(buff,name,"","",2+4+16),0);
-}
-#endif /* HAVE_ISAM */
diff --git a/sql/ha_isammrg.h b/sql/ha_isammrg.h
deleted file mode 100644
index 657e5060272..00000000000
--- a/sql/ha_isammrg.h
+++ /dev/null
@@ -1,69 +0,0 @@
-/* Copyright (C) 2000 MySQL AB & MySQL Finland AB & TCX DataKonsult AB
-
- 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; either version 2 of the License, or
- (at your option) any later version.
-
- 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */
-
-
-#ifdef __GNUC__
-#pragma interface /* gcc class implementation */
-#endif
-
-/* class for the the myisam merge handler */
-
-#include <merge.h>
-
-class ha_isammrg: public handler
-{
- MRG_INFO *file;
-
- public:
- ha_isammrg(TABLE *table): handler(table), file(0) {}
- ~ha_isammrg() {}
- const char *table_type() const { return "MRG_ISAM"; }
- const char **bas_ext() const;
- ulong table_flags() const { return (HA_READ_RND_SAME |
- HA_REC_NOT_IN_SEQ | HA_FILE_BASED); }
- ulong index_flags(uint idx, uint part, bool all_parts) const
- { DBUG_ASSERT(0); return 0; }
-
- uint max_supported_keys() const { return 0; }
- bool low_byte_first() const { return 0; }
- uint min_record_length(uint options) const;
-
- 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 delete_row(const byte * buf);
- int index_read(byte * buf, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_read_idx(byte * buf, uint indx, const byte * key,
- uint key_len, enum ha_rkey_function find_flag);
- int index_next(byte * buf);
- int index_prev(byte * buf);
- int index_first(byte * buf);
- int index_last(byte * buf);
- int rnd_init(bool scan);
- int rnd_next(byte *buf);
- int rnd_pos(byte * buf, byte *pos);
- void position(const byte *record);
- void info(uint);
- int extra(enum ha_extra_function operation);
- int external_lock(THD *thd, int lock_type);
- uint lock_count(void) const;
- int create(const char *name, TABLE *form, HA_CREATE_INFO *create_info);
- THR_LOCK_DATA **store_lock(THD *thd, THR_LOCK_DATA **to,
- enum thr_lock_type lock_type);
- uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
-};
diff --git a/sql/ha_myisam.cc b/sql/ha_myisam.cc
index 7482c6d5fa8..726647cd131 100644
--- a/sql/ha_myisam.cc
+++ b/sql/ha_myisam.cc
@@ -249,7 +249,7 @@ int ha_myisam::close(void)
int ha_myisam::write_row(byte * buf)
{
- statistic_increment(current_thd->status_var.ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
/* If we have a timestamp column, update it to the current time */
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
@@ -602,7 +602,7 @@ int ha_myisam::repair(THD *thd, MI_CHECK &param, bool optimize)
local_testflag|= T_STATISTICS;
param.testflag|= T_STATISTICS; // We get this for free
statistics_done=1;
- if (current_thd->variables.myisam_repair_threads>1)
+ if (thd->variables.myisam_repair_threads>1)
{
char buf[40];
/* TODO: respect myisam_repair_threads variable */
@@ -1084,7 +1084,7 @@ bool ha_myisam::is_crashed() const
int ha_myisam::update_row(const byte * old_data, byte * new_data)
{
- statistic_increment(current_thd->status_var.ha_update_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
return mi_update(file,old_data,new_data);
@@ -1092,7 +1092,7 @@ int ha_myisam::update_row(const byte * old_data, byte * new_data)
int ha_myisam::delete_row(const byte * buf)
{
- statistic_increment(current_thd->status_var.ha_delete_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
return mi_delete(file,buf);
}
@@ -1100,7 +1100,8 @@ int ha_myisam::index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=mi_rkey(file,buf,active_index, key, key_len, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1109,7 +1110,8 @@ int ha_myisam::index_read(byte * buf, const byte * key,
int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(current_thd->status_var.ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=mi_rkey(file,buf,index, key, key_len, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1118,7 +1120,8 @@ int ha_myisam::index_read_idx(byte * buf, uint index, const byte * key,
int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=mi_rkey(file,buf,active_index, key, key_len, HA_READ_PREFIX_LAST);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1127,7 +1130,8 @@ int ha_myisam::index_read_last(byte * buf, const byte * key, uint key_len)
int ha_myisam::index_next(byte * buf)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=mi_rnext(file,buf,active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1136,7 +1140,8 @@ int ha_myisam::index_next(byte * buf)
int ha_myisam::index_prev(byte * buf)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_prev_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_prev_count,
+ &LOCK_status);
int error=mi_rprev(file,buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1145,7 +1150,7 @@ int ha_myisam::index_prev(byte * buf)
int ha_myisam::index_first(byte * buf)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_first_count,
+ statistic_increment(table->in_use->status_var.ha_read_first_count,
&LOCK_status);
int error=mi_rfirst(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -1155,7 +1160,8 @@ int ha_myisam::index_first(byte * buf)
int ha_myisam::index_last(byte * buf)
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_last_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_last_count,
+ &LOCK_status);
int error=mi_rlast(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1166,7 +1172,8 @@ int ha_myisam::index_next_same(byte * buf,
uint length __attribute__((unused)))
{
DBUG_ASSERT(inited==INDEX);
- statistic_increment(current_thd->status_var.ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=mi_rnext_same(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -1182,7 +1189,7 @@ int ha_myisam::rnd_init(bool scan)
int ha_myisam::rnd_next(byte *buf)
{
- statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
&LOCK_status);
int error=mi_scan(file, buf);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -1196,8 +1203,9 @@ int ha_myisam::restart_rnd_next(byte *buf, byte *pos)
int ha_myisam::rnd_pos(byte * buf, byte *pos)
{
- statistic_increment(current_thd->status_var.ha_read_rnd_count,&LOCK_status);
- int error=mi_rrnd(file, buf, ha_get_ptr(pos,ref_length));
+ statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+ &LOCK_status);
+ int error=mi_rrnd(file, buf, my_get_ptr(pos,ref_length));
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
@@ -1205,7 +1213,7 @@ int ha_myisam::rnd_pos(byte * buf, byte *pos)
void ha_myisam::position(const byte* record)
{
my_off_t position=mi_position(file);
- ha_store_ptr(ref, ref_length, position);
+ my_store_ptr(ref, ref_length, position);
}
void ha_myisam::info(uint flag)
@@ -1261,7 +1269,7 @@ void ha_myisam::info(uint flag)
if (flag & HA_STATUS_ERRKEY)
{
errkey = info.errkey;
- ha_store_ptr(dupp_ref, ref_length, info.dupp_key_pos);
+ my_store_ptr(dupp_ref, ref_length, info.dupp_key_pos);
}
if (flag & HA_STATUS_TIME)
update_time = info.update_time;
@@ -1369,9 +1377,9 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
keydef[i].keysegs=pos->key_parts;
for (j=0 ; j < pos->key_parts ; j++)
{
- keydef[i].seg[j].flag=pos->key_part[j].key_part_flag;
Field *field=pos->key_part[j].field;
type=field->key_type();
+ keydef[i].seg[j].flag=pos->key_part[j].key_part_flag;
if (options & HA_OPTION_PACK_KEYS ||
(pos->flags & (HA_PACK_KEY | HA_BINARY_PACK_KEY |
@@ -1386,8 +1394,8 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
if (j == 0)
keydef[i].flag|=HA_PACK_KEY;
if (!(field->flags & ZEROFILL_FLAG) &&
- (field->type() == FIELD_TYPE_STRING ||
- field->type() == FIELD_TYPE_VAR_STRING ||
+ (field->type() == MYSQL_TYPE_STRING ||
+ field->type() == MYSQL_TYPE_VAR_STRING ||
((int) (pos->key_part[j].length - field->decimals()))
>= 4))
keydef[i].seg[j].flag|=HA_SPACE_PACK;
@@ -1466,30 +1474,31 @@ int ha_myisam::create(const char *name, register TABLE *table_arg,
{
recinfo_pos->type= (int) FIELD_BLOB;
}
- else if (!(options & HA_OPTION_PACK_RECORD))
+ else if (!(options & HA_OPTION_PACK_RECORD) ||
+ found->type() == MYSQL_TYPE_VARCHAR)
recinfo_pos->type= (int) FIELD_NORMAL;
else if (found->zero_pack())
recinfo_pos->type= (int) FIELD_SKIP_ZERO;
else
recinfo_pos->type= (int) ((length <= 3 ||
- (found->flags & ZEROFILL_FLAG)) ?
- FIELD_NORMAL :
- found->type() == FIELD_TYPE_STRING ||
- found->type() == FIELD_TYPE_VAR_STRING ?
- FIELD_SKIP_ENDSPACE :
- FIELD_SKIP_PRESPACE);
+ (found->flags & ZEROFILL_FLAG)) ?
+ FIELD_NORMAL :
+ found->type() == MYSQL_TYPE_STRING ||
+ found->type() == MYSQL_TYPE_VAR_STRING ?
+ FIELD_SKIP_ENDSPACE :
+ FIELD_SKIP_PRESPACE);
if (found->null_ptr)
{
recinfo_pos->null_bit=found->null_bit;
recinfo_pos->null_pos= (uint) (found->null_ptr-
- (uchar*) table_arg->record[0]);
+ (uchar*) table_arg->record[0]);
}
else
{
recinfo_pos->null_bit=0;
recinfo_pos->null_pos=0;
}
- (recinfo_pos++) ->length=(uint16) length;
+ (recinfo_pos++)->length= (uint16) length;
recpos=minpos+length;
DBUG_PRINT("loop",("length: %d type: %d",
recinfo_pos[-1].length,recinfo_pos[-1].type));
@@ -1606,7 +1615,7 @@ int ha_myisam::ft_read(byte * buf)
if (!ft_handler)
return -1;
- thread_safe_increment(current_thd->status_var.ha_read_next_count,
+ thread_safe_increment(table->in_use->status_var.ha_read_next_count,
&LOCK_status); // why ?
error=ft_handler->please->read_next(ft_handler,(char*) buf);
diff --git a/sql/ha_myisammrg.cc b/sql/ha_myisammrg.cc
index 903dd9dec2f..744128faf69 100644
--- a/sql/ha_myisammrg.cc
+++ b/sql/ha_myisammrg.cc
@@ -35,6 +35,17 @@
const char **ha_myisammrg::bas_ext() const
{ static const char *ext[]= { ".MRG", NullS }; return ext; }
+const char *ha_myisammrg::index_type(uint key_number)
+{
+ return ((table->key_info[key_number].flags & HA_FULLTEXT) ?
+ "FULLTEXT" :
+ (table->key_info[key_number].flags & HA_SPATIAL) ?
+ "SPATIAL" :
+ (table->key_info[key_number].algorithm == HA_KEY_ALG_RTREE) ?
+ "RTREE" :
+ "BTREE");
+}
+
int ha_myisammrg::open(const char *name, int mode, uint test_if_locked)
{
@@ -81,7 +92,7 @@ int ha_myisammrg::close(void)
int ha_myisammrg::write_row(byte * buf)
{
- statistic_increment(current_thd->status_var.ha_write_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_write_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_INSERT)
table->timestamp_field->set_time();
if (table->next_number_field && buf == table->record[0])
@@ -91,7 +102,7 @@ int ha_myisammrg::write_row(byte * buf)
int ha_myisammrg::update_row(const byte * old_data, byte * new_data)
{
- statistic_increment(current_thd->status_var.ha_update_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_update_count,&LOCK_status);
if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
table->timestamp_field->set_time();
return myrg_update(file,old_data,new_data);
@@ -99,14 +110,15 @@ int ha_myisammrg::update_row(const byte * old_data, byte * new_data)
int ha_myisammrg::delete_row(const byte * buf)
{
- statistic_increment(current_thd->status_var.ha_delete_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_delete_count,&LOCK_status);
return myrg_delete(file,buf);
}
int ha_myisammrg::index_read(byte * buf, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(current_thd->status_var.ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=myrg_rkey(file,buf,active_index, key, key_len, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -115,7 +127,8 @@ int ha_myisammrg::index_read(byte * buf, const byte * key,
int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
uint key_len, enum ha_rkey_function find_flag)
{
- statistic_increment(current_thd->status_var.ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=myrg_rkey(file,buf,index, key, key_len, find_flag);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -123,7 +136,8 @@ int ha_myisammrg::index_read_idx(byte * buf, uint index, const byte * key,
int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len)
{
- statistic_increment(current_thd->status_var.ha_read_key_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_key_count,
+ &LOCK_status);
int error=myrg_rkey(file,buf,active_index, key, key_len,
HA_READ_PREFIX_LAST);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -132,7 +146,8 @@ int ha_myisammrg::index_read_last(byte * buf, const byte * key, uint key_len)
int ha_myisammrg::index_next(byte * buf)
{
- statistic_increment(current_thd->status_var.ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=myrg_rnext(file,buf,active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -140,7 +155,8 @@ int ha_myisammrg::index_next(byte * buf)
int ha_myisammrg::index_prev(byte * buf)
{
- statistic_increment(current_thd->status_var.ha_read_prev_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_prev_count,
+ &LOCK_status);
int error=myrg_rprev(file,buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -148,7 +164,7 @@ int ha_myisammrg::index_prev(byte * buf)
int ha_myisammrg::index_first(byte * buf)
{
- statistic_increment(current_thd->status_var.ha_read_first_count,
+ statistic_increment(table->in_use->status_var.ha_read_first_count,
&LOCK_status);
int error=myrg_rfirst(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -157,7 +173,8 @@ int ha_myisammrg::index_first(byte * buf)
int ha_myisammrg::index_last(byte * buf)
{
- statistic_increment(current_thd->status_var.ha_read_last_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_last_count,
+ &LOCK_status);
int error=myrg_rlast(file, buf, active_index);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -167,7 +184,8 @@ int ha_myisammrg::index_next_same(byte * buf,
const byte *key __attribute__((unused)),
uint length __attribute__((unused)))
{
- statistic_increment(current_thd->status_var.ha_read_next_count,&LOCK_status);
+ statistic_increment(table->in_use->status_var.ha_read_next_count,
+ &LOCK_status);
int error=myrg_rnext_same(file,buf);
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
@@ -180,7 +198,7 @@ int ha_myisammrg::rnd_init(bool scan)
int ha_myisammrg::rnd_next(byte *buf)
{
- statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
+ statistic_increment(table->in_use->status_var.ha_read_rnd_next_count,
&LOCK_status);
int error=myrg_rrnd(file, buf, HA_OFFSET_ERROR);
table->status=error ? STATUS_NOT_FOUND: 0;
@@ -189,8 +207,9 @@ int ha_myisammrg::rnd_next(byte *buf)
int ha_myisammrg::rnd_pos(byte * buf, byte *pos)
{
- statistic_increment(current_thd->status_var.ha_read_rnd_count,&LOCK_status);
- int error=myrg_rrnd(file, buf, ha_get_ptr(pos,ref_length));
+ statistic_increment(table->in_use->status_var.ha_read_rnd_count,
+ &LOCK_status);
+ int error=myrg_rrnd(file, buf, my_get_ptr(pos,ref_length));
table->status=error ? STATUS_NOT_FOUND: 0;
return error;
}
@@ -198,7 +217,7 @@ int ha_myisammrg::rnd_pos(byte * buf, byte *pos)
void ha_myisammrg::position(const byte *record)
{
ulonglong position= myrg_position(file);
- ha_store_ptr(ref, ref_length, (my_off_t) position);
+ my_store_ptr(ref, ref_length, (my_off_t) position);
}
diff --git a/sql/ha_myisammrg.h b/sql/ha_myisammrg.h
index 264c580220c..6058c32c805 100644
--- a/sql/ha_myisammrg.h
+++ b/sql/ha_myisammrg.h
@@ -32,6 +32,7 @@ class ha_myisammrg: public handler
~ha_myisammrg() {}
const char *table_type() const { return "MRG_MyISAM"; }
const char **bas_ext() const;
+ const char *index_type(uint key_number);
ulong table_flags() const
{
return (HA_REC_NOT_IN_SEQ | HA_AUTO_PART_KEY | HA_READ_RND_SAME |
diff --git a/sql/ha_ndbcluster.cc b/sql/ha_ndbcluster.cc
index 7878684718c..f838bfcd8c3 100644
--- a/sql/ha_ndbcluster.cc
+++ b/sql/ha_ndbcluster.cc
@@ -39,9 +39,6 @@ static const int parallelism= 240;
// createable against NDB from this handler
static const int max_transactions= 256;
-// Default value for prefetch of autoincrement values
-static const ha_rows autoincrement_prefetch= 32;
-
// connectstring to cluster if given by mysqld
const char *ndbcluster_connectstring= 0;
@@ -103,51 +100,52 @@ struct err_code_mapping
{
int ndb_err;
int my_err;
+ int show_warning;
};
static const err_code_mapping err_map[]=
{
- { 626, HA_ERR_KEY_NOT_FOUND },
- { 630, HA_ERR_FOUND_DUPP_KEY },
- { 893, HA_ERR_FOUND_DUPP_UNIQUE },
- { 721, HA_ERR_TABLE_EXIST },
- { 4244, HA_ERR_TABLE_EXIST },
-
- { 709, HA_ERR_NO_SUCH_TABLE },
- { 284, HA_ERR_NO_SUCH_TABLE },
-
- { 266, HA_ERR_LOCK_WAIT_TIMEOUT },
- { 274, HA_ERR_LOCK_WAIT_TIMEOUT },
- { 296, HA_ERR_LOCK_WAIT_TIMEOUT },
- { 297, HA_ERR_LOCK_WAIT_TIMEOUT },
- { 237, HA_ERR_LOCK_WAIT_TIMEOUT },
-
- { 623, HA_ERR_RECORD_FILE_FULL },
- { 624, HA_ERR_RECORD_FILE_FULL },
- { 625, HA_ERR_RECORD_FILE_FULL },
- { 826, HA_ERR_RECORD_FILE_FULL },
- { 827, HA_ERR_RECORD_FILE_FULL },
- { 832, HA_ERR_RECORD_FILE_FULL },
-
- { 0, 1 },
-
- { -1, -1 }
+ { 626, HA_ERR_KEY_NOT_FOUND, 0 },
+ { 630, HA_ERR_FOUND_DUPP_KEY, 0 },
+ { 893, HA_ERR_FOUND_DUPP_KEY, 0 },
+ { 721, HA_ERR_TABLE_EXIST, 1 },
+ { 4244, HA_ERR_TABLE_EXIST, 1 },
+
+ { 709, HA_ERR_NO_SUCH_TABLE, 1 },
+ { 284, HA_ERR_NO_SUCH_TABLE, 1 },
+
+ { 266, HA_ERR_LOCK_WAIT_TIMEOUT, 1 },
+ { 274, HA_ERR_LOCK_WAIT_TIMEOUT, 1 },
+ { 296, HA_ERR_LOCK_WAIT_TIMEOUT, 1 },
+ { 297, HA_ERR_LOCK_WAIT_TIMEOUT, 1 },
+ { 237, HA_ERR_LOCK_WAIT_TIMEOUT, 1 },
+
+ { 623, HA_ERR_RECORD_FILE_FULL, 1 },
+ { 624, HA_ERR_RECORD_FILE_FULL, 1 },
+ { 625, HA_ERR_RECORD_FILE_FULL, 1 },
+ { 826, HA_ERR_RECORD_FILE_FULL, 1 },
+ { 827, HA_ERR_RECORD_FILE_FULL, 1 },
+ { 832, HA_ERR_RECORD_FILE_FULL, 1 },
+
+ { 0, 1, 0 },
+
+ { -1, -1, 1 }
};
static int ndb_to_mysql_error(const NdbError *err)
{
uint i;
- for (i=0 ; err_map[i].ndb_err != err->code ; i++)
+ for (i=0; err_map[i].ndb_err != err->code && err_map[i].my_err != -1; i++);
+ if (err_map[i].show_warning)
{
- if (err_map[i].my_err == -1){
- // Push the NDB error message as warning
- push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
- ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
- err->code, err->message, "NDB");
- return err->code;
- }
+ // Push the NDB error message as warning
+ push_warning_printf(current_thd, MYSQL_ERROR::WARN_LEVEL_ERROR,
+ ER_GET_ERRMSG, ER(ER_GET_ERRMSG),
+ err->code, err->message, "NDB");
}
+ if (err_map[i].my_err == -1)
+ return err->code;
return err_map[i].my_err;
}
@@ -161,7 +159,7 @@ int execute_no_commit(ha_ndbcluster *h, NdbConnection *trans)
if (m_batch_execute)
return 0;
#endif
- return trans->execute(NoCommit,AbortOnError,1);
+ return trans->execute(NoCommit,AbortOnError,h->m_force_send);
}
inline
@@ -172,7 +170,18 @@ int execute_commit(ha_ndbcluster *h, NdbConnection *trans)
if (m_batch_execute)
return 0;
#endif
- return trans->execute(Commit,AbortOnError,1);
+ return trans->execute(Commit,AbortOnError,h->m_force_send);
+}
+
+inline
+int execute_commit(THD *thd, NdbConnection *trans)
+{
+ int m_batch_execute= 0;
+#ifdef NOT_USED
+ if (m_batch_execute)
+ return 0;
+#endif
+ return trans->execute(Commit,AbortOnError,thd->variables.ndb_force_send);
}
inline
@@ -183,7 +192,7 @@ int execute_no_commit_ie(ha_ndbcluster *h, NdbConnection *trans)
if (m_batch_execute)
return 0;
#endif
- return trans->execute(NoCommit,IgnoreError,1);
+ return trans->execute(NoCommit,IgnoreError,h->m_force_send);
}
/*
@@ -226,6 +235,8 @@ void ha_ndbcluster::set_rec_per_key()
void ha_ndbcluster::records_update()
{
+ if (m_ha_not_exact_count)
+ return;
DBUG_ENTER("ha_ndbcluster::records_update");
struct Ndb_table_local_info *info= (struct Ndb_table_local_info *)m_table_info;
DBUG_PRINT("info", ("id=%d, no_uncommitted_rows_count=%d",
@@ -249,6 +260,8 @@ void ha_ndbcluster::records_update()
void ha_ndbcluster::no_uncommitted_rows_execute_failure()
{
+ if (m_ha_not_exact_count)
+ return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_execute_failure");
THD *thd= current_thd;
((Thd_ndb*)(thd->transaction.thd_ndb))->error= 1;
@@ -257,6 +270,8 @@ void ha_ndbcluster::no_uncommitted_rows_execute_failure()
void ha_ndbcluster::no_uncommitted_rows_init(THD *thd)
{
+ if (m_ha_not_exact_count)
+ return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_init");
struct Ndb_table_local_info *info= (struct Ndb_table_local_info *)m_table_info;
Thd_ndb *thd_ndb= (Thd_ndb *)thd->transaction.thd_ndb;
@@ -274,6 +289,8 @@ void ha_ndbcluster::no_uncommitted_rows_init(THD *thd)
void ha_ndbcluster::no_uncommitted_rows_update(int c)
{
+ if (m_ha_not_exact_count)
+ return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_update");
struct Ndb_table_local_info *info=
(struct Ndb_table_local_info *)m_table_info;
@@ -286,6 +303,8 @@ void ha_ndbcluster::no_uncommitted_rows_update(int c)
void ha_ndbcluster::no_uncommitted_rows_reset(THD *thd)
{
+ if (m_ha_not_exact_count)
+ return;
DBUG_ENTER("ha_ndbcluster::no_uncommitted_rows_reset");
((Thd_ndb*)(thd->transaction.thd_ndb))->count++;
((Thd_ndb*)(thd->transaction.thd_ndb))->error= 0;
@@ -324,7 +343,7 @@ int ha_ndbcluster::ndb_err(NdbConnection *trans)
DBUG_PRINT("info", ("transformed ndbcluster error %d to mysql error %d",
err.code, res));
if (res == HA_ERR_FOUND_DUPP_KEY)
- dupkey= table->primary_key;
+ m_dupkey= table->primary_key;
DBUG_RETURN(res);
}
@@ -387,6 +406,7 @@ static inline bool ndb_supported_type(enum_field_types type)
return TRUE;
case MYSQL_TYPE_NULL:
case MYSQL_TYPE_GEOMETRY:
+ case MYSQL_TYPE_VARCHAR:
break;
}
return FALSE;
@@ -551,7 +571,7 @@ int ha_ndbcluster::get_ndb_blobs_value(NdbBlob *last_ndb_blob)
blob_size+= 8 - blob_size % 8;
if (loop == 1)
{
- char *buf= blobs_buffer + offset;
+ char *buf= m_blobs_buffer + offset;
uint32 len= 0xffffffff; // Max uint32
DBUG_PRINT("value", ("read blob ptr=%x len=%u",
(uint)buf, (uint)blob_len));
@@ -563,15 +583,15 @@ int ha_ndbcluster::get_ndb_blobs_value(NdbBlob *last_ndb_blob)
offset+= blob_size;
}
}
- if (loop == 0 && offset > blobs_buffer_size)
+ if (loop == 0 && offset > m_blobs_buffer_size)
{
- my_free(blobs_buffer, MYF(MY_ALLOW_ZERO_PTR));
- blobs_buffer_size= 0;
+ my_free(m_blobs_buffer, MYF(MY_ALLOW_ZERO_PTR));
+ m_blobs_buffer_size= 0;
DBUG_PRINT("value", ("allocate blobs buffer size %u", offset));
- blobs_buffer= my_malloc(offset, MYF(MY_WME));
- if (blobs_buffer == NULL)
+ m_blobs_buffer= my_malloc(offset, MYF(MY_WME));
+ if (m_blobs_buffer == NULL)
DBUG_RETURN(-1);
- blobs_buffer_size= offset;
+ m_blobs_buffer_size= offset;
}
}
DBUG_RETURN(0);
@@ -777,7 +797,8 @@ int ha_ndbcluster::build_index_list(TABLE *tab, enum ILBP phase)
error= create_unique_index(unique_index_name, key_info);
break;
case UNIQUE_INDEX:
- error= create_unique_index(unique_index_name, key_info);
+ if (!(error= check_index_fields_not_null(i)))
+ error= create_unique_index(unique_index_name, key_info);
break;
case ORDERED_INDEX:
error= create_ordered_index(index_name, key_info);
@@ -829,6 +850,26 @@ NDB_INDEX_TYPE ha_ndbcluster::get_index_type_from_table(uint inx) const
ORDERED_INDEX);
}
+int ha_ndbcluster::check_index_fields_not_null(uint inx)
+{
+ KEY* key_info= table->key_info + inx;
+ KEY_PART_INFO* key_part= key_info->key_part;
+ KEY_PART_INFO* end= key_part+key_info->key_parts;
+ DBUG_ENTER("check_index_fields_not_null");
+
+ for (; key_part != end; key_part++)
+ {
+ Field* field= key_part->field;
+ if (field->maybe_null())
+ {
+ my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX),
+ MYF(0),field->field_name);
+ DBUG_RETURN(ER_NULL_COLUMN_IN_INDEX);
+ }
+ }
+
+ DBUG_RETURN(0);
+}
void ha_ndbcluster::release_metadata()
{
@@ -854,7 +895,7 @@ int ha_ndbcluster::get_ndb_lock_type(enum thr_lock_type type)
{
if (type >= TL_WRITE_ALLOW_WRITE)
return NdbOperation::LM_Exclusive;
- else if (uses_blob_value(retrieve_all_fields))
+ else if (uses_blob_value(m_retrieve_all_fields))
return NdbOperation::LM_Read;
else
return NdbOperation::LM_CommittedRead;
@@ -1018,7 +1059,8 @@ int ha_ndbcluster::pk_read(const byte *key, uint key_len, byte *buf)
{
Field *field= table->field[i];
if ((thd->query_id == field->query_id) ||
- retrieve_all_fields)
+ m_retrieve_all_fields ||
+ (field->flags & PRI_KEY_FLAG) && m_retrieve_primary_key)
{
if (get_ndb_value(op, field, i, buf))
ERR_RETURN(trans->getNdbError());
@@ -1055,7 +1097,7 @@ int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data)
THD *thd= current_thd;
DBUG_ENTER("complemented_pk_read");
- if (retrieve_all_fields)
+ if (m_retrieve_all_fields)
// We have allready retrieved all fields, nothing to complement
DBUG_RETURN(0);
@@ -1093,6 +1135,34 @@ int ha_ndbcluster::complemented_pk_read(const byte *old_data, byte *new_data)
DBUG_RETURN(0);
}
+/*
+ Peek to check if a particular row already exists
+*/
+
+int ha_ndbcluster::peek_row()
+{
+ NdbConnection *trans= m_active_trans;
+ NdbOperation *op;
+ THD *thd= current_thd;
+ DBUG_ENTER("peek_row");
+
+ NdbOperation::LockMode lm=
+ (NdbOperation::LockMode)get_ndb_lock_type(m_lock.type);
+ if (!(op= trans->getNdbOperation((const NDBTAB *) m_table)) ||
+ op->readTuple(lm) != 0)
+ ERR_RETURN(trans->getNdbError());
+
+ int res;
+ if ((res= set_primary_key(op)))
+ ERR_RETURN(trans->getNdbError());
+
+ if (execute_no_commit_ie(this,trans) != 0)
+ {
+ table->status= STATUS_NOT_FOUND;
+ DBUG_RETURN(ndb_err(trans));
+ }
+ DBUG_RETURN(0);
+}
/*
Read one record from NDB using unique secondary index
@@ -1128,9 +1198,10 @@ int ha_ndbcluster::unique_index_read(const byte *key,
for (i= 0; key_part != end; key_part++, i++)
{
- if (set_ndb_key(op, key_part->field, i, key_ptr))
+ if (set_ndb_key(op, key_part->field, i,
+ key_part->null_bit ? key_ptr + 1 : key_ptr))
ERR_RETURN(trans->getNdbError());
- key_ptr+= key_part->length;
+ key_ptr+= key_part->store_length;
}
// Get non-index attribute(s)
@@ -1138,7 +1209,7 @@ int ha_ndbcluster::unique_index_read(const byte *key,
{
Field *field= table->field[i];
if ((thd->query_id == field->query_id) ||
- (field->flags & PRI_KEY_FLAG))
+ (field->flags & PRI_KEY_FLAG)) // && m_retrieve_primary_key ??
{
if (get_ndb_value(op, field, i, buf))
ERR_RETURN(op->getNdbError());
@@ -1192,14 +1263,14 @@ inline int ha_ndbcluster::next_result(byte *buf)
/*
We can only handle one tuple with blobs at a time.
*/
- if (ops_pending && blobs_pending)
+ if (m_ops_pending && m_blobs_pending)
{
if (execute_no_commit(this,trans) != 0)
DBUG_RETURN(ndb_err(trans));
- ops_pending= 0;
- blobs_pending= FALSE;
+ m_ops_pending= 0;
+ m_blobs_pending= FALSE;
}
- check= cursor->nextResult(contact_ndb);
+ check= cursor->nextResult(contact_ndb, m_force_send);
if (check == 0)
{
// One more record found
@@ -1219,10 +1290,11 @@ inline int ha_ndbcluster::next_result(byte *buf)
all pending update or delete operations should
be sent to NDB
*/
- DBUG_PRINT("info", ("ops_pending: %d", ops_pending));
- if (ops_pending)
+ DBUG_PRINT("info", ("ops_pending: %d", m_ops_pending));
+ if (m_ops_pending)
{
- if (current_thd->transaction.on)
+ // if (current_thd->transaction.on)
+ if (m_transaction_on)
{
if (execute_no_commit(this,trans) != 0)
DBUG_RETURN(ndb_err(trans));
@@ -1234,7 +1306,7 @@ inline int ha_ndbcluster::next_result(byte *buf)
int res= trans->restart();
DBUG_ASSERT(res == 0);
}
- ops_pending= 0;
+ m_ops_pending= 0;
}
contact_ndb= (check == 2);
@@ -1290,7 +1362,6 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
Field *field= key_part->field;
uint part_len= key_part->length;
uint part_store_len= key_part->store_length;
- bool part_nullable= (bool) key_part->null_bit;
// Info about each key part
struct part_st {
bool part_last;
@@ -1312,9 +1383,9 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
p.part_last= (tot_len + part_store_len >= key_tot_len[j]);
p.key= keys[j];
p.part_ptr= &p.key->key[tot_len];
- p.part_null= (field->maybe_null() && *p.part_ptr);
+ p.part_null= key_part->null_bit && *p.part_ptr;
p.bound_ptr= (const char *)
- p.part_null ? 0 : part_nullable ? p.part_ptr + 1 : p.part_ptr;
+ p.part_null ? 0 : key_part->null_bit ? p.part_ptr + 1 : p.part_ptr;
if (j == 0)
{
@@ -1393,8 +1464,13 @@ int ha_ndbcluster::set_bounds(NdbIndexScanOperation *op,
// Set bound if not cancelled via type -1
if (p.bound_type != -1)
- if (op->setBound(field->field_name, p.bound_type, p.bound_ptr))
+ {
+ char truncated_field_name[NDB_MAX_ATTR_NAME_SIZE];
+ strnmov(truncated_field_name,field->field_name,sizeof(truncated_field_name));
+ truncated_field_name[sizeof(truncated_field_name)-1]= '\0';
+ if (op->setBound(truncated_field_name, p.bound_type, p.bound_ptr))
ERR_RETURN(op->getNdbError());
+ }
}
}
@@ -1418,7 +1494,7 @@ int ha_ndbcluster::define_read_attrs(byte* buf, NdbOperation* op)
Field *field= table->field[i];
if ((thd->query_id == field->query_id) ||
(field->flags & PRI_KEY_FLAG) ||
- retrieve_all_fields)
+ m_retrieve_all_fields)
{
if (get_ndb_value(op, field, i, buf))
ERR_RETURN(op->getNdbError());
@@ -1487,7 +1563,7 @@ int ha_ndbcluster::ordered_index_scan(const key_range *start_key,
DBUG_ASSERT(op->getSorted() == sorted);
DBUG_ASSERT(op->getLockMode() ==
(NdbOperation::LockMode)get_ndb_lock_type(m_lock.type));
- if(op->reset_bounds())
+ if(op->reset_bounds(m_force_send))
DBUG_RETURN(ndb_err(m_active_trans));
}
@@ -1562,7 +1638,7 @@ int ha_ndbcluster::filtered_scan(const byte *key, uint key_len,
Field* field= key_part->field;
uint ndb_fieldnr= key_part->fieldnr-1;
DBUG_PRINT("key_part", ("fieldnr: %d", ndb_fieldnr));
- // const NDBCOL *col= tab->getColumn(ndb_fieldnr);
+ //const NDBCOL *col= ((const NDBTAB *) m_table)->getColumn(ndb_fieldnr);
uint32 field_len= field->pack_length();
DBUG_DUMP("key", (char*)key, field_len);
@@ -1633,9 +1709,17 @@ int ha_ndbcluster::write_row(byte *record)
DBUG_ENTER("write_row");
- if(m_ignore_dup_key_not_supported)
+ if(m_ignore_dup_key && table->primary_key != MAX_KEY)
{
- DBUG_RETURN(HA_ERR_WRONG_COMMAND);
+ int peek_res= peek_row();
+
+ if (!peek_res)
+ {
+ m_dupkey= table->primary_key;
+ DBUG_RETURN(HA_ERR_FOUND_DUPP_KEY);
+ }
+ if (peek_res != HA_ERR_KEY_NOT_FOUND)
+ DBUG_RETURN(peek_res);
}
statistic_increment(thd->status_var.ha_write_count, &LOCK_status);
@@ -1663,9 +1747,9 @@ int ha_ndbcluster::write_row(byte *record)
if (has_auto_increment)
{
- skip_auto_increment= FALSE;
+ m_skip_auto_increment= FALSE;
update_auto_increment();
- skip_auto_increment= !auto_increment_column_changed;
+ m_skip_auto_increment= !auto_increment_column_changed;
}
if ((res= set_primary_key(op)))
@@ -1680,7 +1764,7 @@ int ha_ndbcluster::write_row(byte *record)
if (!(field->flags & PRI_KEY_FLAG) &&
set_ndb_value(op, field, i, &set_blob_value))
{
- skip_auto_increment= TRUE;
+ m_skip_auto_increment= TRUE;
ERR_RETURN(op->getNdbError());
}
}
@@ -1692,25 +1776,26 @@ int ha_ndbcluster::write_row(byte *record)
to NoCommit the transaction between each row.
Find out how this is detected!
*/
- rows_inserted++;
+ m_rows_inserted++;
no_uncommitted_rows_update(1);
- bulk_insert_not_flushed= TRUE;
- if ((rows_to_insert == 1) ||
- ((rows_inserted % bulk_insert_rows) == 0) ||
+ m_bulk_insert_not_flushed= TRUE;
+ if ((m_rows_to_insert == 1) ||
+ ((m_rows_inserted % m_bulk_insert_rows) == 0) ||
set_blob_value)
{
THD *thd= current_thd;
// Send rows to NDB
DBUG_PRINT("info", ("Sending inserts to NDB, "\
"rows_inserted:%d, bulk_insert_rows: %d",
- (int)rows_inserted, (int)bulk_insert_rows));
+ (int)m_rows_inserted, (int)m_bulk_insert_rows));
- bulk_insert_not_flushed= FALSE;
- if (thd->transaction.on)
+ m_bulk_insert_not_flushed= FALSE;
+ // if (thd->transaction.on)
+ if (m_transaction_on)
{
if (execute_no_commit(this,trans) != 0)
{
- skip_auto_increment= TRUE;
+ m_skip_auto_increment= TRUE;
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
}
@@ -1719,7 +1804,7 @@ int ha_ndbcluster::write_row(byte *record)
{
if (execute_commit(this,trans) != 0)
{
- skip_auto_increment= TRUE;
+ m_skip_auto_increment= TRUE;
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
}
@@ -1727,7 +1812,7 @@ int ha_ndbcluster::write_row(byte *record)
DBUG_ASSERT(res == 0);
}
}
- if ((has_auto_increment) && (skip_auto_increment))
+ if ((has_auto_increment) && (m_skip_auto_increment))
{
Uint64 next_val= (Uint64) table->next_number_field->val_int() + 1;
DBUG_PRINT("info",
@@ -1737,7 +1822,7 @@ int ha_ndbcluster::write_row(byte *record)
DBUG_PRINT("info",
("Setting next auto increment value to %u", next_val));
}
- skip_auto_increment= TRUE;
+ m_skip_auto_increment= TRUE;
DBUG_RETURN(0);
}
@@ -1759,7 +1844,7 @@ int ha_ndbcluster::key_cmp(uint keynr, const byte * old_row,
(new_row[key_part->null_offset] & key_part->null_bit))
return 1;
}
- if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
if (key_part->field->cmp_binary((char*) (old_row + key_part->offset),
@@ -1817,7 +1902,9 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
}
// Delete old row
DBUG_PRINT("info", ("insert succeded"));
+ m_primary_key_update= TRUE;
delete_res= delete_row(old_data);
+ m_primary_key_update= FALSE;
if (delete_res)
{
DBUG_PRINT("info", ("delete failed"));
@@ -1840,9 +1927,9 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
DBUG_PRINT("info", ("Calling updateTuple on cursor"));
if (!(op= cursor->updateTuple()))
ERR_RETURN(trans->getNdbError());
- ops_pending++;
+ m_ops_pending++;
if (uses_blob_value(FALSE))
- blobs_pending= TRUE;
+ m_blobs_pending= TRUE;
}
else
{
@@ -1877,7 +1964,7 @@ int ha_ndbcluster::update_row(const byte *old_data, byte *new_data)
for (i= 0; i < table->fields; i++)
{
Field *field= table->field[i];
- if ((thd->query_id == field->query_id) &&
+ if (((thd->query_id == field->query_id) || m_retrieve_all_fields) &&
(!(field->flags & PRI_KEY_FLAG)) &&
set_ndb_value(op, field, i))
ERR_RETURN(op->getNdbError());
@@ -1919,7 +2006,7 @@ int ha_ndbcluster::delete_row(const byte *record)
DBUG_PRINT("info", ("Calling deleteTuple on cursor"));
if (cursor->deleteTuple() != 0)
ERR_RETURN(trans->getNdbError());
- ops_pending++;
+ m_ops_pending++;
no_uncommitted_rows_update(-1);
@@ -1949,8 +2036,10 @@ int ha_ndbcluster::delete_row(const byte *record)
else
{
int res;
- if ((res= set_primary_key(op)))
- return res;
+ if ((res= (m_primary_key_update ?
+ set_primary_key_from_old_data(op, record)
+ : set_primary_key(op))))
+ return res;
}
}
@@ -2144,17 +2233,15 @@ void ha_ndbcluster::print_results()
break;
}
case NdbDictionary::Column::Char:{
- char buf[field->pack_length()+1];
- char *value= (char *) field->ptr;
- snprintf(buf, field->pack_length(), "%s", value);
- fprintf(DBUG_FILE, "Char\t'%s'", buf);
+ const char *value= (char *) field->ptr;
+ fprintf(DBUG_FILE, "Char\t'%.*s'", field->pack_length(), value);
break;
}
case NdbDictionary::Column::Varchar:
case NdbDictionary::Column::Binary:
case NdbDictionary::Column::Varbinary: {
- char *value= (char *) field->ptr;
- fprintf(DBUG_FILE, "'%s'", value);
+ const char *value= (char *) field->ptr;
+ fprintf(DBUG_FILE, "Var\t'%.*s'", field->pack_length(), value);
break;
}
case NdbDictionary::Column::Datetime: {
@@ -2205,6 +2292,28 @@ int ha_ndbcluster::index_end()
DBUG_RETURN(close_scan());
}
+/**
+ * Check if key contains null
+ */
+static
+int
+check_null_in_key(const KEY* key_info, const byte *key, uint key_len)
+{
+ KEY_PART_INFO *curr_part, *end_part;
+ const byte* end_ptr = key + key_len;
+ curr_part= key_info->key_part;
+ end_part= curr_part + key_info->key_parts;
+
+
+ for (; curr_part != end_part && key < end_ptr; curr_part++)
+ {
+ if(curr_part->null_bit && *key)
+ return 1;
+
+ key += curr_part->store_length;
+ }
+ return 0;
+}
int ha_ndbcluster::index_read(byte *buf,
const byte *key, uint key_len,
@@ -2222,6 +2331,8 @@ int ha_ndbcluster::index_read(byte *buf,
case PRIMARY_KEY_INDEX:
if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len)
{
+ if(m_active_cursor && (error= close_scan()))
+ DBUG_RETURN(error);
DBUG_RETURN(pk_read(key, key_len, buf));
}
else if (type == PRIMARY_KEY_INDEX)
@@ -2231,8 +2342,11 @@ int ha_ndbcluster::index_read(byte *buf,
break;
case UNIQUE_ORDERED_INDEX:
case UNIQUE_INDEX:
- if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len)
+ if (find_flag == HA_READ_KEY_EXACT && key_info->key_length == key_len &&
+ !check_null_in_key(key_info, key, key_len))
{
+ if(m_active_cursor && (error= close_scan()))
+ DBUG_RETURN(error);
DBUG_RETURN(unique_index_read(key, key_len, buf));
}
else if (type == UNIQUE_INDEX)
@@ -2309,14 +2423,14 @@ int ha_ndbcluster::index_last(byte *buf)
int res;
if((res= ordered_index_scan(0, 0, TRUE, buf)) == 0){
NdbResultSet *cursor= m_active_cursor;
- while((res= cursor->nextResult(TRUE)) == 0);
+ while((res= cursor->nextResult(TRUE, m_force_send)) == 0);
if(res == 1){
unpack_record(buf);
table->status= 0;
DBUG_RETURN(0);
}
}
- DBUG_RETURN(1);
+ DBUG_RETURN(res);
}
@@ -2339,6 +2453,8 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
start_key->length == key_info->key_length &&
start_key->flag == HA_READ_KEY_EXACT)
{
+ if(m_active_cursor && (error= close_scan()))
+ DBUG_RETURN(error);
error= pk_read(start_key->key, start_key->length, buf);
DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error);
}
@@ -2346,10 +2462,12 @@ int ha_ndbcluster::read_range_first_to_buf(const key_range *start_key,
case UNIQUE_ORDERED_INDEX:
case UNIQUE_INDEX:
key_info= table->key_info + active_index;
- if (start_key &&
- start_key->length == key_info->key_length &&
- start_key->flag == HA_READ_KEY_EXACT)
+ if (start_key && start_key->length == key_info->key_length &&
+ start_key->flag == HA_READ_KEY_EXACT &&
+ !check_null_in_key(key_info, start_key->key, start_key->length))
{
+ if(m_active_cursor && (error= close_scan()))
+ DBUG_RETURN(error);
error= unique_index_read(start_key->key, start_key->length, buf);
DBUG_RETURN(error == HA_ERR_KEY_NOT_FOUND ? HA_ERR_END_OF_FILE : error);
}
@@ -2395,7 +2513,7 @@ int ha_ndbcluster::rnd_init(bool scan)
{
if (!scan)
DBUG_RETURN(1);
- int res= cursor->restart();
+ int res= cursor->restart(m_force_send);
DBUG_ASSERT(res == 0);
}
index_init(table->primary_key);
@@ -2412,21 +2530,21 @@ int ha_ndbcluster::close_scan()
DBUG_RETURN(1);
- if (ops_pending)
+ if (m_ops_pending)
{
/*
Take over any pending transactions to the
deleteing/updating transaction before closing the scan
*/
- DBUG_PRINT("info", ("ops_pending: %d", ops_pending));
+ DBUG_PRINT("info", ("ops_pending: %d", m_ops_pending));
if (execute_no_commit(this,trans) != 0) {
no_uncommitted_rows_execute_failure();
DBUG_RETURN(ndb_err(trans));
}
- ops_pending= 0;
+ m_ops_pending= 0;
}
- cursor->close();
+ cursor->close(m_force_send);
m_active_cursor= NULL;
DBUG_RETURN(0);
}
@@ -2540,14 +2658,17 @@ void ha_ndbcluster::info(uint flag)
DBUG_PRINT("info", ("HA_STATUS_VARIABLE"));
if (m_table_info)
{
- records_update();
+ if (m_ha_not_exact_count)
+ records= 100;
+ else
+ records_update();
}
else
{
- Uint64 rows;
- if(ndb_get_table_statistics(m_ndb, m_tabname, &rows, 0) == 0){
- records= rows;
- }
+ Uint64 rows= 100;
+ if (current_thd->variables.ndb_use_exact_count)
+ ndb_get_table_statistics(m_ndb, m_tabname, &rows, 0);
+ records= rows;
}
}
if (flag & HA_STATUS_CONST)
@@ -2558,7 +2679,7 @@ void ha_ndbcluster::info(uint flag)
if (flag & HA_STATUS_ERRKEY)
{
DBUG_PRINT("info", ("HA_STATUS_ERRKEY"));
- errkey= dupkey;
+ errkey= m_dupkey;
}
if (flag & HA_STATUS_AUTO)
DBUG_PRINT("info", ("HA_STATUS_AUTO"));
@@ -2653,20 +2774,21 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
m_use_write= TRUE;
} else
{
- m_ignore_dup_key_not_supported= TRUE;
+ DBUG_PRINT("info", ("Ignoring duplicate key"));
+ m_ignore_dup_key= TRUE;
}
break;
case HA_EXTRA_NO_IGNORE_DUP_KEY:
DBUG_PRINT("info", ("HA_EXTRA_NO_IGNORE_DUP_KEY"));
DBUG_PRINT("info", ("Turning OFF use of write instead of insert"));
m_use_write= FALSE;
- m_ignore_dup_key_not_supported= FALSE;
+ m_ignore_dup_key= FALSE;
break;
case HA_EXTRA_RETRIEVE_ALL_COLS: /* Retrieve all columns, not just those
where field->query_id is the same as
the current query id */
DBUG_PRINT("info", ("HA_EXTRA_RETRIEVE_ALL_COLS"));
- retrieve_all_fields= TRUE;
+ m_retrieve_all_fields= TRUE;
break;
case HA_EXTRA_PREPARE_FOR_DELETE:
DBUG_PRINT("info", ("HA_EXTRA_PREPARE_FOR_DELETE"));
@@ -2679,6 +2801,7 @@ int ha_ndbcluster::extra(enum ha_extra_function operation)
break;
case HA_EXTRA_RETRIEVE_PRIMARY_KEY:
DBUG_PRINT("info", ("HA_EXTRA_RETRIEVE_PRIMARY_KEY"));
+ m_retrieve_primary_key= TRUE;
break;
case HA_EXTRA_CHANGE_KEY_TO_UNIQUE:
DBUG_PRINT("info", ("HA_EXTRA_CHANGE_KEY_TO_UNIQUE"));
@@ -2712,8 +2835,8 @@ void ha_ndbcluster::start_bulk_insert(ha_rows rows)
DBUG_ENTER("start_bulk_insert");
DBUG_PRINT("enter", ("rows: %d", (int)rows));
- rows_inserted= 0;
- rows_to_insert= rows;
+ m_rows_inserted= 0;
+ m_rows_to_insert= rows;
/*
Calculate how many rows that should be inserted
@@ -2727,7 +2850,7 @@ void ha_ndbcluster::start_bulk_insert(ha_rows rows)
batch= bytesperbatch/bytes;
batch= batch == 0 ? 1 : batch;
DBUG_PRINT("info", ("batch: %d, bytes: %d", batch, bytes));
- bulk_insert_rows= batch;
+ m_bulk_insert_rows= batch;
DBUG_VOID_RETURN;
}
@@ -2741,22 +2864,22 @@ int ha_ndbcluster::end_bulk_insert()
DBUG_ENTER("end_bulk_insert");
// Check if last inserts need to be flushed
- if (bulk_insert_not_flushed)
+ if (m_bulk_insert_not_flushed)
{
NdbConnection *trans= m_active_trans;
// Send rows to NDB
DBUG_PRINT("info", ("Sending inserts to NDB, "\
"rows_inserted:%d, bulk_insert_rows: %d",
- rows_inserted, bulk_insert_rows));
- bulk_insert_not_flushed= FALSE;
+ m_rows_inserted, m_bulk_insert_rows));
+ m_bulk_insert_not_flushed= FALSE;
if (execute_no_commit(this,trans) != 0) {
no_uncommitted_rows_execute_failure();
my_errno= error= ndb_err(trans);
}
}
- rows_inserted= 0;
- rows_to_insert= 1;
+ m_rows_inserted= 0;
+ m_rows_to_insert= 1;
DBUG_RETURN(error);
}
@@ -2778,7 +2901,7 @@ int ha_ndbcluster::reset()
const char **ha_ndbcluster::bas_ext() const
-{ static const char *ext[]= { ".ndb", NullS }; return ext; }
+{ static const char *ext[]= { ha_ndb_ext, NullS }; return ext; }
/*
@@ -2937,13 +3060,24 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
pointer to point to the NDB transaction.
*/
+ // store thread specific data first to set the right context
+ m_force_send= thd->variables.ndb_force_send;
+ m_ha_not_exact_count= !thd->variables.ndb_use_exact_count;
+ m_autoincrement_prefetch= thd->variables.ndb_autoincrement_prefetch_sz;
+ if (!thd->transaction.on)
+ m_transaction_on= FALSE;
+ else
+ m_transaction_on= thd->variables.ndb_use_transactions;
+ // m_use_local_query_cache= thd->variables.ndb_use_local_query_cache;
+
m_active_trans= thd->transaction.all.ndb_tid ?
(NdbConnection*)thd->transaction.all.ndb_tid:
(NdbConnection*)thd->transaction.stmt.ndb_tid;
DBUG_ASSERT(m_active_trans);
// Start of transaction
- retrieve_all_fields= FALSE;
- ops_pending= 0;
+ m_retrieve_all_fields= FALSE;
+ m_retrieve_primary_key= FALSE;
+ m_ops_pending= 0;
{
NDBDICT *dict= m_ndb->getDictionary();
const NDBTAB *tab;
@@ -2991,13 +3125,13 @@ int ha_ndbcluster::external_lock(THD *thd, int lock_type)
DBUG_PRINT("warning", ("m_active_cursor != NULL"));
m_active_cursor= NULL;
- if (blobs_pending)
+ if (m_blobs_pending)
DBUG_PRINT("warning", ("blobs_pending != 0"));
- blobs_pending= 0;
+ m_blobs_pending= 0;
- if (ops_pending)
+ if (m_ops_pending)
DBUG_PRINT("warning", ("ops_pending != 0L"));
- ops_pending= 0;
+ m_ops_pending= 0;
}
DBUG_RETURN(error);
}
@@ -3034,8 +3168,9 @@ int ha_ndbcluster::start_stmt(THD *thd)
m_active_trans= trans;
// Start of statement
- retrieve_all_fields= FALSE;
- ops_pending= 0;
+ m_retrieve_all_fields= FALSE;
+ m_retrieve_primary_key= FALSE;
+ m_ops_pending= 0;
DBUG_RETURN(error);
}
@@ -3057,7 +3192,7 @@ int ndbcluster_commit(THD *thd, void *ndb_transaction)
"stmt" : "all"));
DBUG_ASSERT(ndb && trans);
- if (execute_commit(0,trans) != 0)
+ if (execute_commit(thd,trans) != 0)
{
const NdbError err= trans->getNdbError();
const NdbOperation *error_op= trans->getNdbErrorOperation();
@@ -3112,7 +3247,12 @@ static int create_ndb_column(NDBCOL &col,
HA_CREATE_INFO *info)
{
// Set name
- col.setName(field->field_name);
+ {
+ char truncated_field_name[NDB_MAX_ATTR_NAME_SIZE];
+ strnmov(truncated_field_name,field->field_name,sizeof(truncated_field_name));
+ truncated_field_name[sizeof(truncated_field_name)-1]= '\0';
+ col.setName(truncated_field_name);
+ }
// Get char set
CHARSET_INFO *cs= field->charset();
// Set type and sizes
@@ -3307,7 +3447,7 @@ int ha_ndbcluster::create(const char *name,
{
NDBTAB tab;
NDBCOL col;
- uint pack_length, length, i;
+ uint pack_length, length, i, pk_length= 0;
const void *data, *pack_data;
const char **key_names= form->keynames.type_names;
char name2[FN_HEADLEN];
@@ -3354,6 +3494,8 @@ int ha_ndbcluster::create(const char *name,
if ((my_errno= create_ndb_column(col, field, info)))
DBUG_RETURN(my_errno);
tab.addColumn(col);
+ if(col.getPrimaryKey())
+ pk_length += (field->pack_length() + 3) / 4;
}
// No primary key, create shadow key as 64 bit, auto increment
@@ -3367,6 +3509,39 @@ int ha_ndbcluster::create(const char *name,
col.setPrimaryKey(TRUE);
col.setAutoIncrement(TRUE);
tab.addColumn(col);
+ pk_length += 2;
+ }
+
+ // Make sure that blob tables don't have to big part size
+ for (i= 0; i < form->fields; i++)
+ {
+ /**
+ * The extra +7 concists
+ * 2 - words from pk in blob table
+ * 5 - from extra words added by tup/dict??
+ */
+ switch (form->field[i]->real_type()) {
+ case MYSQL_TYPE_BLOB:
+ case MYSQL_TYPE_MEDIUM_BLOB:
+ case MYSQL_TYPE_LONG_BLOB:
+ {
+ NdbDictionary::Column * col = tab.getColumn(i);
+ int size = pk_length + (col->getPartSize()+3)/4 + 7;
+ if(size > NDB_MAX_TUPLE_SIZE_IN_WORDS &&
+ (pk_length+7) < NDB_MAX_TUPLE_SIZE_IN_WORDS)
+ {
+ size = NDB_MAX_TUPLE_SIZE_IN_WORDS - pk_length - 7;
+ col->setPartSize(4*size);
+ }
+ /**
+ * If size > NDB_MAX and pk_length+7 >= NDB_MAX
+ * then the table can't be created anyway, so skip
+ * changing part size, and have error later
+ */
+ }
+ default:
+ break;
+ }
}
if ((my_errno= check_ndb_connection()))
@@ -3440,7 +3615,12 @@ int ha_ndbcluster::create_index(const char *name,
{
Field *field= key_part->field;
DBUG_PRINT("info", ("attr: %s", field->field_name));
- ndb_index.addColumnName(field->field_name);
+ {
+ char truncated_field_name[NDB_MAX_ATTR_NAME_SIZE];
+ strnmov(truncated_field_name,field->field_name,sizeof(truncated_field_name));
+ truncated_field_name[sizeof(truncated_field_name)-1]= '\0';
+ ndb_index.addColumnName(truncated_field_name);
+ }
}
if (dict->createIndex(ndb_index))
@@ -3567,13 +3747,17 @@ ulonglong ha_ndbcluster::get_auto_increment()
Uint64 auto_value;
DBUG_ENTER("get_auto_increment");
DBUG_PRINT("enter", ("m_tabname: %s", m_tabname));
- cache_size= ((rows_to_insert - rows_inserted < autoincrement_prefetch) ?
- rows_to_insert - rows_inserted :
- max(rows_to_insert, autoincrement_prefetch));
- auto_value= ((skip_auto_increment) ?
- m_ndb->readAutoIncrementValue((const NDBTAB *) m_table) :
- m_ndb->getAutoIncrementValue((const NDBTAB *) m_table, cache_size));
- DBUG_RETURN((ulonglong) auto_value);
+ cache_size=
+ (m_rows_to_insert - m_rows_inserted < m_autoincrement_prefetch) ?
+ m_rows_to_insert - m_rows_inserted
+ : (m_rows_to_insert > m_autoincrement_prefetch) ?
+ m_rows_to_insert
+ : m_autoincrement_prefetch;
+ auto_value=
+ (m_skip_auto_increment) ?
+ m_ndb->readAutoIncrementValue((const NDBTAB *) m_table)
+ : m_ndb->getAutoIncrementValue((const NDBTAB *) m_table, cache_size);
+ DBUG_RETURN((longlong)auto_value);
}
@@ -3591,21 +3775,29 @@ ha_ndbcluster::ha_ndbcluster(TABLE *table_arg):
m_table_flags(HA_REC_NOT_IN_SEQ |
HA_NULL_IN_KEY |
HA_AUTO_PART_KEY |
+ HA_NO_VARCHAR |
HA_NO_PREFIX_CHAR_KEYS),
m_share(0),
m_use_write(FALSE),
- m_ignore_dup_key_not_supported(FALSE),
- retrieve_all_fields(FALSE),
- rows_to_insert(1),
- rows_inserted(0),
- bulk_insert_rows(1024),
- bulk_insert_not_flushed(FALSE),
- ops_pending(0),
- skip_auto_increment(TRUE),
- blobs_pending(0),
- blobs_buffer(0),
- blobs_buffer_size(0),
- dupkey((uint) -1)
+ m_ignore_dup_key(FALSE),
+ m_primary_key_update(FALSE),
+ m_retrieve_all_fields(FALSE),
+ m_retrieve_primary_key(FALSE),
+ m_rows_to_insert(1),
+ m_rows_inserted(0),
+ m_bulk_insert_rows(1024),
+ m_bulk_insert_not_flushed(FALSE),
+ m_ops_pending(0),
+ m_skip_auto_increment(TRUE),
+ m_blobs_pending(0),
+ m_blobs_buffer(0),
+ m_blobs_buffer_size(0),
+ m_dupkey((uint) -1),
+ m_ha_not_exact_count(FALSE),
+ m_force_send(TRUE),
+ m_autoincrement_prefetch(32),
+ m_transaction_on(TRUE),
+ m_use_local_query_cache(FALSE)
{
int i;
@@ -3639,8 +3831,8 @@ ha_ndbcluster::~ha_ndbcluster()
if (m_share)
free_share(m_share);
release_metadata();
- my_free(blobs_buffer, MYF(MY_ALLOW_ZERO_PTR));
- blobs_buffer= 0;
+ my_free(m_blobs_buffer, MYF(MY_ALLOW_ZERO_PTR));
+ m_blobs_buffer= 0;
// Check for open cursor/transaction
if (m_active_cursor) {
@@ -4054,7 +4246,7 @@ bool ndbcluster_init()
new Ndb_cluster_connection(ndbcluster_connectstring)) == 0)
{
DBUG_PRINT("error",("Ndb_cluster_connection(%s)",ndbcluster_connectstring));
- DBUG_RETURN(TRUE);
+ goto ndbcluster_init_error;
}
// Create a Ndb object to open the connection to NDB
@@ -4063,25 +4255,33 @@ bool ndbcluster_init()
if (g_ndb->init() != 0)
{
ERR_PRINT (g_ndb->getNdbError());
- DBUG_RETURN(TRUE);
+ goto ndbcluster_init_error;
}
- if ((res= g_ndb_cluster_connection->connect(1)) == 0)
+ if ((res= g_ndb_cluster_connection->connect(0,0,0)) == 0)
{
+ DBUG_PRINT("info",("NDBCLUSTER storage engine at %s on port %d",
+ g_ndb_cluster_connection->get_connected_host(),
+ g_ndb_cluster_connection->get_connected_port()));
g_ndb->waitUntilReady(10);
}
else if(res == 1)
{
if (g_ndb_cluster_connection->start_connect_thread()) {
DBUG_PRINT("error", ("g_ndb_cluster_connection->start_connect_thread()"));
- DBUG_RETURN(TRUE);
+ goto ndbcluster_init_error;
+ }
+ {
+ char buf[1024];
+ DBUG_PRINT("info",("NDBCLUSTER storage engine not started, will connect using %s",
+ g_ndb_cluster_connection->get_connectstring(buf,sizeof(buf))));
}
}
else
{
DBUG_ASSERT(res == -1);
DBUG_PRINT("error", ("permanent error"));
- DBUG_RETURN(TRUE);
+ goto ndbcluster_init_error;
}
(void) hash_init(&ndbcluster_open_tables,system_charset_info,32,0,0,
@@ -4091,9 +4291,12 @@ bool ndbcluster_init()
ndbcluster_inited= 1;
#ifdef USE_DISCOVER_ON_STARTUP
if (ndb_discover_tables() != 0)
- DBUG_RETURN(TRUE);
+ goto ndbcluster_init_error;
#endif
DBUG_RETURN(FALSE);
+ ndbcluster_init_error:
+ ndbcluster_end();
+ DBUG_RETURN(TRUE);
}
@@ -4256,6 +4459,65 @@ ha_ndbcluster::records_in_range(uint inx, key_range *min_key,
DBUG_RETURN(10); /* Good guess when you don't know anything */
}
+ulong ha_ndbcluster::table_flags(void) const
+{
+ if (m_ha_not_exact_count)
+ return m_table_flags | HA_NOT_EXACT_COUNT;
+ else
+ return m_table_flags;
+}
+const char * ha_ndbcluster::table_type() const
+{
+ return("ndbcluster");
+}
+uint ha_ndbcluster::max_supported_record_length() const
+{
+ return NDB_MAX_TUPLE_SIZE;
+}
+uint ha_ndbcluster::max_supported_keys() const
+{
+ return MAX_KEY;
+}
+uint ha_ndbcluster::max_supported_key_parts() const
+{
+ return NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY;
+}
+uint ha_ndbcluster::max_supported_key_length() const
+{
+ return NDB_MAX_KEY_SIZE;
+}
+bool ha_ndbcluster::low_byte_first() const
+{
+#ifdef WORDS_BIGENDIAN
+ return FALSE;
+#else
+ return TRUE;
+#endif
+}
+bool ha_ndbcluster::has_transactions()
+{
+ return m_transaction_on;
+}
+const char* ha_ndbcluster::index_type(uint key_number)
+{
+ switch (get_index_type(key_number)) {
+ case ORDERED_INDEX:
+ case UNIQUE_ORDERED_INDEX:
+ case PRIMARY_KEY_ORDERED_INDEX:
+ return "BTREE";
+ case UNIQUE_INDEX:
+ case PRIMARY_KEY_INDEX:
+ default:
+ return "HASH";
+ }
+}
+uint8 ha_ndbcluster::table_cache_type()
+{
+ if (m_use_local_query_cache)
+ return HA_CACHE_TBL_TRANSACT;
+ else
+ return HA_CACHE_TBL_NOCACHE;
+}
/*
Handling the shared NDB_SHARE structure that is needed to
@@ -4422,13 +4684,12 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
{
DBUG_ENTER("ndb_get_table_statistics");
DBUG_PRINT("enter", ("table: %s", table));
-
+ NdbConnection* pTrans= ndb->startTransaction();
do
{
- NdbConnection* pTrans= ndb->startTransaction();
if (pTrans == NULL)
break;
-
+
NdbScanOperation* pOp= pTrans->getNdbScanOperation(table);
if (pOp == NULL)
break;
@@ -4445,13 +4706,13 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
pOp->getValue(NdbDictionary::Column::ROW_COUNT, (char*)&rows);
pOp->getValue(NdbDictionary::Column::COMMIT_COUNT, (char*)&commits);
- check= pTrans->execute(NoCommit);
+ check= pTrans->execute(NoCommit, AbortOnError, TRUE);
if (check == -1)
break;
Uint64 sum_rows= 0;
Uint64 sum_commits= 0;
- while((check= rs->nextResult(TRUE)) == 0)
+ while((check= rs->nextResult(TRUE, TRUE)) == 0)
{
sum_rows+= rows;
sum_commits+= commits;
@@ -4460,6 +4721,8 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
if (check == -1)
break;
+ rs->close(TRUE);
+
ndb->closeTransaction(pTrans);
if(row_count)
* row_count= sum_rows;
@@ -4469,6 +4732,7 @@ ndb_get_table_statistics(Ndb* ndb, const char * table,
DBUG_RETURN(0);
} while(0);
+ ndb->closeTransaction(pTrans);
DBUG_PRINT("exit", ("failed"));
DBUG_RETURN(-1);
}
diff --git a/sql/ha_ndbcluster.h b/sql/ha_ndbcluster.h
index 245d906c5ae..2f18a52b8e9 100644
--- a/sql/ha_ndbcluster.h
+++ b/sql/ha_ndbcluster.h
@@ -26,7 +26,6 @@
#endif
#include <ndbapi_limits.h>
-#include <ndb_types.h>
class Ndb; // Forward declaration
class NdbOperation; // Forward declaration
@@ -119,15 +118,14 @@ class ha_ndbcluster: public handler
int reset();
int external_lock(THD *thd, int lock_type);
int start_stmt(THD *thd);
- const char * table_type() const { return("ndbcluster");}
+ const char * table_type() const;
const char ** bas_ext() const;
- ulong table_flags(void) const { return m_table_flags; }
+ ulong table_flags(void) const;
ulong index_flags(uint idx, uint part, bool all_parts) const;
- uint max_supported_record_length() const { return NDB_MAX_TUPLE_SIZE; };
- uint max_supported_keys() const { return MAX_KEY; }
- uint max_supported_key_parts() const
- { return NDB_MAX_NO_OF_ATTRIBUTES_IN_KEY; };
- uint max_supported_key_length() const { return NDB_MAX_KEY_SIZE;};
+ uint max_supported_record_length() const;
+ uint max_supported_keys() const;
+ uint max_supported_key_parts() const;
+ uint max_supported_key_length() const;
int rename_table(const char *from, const char *to);
int delete_table(const char *name);
@@ -136,28 +134,9 @@ class ha_ndbcluster: public handler
THR_LOCK_DATA **to,
enum thr_lock_type lock_type);
- bool low_byte_first() const
- {
-#ifdef WORDS_BIGENDIAN
- return FALSE;
-#else
- return TRUE;
-#endif
- }
- bool has_transactions() { return TRUE; }
-
- const char* index_type(uint key_number) {
- switch (get_index_type(key_number)) {
- case ORDERED_INDEX:
- case UNIQUE_ORDERED_INDEX:
- case PRIMARY_KEY_ORDERED_INDEX:
- return "BTREE";
- case UNIQUE_INDEX:
- case PRIMARY_KEY_INDEX:
- default:
- return "HASH";
- }
- }
+ bool low_byte_first() const;
+ bool has_transactions();
+ const char* index_type(uint key_number);
double scan_time();
ha_rows records_in_range(uint inx, key_range *min_key, key_range *max_key);
@@ -166,7 +145,7 @@ class ha_ndbcluster: public handler
static Thd_ndb* seize_thd_ndb();
static void release_thd_ndb(Thd_ndb* thd_ndb);
- uint8 table_cache_type() { return HA_CACHE_TBL_NOCACHE; }
+ uint8 table_cache_type();
private:
int alter_table_name(const char *from, const char *to);
@@ -181,9 +160,11 @@ class ha_ndbcluster: public handler
void release_metadata();
NDB_INDEX_TYPE get_index_type(uint idx_no) const;
NDB_INDEX_TYPE get_index_type_from_table(uint index_no) const;
-
+ int check_index_fields_not_null(uint index_no);
+
int pk_read(const byte *key, uint key_len, byte *buf);
int complemented_pk_read(const byte *old_data, byte *new_data);
+ int peek_row();
int unique_index_read(const byte *key, uint key_len,
byte *buf);
int ordered_index_scan(const key_range *start_key,
@@ -243,19 +224,27 @@ class ha_ndbcluster: public handler
typedef union { NdbRecAttr *rec; NdbBlob *blob; void *ptr; } NdbValue;
NdbValue m_value[NDB_MAX_ATTRIBUTES_IN_TABLE];
bool m_use_write;
- bool m_ignore_dup_key_not_supported;
- bool retrieve_all_fields;
- ha_rows rows_to_insert;
- ha_rows rows_inserted;
- ha_rows bulk_insert_rows;
- bool bulk_insert_not_flushed;
- ha_rows ops_pending;
- bool skip_auto_increment;
- bool blobs_pending;
+ bool m_ignore_dup_key;
+ bool m_primary_key_update;
+ bool m_retrieve_all_fields;
+ bool m_retrieve_primary_key;
+ ha_rows m_rows_to_insert;
+ ha_rows m_rows_inserted;
+ ha_rows m_bulk_insert_rows;
+ bool m_bulk_insert_not_flushed;
+ ha_rows m_ops_pending;
+ bool m_skip_auto_increment;
+ bool m_blobs_pending;
// memory for blobs in one tuple
- char *blobs_buffer;
- uint32 blobs_buffer_size;
- uint dupkey;
+ char *m_blobs_buffer;
+ uint32 m_blobs_buffer_size;
+ uint m_dupkey;
+ // set from thread variables at external lock
+ bool m_ha_not_exact_count;
+ bool m_force_send;
+ ha_rows m_autoincrement_prefetch;
+ bool m_transaction_on;
+ bool m_use_local_query_cache;
void set_rec_per_key();
void records_update();
@@ -265,6 +254,8 @@ class ha_ndbcluster: public handler
void no_uncommitted_rows_reset(THD *);
friend int execute_no_commit(ha_ndbcluster*, NdbConnection*);
+ friend int execute_commit(ha_ndbcluster*, NdbConnection*);
+ friend int execute_no_commit_ie(ha_ndbcluster*, NdbConnection*);
};
bool ndbcluster_init(void);
diff --git a/sql/handler.cc b/sql/handler.cc
index bb5e980f7bf..edb4d5b488b 100644
--- a/sql/handler.cc
+++ b/sql/handler.cc
@@ -105,6 +105,9 @@ const char *tx_isolation_names[] =
TYPELIB tx_isolation_typelib= {array_elements(tx_isolation_names)-1,"",
tx_isolation_names, NULL};
+static TYPELIB known_extensions= {0,"known_exts", NULL, NULL};
+uint known_extensions_id= 0;
+
enum db_type ha_resolve_by_name(const char *name, uint namelen)
{
THD *thd= current_thd;
@@ -465,6 +468,21 @@ int ha_release_temporary_latches(THD *thd)
return 0;
}
+
+/*
+ Export statistics for different engines. Currently we use it only for
+ InnoDB.
+*/
+
+int ha_update_statistics()
+{
+#ifdef HAVE_INNOBASE_DB
+ if (opt_innodb)
+ innodb_export_status();
+#endif
+ return 0;
+}
+
int ha_commit_trans(THD *thd, THD_TRANS* trans)
{
int error=0;
@@ -514,7 +532,8 @@ int ha_commit_trans(THD *thd, THD_TRANS* trans)
if ((error=ndbcluster_commit(thd,trans->ndb_tid)))
{
if (error == -1)
- my_error(ER_ERROR_DURING_COMMIT, MYF(0));
+ my_message(ER_ERROR_DURING_COMMIT, ER(ER_ERROR_DURING_COMMIT),
+ MYF(0));
error=1;
}
if (trans == &thd->transaction.all)
@@ -577,13 +596,20 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
if (opt_using_transactions)
{
bool operation_done=0;
+ /*
+ As rollback can be 30 times slower than insert in InnoDB, and user may
+ not know there's rollback (if it's because of a dupl row), better warn.
+ */
+ const char *save_proc_info= thd->proc_info;
+ thd->proc_info= "Rolling back";
#ifdef HAVE_NDBCLUSTER_DB
if (trans->ndb_tid)
{
if ((error=ndbcluster_rollback(thd, trans->ndb_tid)))
{
if (error == -1)
- my_error(ER_ERROR_DURING_ROLLBACK, MYF(0));
+ my_message(ER_ERROR_DURING_ROLLBACK, ER(ER_ERROR_DURING_ROLLBACK),
+ MYF(0));
error=1;
}
trans->ndb_tid = 0;
@@ -648,6 +674,7 @@ int ha_rollback_trans(THD *thd, THD_TRANS *trans)
thd->variables.tx_isolation=thd->session_tx_isolation;
if (operation_done)
statistic_increment(thd->status_var.ha_rollback_count,&LOCK_status);
+ thd->proc_info= save_proc_info;
}
#endif /* USING_TRANSACTIONS */
DBUG_RETURN(error);
@@ -709,7 +736,7 @@ int ha_rollback_to_savepoint(THD *thd, char *savepoint_name)
if (unlikely((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) &&
my_b_tell(&thd->transaction.trans_log)))
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
if (mysql_bin_log.write(&qinfo))
error= 1;
}
@@ -747,7 +774,7 @@ int ha_savepoint(THD *thd, char *savepoint_name)
innobase_savepoint(thd,savepoint_name,
my_b_tell(&thd->transaction.trans_log));
#endif
- Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, TRUE, FALSE);
if (mysql_bin_log.write(&qinfo))
error= 1;
}
@@ -760,6 +787,25 @@ int ha_savepoint(THD *thd, char *savepoint_name)
DBUG_RETURN(error);
}
+
+int ha_start_consistent_snapshot(THD *thd)
+{
+#ifdef HAVE_INNOBASE_DB
+ if ((have_innodb == SHOW_OPTION_YES) &&
+ !innobase_start_trx_and_assign_read_view(thd))
+ return 0;
+#endif
+ /*
+ Same idea as when one wants to CREATE TABLE in one engine which does not
+ exist:
+ */
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_UNKNOWN_ERROR,
+ "This MySQL server does not support any "
+ "consistent-read capable storage engine");
+ return 0;
+}
+
+
bool ha_flush_logs()
{
bool result=0;
@@ -924,8 +970,10 @@ int handler::read_first_row(byte * buf, uint primary_key)
/*
If there is very few deleted rows in the table, find the first row by
scanning the table.
+ TODO remove the test for HA_READ_ORDER
*/
- if (deleted < 10 || primary_key >= MAX_KEY)
+ if (deleted < 10 || primary_key >= MAX_KEY ||
+ !(index_flags(primary_key, 0, 0) & HA_READ_ORDER))
{
(void) ha_rnd_init(1);
while ((error= rnd_next(buf)) == HA_ERR_RECORD_DELETED) ;
@@ -1169,7 +1217,7 @@ void handler::print_error(int error, myf errflag)
str.length(max_length-4);
str.append("...");
}
- my_error(ER_DUP_ENTRY,MYF(0),str.c_ptr(),key_nr+1);
+ my_error(ER_DUP_ENTRY, MYF(0), str.c_ptr(), key_nr+1);
DBUG_VOID_RETURN;
}
textno=ER_DUP_KEY;
@@ -1191,7 +1239,7 @@ void handler::print_error(int error, myf errflag)
textno=ER_CRASHED_ON_REPAIR;
break;
case HA_ERR_OUT_OF_MEM:
- my_error(ER_OUT_OF_RESOURCES,errflag);
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), errflag);
DBUG_VOID_RETURN;
case HA_ERR_WRONG_COMMAND:
textno=ER_ILLEGAL_HA;
@@ -1238,7 +1286,7 @@ void handler::print_error(int error, myf errflag)
uint length=dirname_part(buff,table->path);
buff[length-1]=0;
db=buff+dirname_length(buff);
- my_error(ER_NO_SUCH_TABLE,MYF(0),db,table->table_name);
+ my_error(ER_NO_SUCH_TABLE, MYF(0), db, table->table_name);
break;
}
default:
@@ -1252,16 +1300,16 @@ void handler::print_error(int error, myf errflag)
{
const char* engine= table_type();
if (temporary)
- my_error(ER_GET_TEMPORARY_ERRMSG,MYF(0),error,str.ptr(),engine);
+ my_error(ER_GET_TEMPORARY_ERRMSG, MYF(0), error, str.ptr(), engine);
else
- my_error(ER_GET_ERRMSG,MYF(0),error,str.ptr(),engine);
+ my_error(ER_GET_ERRMSG, MYF(0), error, str.ptr(), engine);
}
else
my_error(ER_GET_ERRNO,errflag,error);
DBUG_VOID_RETURN;
}
}
- my_error(textno,errflag,table->table_name,error);
+ my_error(textno, errflag, table->table_name, error);
DBUG_VOID_RETURN;
}
@@ -1383,7 +1431,7 @@ int ha_create_table(const char *name, HA_CREATE_INFO *create_info,
error=table.file->create(name,&table,create_info);
VOID(closefrm(&table));
if (error)
- my_error(ER_CANT_CREATE_TABLE,MYF(ME_BELL+ME_WAITTANG),name,error);
+ my_error(ER_CANT_CREATE_TABLE, MYF(ME_BELL+ME_WAITTANG), name,error);
DBUG_RETURN(error != 0);
}
@@ -1755,3 +1803,65 @@ int handler::index_read_idx(byte * buf, uint index, const byte * key,
error= ha_index_end();
return error;
}
+
+
+/*
+ Returns a list of all known extensions.
+
+ SYNOPSIS
+ ha_known_exts()
+
+ NOTES
+ No mutexes, worst case race is a minor surplus memory allocation
+ We have to recreate the extension map if mysqld is restarted (for example
+ within libmysqld)
+
+ RETURN VALUE
+ pointer pointer to TYPELIB structure
+*/
+
+TYPELIB *ha_known_exts(void)
+{
+ if (!known_extensions.type_names || mysys_usage_id != known_extensions_id)
+ {
+ show_table_type_st *types;
+ List<char> found_exts;
+ List_iterator_fast<char> it(found_exts);
+ const char **ext, *old_ext;
+
+ known_extensions_id= mysys_usage_id;
+ found_exts.push_back((char*) ".db");
+ for (types= sys_table_types; types->type; types++)
+ {
+ if (*types->value == SHOW_OPTION_YES)
+ {
+ handler *file= get_new_handler(0,(enum db_type) types->db_type);
+ for (ext= file->bas_ext(); *ext; ext++)
+ {
+ while ((old_ext= it++))
+ {
+ if (!strcmp(old_ext, *ext))
+ break;
+ }
+ if (!old_ext)
+ found_exts.push_back((char *) *ext);
+
+ it.rewind();
+ }
+ delete file;
+ }
+ }
+ ext= (const char **) my_once_alloc(sizeof(char *)*
+ (found_exts.elements+1),
+ MYF(MY_WME | MY_FAE));
+
+ DBUG_ASSERT(ext);
+ known_extensions.count= found_exts.elements;
+ known_extensions.type_names= ext;
+
+ while ((old_ext= it++))
+ *ext++= old_ext;
+ *ext= 0;
+ }
+ return &known_extensions;
+}
diff --git a/sql/handler.h b/sql/handler.h
index c408425ed60..c9adaefa888 100644
--- a/sql/handler.h
+++ b/sql/handler.h
@@ -44,6 +44,7 @@
#define HA_ADMIN_INVALID -5
#define HA_ADMIN_REJECT -6
#define HA_ADMIN_TRY_ALTER -7
+#define HA_ADMIN_WRONG_CHECKSUM -8
/* Bits in table_flags() to show what database can do */
#define HA_READ_RND_SAME (1 << 0) /* can switch index during the scan
@@ -73,6 +74,7 @@
#define HA_HAS_CHECKSUM (1 << 24)
/* Table data are stored in separate files (for lower_case_table_names) */
#define HA_FILE_BASED (1 << 26)
+#define HA_NO_VARCHAR (1 << 27)
/* bits in index_flags(index_number) for what you can do with index */
@@ -138,6 +140,8 @@
#define HA_CACHE_TBL_ASKTRANSACT 2
#define HA_CACHE_TBL_TRANSACT 4
+/* Options of START TRANSACTION statement (and later of SET TRANSACTION stmt) */
+#define MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT 1
enum db_type
{
@@ -191,6 +195,41 @@ typedef struct st_thd_trans {
void *ndb_tid;
} THD_TRANS;
+#ifndef XIDDATASIZE /* no xa.h included */
+
+/* XXX - may be we should disable xa completely in this case ? */
+#define XIDDATASIZE 128
+#define MAXGTRIDSIZE 64
+#define MAXBQUALSIZE 64
+
+struct xid_t {
+ long formatID;
+ long gtrid_length;
+ long bqual_length;
+ char data[XIDDATASIZE];
+};
+
+typedef struct xid_t XID;
+
+
+#endif
+
+typedef struct
+{
+ byte slot;
+ uint savepoint_offset;
+ int (*close_connection)(THD *thd);
+ int (*savepoint_set)(THD *thd, void *sv);
+ int (*savepoint_rollback)(THD *thd, void *sv);
+ int (*savepoint_release)(THD *thd, void *sv);
+ int (*commit)(THD *thd, bool all);
+ int (*rollback)(THD *thd, bool all);
+ int (*prepare)(THD *thd, bool all);
+ int (*recover)(XID *xid_list, uint len);
+ int (*commit_by_xid)(XID *xid);
+ int (*rollback_by_xid)(XID *xid);
+} handlerton;
+
enum enum_tx_isolation { ISO_READ_UNCOMMITTED, ISO_READ_COMMITTED,
ISO_REPEATABLE_READ, ISO_SERIALIZABLE};
@@ -214,6 +253,7 @@ typedef struct st_ha_create_information
uint merge_insert_method;
bool table_existed; /* 1 in create if table existed */
bool frm_only; /* 1 if no ha_create_table() */
+ bool varchar; /* 1 if table has a VARCHAR */
} HA_CREATE_INFO;
@@ -221,6 +261,8 @@ typedef struct st_ha_create_information
struct st_table;
typedef struct st_table TABLE;
+struct st_foreign_key_info;
+typedef struct st_foreign_key_info FOREIGN_KEY_INFO;
typedef struct st_ha_check_opt
{
@@ -409,7 +451,7 @@ public:
virtual int extra_opt(enum ha_extra_function operation, ulong cache_size)
{ return extra(operation); }
virtual int reset() { return extra(HA_EXTRA_RESET); }
- virtual int external_lock(THD *thd, int lock_type)=0;
+ virtual int external_lock(THD *thd, int lock_type) { return 0; }
virtual void unlock_row() {}
virtual int start_stmt(THD *thd) {return 0;}
/*
@@ -463,6 +505,8 @@ public:
virtual char* get_foreign_key_create_info()
{ return(NULL);} /* gets foreign key create string from InnoDB */
/* used in REPLACE; is > 0 if table is referred by a FOREIGN KEY */
+ virtual int get_foreign_key_list(THD *thd, List<FOREIGN_KEY_INFO> *f_key_list)
+ { return 0; }
virtual uint referenced_by_foreign_key() { return 0;}
virtual void init_table_handle_for_HANDLER()
{ return; } /* prepare InnoDB for HANDLER */
@@ -575,6 +619,7 @@ int ha_report_binlog_offset_and_commit(THD *thd, char *log_file_name,
my_off_t end_offset);
int ha_commit_complete(THD *thd);
int ha_release_temporary_latches(THD *thd);
+int ha_update_statistics();
int ha_commit_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_trans(THD *thd, THD_TRANS *trans);
int ha_rollback_to_savepoint(THD *thd, char *savepoint_name);
@@ -590,5 +635,5 @@ int ha_discover(THD* thd, const char* dbname, const char* name,
int ha_find_files(THD *thd,const char *db,const char *path,
const char *wild, bool dir,List<char>* files);
int ha_table_exists(THD* thd, const char* db, const char* name);
-
-
+TYPELIB *ha_known_exts(void);
+int ha_start_consistent_snapshot(THD *thd);
diff --git a/sql/item.cc b/sql/item.cc
index 6730b0dd4a2..f00a35fe628 100644
--- a/sql/item.cc
+++ b/sql/item.cc
@@ -26,6 +26,7 @@
#include "sql_acl.h"
#include "sp_head.h"
#include "sql_trigger.h"
+#include "sql_select.h"
static void mark_as_dependent(THD *thd,
SELECT_LEX *last, SELECT_LEX *current,
@@ -45,12 +46,11 @@ void item_init(void)
}
Item::Item():
- name_length(0), fixed(0),
+ name(0), orig_name(0), name_length(0), fixed(0),
collation(default_charset(), DERIVATION_COERCIBLE)
{
marker= 0;
maybe_null=null_value=with_sum_func=unsigned_flag=0;
- name= 0;
decimals= 0; max_length= 0;
/* Put item in free list so that we can free all items at end */
@@ -80,6 +80,7 @@ Item::Item():
Item::Item(THD *thd, Item *item):
str_value(item->str_value),
name(item->name),
+ orig_name(item->orig_name),
max_length(item->max_length),
marker(item->marker),
decimals(item->decimals),
@@ -110,25 +111,68 @@ void Item::print_item_w_name(String *str)
void Item::cleanup()
{
DBUG_ENTER("Item::cleanup");
- DBUG_PRINT("info", ("Item: 0x%lx", this));
- DBUG_PRINT("info", ("Type: %d", (int)type()));
+ DBUG_PRINT("info", ("Item: 0x%lx, Type: %d, name %s, original name %s",
+ this, (int)type(), name ? name : "(null)",
+ orig_name ? orig_name : "null"));
fixed=0;
marker= 0;
+ if (orig_name)
+ name= orig_name;
DBUG_VOID_RETURN;
}
+
+/*
+ cleanup() item if it is 'fixed'
+
+ SYNOPSIS
+ cleanup_processor()
+ arg - a dummy parameter, is not used here
+*/
+
+bool Item::cleanup_processor(byte *arg)
+{
+ if (fixed)
+ cleanup();
+ return FALSE;
+}
+
+
+/*
+ rename item (used for views, cleanup() return original name)
+
+ SYNOPSIS
+ Item::rename()
+ new_name new name of item;
+*/
+
+void Item::rename(char *new_name)
+{
+ /*
+ we can compare pointers to names here, bacause if name was not changed,
+ pointer will be same
+ */
+ if (!orig_name && new_name != name)
+ orig_name= name;
+ name= new_name;
+}
+
+
Item_ident::Item_ident(const char *db_name_par,const char *table_name_par,
const char *field_name_par)
:orig_db_name(db_name_par), orig_table_name(table_name_par),
orig_field_name(field_name_par),
- db_name(db_name_par), table_name(table_name_par),
- field_name(field_name_par), cached_field_index(NO_CACHED_FIELD_INDEX),
+ db_name(db_name_par), table_name(table_name_par),
+ field_name(field_name_par),
+ alias_name_used(FALSE), cached_field_index(NO_CACHED_FIELD_INDEX),
cached_table(0), depended_from(0)
{
name = (char*) field_name_par;
}
-// Constructor used by Item_field & Item_ref (see Item comment)
+
+/* Constructor used by Item_field & Item_ref (see Item comment) */
+
Item_ident::Item_ident(THD *thd, Item_ident *item)
:Item(thd, item),
orig_db_name(item->orig_db_name),
@@ -137,6 +181,7 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
db_name(item->db_name),
table_name(item->table_name),
field_name(item->field_name),
+ alias_name_used(item->alias_name_used),
cached_field_index(item->cached_field_index),
cached_table(item->cached_table),
depended_from(item->depended_from)
@@ -145,10 +190,14 @@ Item_ident::Item_ident(THD *thd, Item_ident *item)
void Item_ident::cleanup()
{
DBUG_ENTER("Item_ident::cleanup");
- DBUG_PRINT("enter", ("b:%s(%s), t:%s(%s), f:%s(%s)",
- db_name, orig_db_name,
- table_name, orig_table_name,
- field_name, orig_field_name));
+#ifdef CANT_BE_USED_AS_MEMORY_IS_FREED
+ db_name ? db_name : "(null)",
+ orig_db_name ? orig_db_name : "(null)",
+ table_name ? table_name : "(null)",
+ orig_table_name ? orig_table_name : "(null)",
+ field_name ? field_name : "(null)",
+ orig_field_name ? orig_field_name : "(null)"));
+#endif
Item::cleanup();
db_name= orig_db_name;
table_name= orig_table_name;
@@ -261,6 +310,41 @@ bool Item::eq(const Item *item, bool binary_cmp) const
}
+Item *Item::safe_charset_converter(CHARSET_INFO *tocs)
+{
+ /*
+ Don't allow automatic conversion to non-Unicode charsets,
+ as it potentially loses data.
+ */
+ if (!(tocs->state & MY_CS_UNICODE))
+ return NULL; // safe conversion is not possible
+ return new Item_func_conv_charset(this, tocs);
+}
+
+
+Item *Item_string::safe_charset_converter(CHARSET_INFO *tocs)
+{
+ Item_string *conv;
+ uint conv_errors;
+ String tmp, cstr, *ostr= val_str(&tmp);
+ cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(), tocs, &conv_errors);
+ if (conv_errors || !(conv= new Item_string(cstr.ptr(), cstr.length(),
+ cstr.charset(),
+ collation.derivation)))
+ {
+ /*
+ Safe conversion is not possible (or EOM).
+ We could not convert a string into the requested character set
+ without data loss. The target charset does not cover all the
+ characters from the string. Operation cannot be done correctly.
+ */
+ return NULL;
+ }
+ conv->str_value.copy();
+ return conv;
+}
+
+
bool Item_string::eq(const Item *item, bool binary_cmp) const
{
if (type() == item->type())
@@ -355,7 +439,43 @@ Item_splocal::type() const
}
-bool DTCollation::aggregate(DTCollation &dt, bool superset_conversion)
+
+/*
+ Aggregate two collations together taking
+ into account their coercibility (aka derivation):
+
+ 0 == DERIVATION_EXPLICIT - an explicitely written COLLATE clause
+ 1 == DERIVATION_NONE - a mix of two different collations
+ 2 == DERIVATION_IMPLICIT - a column
+ 3 == DERIVATION_COERCIBLE - a string constant
+
+ The most important rules are:
+
+ 1. If collations are the same:
+ chose this collation, and the strongest derivation.
+
+ 2. If collations are different:
+ - Character sets may differ, but only if conversion without
+ data loss is possible. The caller provides flags whether
+ character set conversion attempts should be done. If no
+ flags are substituted, then the character sets must be the same.
+ Currently processed flags are:
+ MY_COLL_ALLOW_SUPERSET_CONV - allow conversion to a superset
+ MY_COLL_ALLOW_COERCIBLE_CONV - allow conversion of a coercible value
+ - two EXPLICIT collations produce an error, e.g. this is wrong:
+ CONCAT(expr1 collate latin1_swedish_ci, expr2 collate latin1_german_ci)
+ - the side with smaller derivation value wins,
+ i.e. a column is stronger than a string constant,
+ an explicit COLLATE clause is stronger than a column.
+ - if derivations are the same, we have DERIVATION_NONE,
+ we'll wait for an explicit COLLATE clause which possibly can
+ come from another argument later: for example, this is valid,
+ but we don't know yet when collecting the first two arguments:
+ CONCAT(latin1_swedish_ci_column,
+ latin1_german1_ci_column,
+ expr COLLATE latin1_german2_ci)
+*/
+bool DTCollation::aggregate(DTCollation &dt, uint flags)
{
nagg++;
if (!my_charset_same(collation, dt.collation))
@@ -386,28 +506,37 @@ bool DTCollation::aggregate(DTCollation &dt, bool superset_conversion)
else
; // Do nothing
}
- else if (superset_conversion)
+ else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
+ derivation < dt.derivation &&
+ collation->state & MY_CS_UNICODE)
{
- if (derivation < dt.derivation &&
- collation->state & MY_CS_UNICODE)
- ; // Do nothing
- else if (dt.derivation < derivation &&
- dt.collation->state & MY_CS_UNICODE)
- {
- set(dt);
- strong= nagg;
- }
- else
- {
- // Cannot convert to superset
- set(0, DERIVATION_NONE);
- return 1;
- }
+ // Do nothing
+ }
+ else if ((flags & MY_COLL_ALLOW_SUPERSET_CONV) &&
+ dt.derivation < derivation &&
+ dt.collation->state & MY_CS_UNICODE)
+ {
+ set(dt);
+ strong= nagg;
+ }
+ else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
+ derivation < dt.derivation &&
+ dt.derivation >= DERIVATION_COERCIBLE)
+ {
+ // Do nothing;
+ }
+ else if ((flags & MY_COLL_ALLOW_COERCIBLE_CONV) &&
+ dt.derivation < derivation &&
+ derivation >= DERIVATION_COERCIBLE)
+ {
+ set(dt);
+ strong= nagg;
}
else
{
+ // Cannot apply conversion
set(0, DERIVATION_NONE);
- return 1;
+ return 1;
}
}
else if (derivation < dt.derivation)
@@ -511,6 +640,7 @@ void Item_field::set_field(Field *field_par)
table_name=field_par->table_name;
field_name=field_par->field_name;
db_name=field_par->table->table_cache_key;
+ alias_name_used= field_par->table->alias_name_used;
unsigned_flag=test(field_par->flags & UNSIGNED_FLAG);
collation.set(field_par->charset(), DERIVATION_IMPLICIT);
fixed= 1;
@@ -560,7 +690,8 @@ void Item_ident::print(String *str)
THD *thd= current_thd;
char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
const char *d_name= db_name, *t_name= table_name;
- if (lower_case_table_names)
+ if (lower_case_table_names== 1 ||
+ (lower_case_table_names == 2 && !alias_name_used))
{
if (table_name && table_name[0])
{
@@ -582,7 +713,7 @@ void Item_ident::print(String *str)
append_identifier(thd, str, nm, strlen(nm));
return;
}
- if (db_name && db_name[0])
+ if (db_name && db_name[0] && !alias_name_used)
{
append_identifier(thd, str, d_name, strlen(d_name));
str->append('.');
@@ -613,7 +744,7 @@ String *Item_field::val_str(String *str)
return field->val_str(str,&str_value);
}
-double Item_field::val()
+double Item_field::val_real()
{
DBUG_ASSERT(fixed == 1);
if ((null_value=field->is_null()))
@@ -806,7 +937,7 @@ void Item_string::print(String *str)
bool Item_null::eq(const Item *item, bool binary_cmp) const
{ return item->type() == type(); }
-double Item_null::val()
+double Item_null::val_real()
{
// following assert is redundant, because fixed=1 assigned in constructor
DBUG_ASSERT(fixed == 1);
@@ -830,6 +961,12 @@ String *Item_null::val_str(String *str)
}
+Item *Item_null::safe_charset_converter(CHARSET_INFO *tocs)
+{
+ collation.set(tocs);
+ return this;
+}
+
/*********************** Item_param related ******************************/
/*
@@ -845,12 +982,13 @@ default_set_param_func(Item_param *param,
param->set_null();
}
+
Item_param::Item_param(unsigned pos_in_query_arg) :
state(NO_VALUE),
item_result_type(STRING_RESULT),
/* Don't pretend to be a literal unless value for this item is set. */
item_type(PARAM_ITEM),
- param_type(MYSQL_TYPE_STRING),
+ param_type(MYSQL_TYPE_VARCHAR),
pos_in_query(pos_in_query_arg),
set_param_func(default_set_param_func)
{
@@ -863,6 +1001,7 @@ Item_param::Item_param(unsigned pos_in_query_arg) :
maybe_null= 1;
}
+
void Item_param::set_null()
{
DBUG_ENTER("Item_param::set_null");
@@ -903,6 +1042,21 @@ void Item_param::set_double(double d)
}
+/*
+ Set parameter value from TIME value.
+
+ SYNOPSIS
+ set_time()
+ tm - datetime value to set (time_type is ignored)
+ type - type of datetime value
+ max_length_arg - max length of datetime value as string
+
+ NOTE
+ If we value to be stored is not normalized, zero value will be stored
+ instead and proper warning will be produced. This function relies on
+ the fact that even wrong value sent over binary protocol fits into
+ MAX_DATE_STRING_REP_LENGTH buffer.
+*/
void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg)
{
DBUG_ENTER("Item_param::set_time");
@@ -910,6 +1064,17 @@ void Item_param::set_time(TIME *tm, timestamp_type type, uint32 max_length_arg)
value.time= *tm;
value.time.time_type= type;
+ if (value.time.year > 9999 || value.time.month > 12 ||
+ value.time.day > 31 ||
+ type != MYSQL_TIMESTAMP_TIME && value.time.hour > 23 ||
+ value.time.minute > 59 || value.time.second > 59)
+ {
+ char buff[MAX_DATE_STRING_REP_LENGTH];
+ uint length= my_TIME_to_str(&value.time, buff);
+ make_truncated_value_warning(current_thd, buff, length, type, 0);
+ set_zero_time(&value.time, MYSQL_TIMESTAMP_ERROR);
+ }
+
state= TIME_VALUE;
maybe_null= 0;
max_length= max_length_arg;
@@ -925,7 +1090,9 @@ bool Item_param::set_str(const char *str, ulong length)
Assign string with no conversion: data is converted only after it's
been written to the binary log.
*/
- if (str_value.copy(str, length, &my_charset_bin, &my_charset_bin))
+ uint dummy_errors;
+ if (str_value.copy(str, length, &my_charset_bin, &my_charset_bin,
+ &dummy_errors))
DBUG_RETURN(TRUE);
state= STRING_VALUE;
maybe_null= 0;
@@ -1115,7 +1282,7 @@ bool Item_param::get_date(TIME *res, uint fuzzydate)
}
-double Item_param::val()
+double Item_param::val_real()
{
switch (state) {
case REAL_VALUE:
@@ -1282,6 +1449,10 @@ bool Item_param::convert_str_value(THD *thd)
value.cs_info.character_set_client,
value.cs_info.final_character_set_of_str_value);
}
+ else
+ str_value.set_charset(value.cs_info.final_character_set_of_str_value);
+ /* Here str_value is guaranteed to be in final_character_set_of_str_value */
+
max_length= str_value.length();
decimals= 0;
/*
@@ -1356,10 +1527,10 @@ bool Item::fix_fields(THD *thd,
// We do not check fields which are fixed during construction
DBUG_ASSERT(fixed == 0 || basic_const_item());
fixed= 1;
- return 0;
+ return FALSE;
}
-double Item_ref_null_helper::val()
+double Item_ref_null_helper::val_real()
{
DBUG_ASSERT(fixed == 1);
double tmp= (*ref)->val_result();
@@ -1423,170 +1594,418 @@ static void mark_as_dependent(THD *thd, SELECT_LEX *last, SELECT_LEX *current,
}
-bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
+
+
+/*
+ Search a GROUP BY clause for a field with a certain name.
+
+ SYNOPSIS
+ find_field_in_group_list()
+ find_item the item being searched for
+ group_list GROUP BY clause
+
+ DESCRIPTION
+ Search the GROUP BY list for a column named as find_item. When searching
+ preference is given to columns that are qualified with the same table (and
+ database) name as the one being searched for.
+
+ RETURN
+ - the found item on success
+ - NULL if find_item is not in group_list
+*/
+
+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;
+ ORDER *found_group= NULL;
+ int found_match_degree= 0;
+ Item_field *cur_field;
+ int cur_match_degree= 0;
+
+ if (find_item->type() == Item::FIELD_ITEM ||
+ find_item->type() == Item::REF_ITEM)
+ {
+ db_name= ((Item_ident*) find_item)->db_name;
+ table_name= ((Item_ident*) find_item)->table_name;
+ field_name= ((Item_ident*) find_item)->field_name;
+ }
+ else
+ return NULL;
+
+ DBUG_ASSERT(field_name);
+
+ for (ORDER *cur_group= group_list ; cur_group ; cur_group= cur_group->next)
+ {
+ if ((*(cur_group->item))->type() == Item::FIELD_ITEM)
+ {
+ cur_field= (Item_field*) *cur_group->item;
+ cur_match_degree= 0;
+
+ DBUG_ASSERT(cur_field->field_name);
+
+ if (!my_strcasecmp(system_charset_info,
+ cur_field->field_name, field_name))
+ ++cur_match_degree;
+ else
+ continue;
+
+ if (cur_field->table_name && table_name)
+ {
+ /* If field_name is qualified by a table name. */
+ if (strcmp(cur_field->table_name, table_name))
+ /* Same field names, different tables. */
+ return NULL;
+
+ ++cur_match_degree;
+ if (cur_field->db_name && db_name)
+ {
+ /* If field_name is also qualified by a database name. */
+ if (strcmp(cur_field->db_name, db_name))
+ /* Same field names, different databases. */
+ return NULL;
+ ++cur_match_degree;
+ }
+ }
+
+ if (cur_match_degree > found_match_degree)
+ {
+ found_match_degree= cur_match_degree;
+ found_group= cur_group;
+ }
+ else if (found_group && (cur_match_degree == found_match_degree) &&
+ ! (*(found_group->item))->eq(cur_field, 0))
+ {
+ /*
+ If the current resolve candidate matches equally well as the current
+ best match, they must reference the same column, otherwise the field
+ is ambiguous.
+ */
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ find_item->full_name(), current_thd->where);
+ return NULL;
+ }
+ }
+ }
+
+ if (found_group)
+ return found_group->item;
+ else
+ return NULL;
+}
+
+
+/*
+ Resolve a column reference in a sub-select.
+
+ SYNOPSIS
+ resolve_ref_in_select_and_group()
+ thd current thread
+ ref column reference being resolved
+ select the sub-select that ref is resolved against
+
+ DESCRIPTION
+ Resolve a column reference (usually inside a HAVING clause) against the
+ SELECT and GROUP BY clauses of the query described by 'select'. The name
+ resolution algorithm searches both the SELECT and GROUP BY clauses, and in
+ case of a name conflict prefers GROUP BY column names over SELECT names. If
+ both clauses contain different fields with the same names, a warning is
+ issued that name of 'ref' is ambiguous. We extend ANSI SQL in that when no
+ GROUP BY column is found, then a HAVING name is resolved as a possibly
+ derived SELECT column.
+
+ NOTES
+ The resolution procedure is:
+ - Search for a column or derived column named col_ref_i [in table T_j]
+ in the SELECT clause of Q.
+ - Search for a column named col_ref_i [in table T_j]
+ in the GROUP BY clause of Q.
+ - If found different columns with the same name in GROUP BY and SELECT
+ - issue a warning and return the GROUP BY column,
+ - otherwise return the found SELECT column.
+
+
+ RETURN
+ NULL - there was an error, and the error was already reported
+ not_found_item - the item was not resolved, no error was reported
+ resolved item - if the item was resolved
+*/
+
+static Item**
+resolve_ref_in_select_and_group(THD *thd, Item_ident *ref, SELECT_LEX *select)
+{
+ Item **group_by_ref= NULL;
+ Item **select_ref= NULL;
+ ORDER *group_list= (ORDER*) select->group_list.first;
+ bool ambiguous_fields= FALSE;
+ uint counter;
+ bool not_used;
+
+ /*
+ Search for a column or derived column named as 'ref' in the SELECT
+ clause of the current select.
+ */
+ if (!(select_ref= find_item_in_list(ref, *(select->get_item_list()), &counter,
+ REPORT_EXCEPT_NOT_FOUND, &not_used)))
+ return NULL; /* Some error occurred. */
+
+ /* If this is a non-aggregated field inside HAVING, search in GROUP BY. */
+ if (select->having_fix_field && !ref->with_sum_func && group_list)
+ {
+ group_by_ref= find_field_in_group_list(ref, group_list);
+
+ /* Check if the fields found in SELECT and GROUP BY are the same field. */
+ if (group_by_ref && (select_ref != not_found_item) &&
+ !((*group_by_ref)->eq(*select_ref, 0)))
+ {
+ ambiguous_fields= TRUE;
+ push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_NON_UNIQ_ERROR,
+ ER(ER_NON_UNIQ_ERROR), ref->full_name(),
+ current_thd->where);
+
+ }
+ }
+
+ if (select_ref != not_found_item || group_by_ref)
+ {
+ if (select_ref != not_found_item && !ambiguous_fields)
+ {
+ DBUG_ASSERT(*select_ref);
+ if (! (*select_ref)->fixed)
+ {
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0),
+ ref->name, "forward reference in item list");
+ return NULL;
+ }
+ return (select->ref_pointer_array + counter);
+ }
+ else if (group_by_ref)
+ return group_by_ref;
+ else
+ {
+ DBUG_ASSERT(FALSE);
+ return NULL; /* So there is no compiler warning. */
+ }
+ }
+ else
+ return (Item**) not_found_item;
+}
+
+
+/*
+ Resolve the name of a column reference.
+
+ SYNOPSIS
+ Item_field::fix_fields()
+ thd [in] current thread
+ tables [in] the tables in a FROM clause
+ reference [in/out] view column if this item was resolved to a view column
+
+ DESCRIPTION
+ The method resolves the column reference represented by 'this' as a column
+ present in one of: FROM clause, SELECT clause, GROUP BY clause of a query
+ Q, or in outer queries that contain Q.
+
+ NOTES
+ The name resolution algorithm used is (where [T_j] is an optional table
+ name that qualifies the column name):
+
+ resolve_column_reference([T_j].col_ref_i)
+ {
+ search for a column or derived column named col_ref_i
+ [in table T_j] in the FROM clause of Q;
+
+ if such a column is NOT found AND // Lookup in outer queries.
+ there are outer queries
+ {
+ for each outer query Q_k beginning from the inner-most one
+ {
+ if - Q_k is not a group query AND
+ - Q_k is not inside an aggregate function
+ OR
+ - Q_(k-1) is not in a HAVING or SELECT clause of Q_k
+ {
+ search for a column or derived column named col_ref_i
+ [in table T_j] in the FROM clause of Q_k;
+ }
+
+ if such a column is not found
+ Search for a column or derived column named col_ref_i
+ [in table T_j] in the SELECT and GROUP clauses of Q_k.
+ }
+ }
+ }
+
+ Notice that compared to Item_ref::fix_fields, here we first search the FROM
+ clause, and then we search the SELECT and GROUP BY clauses.
+
+ RETURN
+ TRUE if error
+ FALSE on success
+*/
+
+bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
{
DBUG_ASSERT(fixed == 0);
if (!field) // If field is not checked
{
- bool upward_lookup= 0;
- Field *tmp= (Field *)not_found_field;
- if ((tmp= find_field_in_tables(thd, this, tables, ref, 0,
+ bool upward_lookup= FALSE;
+ Field *from_field= (Field *)not_found_field;
+ if ((from_field= find_field_in_tables(thd, this, tables, reference,
+ IGNORE_EXCEPT_NON_UNIQUE,
!any_privileges)) ==
not_found_field)
{
- /*
- We can't find table field in table list of current select,
- consequently we have to find it in outer subselect(s).
- We can't join lists of outer & current select, because of scope
- of view rules. For example if both tables (outer & current) have
- field 'field' it is not mistake to refer to this field without
- mention of table name, but if we join tables in one list it will
- cause error ER_NON_UNIQ_ERROR in find_field_in_tables.
- */
SELECT_LEX *last= 0;
-#ifdef EMBEDDED_LIBRARY
- thd->net.last_errno= 0;
-#endif
TABLE_LIST *table_list;
- Item **refer= (Item **)not_found_item;
- uint counter;
- bool not_used;
- // Prevent using outer fields in subselects, that is not supported now
- SELECT_LEX *cursel= (SELECT_LEX *) thd->lex->current_select;
- if (cursel->master_unit()->first_select()->linkage != DERIVED_TABLE_TYPE)
+ Item **ref= (Item **) not_found_item;
+ SELECT_LEX *current_sel= (SELECT_LEX *) thd->lex->current_select;
+ /*
+ If there is an outer select, and it is not a derived table (which do
+ not support the use of outer fields for now), try to resolve this
+ reference in the outer select(s).
+
+ We treat each subselect as a separate namespace, so that different
+ subselects may contain columns with the same names. The subselects are
+ searched starting from the innermost.
+ */
+ if (current_sel->master_unit()->first_select()->linkage !=
+ DERIVED_TABLE_TYPE)
{
- SELECT_LEX_UNIT *prev_unit= cursel->master_unit();
- for (SELECT_LEX *sl= prev_unit->outer_select();
- sl;
- sl= (prev_unit= sl->master_unit())->outer_select())
+ SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
+ SELECT_LEX *outer_sel= prev_unit->outer_select();
+ for ( ; outer_sel ;
+ outer_sel= (prev_unit= outer_sel->master_unit())->outer_select())
{
- upward_lookup= 1;
- table_list= (last= sl)->get_table_list();
- if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
- {
+ last= outer_sel;
+ Item_subselect *prev_subselect_item= prev_unit->item;
+ upward_lookup= TRUE;
+
+ /* Search in the tables of the FROM clause of the outer select. */
+ table_list= outer_sel->get_table_list();
+ if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
/*
- it is primary INSERT st_select_lex => skip first table
- resolving
+ It is a primary INSERT st_select_lex => do not resolve against the
+ first table.
*/
table_list= table_list->next_local;
- }
- Item_subselect *prev_subselect_item= prev_unit->item;
enum_parsing_place place= prev_subselect_item->parsing_place;
/*
- check table fields only if subquery used somewhere out of HAVING
- or outer SELECT do not use groupping (i.e. tables are accessable)
+ Check table fields only if the subquery is used somewhere out of
+ HAVING, or the outer SELECT does not use grouping (i.e. tables are
+ accessible).
*/
if ((place != IN_HAVING ||
- (sl->with_sum_func == 0 && sl->group_list.elements == 0)) &&
- (tmp= find_field_in_tables(thd, this,
- table_list, ref,
- 0, 1)) != not_found_field)
+ (outer_sel->with_sum_func == 0 &&
+ outer_sel->group_list.elements == 0)) &&
+ (from_field= find_field_in_tables(thd, this, table_list,
+ reference,
+ IGNORE_EXCEPT_NON_UNIQUE,
+ TRUE)) !=
+ not_found_field)
{
- if (tmp)
+ if (from_field)
{
- if (tmp != view_ref_found)
+ if (from_field != view_ref_found)
{
- prev_subselect_item->used_tables_cache|= tmp->table->map;
+ prev_subselect_item->used_tables_cache|= from_field->table->map;
prev_subselect_item->const_item_cache= 0;
}
else
{
prev_subselect_item->used_tables_cache|=
- (*ref)->used_tables();
+ (*reference)->used_tables();
prev_subselect_item->const_item_cache&=
- (*ref)->const_item();
+ (*reference)->const_item();
}
}
break;
}
- if (sl->resolve_mode == SELECT_LEX::SELECT_MODE &&
- (refer= find_item_in_list(this, sl->item_list, &counter,
- REPORT_EXCEPT_NOT_FOUND,
- &not_used)) !=
- (Item **) not_found_item)
+
+ /* Search in the SELECT and GROUP lists of the outer select. */
+ if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE)
{
- if (*refer && (*refer)->fixed) // Avoid crash in case of error
- {
- prev_subselect_item->used_tables_cache|= (*refer)->used_tables();
- prev_subselect_item->const_item_cache&= (*refer)->const_item();
- }
- break;
+ if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel)))
+ return TRUE; /* Some error occured (e.g. ambigous names). */
+ if (ref != not_found_item)
+ {
+ DBUG_ASSERT(*ref && (*ref)->fixed);
+ prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
+ prev_subselect_item->const_item_cache&= (*ref)->const_item();
+ break;
+ }
}
// Reference is not found => depend from outer (or just error)
prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
prev_subselect_item->const_item_cache= 0;
- if (sl->master_unit()->first_select()->linkage ==
+ if (outer_sel->master_unit()->first_select()->linkage ==
DERIVED_TABLE_TYPE)
break; // do not look over derived table
}
}
- if (!tmp)
- return -1;
- if (!refer)
- return 1;
- if (tmp == not_found_field && refer == (Item **)not_found_item)
+
+ DBUG_ASSERT(ref);
+ if (!from_field)
+ return TRUE;
+ if (ref == not_found_item && from_field == not_found_field)
{
if (upward_lookup)
{
- // We can't say exactly what absend table or field
- my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
- full_name(), thd->where);
+ // We can't say exactly what absent table or field
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), full_name(), thd->where);
}
else
{
// Call to report error
- find_field_in_tables(thd, this, tables, ref, 1, 1);
+ find_field_in_tables(thd, this, tables, reference, REPORT_ALL_ERRORS,
+ TRUE);
}
- return -1;
+ return TRUE;
}
- else if (refer != (Item **)not_found_item)
+ else if (ref != not_found_item)
{
- if (!(*refer)->fixed)
- {
- my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
- "forward reference in item list");
- return -1;
- }
+ /* Should have been checked in resolve_ref_in_select_and_group(). */
+ DBUG_ASSERT(*ref && (*ref)->fixed);
- Item_ref *rf= new Item_ref(last->ref_pointer_array + counter,
- (char *)table_name, (char *)field_name);
+ Item_ref *rf= new Item_ref(ref, (char *)table_name, (char *)field_name);
if (!rf)
- return 1;
- thd->change_item_tree(ref, rf);
+ return TRUE;
+ thd->change_item_tree(reference, rf);
/*
rf is Item_ref => never substitute other items (in this case)
during fix_fields() => we can use rf after fix_fields()
*/
- if (rf->fix_fields(thd, tables, ref) || rf->check_cols(1))
- return 1;
+ if (rf->fix_fields(thd, tables, reference) || rf->check_cols(1))
+ return TRUE;
- mark_as_dependent(thd, last, cursel, rf);
- return 0;
+ mark_as_dependent(thd, last, current_sel, rf);
+ return FALSE;
}
else
{
- mark_as_dependent(thd, last, cursel, this);
+ mark_as_dependent(thd, last, current_sel, this);
if (last->having_fix_field)
{
Item_ref *rf;
rf= new Item_ref((cached_table->db[0] ? cached_table->db : 0),
(char*) cached_table->alias, (char*) field_name);
if (!rf)
- return 1;
- thd->change_item_tree(ref, rf);
+ return TRUE;
+ thd->change_item_tree(reference, rf);
/*
rf is Item_ref => never substitute other items (in this case)
during fix_fields() => we can use rf after fix_fields()
*/
- return rf->fix_fields(thd, tables, ref) || rf->check_cols(1);
+ return rf->fix_fields(thd, tables, reference) || rf->check_cols(1);
}
}
}
- else if (!tmp)
- return -1;
+ else if (!from_field)
+ return TRUE;
/*
if it is not expression from merged VIEW we will set this field.
@@ -1600,8 +2019,8 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
Also we suppose that view can't be changed during PS/SP life.
*/
- if (tmp != view_ref_found)
- set_field(tmp);
+ if (from_field != view_ref_found)
+ set_field(from_field);
}
else if (thd->set_query_id && field->query_id != thd->query_id)
{
@@ -1629,22 +2048,25 @@ bool Item_field::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
db, tab, field_name) &
VIEW_ANY_ACL)))
{
- my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
- ER(ER_COLUMNACCESS_DENIED_ERROR),
- MYF(0),
- "ANY",
- thd->priv_user,
- thd->host_or_ip,
- field_name,
- tab);
- return 1;
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ "ANY", thd->priv_user, thd->host_or_ip,
+ field_name, tab);
+ return TRUE;
}
}
#endif
fixed= 1;
- return 0;
+ return FALSE;
}
+
+Item *Item_field::safe_charset_converter(CHARSET_INFO *tocs)
+{
+ no_const_subst= 1;
+ return Item::safe_charset_converter(tocs);
+}
+
+
void Item_field::cleanup()
{
DBUG_ENTER("Item_field::cleanup");
@@ -1819,18 +2241,56 @@ void Item::make_field(Send_field *tmp_field)
void Item_empty_string::make_field(Send_field *tmp_field)
{
- init_make_field(tmp_field,FIELD_TYPE_VAR_STRING);
+ init_make_field(tmp_field, MYSQL_TYPE_VARCHAR);
}
enum_field_types Item::field_type() const
{
- return ((result_type() == STRING_RESULT) ? FIELD_TYPE_VAR_STRING :
+ return ((result_type() == STRING_RESULT) ? MYSQL_TYPE_VARCHAR :
(result_type() == INT_RESULT) ? FIELD_TYPE_LONGLONG :
FIELD_TYPE_DOUBLE);
}
+/*
+ Create a field to hold a string value from an item
+
+ SYNOPSIS
+ make_string_field()
+ table Table for which the field is created
+
+ IMPLEMENTATION
+ If max_length > CONVERT_IF_BIGGER_TO_BLOB create a blob
+ If max_length > 0 create a varchar
+ If max_length == 0 create a CHAR(0)
+*/
+
+
+Field *Item::make_string_field(TABLE *table)
+{
+ if (max_length > CONVERT_IF_BIGGER_TO_BLOB)
+ return new Field_blob(max_length, maybe_null, name, table,
+ collation.collation);
+ if (max_length > 0)
+ return new Field_varstring(max_length, maybe_null, name, table,
+ collation.collation);
+ return new Field_string(max_length, maybe_null, name, table,
+ collation.collation);
+}
+
+
+/*
+ Create a field based on field_type of argument
+
+ For now, this is only used to create a field for
+ IFNULL(x,something)
+
+ RETURN
+ 0 error
+ # Created field
+*/
+
Field *Item::tmp_table_field_from_field_type(TABLE *table)
{
/*
@@ -1880,32 +2340,24 @@ Field *Item::tmp_table_field_from_field_type(TABLE *table)
return new Field_year((char*) 0, max_length, null_ptr, 0, Field::NONE,
name, table);
default:
- /* This case should never be choosen */
+ /* 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_ENUM:
case MYSQL_TYPE_SET:
- case MYSQL_TYPE_VAR_STRING:
- if (max_length > 255)
- break; // If blob
- return new Field_varstring(max_length, maybe_null, name, table,
- collation.collation);
case MYSQL_TYPE_STRING:
- if (max_length > 255) // If blob
- break;
- return new Field_string(max_length, maybe_null, name, table,
- collation.collation);
+ 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:
case MYSQL_TYPE_GEOMETRY:
+ return new Field_blob(max_length, maybe_null, name, table,
+ collation.collation);
break; // Blob handled outside of case
}
-
- /* blob is special as it's generated for both blobs and long strings */
- return new Field_blob(max_length, maybe_null, name, table,
- collation.collation);
}
@@ -2018,7 +2470,7 @@ int Item::save_in_field(Field *field, bool no_conversions)
}
else if (result_type() == REAL_RESULT)
{
- double nr=val();
+ double nr= val_real();
if (null_value)
return set_field_to_null(field);
field->set_notnull();
@@ -2088,8 +2540,7 @@ Item_real::Item_real(const char *str_arg, uint length)
when we are in the parser
*/
DBUG_ASSERT(str_arg[length] == 0);
- my_printf_error(ER_ILLEGAL_VALUE_FOR_TYPE, ER(ER_ILLEGAL_VALUE_FOR_TYPE),
- MYF(0), "double", (char*) str_arg);
+ my_error(ER_ILLEGAL_VALUE_FOR_TYPE, MYF(0), "double", (char*) str_arg);
}
presentation= name=(char*) str_arg;
decimals=(uint8) nr_of_decimals(str_arg);
@@ -2100,7 +2551,7 @@ Item_real::Item_real(const char *str_arg, uint length)
int Item_real::save_in_field(Field *field, bool no_conversions)
{
- double nr=val();
+ double nr= val_real();
if (null_value)
return set_field_to_null(field);
field->set_notnull();
@@ -2220,6 +2671,7 @@ bool Item::send(Protocol *protocol, String *buffer)
case MYSQL_TYPE_GEOMETRY:
case MYSQL_TYPE_STRING:
case MYSQL_TYPE_VAR_STRING:
+ case MYSQL_TYPE_VARCHAR:
{
String *res;
if ((res=val_str(buffer)))
@@ -2262,15 +2714,14 @@ bool Item::send(Protocol *protocol, String *buffer)
case MYSQL_TYPE_FLOAT:
{
float nr;
- nr= (float) val();
+ nr= (float) val_real();
if (!null_value)
result= protocol->store(nr, decimals, buffer);
break;
}
case MYSQL_TYPE_DOUBLE:
{
- double nr;
- nr= val();
+ double nr= val_real();
if (!null_value)
result= protocol->store(nr, decimals, buffer);
break;
@@ -2312,218 +2763,255 @@ bool Item_field::send(Protocol *protocol, String *buffer)
/*
- This is used for HAVING clause
- Find field in select list having the same name
+ Resolve the name of a reference to a column reference.
+
+ SYNOPSIS
+ Item_ref::fix_fields()
+ thd [in] current thread
+ tables [in] the tables in a FROM clause
+ reference [in/out] view column if this item was resolved to a view column
+
+ DESCRIPTION
+ The method resolves the column reference represented by 'this' as a column
+ present in one of: GROUP BY clause, SELECT clause, outer queries. It is
+ used typically for columns in the HAVING clause which are not under
+ aggregate functions.
+
+ NOTES
+ The name resolution algorithm used is (where [T_j] is an optional table
+ name that qualifies the column name):
+
+ resolve_extended([T_j].col_ref_i)
+ {
+ Search for a column or derived column named col_ref_i [in table T_j]
+ in the SELECT and GROUP clauses of Q.
+
+ if such a column is NOT found AND // Lookup in outer queries.
+ there are outer queries
+ {
+ for each outer query Q_k beginning from the inner-most one
+ {
+ Search for a column or derived column named col_ref_i
+ [in table T_j] in the SELECT and GROUP clauses of Q_k.
+
+ if such a column is not found AND
+ - Q_k is not a group query AND
+ - Q_k is not inside an aggregate function
+ OR
+ - Q_(k-1) is not in a HAVING or SELECT clause of Q_k
+ {
+ search for a column or derived column named col_ref_i
+ [in table T_j] in the FROM clause of Q_k;
+ }
+ }
+ }
+ }
+
+ This procedure treats GROUP BY and SELECT clauses as one namespace for
+ column references in HAVING. Notice that compared to
+ Item_field::fix_fields, here we first search the SELECT and GROUP BY
+ clauses, and then we search the FROM clause.
+
+ RETURN
+ TRUE if error
+ FALSE on success
*/
bool Item_ref::fix_fields(THD *thd, TABLE_LIST *tables, Item **reference)
{
DBUG_ASSERT(fixed == 0);
- uint counter;
- bool not_used;
+ SELECT_LEX *current_sel= thd->lex->current_select;
+
if (!ref)
{
- TABLE_LIST *table_list;
- bool upward_lookup= 0;
- SELECT_LEX_UNIT *prev_unit= thd->lex->current_select->master_unit();
- SELECT_LEX *sl= prev_unit->outer_select();
- /*
- Finding only in current select will be performed for selects that have
- not outer one and for derived tables (which not support using outer
- fields for now)
- */
- if ((ref= find_item_in_list(this,
- *(thd->lex->current_select->get_item_list()),
- &counter,
- ((sl &&
- thd->lex->current_select->master_unit()->
- first_select()->linkage !=
- DERIVED_TABLE_TYPE) ?
- REPORT_EXCEPT_NOT_FOUND :
- REPORT_ALL_ERRORS), &not_used)) ==
- (Item **)not_found_item)
+ SELECT_LEX_UNIT *prev_unit= current_sel->master_unit();
+ SELECT_LEX *outer_sel= prev_unit->outer_select();
+ ORDER *group_list= (ORDER*) current_sel->group_list.first;
+ bool ambiguous_fields= FALSE;
+ Item **group_by_ref= NULL;
+
+ if (!(ref= resolve_ref_in_select_and_group(thd, this, current_sel)))
+ return TRUE; /* Some error occured (e.g. ambigous names). */
+
+ if (ref == not_found_item) /* This reference was not resolved. */
{
- Field *tmp= (Field*) not_found_field;
- SELECT_LEX *last= 0;
- upward_lookup= 1;
/*
- We can't find table field in select list of current select,
- consequently we have to find it in outer subselect(s).
- We can't join lists of outer & current select, because of scope
- of view rules. For example if both tables (outer & current) have
- field 'field' it is not mistake to refer to this field without
- mention of table name, but if we join tables in one list it will
- cause error ER_NON_UNIQ_ERROR in find_item_in_list.
+ If there is an outer select, and it is not a derived table (which do
+ not support the use of outer fields for now), try to resolve this
+ reference in the outer select(s).
+
+ We treat each subselect as a separate namespace, so that different
+ subselects may contain columns with the same names. The subselects are
+ searched starting from the innermost.
*/
- for ( ; sl ; sl= (prev_unit= sl->master_unit())->outer_select())
+ if (outer_sel && (current_sel->master_unit()->first_select()->linkage !=
+ DERIVED_TABLE_TYPE))
{
- last= sl;
- Item_subselect *prev_subselect_item= prev_unit->item;
- if (sl->resolve_mode == SELECT_LEX::SELECT_MODE &&
- (ref= find_item_in_list(this, sl->item_list,
- &counter, REPORT_EXCEPT_NOT_FOUND,
- &not_used)) !=
- (Item **)not_found_item)
- {
- if (*ref && (*ref)->fixed) // Avoid crash in case of error
- {
- prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
- prev_subselect_item->const_item_cache&= (*ref)->const_item();
- }
- break;
- }
- table_list= sl->get_table_list();
- if (sl->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
- {
- // it is primary INSERT st_select_lex => skip first table resolving
- table_list= table_list->next_local;
- }
- enum_parsing_place place= prev_subselect_item->parsing_place;
- /*
- Check table fields only if subquery used somewhere out of HAVING
- or SELECT list or outer SELECT do not use groupping (i.e. tables
- are accessable)
- */
- if ((place != IN_HAVING ||
- (sl->with_sum_func == 0 && sl->group_list.elements == 0)) &&
- (tmp= find_field_in_tables(thd, this,
- table_list, reference,
- 0, 1)) != not_found_field)
- {
- if (tmp)
+ TABLE_LIST *table_list;
+ Field *from_field= (Field*) not_found_field;
+ SELECT_LEX *last= 0;
+
+ for ( ; outer_sel ;
+ outer_sel= (prev_unit= outer_sel->master_unit())->outer_select())
+ {
+ last= outer_sel;
+ Item_subselect *prev_subselect_item= prev_unit->item;
+
+ /* Search in the SELECT and GROUP lists of the outer select. */
+ if (outer_sel->resolve_mode == SELECT_LEX::SELECT_MODE)
{
- if (tmp != view_ref_found)
+ if (!(ref= resolve_ref_in_select_and_group(thd, this, outer_sel)))
+ return TRUE; /* Some error occured (e.g. ambigous names). */
+ if (ref != not_found_item)
{
- prev_subselect_item->used_tables_cache|= tmp->table->map;
- prev_subselect_item->const_item_cache= 0;
+ DBUG_ASSERT(*ref && (*ref)->fixed);
+ prev_subselect_item->used_tables_cache|= (*ref)->used_tables();
+ prev_subselect_item->const_item_cache&= (*ref)->const_item();
+ break;
}
- else
+ }
+
+ /* Search in the tables of the FROM clause of the outer select. */
+ table_list= outer_sel->get_table_list();
+ if (outer_sel->resolve_mode == SELECT_LEX::INSERT_MODE && table_list)
+ /*
+ It is a primary INSERT st_select_lex => do not resolve against the
+ first table.
+ */
+ table_list= table_list->next_local;
+
+ enum_parsing_place place= prev_subselect_item->parsing_place;
+ /*
+ Check table fields only if the subquery is used somewhere out of
+ HAVING or the outer SELECT does not use grouping (i.e. tables are
+ accessible).
+ TODO:
+ Here we could first find the field anyway, and then test this
+ condition, so that we can give a better error message -
+ ER_WRONG_FIELD_WITH_GROUP, instead of the less informative
+ ER_BAD_FIELD_ERROR which we produce now.
+ */
+ if ((place != IN_HAVING ||
+ (!outer_sel->with_sum_func &&
+ outer_sel->group_list.elements == 0)))
+ {
+ if ((from_field= find_field_in_tables(thd, this, table_list,
+ reference,
+ IGNORE_EXCEPT_NON_UNIQUE,
+ TRUE)) !=
+ not_found_field)
{
- prev_subselect_item->used_tables_cache|=
- (*reference)->used_tables();
- prev_subselect_item->const_item_cache&=
- (*reference)->const_item();
+ if (from_field != view_ref_found)
+ {
+ prev_subselect_item->used_tables_cache|= from_field->table->map;
+ prev_subselect_item->const_item_cache= 0;
+ }
+ else
+ {
+ prev_subselect_item->used_tables_cache|=
+ (*reference)->used_tables();
+ prev_subselect_item->const_item_cache&=
+ (*reference)->const_item();
+ }
+ break;
}
}
- break;
- }
- // Reference is not found => depend from outer (or just error)
- prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
- prev_subselect_item->const_item_cache= 0;
+ /* Reference is not found => depend on outer (or just error). */
+ prev_subselect_item->used_tables_cache|= OUTER_REF_TABLE_BIT;
+ prev_subselect_item->const_item_cache= 0;
- if (sl->master_unit()->first_select()->linkage ==
- DERIVED_TABLE_TYPE)
- break; // do not look over derived table
- }
+ if (outer_sel->master_unit()->first_select()->linkage ==
+ DERIVED_TABLE_TYPE)
+ break; /* Do not consider derived tables. */
+ }
- if (!ref)
- return 1;
- if (!tmp)
- return -1;
- if (ref == (Item **)not_found_item && tmp == not_found_field)
- {
- if (upward_lookup)
- {
- // We can't say exactly what absend (table or field)
- my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
- full_name(), thd->where);
- }
- else
- {
- // Call to report error
- find_item_in_list(this,
- *(thd->lex->current_select->get_item_list()),
- &counter, REPORT_ALL_ERRORS, &not_used);
- }
- ref= 0; // Safety
- return 1;
- }
- if (tmp != not_found_field)
- {
- /*
- Set ref to 0 as we are replacing this item with the found item
- and this will ensure we get an error if this item would be
- used elsewhere
- */
- ref= 0; // Safety
- if (tmp != view_ref_found)
- {
- Item_field* fld;
- if (!(fld= new Item_field(tmp)))
- return 1;
- thd->change_item_tree(reference, fld);
- mark_as_dependent(thd, last, thd->lex->current_select, fld);
- return 0;
- }
- /*
- We can leave expression substituted from view for next PS/SP
- rexecution (i.e. do not register this substitution for reverting
- on cleupup() (register_item_tree_changing())), because this
- subtree will be fix_field'ed during
- setup_tables()->setup_ancestor() (i.e. before all other
- expressions of query, and references on tables which do not
- present in query will not make problems.
-
- Also we suppose that view can't be changed during PS/SP life.
- */
- }
- else
- {
- if (!(*ref)->fixed)
+ DBUG_ASSERT(ref);
+ if (!from_field)
+ return TRUE;
+ if (ref == not_found_item && from_field == not_found_field)
{
- my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
- "forward reference in item list");
- return -1;
+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
+ this->full_name(), current_thd->where);
+ ref= 0; // Safety
+ return TRUE;
+ }
+ if (from_field != not_found_field)
+ {
+ /*
+ Set ref to 0 as we are replacing this item with the found item and
+ this will ensure we get an error if this item would be used
+ elsewhere
+ */
+ ref= 0; // Safety
+ if (from_field != view_ref_found)
+ {
+ Item_field* fld;
+ if (!(fld= new Item_field(from_field)))
+ return TRUE;
+ thd->change_item_tree(reference, fld);
+ mark_as_dependent(thd, last, thd->lex->current_select, fld);
+ return FALSE;
+ }
+ /*
+ We can leave expression substituted from view for next PS/SP
+ re-execution (i.e. do not register this substitution for reverting
+ on cleanup() (register_item_tree_changing())), because this subtree
+ will be fix_field'ed during setup_tables()->setup_ancestor()
+ (i.e. before all other expressions of query, and references on
+ tables which do not present in query will not make problems.
+
+ Also we suppose that view can't be changed during PS/SP life.
+ */
+ }
+ else
+ {
+ /* Should be checked in resolve_ref_in_select_and_group(). */
+ DBUG_ASSERT(*ref && (*ref)->fixed);
+ mark_as_dependent(thd, last, current_sel, this);
}
- mark_as_dependent(thd, last, thd->lex->current_select,
- this);
- ref= last->ref_pointer_array + counter;
}
- }
- else if (!ref)
- return 1;
- else
- {
- if (!(*ref)->fixed)
+ else
{
- my_error(ER_ILLEGAL_REFERENCE, MYF(0), name,
- "forward reference in item list");
- return -1;
+ /* The current reference cannot be resolved in this query. */
+ my_error(ER_BAD_FIELD_ERROR,MYF(0),
+ this->full_name(), current_thd->where);
+ return TRUE;
}
- ref= thd->lex->current_select->ref_pointer_array + counter;
}
}
/*
- The following conditional is changed as to correctly identify
- incorrect references in group functions or forward references
- with sub-select's / derived tables, while it prevents this
- check when Item_ref is created in an expression involving
- summing function, which is to be placed in the user variable.
+ Check if this is an incorrect reference in a group function or forward
+ reference. Do not issue an error if this is an unnamed reference inside an
+ aggregate function.
*/
if (((*ref)->with_sum_func && name &&
(depended_from ||
- !(thd->lex->current_select->linkage != GLOBAL_OPTIONS_TYPE &&
- thd->lex->current_select->having_fix_field))) ||
+ !(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?
- "reference on group function":
- "forward reference in item list"));
- return 1;
+ my_error(ER_ILLEGAL_REFERENCE, MYF(0),
+ name, ((*ref)->with_sum_func?
+ "reference to group function":
+ "forward reference in item list"));
+ return TRUE;
}
max_length= (*ref)->max_length;
maybe_null= (*ref)->maybe_null;
decimals= (*ref)->decimals;
collation.set((*ref)->collation);
with_sum_func= (*ref)->with_sum_func;
+ if ((*ref)->type() == FIELD_ITEM)
+ alias_name_used= ((Item_ident *) (*ref))->alias_name_used;
+ else
+ alias_name_used= TRUE; // it is not field, so it is was resolved by alias
fixed= 1;
if (ref && (*ref)->check_cols(1))
- return 1;
- return 0;
+ return TRUE;
+ return FALSE;
}
@@ -2561,7 +3049,7 @@ double Item_ref::val_result()
return 0.0;
return result_field->val_real();
}
- return val();
+ return val_real();
}
@@ -2627,34 +3115,33 @@ bool Item_default_value::fix_fields(THD *thd,
if (!arg)
{
fixed= 1;
- return 0;
+ return FALSE;
}
if (arg->fix_fields(thd, table_list, &arg))
- return 1;
+ return TRUE;
if (arg->type() == REF_ITEM)
{
Item_ref *ref= (Item_ref *)arg;
if (ref->ref[0]->type() != FIELD_ITEM)
{
- return 1;
+ return TRUE;
}
arg= ref->ref[0];
}
field_arg= (Item_field *)arg;
if (field_arg->field->flags & NO_DEFAULT_VALUE_FLAG)
{
- my_printf_error(ER_NO_DEFAULT_FOR_FIELD, ER(ER_NO_DEFAULT_FOR_FIELD),
- MYF(0), field_arg->field->field_name);
- return 1;
+ my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), field_arg->field->field_name);
+ return TRUE;
}
if (!(def_field= (Field*) sql_alloc(field_arg->field->size_of())))
- return 1;
+ return TRUE;
memcpy(def_field, field_arg->field, field_arg->field->size_of());
def_field->move_field(def_field->table->default_values -
def_field->table->record[0]);
set_field(def_field);
- return 0;
+ return FALSE;
}
void Item_default_value::print(String *str)
@@ -2682,14 +3169,14 @@ bool Item_insert_value::fix_fields(THD *thd,
{
DBUG_ASSERT(fixed == 0);
if (arg->fix_fields(thd, table_list, &arg))
- return 1;
+ return TRUE;
if (arg->type() == REF_ITEM)
{
Item_ref *ref= (Item_ref *)arg;
if (ref->ref[0]->type() != FIELD_ITEM)
{
- return 1;
+ return TRUE;
}
arg= ref->ref[0];
}
@@ -2698,7 +3185,7 @@ bool Item_insert_value::fix_fields(THD *thd,
{
Field *def_field= (Field*) sql_alloc(field_arg->field->size_of());
if (!def_field)
- return 1;
+ return TRUE;
memcpy(def_field, field_arg->field, field_arg->field->size_of());
def_field->move_field(def_field->table->insert_values -
def_field->table->record[0]);
@@ -2711,7 +3198,7 @@ bool Item_insert_value::fix_fields(THD *thd,
set_field(new Field_null(0, 0, Field::NONE, tmp_field->field_name,
tmp_field->table, &my_charset_bin));
}
- return 0;
+ return FALSE;
}
void Item_insert_value::print(String *str)
@@ -2735,16 +3222,12 @@ void Item_insert_value::print(String *str)
NOTE
This function does almost the same as fix_fields() for Item_field
but is invoked during trigger definition parsing and takes TABLE
- object as its argument.
-
- RETURN VALUES
- 0 ok
- 1 field was not found.
+ object as its argument. If proper field was not found in table
+ error will be reported at fix_fields() time.
*/
-bool Item_trigger_field::setup_field(THD *thd, TABLE *table,
+void Item_trigger_field::setup_field(THD *thd, TABLE *table,
enum trg_event_type event)
{
- bool result= 1;
uint field_idx= (uint)-1;
bool save_set_query_id= thd->set_query_id;
@@ -2758,12 +3241,9 @@ bool Item_trigger_field::setup_field(THD *thd, TABLE *table,
field= (row_version == OLD_ROW && event == TRG_EVENT_UPDATE) ?
table->triggers->old_field[field_idx] :
table->field[field_idx];
- result= 0;
}
thd->set_query_id= save_set_query_id;
-
- return result;
}
@@ -2787,10 +3267,18 @@ bool Item_trigger_field::fix_fields(THD *thd,
FIXME may be we still should bother about permissions here.
*/
DBUG_ASSERT(fixed == 0);
- // QQ: May be this should be moved to setup_field?
- set_field(field);
- fixed= 1;
- return 0;
+
+ if (field)
+ {
+ // QQ: May be this should be moved to setup_field?
+ set_field(field);
+ fixed= 1;
+ return 0;
+ }
+
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), field_name,
+ (row_version == NEW_ROW) ? "NEW" : "OLD");
+ return 1;
}
@@ -2863,7 +3351,7 @@ void resolve_const_item(THD *thd, Item **ref, Item *comp_item)
}
else
{ // It must REAL_RESULT
- double result=item->val();
+ 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 Item_null(name) : (Item*)
@@ -2898,7 +3386,7 @@ bool field_is_equal_to_item(Field *field,Item *item)
}
if (res_type == INT_RESULT)
return 1; // Both where of type int
- double result=item->val();
+ double result= item->val_real();
if (item->null_value)
return 1;
return result == field->val_real();
@@ -2971,7 +3459,7 @@ void Item_cache_str::store(Item *item)
}
-double Item_cache_str::val()
+double Item_cache_str::val_real()
{
DBUG_ASSERT(fixed == 1);
int err;
@@ -3202,10 +3690,10 @@ bool Item_type_holder::join_types(THD *thd, Item *item)
if (item_type == STRING_RESULT && collation.aggregate(item->collation))
{
my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
- old_cs, old_derivation,
- item->collation.collation->name,
- item->collation.derivation_name(),
- "UNION");
+ old_cs, old_derivation,
+ item->collation.collation->name,
+ item->collation.derivation_name(),
+ "UNION");
return 1;
}
@@ -3239,7 +3727,7 @@ uint32 Item_type_holder::real_length(Item *item)
}
}
-double Item_type_holder::val()
+double Item_type_holder::val_real()
{
DBUG_ASSERT(0); // should never be called
return 0.0;
@@ -3275,5 +3763,6 @@ void Item_result_field::cleanup()
template class List<Item>;
template class List_iterator<Item>;
template class List_iterator_fast<Item>;
+template class List_iterator_fast<Item_field>;
template class List<List_item>;
#endif
diff --git a/sql/item.h b/sql/item.h
index d3e53af1523..cf3dc8896a5 100644
--- a/sql/item.h
+++ b/sql/item.h
@@ -32,12 +32,32 @@ class Item_field;
enum Derivation
{
+ DERIVATION_IGNORABLE= 4,
DERIVATION_COERCIBLE= 3,
DERIVATION_IMPLICIT= 2,
DERIVATION_NONE= 1,
DERIVATION_EXPLICIT= 0
};
+/*
+ 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
+ (combintion of the above two)
+ 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_ALLOW_CONV 3
+#define MY_COLL_DISALLOW_NONE 4
+#define MY_COLL_CMP_CONV 7
+
class DTCollation {
public:
CHARSET_INFO *collation;
@@ -73,13 +93,14 @@ public:
{ collation= collation_arg; }
void set(Derivation derivation_arg)
{ derivation= derivation_arg; }
- bool aggregate(DTCollation &dt, bool superset_conversion= FALSE);
- bool set(DTCollation &dt1, DTCollation &dt2, bool superset_conversion= FALSE)
- { set(dt1); return aggregate(dt2, superset_conversion); }
+ bool aggregate(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_IGNORABLE: return "IGNORABLE";
case DERIVATION_COERCIBLE: return "COERCIBLE";
case DERIVATION_IMPLICIT: return "IMPLICIT";
case DERIVATION_EXPLICIT: return "EXPLICIT";
@@ -99,8 +120,9 @@ public:
static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
- static void operator delete(void *ptr,size_t size) {}
- static void operator delete(void *ptr,size_t size, MEM_ROOT *mem_root) {}
+ static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
+ static void operator delete(void *ptr,size_t size, MEM_ROOT *mem_root)
+ { TRASH(ptr, size); }
enum Type {FIELD_ITEM, FUNC_ITEM, SUM_FUNC_ITEM, STRING_ITEM,
INT_ITEM, REAL_ITEM, NULL_ITEM, VARBIN_ITEM,
@@ -118,6 +140,8 @@ public:
*/
String str_value;
my_string name; /* Name from select */
+ /* Original item name (if it was renamed)*/
+ my_string orig_name;
Item *next;
uint32 max_length;
uint name_length; /* Length of name */
@@ -145,9 +169,11 @@ public:
name=0;
} /*lint -e1509 */
void set_name(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(Send_field *field);
+ Field *make_string_field(TABLE *table);
virtual bool fix_fields(THD *, struct st_table_list *, Item **);
/*
should be used in case where we are sure that we do not need
@@ -167,7 +193,7 @@ public:
virtual enum_field_types field_type() const;
virtual enum Type type() const =0;
/* valXXX methods must return NULL or 0 or 0.0 if null_value is set. */
- virtual double val()=0;
+ virtual double val_real()=0;
virtual longlong val_int()=0;
/*
Return string representation of this item object.
@@ -198,7 +224,7 @@ public:
virtual Field *get_tmp_table_field() { return 0; }
virtual Field *tmp_table_field(TABLE *t_arg) { return 0; }
virtual const char *full_name() const { return name ? name : "???"; }
- virtual double val_result() { return val(); }
+ virtual double val_result() { return val_real(); }
virtual longlong val_int_result() { return val_int(); }
virtual String *str_result(String* tmp) { return val_str(tmp); }
/* bit map of tables used by item */
@@ -245,6 +271,14 @@ public:
virtual bool get_time(TIME *ltime);
virtual bool get_date_result(TIME *ltime,uint fuzzydate)
{ return get_date(ltime,fuzzydate); }
+ /*
+ This function is used only in Item_func_isnull/Item_func_isnotnull
+ (implementations of IS NULL/IS NOT NULL clauses). Item_func_is{not}null
+ calls this method instead of one of val/result*() methods, which
+ normally will set null_value. This allows to determine nullness of
+ a complex expression without fully evaluating it.
+ Any new item which can be NULL must implement this call.
+ */
virtual bool is_null() { return 0; }
/*
it is "top level" item of WHERE clause and we do not need correct NULL
@@ -283,6 +317,7 @@ public:
virtual bool remove_dependence_processor(byte * arg) { return 0; }
virtual bool remove_fixed(byte * arg) { fixed= 0; return 0; }
+ virtual bool cleanup_processor(byte *arg);
virtual bool collect_item_field_processor(byte * arg) { return 0; }
virtual Item *equal_fields_propagator(byte * arg) { return this; }
virtual Item *set_no_const_sub(byte *arg) { return this; }
@@ -305,6 +340,7 @@ public:
virtual Item_field *filed_for_view_update() { return 0; }
virtual Item *neg_transformer(THD *thd) { return NULL; }
+ virtual Item *safe_charset_converter(CHARSET_INFO *tocs);
void delete_self()
{
cleanup();
@@ -341,10 +377,10 @@ public:
// the item in the frame
enum Type type() const;
- inline double val()
+ inline double val_real()
{
Item *it= this_item();
- double ret= it->val();
+ double ret= it->val_real();
Item::null_value= it->null_value;
return ret;
}
@@ -436,6 +472,7 @@ public:
const char *db_name;
const char *table_name;
const char *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.
stmts for speeding up their re-execution. Holds NO_CACHED_FIELD_INDEX
@@ -505,7 +542,7 @@ public:
Item_field(Field *field);
enum Type type() const { return FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- double val();
+ double val_real();
longlong val_int();
String *val_str(String*);
double val_result();
@@ -541,6 +578,7 @@ public:
bool replace_equal_field_processor(byte *arg);
inline uint32 max_disp_length() { return field->max_length(); }
Item_field *filed_for_view_update() { return this; }
+ Item *safe_charset_converter(CHARSET_INFO *tocs);
friend class Item_default_value;
friend class Item_insert_value;
friend class st_select_lex_unit;
@@ -555,10 +593,11 @@ public:
max_length= 0;
name= name_par ? name_par : (char*) "NULL";
fixed= 1;
+ collation.set(&my_charset_bin, DERIVATION_IGNORABLE);
}
enum Type type() const { return NULL_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
int save_in_field(Field *field, bool no_conversions);
@@ -572,6 +611,7 @@ public:
Item *new_item() { return new Item_null(name); }
bool is_null() { return 1; }
void print(String *str) { str->append("NULL", 4); }
+ Item *safe_charset_converter(CHARSET_INFO *tocs);
};
@@ -646,7 +686,7 @@ public:
enum Type type() const { return item_type; }
enum_field_types field_type() const { return param_type; }
- double val();
+ double val_real();
longlong val_int();
String *val_str(String*);
bool get_time(TIME *tm);
@@ -684,6 +724,8 @@ public:
void print(String *str);
/* parameter never equal to other parameter of other item */
bool eq(const Item *item, bool binary_cmp) const { return 0; }
+ bool is_null()
+ { DBUG_ASSERT(state != NO_VALUE); return state == NULL_VALUE; }
};
class Item_int :public Item_num
@@ -703,7 +745,7 @@ public:
enum Item_result result_type () const { return INT_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_LONGLONG; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
String *val_str(String*);
int save_in_field(Field *field, bool no_conversions);
bool basic_const_item() const { return 1; }
@@ -732,7 +774,7 @@ public:
Item_uint(const char *str_arg, uint length);
Item_uint(uint32 i) :Item_int((longlong) i, 10)
{ unsigned_flag= 1; }
- double val()
+ double val_real()
{ DBUG_ASSERT(fixed == 1); return ulonglong2double((ulonglong)value); }
String *val_str(String*);
Item *new_item() { return new Item_uint(name,max_length); }
@@ -761,7 +803,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; }
- double val() { DBUG_ASSERT(fixed == 1); return value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return value; }
longlong val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -832,7 +874,7 @@ public:
fixed= 1;
}
enum Type type() const { return STRING_ITEM; }
- double val()
+ double val_real()
{
DBUG_ASSERT(fixed == 1);
int err;
@@ -853,7 +895,7 @@ public:
}
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_STRING; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
bool basic_const_item() const { return 1; }
bool eq(const Item *item, bool binary_cmp) const;
Item *new_item()
@@ -861,6 +903,7 @@ public:
return new Item_string(name, str_value.ptr(),
str_value.length(), &my_charset_bin);
}
+ Item *safe_charset_converter(CHARSET_INFO *tocs);
String *const_string() { return &str_value; }
inline void append(char *str, uint length) { str_value.append(str, length); }
void print(String *str);
@@ -921,14 +964,14 @@ class Item_varbinary :public Item
public:
Item_varbinary(const char *str,uint str_length);
enum Type type() const { return VARBIN_ITEM; }
- double val()
+ double val_real()
{ DBUG_ASSERT(fixed == 1); return (double) Item_varbinary::val_int(); }
longlong val_int();
bool basic_const_item() const { return 1; }
String *val_str(String*) { DBUG_ASSERT(fixed == 1); return &str_value; }
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_STRING; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
// to prevent drop fixed flag (no need parent cleanup call)
void cleanup() {}
};
@@ -973,7 +1016,7 @@ public:
enum Type type() const { return REF_ITEM; }
bool eq(const Item *item, bool binary_cmp) const
{ return ref && (*ref)->eq(item, binary_cmp); }
- double val()
+ double val_real()
{
double tmp=(*ref)->val_result();
null_value=(*ref)->null_value;
@@ -1038,7 +1081,7 @@ public:
Item_ref_null_helper(Item_in_subselect* master, Item **item,
const char *table_name_par, const char *field_name_par):
Item_ref(item, table_name_par, field_name_par), owner(master) {}
- double val();
+ double val_real();
longlong val_int();
String* val_str(String* s);
bool get_date(TIME *ltime, uint fuzzydate);
@@ -1106,7 +1149,7 @@ public:
enum Type type() const { return COPY_STR_ITEM; }
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return cached_field_type; }
- double val()
+ double val_real()
{
int err;
return (null_value ? 0.0 :
@@ -1282,13 +1325,15 @@ public:
/* Is this item represents row from NEW or OLD row ? */
enum row_version_type {OLD_ROW, NEW_ROW};
row_version_type row_version;
+ /* Next in list of all Item_trigger_field's in trigger */
+ Item_trigger_field *next_trg_field;
Item_trigger_field(row_version_type row_ver_par,
const char *field_name_par):
Item_field((const char *)NULL, (const char *)NULL, field_name_par),
row_version(row_ver_par)
{}
- bool setup_field(THD *thd, TABLE *table, enum trg_event_type event);
+ void setup_field(THD *thd, TABLE *table, enum trg_event_type event);
enum Type type() const { return TRIGGER_FIELD_ITEM; }
bool eq(const Item *item, bool binary_cmp) const;
bool fix_fields(THD *, struct st_table_list *, Item **);
@@ -1331,10 +1376,10 @@ class Item_cache_int: public Item_cache
{
longlong value;
public:
- Item_cache_int(): Item_cache() {}
+ Item_cache_int(): Item_cache(), value(0) {}
void store(Item *item);
- double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
String* val_str(String *str)
{
@@ -1349,10 +1394,10 @@ class Item_cache_real: public Item_cache
{
double value;
public:
- Item_cache_real(): Item_cache() {}
+ Item_cache_real(): Item_cache(), value(0) {}
void store(Item *item);
- double val() { DBUG_ASSERT(fixed == 1); return value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return value; }
longlong val_int()
{
DBUG_ASSERT(fixed == 1);
@@ -1371,10 +1416,10 @@ class Item_cache_str: public Item_cache
char buffer[80];
String *value, value_buff;
public:
- Item_cache_str(): Item_cache() { }
+ Item_cache_str(): Item_cache(), value(0) { }
void store(Item *item);
- double val();
+ double val_real();
longlong val_int();
String* val_str(String *) { DBUG_ASSERT(fixed == 1); return value; }
enum Item_result result_type() const { return STRING_RESULT; }
@@ -1406,7 +1451,7 @@ public:
{
illegal_method_call((const char*)"make_field");
};
- double val()
+ double val_real()
{
illegal_method_call((const char*)"val");
return 0;
@@ -1457,7 +1502,7 @@ public:
Item_result result_type () const { return item_type; }
enum Type type() const { return TYPE_HOLDER; }
- double val();
+ double val_real();
longlong val_int();
String *val_str(String*);
bool join_types(THD *thd, Item *);
diff --git a/sql/item_buff.cc b/sql/item_buff.cc
index 1559cfe958e..66de26dba9a 100644
--- a/sql/item_buff.cc
+++ b/sql/item_buff.cc
@@ -70,7 +70,7 @@ Item_str_buff::~Item_str_buff()
bool Item_real_buff::cmp(void)
{
- double nr=item->val();
+ double nr= item->val_real();
if (null_value != item->null_value || nr != value)
{
null_value= item->null_value;
diff --git a/sql/item_cmpfunc.cc b/sql/item_cmpfunc.cc
index 467cd8313a4..90eee9e76d1 100644
--- a/sql/item_cmpfunc.cc
+++ b/sql/item_cmpfunc.cc
@@ -53,10 +53,10 @@ static void agg_cmp_type(Item_result *type, Item **items, uint nitems)
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2, const char *fname)
{
- my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
- c1.collation->name,c1.derivation_name(),
- c2.collation->name,c2.derivation_name(),
- fname);
+ my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
+ c1.collation->name,c1.derivation_name(),
+ c2.collation->name,c2.derivation_name(),
+ fname);
}
@@ -104,7 +104,7 @@ Item_bool_func2* Le_creator::create(Item *a, Item *b) const
longlong Item_func_not::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
null_value=args[0]->null_value;
return !null_value && value == 0 ? 1 : 0;
}
@@ -116,7 +116,7 @@ longlong Item_func_not::val_int()
longlong Item_func_not_all::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value= args[0]->val();
+ double value= args[0]->val_real();
if (abort_on_null)
{
null_value= 0;
@@ -185,55 +185,14 @@ void Item_bool_func2::fix_length_and_dec()
to the collation of A.
*/
- if (args[0] && args[1])
- {
- uint strong= 0;
- uint weak= 0;
- uint32 dummy_offset;
- DTCollation coll;
-
- if (args[0]->result_type() == STRING_RESULT &&
- args[1]->result_type() == STRING_RESULT &&
- String::needs_conversion(0, args[0]->collation.collation,
- args[1]->collation.collation,
- &dummy_offset) &&
- !coll.set(args[0]->collation, args[1]->collation, TRUE))
- {
- Item* conv= 0;
- Item_arena *arena= thd->current_arena, backup;
- strong= coll.strong;
- weak= strong ? 0 : 1;
- /*
- In case we're in statement prepare, create conversion item
- in its memory: it will be reused on each execute.
- */
- if (arena->is_stmt_prepare())
- thd->set_n_backup_item_arena(arena, &backup);
- if (args[weak]->type() == STRING_ITEM)
- {
- String tmp, cstr;
- String *ostr= args[weak]->val_str(&tmp);
- cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(),
- args[strong]->collation.collation);
- conv= new Item_string(cstr.ptr(),cstr.length(),cstr.charset(),
- args[weak]->collation.derivation);
- ((Item_string*)conv)->str_value.copy();
- }
- else
- {
- conv= new Item_func_conv_charset(args[weak],
- args[strong]->collation.collation);
- conv->collation.set(args[weak]->collation.derivation);
- conv->fix_fields(thd, 0, &conv);
- }
- if (arena->is_stmt_prepare())
- thd->restore_backup_item_arena(arena, &backup);
- if (args[weak]->type() == FIELD_ITEM)
- ((Item_field *)args[weak])->no_const_subst= 1;
- args[weak]= conv ? conv : args[weak];
- }
- }
+ DTCollation coll;
+ if (args[0]->result_type() == STRING_RESULT &&
+ args[1]->result_type() == STRING_RESULT &&
+ agg_arg_charsets(coll, args, 2, MY_COLL_CMP_CONV))
+ return;
+
+
// Make a special case of compare with fields to get nicer DATE comparisons
if (functype() == LIKE_FUNC) // Disable conversion in case of LIKE function.
@@ -425,10 +384,10 @@ int Arg_comparator::compare_e_binary_string()
int Arg_comparator::compare_real()
{
- double val1= (*a)->val();
+ double val1= (*a)->val_real();
if (!(*a)->null_value)
{
- double val2= (*b)->val();
+ double val2= (*b)->val_real();
if (!(*b)->null_value)
{
owner->null_value= 0;
@@ -443,8 +402,8 @@ int Arg_comparator::compare_real()
int Arg_comparator::compare_e_real()
{
- double val1= (*a)->val();
- double val2= (*b)->val();
+ double val1= (*a)->val_real();
+ double val2= (*b)->val_real();
if ((*a)->null_value || (*b)->null_value)
return test((*a)->null_value && (*b)->null_value);
return test(val1 == val2);
@@ -641,17 +600,17 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
{
DBUG_ASSERT(fixed == 0);
if (fix_left(thd, tables, ref))
- return 1;
+ return TRUE;
if (args[0]->maybe_null)
maybe_null=1;
if (!args[1]->fixed && args[1]->fix_fields(thd, tables, args+1))
- return 1;
+ return TRUE;
Item_in_subselect * sub= (Item_in_subselect *)args[1];
if (args[0]->cols() != sub->engine->cols())
{
my_error(ER_OPERAND_COLUMNS, MYF(0), args[0]->cols());
- return 1;
+ return TRUE;
}
if (args[1]->maybe_null)
maybe_null=1;
@@ -660,7 +619,7 @@ bool Item_in_optimizer::fix_fields(THD *thd, struct st_table_list *tables,
not_null_tables_cache|= args[1]->not_null_tables();
const_item_cache&= args[1]->const_item();
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -795,13 +754,13 @@ void Item_func_interval::fix_length_and_dec()
(intervals=(double*) sql_alloc(sizeof(double)*(row->cols()-1))))
{
for (uint i=1 ; i < row->cols(); i++)
- intervals[i-1]=row->el(i)->val();
+ intervals[i-1]= row->el(i)->val_real();
}
}
maybe_null= 0;
max_length= 2;
used_tables_cache|= row->used_tables();
- not_null_tables_cache&= row->not_null_tables();
+ not_null_tables_cache= row->not_null_tables();
with_sum_func= with_sum_func || row->with_sum_func;
const_item_cache&= row->const_item();
}
@@ -817,7 +776,7 @@ void Item_func_interval::fix_length_and_dec()
longlong Item_func_interval::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value= row->el(0)->val();
+ double value= row->el(0)->val_real();
uint i;
if (row->el(0)->null_value)
@@ -840,7 +799,7 @@ longlong Item_func_interval::val_int()
for (i=1 ; i < row->cols() ; i++)
{
- if (row->el(i)->val() > value)
+ if (row->el(i)->val_real() > value)
return i-1;
}
return i-1;
@@ -859,7 +818,7 @@ void Item_func_between::fix_length_and_dec()
return;
agg_cmp_type(&cmp_type, args, 3);
if (cmp_type == STRING_RESULT &&
- agg_arg_collations_for_comparison(cmp_collation, args, 3))
+ agg_arg_charsets(cmp_collation, args, 3, MY_COLL_CMP_CONV))
return;
/*
@@ -914,7 +873,7 @@ longlong Item_func_between::val_int()
}
else if (cmp_type == INT_RESULT)
{
- longlong value=args[0]->val_int(),a,b;
+ longlong value=args[0]->val_int(), a, b;
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
a=args[1]->val_int();
@@ -934,11 +893,11 @@ longlong Item_func_between::val_int()
}
else
{
- double value=args[0]->val(),a,b;
+ double value= args[0]->val_real(),a,b;
if ((null_value=args[0]->null_value))
return 0; /* purecov: inspected */
- a=args[1]->val();
- b=args[2]->val();
+ a= args[1]->val_real();
+ b= args[2]->val_real();
if (!args[1]->null_value && !args[2]->null_value)
return (value >= a && value <= b) ? 1 : 0;
if (args[1]->null_value && args[2]->null_value)
@@ -975,7 +934,7 @@ Item_func_ifnull::fix_length_and_dec()
decimals=max(args[0]->decimals,args[1]->decimals);
agg_result_type(&cached_result_type, args, 2);
if (cached_result_type == STRING_RESULT)
- agg_arg_collations(collation, args, arg_count);
+ agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
else if (cached_result_type != REAL_RESULT)
decimals= 0;
@@ -995,16 +954,16 @@ Field *Item_func_ifnull::tmp_table_field(TABLE *table)
}
double
-Item_func_ifnull::val()
+Item_func_ifnull::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if (!args[0]->null_value)
{
null_value=0;
return value;
}
- value=args[1]->val();
+ value= args[1]->val_real();
if ((null_value=args[1]->null_value))
return 0.0;
return value;
@@ -1071,8 +1030,8 @@ Item_func_if::fix_length_and_dec()
agg_result_type(&cached_result_type, args+1, 2);
if (cached_result_type == STRING_RESULT)
{
- if (agg_arg_collations(collation, args+1, 2))
- return;
+ if (agg_arg_charsets(collation, args+1, 2, MY_COLL_ALLOW_CONV))
+ return;
}
else
{
@@ -1083,11 +1042,11 @@ Item_func_if::fix_length_and_dec()
double
-Item_func_if::val()
+Item_func_if::val_real()
{
DBUG_ASSERT(fixed == 1);
Item *arg= args[0]->val_int() ? args[1] : args[2];
- double value=arg->val();
+ double value= arg->val_real();
null_value=arg->null_value;
return value;
}
@@ -1136,7 +1095,7 @@ Item_func_nullif::fix_length_and_dec()
*/
double
-Item_func_nullif::val()
+Item_func_nullif::val_real()
{
DBUG_ASSERT(fixed == 1);
double value;
@@ -1145,7 +1104,7 @@ Item_func_nullif::val()
null_value=1;
return 0.0;
}
- value=args[0]->val();
+ value= args[0]->val_real();
null_value=args[0]->null_value;
return value;
}
@@ -1220,7 +1179,7 @@ Item *Item_func_case::find_item(String *str)
return else_expr_num != -1 ? args[else_expr_num] : 0;
break;
case REAL_RESULT:
- first_expr_real= args[first_expr_num]->val();
+ first_expr_real= args[first_expr_num]->val_real();
if (args[first_expr_num]->null_value)
return else_expr_num != -1 ? args[else_expr_num] : 0;
break;
@@ -1253,7 +1212,7 @@ Item *Item_func_case::find_item(String *str)
return args[i+1];
break;
case REAL_RESULT:
- if (args[i]->val()==first_expr_real && !args[i]->null_value)
+ if (args[i]->val_real() == first_expr_real && !args[i]->null_value)
return args[i+1];
break;
case ROW_RESULT:
@@ -1305,7 +1264,7 @@ longlong Item_func_case::val_int()
return res;
}
-double Item_func_case::val()
+double Item_func_case::val_real()
{
DBUG_ASSERT(fixed == 1);
char buff[MAX_FIELD_WIDTH];
@@ -1318,7 +1277,7 @@ double Item_func_case::val()
null_value=1;
return 0;
}
- res=item->val();
+ res= item->val_real();
null_value=item->null_value;
return res;
}
@@ -1331,8 +1290,10 @@ void Item_func_case::fix_length_and_dec()
if (!(agg= (Item**) sql_alloc(sizeof(Item*)*(ncases+1))))
return;
- // Aggregate all THEN and ELSE expression types
- // and collations when string result
+ /*
+ Aggregate all THEN and ELSE expression types
+ and collations when string result
+ */
for (nagg= 0 ; nagg < ncases/2 ; nagg++)
agg[nagg]= args[nagg*2+1];
@@ -1342,7 +1303,7 @@ void Item_func_case::fix_length_and_dec()
agg_result_type(&cached_result_type, agg, nagg);
if ((cached_result_type == STRING_RESULT) &&
- agg_arg_collations(collation, agg, nagg))
+ agg_arg_charsets(collation, agg, nagg, MY_COLL_ALLOW_CONV))
return;
@@ -1358,7 +1319,7 @@ void Item_func_case::fix_length_and_dec()
nagg++;
agg_cmp_type(&cmp_type, agg, nagg);
if ((cmp_type == STRING_RESULT) &&
- agg_arg_collations_for_comparison(cmp_collation, agg, nagg))
+ agg_arg_charsets(cmp_collation, agg, nagg, MY_COLL_CMP_CONV))
return;
}
@@ -1439,13 +1400,13 @@ longlong Item_func_coalesce::val_int()
return 0;
}
-double Item_func_coalesce::val()
+double Item_func_coalesce::val_real()
{
DBUG_ASSERT(fixed == 1);
null_value=0;
for (uint i=0 ; i < arg_count ; i++)
{
- double res=args[i]->val();
+ double res= args[i]->val_real();
if (!args[i]->null_value)
return res;
}
@@ -1465,7 +1426,7 @@ void Item_func_coalesce::fix_length_and_dec()
set_if_bigger(decimals,args[i]->decimals);
}
if (cached_result_type == STRING_RESULT)
- agg_arg_collations(collation, args, arg_count);
+ agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV);
else if (cached_result_type != REAL_RESULT)
decimals= 0;
}
@@ -1598,12 +1559,12 @@ in_double::in_double(uint elements)
void in_double::set(uint pos,Item *item)
{
- ((double*) base)[pos]=item->val();
+ ((double*) base)[pos]= item->val_real();
}
byte *in_double::get_value(Item *item)
{
- tmp= item->val();
+ tmp= item->val_real();
if (item->null_value)
return 0; /* purecov: inspected */
return (byte*) &tmp;
@@ -1765,7 +1726,7 @@ 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());
+ (uchar *) y->ptr(),y->length(), 0);
}
@@ -1795,14 +1756,13 @@ void Item_func_in::fix_length_and_dec()
via creating Item_func_conv_charset().
*/
- if (agg_arg_collations_for_comparison(cmp_collation,
- args, arg_count, TRUE))
+ if (agg_arg_collations_for_comparison(cmp_collation, args, arg_count,
+ MY_COLL_ALLOW_SUPERSET_CONV))
return;
if ((!my_charset_same(args[0]->collation.collation,
cmp_collation.collation) || !const_itm))
{
- if (agg_arg_collations_for_comparison(cmp_collation,
- args, arg_count, FALSE))
+ if (agg_arg_collations_for_comparison(cmp_collation, args, arg_count))
return;
}
else
@@ -1811,25 +1771,27 @@ void Item_func_in::fix_length_and_dec()
Conversion is possible:
All IN arguments are constants.
*/
- Item_arena *arena= thd->current_arena, backup;
- if (arena->is_stmt_prepare())
- thd->set_n_backup_item_arena(arena, &backup);
+ Item_arena *arena, backup;
+ arena= thd->change_arena_if_needed(&backup);
+
for (arg= args+1, arg_end= args+arg_count; arg < arg_end; arg++)
{
- if (!my_charset_same(cmp_collation.collation,
+ if (!arg[0]->null_value &&
+ !my_charset_same(cmp_collation.collation,
arg[0]->collation.collation))
{
Item_string *conv;
String tmp, cstr, *ostr= arg[0]->val_str(&tmp);
+ uint dummy_errors;
cstr.copy(ostr->ptr(), ostr->length(), ostr->charset(),
- cmp_collation.collation);
+ cmp_collation.collation, &dummy_errors);
conv= new Item_string(cstr.ptr(),cstr.length(), cstr.charset(),
arg[0]->collation.derivation);
conv->str_value.copy();
arg[0]= conv;
}
}
- if (arena->is_stmt_prepare())
+ if (arena)
thd->restore_backup_item_arena(arena, &backup);
}
}
@@ -1994,7 +1956,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
and_tables_cache= ~(table_map) 0;
if (check_stack_overrun(thd, buff))
- return 1; // Fatal error flag is set!
+ return TRUE; // Fatal error flag is set!
while ((item=li++))
{
table_map tmp_table_map;
@@ -2012,7 +1974,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if ((!item->fixed &&
item->fix_fields(thd, tables, li.ref())) ||
(item= *li.ref())->check_cols(1))
- return 1; /* purecov: inspected */
+ return TRUE; /* purecov: inspected */
used_tables_cache|= item->used_tables();
tmp_table_map= item->not_null_tables();
not_null_tables_cache|= tmp_table_map;
@@ -2025,7 +1987,7 @@ Item_cond::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
thd->lex->current_select->cond_count+= list.elements;
fix_length_and_dec();
fixed= 1;
- return 0;
+ return FALSE;
}
bool Item_cond::walk(Item_processor processor, byte *arg)
@@ -2377,12 +2339,12 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
DBUG_ASSERT(fixed == 0);
if (Item_bool_func2::fix_fields(thd, tlist, ref) ||
escape_item->fix_fields(thd, tlist, &escape_item))
- return 1;
+ return TRUE;
if (!escape_item->const_during_execution())
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"ESCAPE");
- return 1;
+ return TRUE;
}
if (escape_item->const_item())
@@ -2400,7 +2362,7 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
{
String* res2 = args[1]->val_str(&tmp_value2);
if (!res2)
- return 0; // Null argument
+ return FALSE; // Null argument
const size_t len = res2->length();
const char* first = res2->ptr();
@@ -2433,7 +2395,7 @@ bool Item_func_like::fix_fields(THD *thd, TABLE_LIST *tlist, Item ** ref)
}
}
}
- return 0;
+ return FALSE;
}
#ifdef USE_REGEX
@@ -2444,13 +2406,13 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
DBUG_ASSERT(fixed == 0);
if (args[0]->fix_fields(thd, tables, args) || args[0]->check_cols(1) ||
args[1]->fix_fields(thd,tables, args + 1) || args[1]->check_cols(1))
- return 1; /* purecov: inspected */
+ return TRUE; /* purecov: inspected */
with_sum_func=args[0]->with_sum_func || args[1]->with_sum_func;
max_length= 1;
decimals= 0;
- if (agg_arg_collations(cmp_collation, args, 2))
- return 1;
+ if (agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV))
+ return TRUE;
used_tables_cache=args[0]->used_tables() | args[1]->used_tables();
not_null_tables_cache= (args[0]->not_null_tables() |
@@ -2464,18 +2426,19 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (args[1]->null_value)
{ // Will always return NULL
maybe_null=1;
- return 0;
+ return FALSE;
}
int error;
- if ((error=regcomp(&preg,res->c_ptr(),
- (cmp_collation.collation->state & MY_CS_BINSORT) ?
- REG_EXTENDED | REG_NOSUB :
- REG_EXTENDED | REG_NOSUB | REG_ICASE,
- cmp_collation.collation)))
+ if ((error= regcomp(&preg,res->c_ptr(),
+ ((cmp_collation.collation->state &
+ (MY_CS_BINSORT | MY_CS_CSSORT)) ?
+ REG_EXTENDED | REG_NOSUB :
+ REG_EXTENDED | REG_NOSUB | REG_ICASE),
+ cmp_collation.collation)))
{
(void) regerror(error,&preg,buff,sizeof(buff));
- my_printf_error(ER_REGEXP_ERROR,ER(ER_REGEXP_ERROR),MYF(0),buff);
- return 1;
+ my_error(ER_REGEXP_ERROR, MYF(0), buff);
+ return TRUE;
}
regex_compiled=regex_is_const=1;
maybe_null=args[0]->maybe_null;
@@ -2483,7 +2446,7 @@ Item_func_regex::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
else
maybe_null=1;
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -2519,10 +2482,11 @@ longlong Item_func_regex::val_int()
regex_compiled=0;
}
if (regcomp(&preg,res2->c_ptr(),
- (cmp_collation.collation->state & MY_CS_BINSORT) ?
- REG_EXTENDED | REG_NOSUB :
- REG_EXTENDED | REG_NOSUB | REG_ICASE,
- cmp_collation.collation))
+ ((cmp_collation.collation->state &
+ (MY_CS_BINSORT | MY_CS_CSSORT)) ?
+ REG_EXTENDED | REG_NOSUB :
+ REG_EXTENDED | REG_NOSUB | REG_ICASE),
+ cmp_collation.collation))
{
null_value=1;
return 0;
diff --git a/sql/item_cmpfunc.h b/sql/item_cmpfunc.h
index 754ebe08b77..6a7e037bed1 100644
--- a/sql/item_cmpfunc.h
+++ b/sql/item_cmpfunc.h
@@ -20,9 +20,6 @@
#ifdef __GNUC__
#pragma interface /* gcc class implementation */
#endif
-#ifdef __GNUC__
-template class List_iterator_fast<Item_field>;
-#endif
extern Item_result item_cmp_type(Item_result a,Item_result b);
class Item_bool_func2;
@@ -423,7 +420,7 @@ public:
Item_func_ifnull(Item *a,Item *b)
:Item_func(a,b), cached_result_type(INT_RESULT)
{}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
@@ -442,7 +439,7 @@ public:
Item_func_if(Item *a,Item *b,Item *c)
:Item_func(a,b,c), cached_result_type(INT_RESULT)
{}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
@@ -465,7 +462,7 @@ public:
Item_func_nullif(Item *a,Item *b)
:Item_bool_func2(a,b), cached_result_type(INT_RESULT)
{}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
enum Item_result result_type () const { return cached_result_type; }
@@ -484,7 +481,7 @@ public:
Item_func_coalesce(List<Item> &list)
:Item_func(list),cached_result_type(INT_RESULT)
{}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *);
void fix_length_and_dec();
@@ -520,7 +517,7 @@ public:
}
set_arguments(list);
}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *);
void fix_length_and_dec();
@@ -677,11 +674,11 @@ class cmp_item_real :public cmp_item
public:
void store_value(Item *item)
{
- value= item->val();
+ value= item->val_real();
}
int cmp(Item *arg)
{
- return value != arg->val();
+ return value != arg->val_real();
}
int compare(cmp_item *c)
{
@@ -962,7 +959,8 @@ public:
void update_used_tables();
void print(String *str);
void split_sum_func(THD *thd, Item **ref_pointer_array, List<Item> &fields);
- friend int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
+ friend int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
+ COND **conds);
void top_level_item() { abort_on_null=1; }
void copy_andor_arguments(THD *thd, Item_cond *item);
bool walk(Item_processor processor, byte *arg);
@@ -1088,7 +1086,7 @@ public:
};
-class Item_equal_iterator :List_iterator_fast<Item_field>
+class Item_equal_iterator : public List_iterator_fast<Item_field>
{
public:
inline Item_equal_iterator(Item_equal &item_equal)
diff --git a/sql/item_create.cc b/sql/item_create.cc
index e21364045ba..cec6de3eede 100644
--- a/sql/item_create.cc
+++ b/sql/item_create.cc
@@ -370,7 +370,10 @@ Item *create_func_space(Item *a)
{
sp= new Item_string("",0,cs);
if (sp)
- sp->str_value.copy(" ",1,&my_charset_latin1,cs);
+ {
+ uint dummy_errors;
+ sp->str_value.copy(" ", 1, &my_charset_latin1, cs, &dummy_errors);
+ }
}
else
{
diff --git a/sql/item_func.cc b/sql/item_func.cc
index 3cc0fd077a4..aba53b9b397 100644
--- a/sql/item_func.cc
+++ b/sql/item_func.cc
@@ -45,10 +45,10 @@ bool check_reserved_words(LEX_STRING *name)
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
const char *fname)
{
- my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
- c1.collation->name,c1.derivation_name(),
- c2.collation->name,c2.derivation_name(),
- fname);
+ my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
+ c1.collation->name, c1.derivation_name(),
+ c2.collation->name, c2.derivation_name(),
+ fname);
}
static void my_coll_agg_error(DTCollation &c1,
@@ -56,11 +56,11 @@ static void my_coll_agg_error(DTCollation &c1,
DTCollation &c3,
const char *fname)
{
- my_error(ER_CANT_AGGREGATE_3COLLATIONS,MYF(0),
- c1.collation->name,c1.derivation_name(),
- c2.collation->name,c2.derivation_name(),
- c3.collation->name,c3.derivation_name(),
- fname);
+ my_error(ER_CANT_AGGREGATE_3COLLATIONS, MYF(0),
+ c1.collation->name, c1.derivation_name(),
+ c2.collation->name, c2.derivation_name(),
+ c3.collation->name, c3.derivation_name(),
+ fname);
}
@@ -74,12 +74,12 @@ static void my_coll_agg_error(Item** args, uint count, const char *fname)
args[2]->collation,
fname);
else
- my_error(ER_CANT_AGGREGATE_NCOLLATIONS,MYF(0),fname);
+ my_error(ER_CANT_AGGREGATE_NCOLLATIONS, MYF(0), fname);
}
bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count,
- bool allow_superset_conversion)
+ uint flags)
{
uint i;
c.nagg= 0;
@@ -87,29 +87,27 @@ bool Item_func::agg_arg_collations(DTCollation &c, Item **av, uint count,
c.set(av[0]->collation);
for (i= 1; i < count; i++)
{
- if (c.aggregate(av[i]->collation, allow_superset_conversion))
+ if (c.aggregate(av[i]->collation, flags))
{
my_coll_agg_error(av, count, func_name());
return TRUE;
}
}
+ if ((flags & MY_COLL_DISALLOW_NONE) &&
+ c.derivation == DERIVATION_NONE)
+ {
+ my_coll_agg_error(av, count, func_name());
+ return TRUE;
+ }
return FALSE;
}
bool Item_func::agg_arg_collations_for_comparison(DTCollation &c,
Item **av, uint count,
- bool allow_superset_conv)
+ uint flags)
{
- if (agg_arg_collations(c, av, count, allow_superset_conv))
- return TRUE;
-
- if (c.derivation == DERIVATION_NONE)
- {
- my_coll_agg_error(av, count, func_name());
- return TRUE;
- }
- return FALSE;
+ return (agg_arg_collations(c, av, count, flags | MY_COLL_DISALLOW_NONE));
}
@@ -122,6 +120,90 @@ eval_const_cond(COND *cond)
}
+
+/*
+ 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)
+*/
+
+bool Item_func::agg_arg_charsets(DTCollation &coll,
+ Item **args, uint nargs, uint flags)
+{
+ Item **arg, **last, *safe_args[2];
+ if (agg_arg_collations(coll, args, nargs, flags))
+ return TRUE;
+
+ /*
+ For better error reporting: save the first and the second argument.
+ We need this only if the the number of args is 3 or 2:
+ - for a longer argument list, "Illegal mix of collations"
+ doesn't display each argument's characteristics.
+ - if nargs is 1, then this error cannot happen.
+ */
+ if (nargs >=2 && nargs <= 3)
+ {
+ safe_args[0]= args[0];
+ safe_args[1]= args[1];
+ }
+
+ THD *thd= current_thd;
+ Item_arena *arena, backup;
+ bool res= FALSE;
+ /*
+ In case we're in statement prepare, create conversion item
+ in its memory: it will be reused on each execute.
+ */
+ arena= thd->change_arena_if_needed(&backup);
+
+ for (arg= args, last= args + nargs; arg < last; arg++)
+ {
+ Item* conv;
+ uint32 dummy_offset;
+ if (!String::needs_conversion(0, coll.collation,
+ (*arg)->collation.collation,
+ &dummy_offset))
+ continue;
+
+ if (!(conv= (*arg)->safe_charset_converter(coll.collation)))
+ {
+ if (nargs >=2 && nargs <= 3)
+ {
+ /* restore the original arguments for better error message */
+ args[0]= safe_args[0];
+ args[1]= safe_args[1];
+ }
+ my_coll_agg_error(args, nargs, func_name());
+ res= TRUE;
+ break; // we cannot return here, we need to restore "arena".
+ }
+ if ((*arg)->type() == FIELD_ITEM)
+ ((Item_field *)(*arg))->no_const_subst= 1;
+ conv->fix_fields(thd, 0, &conv);
+ *arg= conv;
+ }
+ if (arena)
+ thd->restore_backup_item_arena(arena, &backup);
+ return res;
+}
+
+
+
void Item_func::set_arguments(List<Item> &list)
{
allowed_arg_cols= 1;
@@ -187,7 +269,7 @@ Item_func::Item_func(THD *thd, Item_func *item)
Sets as a side effect the following class variables:
maybe_null Set if any argument may return NULL
with_sum_func Set if any of the arguments contains a sum function
- used_table_cache Set to union of the arguments used table
+ used_tables_cache Set to union of the tables used by arguments
str_value.charset If this is a string function, set this to the
character set for the first argument.
@@ -199,8 +281,8 @@ Item_func::Item_func(THD *thd, Item_func *item)
item.
RETURN VALUES
- 0 ok
- 1 Got error. Stored with my_error().
+ FALSE ok
+ TRUE Got error. Stored with my_error().
*/
bool
@@ -216,7 +298,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
const_item_cache=1;
if (check_stack_overrun(thd, buff))
- return 1; // Fatal error if flag is set!
+ return TRUE; // Fatal error if flag is set!
if (arg_count)
{ // Print purify happy
for (arg=args, arg_end=args+arg_count; arg != arg_end ; arg++)
@@ -228,7 +310,7 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
*/
if ((!(*arg)->fixed && (*arg)->fix_fields(thd, tables, arg)) ||
(*arg)->check_cols(allowed_arg_cols))
- return 1; /* purecov: inspected */
+ return TRUE; /* purecov: inspected */
item= *arg;
if (item->maybe_null)
maybe_null=1;
@@ -240,10 +322,10 @@ Item_func::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
}
}
fix_length_and_dec();
- if (thd->net.last_errno) // An error inside fix_length_and_dec occured
- return 1;
+ if (thd->net.report_error) // An error inside fix_length_and_dec occured
+ return TRUE;
fixed= 1;
- return 0;
+ return FALSE;
}
bool Item_func::walk (Item_processor processor, byte *argument)
@@ -313,6 +395,7 @@ void Item_func::split_sum_func(THD *thd, Item **ref_pointer_array,
{
uint el= fields.elements;
Item *new_item= new Item_ref(ref_pointer_array + el, 0, item->name);
+ new_item->collation.set(item->collation);
fields.push_front(item);
ref_pointer_array[el]= item;
thd->change_item_tree(arg, new_item);
@@ -398,6 +481,7 @@ bool Item_func::eq(const Item *item, bool binary_cmp) const
return 1;
}
+
Field *Item_func::tmp_table_field(TABLE *t_arg)
{
Field *res;
@@ -416,10 +500,7 @@ Field *Item_func::tmp_table_field(TABLE *t_arg)
res= new Field_double(max_length, maybe_null, name, t_arg, decimals);
break;
case STRING_RESULT:
- if (max_length > 255)
- res= new Field_blob(max_length, maybe_null, name, t_arg, collation.collation);
- else
- res= new Field_string(max_length, maybe_null, name, t_arg, collation.collation);
+ res= make_string_field(t_arg);
break;
case ROW_RESULT:
default:
@@ -434,7 +515,7 @@ Field *Item_func::tmp_table_field(TABLE *t_arg)
String *Item_real_func::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals, &my_charset_bin);
@@ -457,7 +538,7 @@ String *Item_num_func::val_str(String *str)
}
else
{
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals,&my_charset_bin);
@@ -534,7 +615,7 @@ String *Item_num_op::val_str(String *str)
}
else
{
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals,&my_charset_bin);
@@ -561,10 +642,10 @@ void Item_func_unsigned::print(String *str)
}
-double Item_func_plus::val()
+double Item_func_plus::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val()+args[1]->val();
+ double value= args[0]->val_real() + args[1]->val_real();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
return value;
@@ -580,7 +661,7 @@ longlong Item_func_plus::val_int()
return 0;
return value;
}
- return (longlong) Item_func_plus::val();
+ return (longlong) Item_func_plus::val_real();
}
@@ -598,10 +679,10 @@ void Item_func_minus::fix_length_and_dec()
}
-double Item_func_minus::val()
+double Item_func_minus::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val() - args[1]->val();
+ double value= args[0]->val_real() - args[1]->val_real();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0;
return value;
@@ -617,14 +698,14 @@ longlong Item_func_minus::val_int()
return 0;
return value;
}
- return (longlong) Item_func_minus::val();
+ return (longlong) Item_func_minus::val_real();
}
-double Item_func_mul::val()
+double Item_func_mul::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val()*args[1]->val();
+ double value= args[0]->val_real() * args[1]->val_real();
if ((null_value=args[0]->null_value || args[1]->null_value))
return 0.0; /* purecov: inspected */
return value;
@@ -640,15 +721,15 @@ longlong Item_func_mul::val_int()
return 0; /* purecov: inspected */
return value;
}
- return (longlong) Item_func_mul::val();
+ return (longlong) Item_func_mul::val_real();
}
-double Item_func_div::val()
+double Item_func_div::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- double val2=args[1]->val();
+ double value= args[0]->val_real();
+ double val2= args[1]->val_real();
if ((null_value= args[0]->null_value || args[1]->null_value))
return 0.0;
if (val2 == 0.0)
@@ -676,7 +757,7 @@ longlong Item_func_div::val_int()
}
return value/val2;
}
- return (longlong) Item_func_div::val();
+ return (longlong) Item_func_div::val_real();
}
@@ -718,11 +799,11 @@ void Item_func_int_div::fix_length_and_dec()
}
-double Item_func_mod::val()
+double Item_func_mod::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value= args[0]->val();
- double val2= args[1]->val();
+ double value= args[0]->val_real();
+ double val2= args[1]->val_real();
if ((null_value= args[0]->null_value || args[1]->null_value))
return 0.0; /* purecov: inspected */
if (val2 == 0.0)
@@ -754,10 +835,10 @@ void Item_func_mod::fix_length_and_dec()
}
-double Item_func_neg::val()
+double Item_func_neg::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
null_value=args[0]->null_value;
return -value;
}
@@ -797,10 +878,10 @@ void Item_func_neg::fix_length_and_dec()
}
-double Item_func_abs::val()
+double Item_func_abs::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
null_value=args[0]->null_value;
return fabs(value);
}
@@ -829,10 +910,10 @@ void Item_func_abs::fix_length_and_dec()
/* Gateway to natural LOG function */
-double Item_func_ln::val()
+double Item_func_ln::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0;
return log(value);
@@ -843,15 +924,15 @@ double Item_func_ln::val()
We have to check if all values are > zero and first one is not one
as these are the cases then result is not a number.
*/
-double Item_func_log::val()
+double Item_func_log::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0;
if (arg_count == 2)
{
- double value2= args[1]->val();
+ double value2= args[1]->val_real();
if ((null_value=(args[1]->null_value || value2 <= 0.0 || value == 1.0)))
return 0.0;
return log(value2) / log(value);
@@ -859,47 +940,47 @@ double Item_func_log::val()
return log(value);
}
-double Item_func_log2::val()
+double Item_func_log2::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0;
return log(value) / M_LN2;
}
-double Item_func_log10::val()
+double Item_func_log10::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value <= 0.0)))
return 0.0; /* purecov: inspected */
return log10(value);
}
-double Item_func_exp::val()
+double Item_func_exp::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0; /* purecov: inspected */
return exp(value);
}
-double Item_func_sqrt::val()
+double Item_func_sqrt::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || value < 0)))
return 0.0; /* purecov: inspected */
return sqrt(value);
}
-double Item_func_pow::val()
+double Item_func_pow::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
- double val2=args[1]->val();
+ double value= args[0]->val_real();
+ double val2= args[1]->val_real();
if ((null_value=(args[0]->null_value || args[1]->null_value)))
return 0.0; /* purecov: inspected */
return pow(value,val2);
@@ -907,35 +988,35 @@ double Item_func_pow::val()
// Trigonometric functions
-double Item_func_acos::val()
+double Item_func_acos::val_real()
{
DBUG_ASSERT(fixed == 1);
// the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
- volatile double value=args[0]->val();
+ volatile double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
return 0.0;
return fix_result(acos(value));
}
-double Item_func_asin::val()
+double Item_func_asin::val_real()
{
DBUG_ASSERT(fixed == 1);
// the volatile's for BUG #2338 to calm optimizer down (because of gcc's bug)
- volatile double value=args[0]->val();
+ volatile double value= args[0]->val_real();
if ((null_value=(args[0]->null_value || (value < -1.0 || value > 1.0))))
return 0.0;
return fix_result(asin(value));
}
-double Item_func_atan::val()
+double Item_func_atan::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
if (arg_count == 2)
{
- double val2= args[1]->val();
+ double val2= args[1]->val_real();
if ((null_value=args[1]->null_value))
return 0.0;
return fix_result(atan2(value,val2));
@@ -943,28 +1024,28 @@ double Item_func_atan::val()
return fix_result(atan(value));
}
-double Item_func_cos::val()
+double Item_func_cos::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
return fix_result(cos(value));
}
-double Item_func_sin::val()
+double Item_func_sin::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
return fix_result(sin(value));
}
-double Item_func_tan::val()
+double Item_func_tan::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0.0;
return fix_result(tan(value));
@@ -1028,7 +1109,7 @@ void Item_func_integer::fix_length_and_dec()
longlong Item_func_ceiling::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
null_value=args[0]->null_value;
return (longlong) ceil(value);
}
@@ -1037,7 +1118,7 @@ longlong Item_func_floor::val_int()
{
DBUG_ASSERT(fixed == 1);
// the volatile's for BUG #3051 to calm optimizer down (because of gcc's bug)
- volatile double value=args[0]->val();
+ volatile double value= args[0]->val_real();
null_value=args[0]->null_value;
return (longlong) floor(value);
}
@@ -1056,10 +1137,10 @@ void Item_func_round::fix_length_and_dec()
}
}
-double Item_func_round::val()
+double Item_func_round::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
int dec=(int) args[1]->val_int();
uint abs_dec=abs(dec);
double tmp;
@@ -1142,7 +1223,7 @@ void Item_func_rand::update_used_tables()
}
-double Item_func_rand::val()
+double Item_func_rand::val_real()
{
DBUG_ASSERT(fixed == 1);
return my_rnd(rand);
@@ -1151,16 +1232,16 @@ double Item_func_rand::val()
longlong Item_func_sign::val_int()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
null_value=args[0]->null_value;
return value < 0.0 ? -1 : (value > 0 ? 1 : 0);
}
-double Item_func_units::val()
+double Item_func_units::val_real()
{
DBUG_ASSERT(fixed == 1);
- double value=args[0]->val();
+ double value= args[0]->val_real();
if ((null_value=args[0]->null_value))
return 0;
return value*mul+add;
@@ -1185,7 +1266,7 @@ void Item_func_min_max::fix_length_and_dec()
cmp_type=item_cmp_type(cmp_type,args[i]->result_type());
}
if (cmp_type == STRING_RESULT)
- agg_arg_collations_for_comparison(collation, args, arg_count);
+ agg_arg_charsets(collation, args, arg_count, MY_COLL_CMP_CONV);
}
@@ -1206,7 +1287,7 @@ String *Item_func_min_max::val_str(String *str)
}
case REAL_RESULT:
{
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals,&my_charset_bin);
@@ -1250,7 +1331,7 @@ String *Item_func_min_max::val_str(String *str)
}
-double Item_func_min_max::val()
+double Item_func_min_max::val_real()
{
DBUG_ASSERT(fixed == 1);
double value=0.0;
@@ -1259,12 +1340,12 @@ double Item_func_min_max::val()
{
if (null_value)
{
- value=args[i]->val();
+ value= args[i]->val_real();
null_value=args[i]->null_value;
}
else
{
- double tmp=args[i]->val();
+ double tmp= args[i]->val_real();
if (!args[i]->null_value && (tmp < value ? cmp_sign : -cmp_sign) > 0)
value=tmp;
}
@@ -1339,7 +1420,7 @@ longlong Item_func_coercibility::val_int()
void Item_func_locate::fix_length_and_dec()
{
maybe_null=0; max_length=11;
- agg_arg_collations_for_comparison(cmp_collation, args, 2);
+ agg_arg_charsets(cmp_collation, args, 2, MY_COLL_CMP_CONV);
}
@@ -1420,10 +1501,10 @@ longlong Item_func_field::val_int()
}
else
{
- double val= args[0]->val();
+ double val= args[0]->val_real();
for (uint i=1; i < arg_count ; i++)
{
- if (val == args[i]->val())
+ if (val == args[i]->val_real())
return (longlong) (i);
}
}
@@ -1438,7 +1519,7 @@ void Item_func_field::fix_length_and_dec()
for (uint i=1; i < arg_count ; i++)
cmp_type= item_cmp_type(cmp_type, args[i]->result_type());
if (cmp_type == STRING_RESULT)
- agg_arg_collations_for_comparison(cmp_collation, args, arg_count);
+ agg_arg_charsets(cmp_collation, args, arg_count, MY_COLL_CMP_CONV);
}
@@ -1601,18 +1682,21 @@ longlong Item_func_bit_count::val_int()
udf_handler::~udf_handler()
{
- if (initialized)
+ if (!not_original)
{
- if (u_d->func_deinit != NULL)
+ if (initialized)
{
- void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*))
- u_d->func_deinit;
- (*deinit)(&initid);
+ if (u_d->func_deinit != NULL)
+ {
+ void (*deinit)(UDF_INIT *) = (void (*)(UDF_INIT*))
+ u_d->func_deinit;
+ (*deinit)(&initid);
+ }
+ free_udf(u_d);
}
- free_udf(u_d);
+ if (buffers) // Because of bug in ecc
+ delete [] buffers;
}
- if (buffers) // Because of bug in ecc
- delete [] buffers;
}
@@ -1626,15 +1710,14 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
DBUG_ENTER("Item_udf_func::fix_fields");
if (check_stack_overrun(thd, buff))
- DBUG_RETURN(1); // Fatal error flag is set!
+ DBUG_RETURN(TRUE); // Fatal error flag is set!
udf_func *tmp_udf=find_udf(u_d->name.str,(uint) u_d->name.length,1);
if (!tmp_udf)
{
- my_printf_error(ER_CANT_FIND_UDF,ER(ER_CANT_FIND_UDF),MYF(0),u_d->name.str,
- errno);
- DBUG_RETURN(1);
+ my_error(ER_CANT_FIND_UDF, MYF(0), u_d->name.str, errno);
+ DBUG_RETURN(TRUE);
}
u_d=tmp_udf;
args=arguments;
@@ -1651,7 +1734,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
{
free_udf(u_d);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
uint i;
Item **arg,**arg_end;
@@ -1664,7 +1747,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
// we can't assign 'item' before, because fix_fields() can change arg
Item *item= *arg;
if (item->check_cols(1))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
/*
TODO: We should think about this. It is not always
right way just to set an UDF result to return my_charset_bin
@@ -1697,7 +1780,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
sizeof(long))))
{
free_udf(u_d);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
func->fix_length_and_dec();
@@ -1736,7 +1819,7 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
}
break;
case Item::REAL_ITEM:
- *((double*) to) = arguments[i]->val();
+ *((double*) to)= arguments[i]->val_real();
if (!arguments[i]->null_value)
{
f_args.args[i]=to;
@@ -1753,10 +1836,10 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
u_d->func_init;
if ((error=(uchar) init(&initid, &f_args, thd->net.last_error)))
{
- my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0),
- u_d->name.str, thd->net.last_error);
+ my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
+ u_d->name.str, thd->net.last_error);
free_udf(u_d);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
func->max_length=min(initid.max_length,MAX_BLOB_WIDTH);
func->maybe_null=initid.maybe_null;
@@ -1766,11 +1849,11 @@ udf_handler::fix_fields(THD *thd, TABLE_LIST *tables, Item_result_field *func,
initialized=1;
if (error)
{
- my_printf_error(ER_CANT_INITIALIZE_UDF,ER(ER_CANT_INITIALIZE_UDF),MYF(0),
- u_d->name.str, ER(ER_UNKNOWN_ERROR));
- DBUG_RETURN(1);
+ my_error(ER_CANT_INITIALIZE_UDF, MYF(0),
+ u_d->name.str, ER(ER_UNKNOWN_ERROR));
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -1803,7 +1886,7 @@ bool udf_handler::get_arguments()
}
break;
case REAL_RESULT:
- *((double*) to) = args[i]->val();
+ *((double*) to)= args[i]->val_real();
if (!args[i]->null_value)
{
f_args.args[i]=to;
@@ -1858,7 +1941,7 @@ String *udf_handler::val_str(String *str,String *save_str)
-double Item_func_udf_float::val()
+double Item_func_udf_float::val_real()
{
DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_func_udf_float::val");
@@ -1871,7 +1954,7 @@ double Item_func_udf_float::val()
String *Item_func_udf_float::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals,&my_charset_bin);
@@ -2013,7 +2096,7 @@ void item_user_lock_release(User_level_lock *ull)
tmp.copy(command, strlen(command), tmp.charset());
tmp.append(ull->key,ull->key_length);
tmp.append("\")", 2);
- Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1);
+ Query_log_event qev(current_thd, tmp.ptr(), tmp.length(),1, FALSE);
qev.error_code=0; // this query is always safe to run on slave
mysql_bin_log.write(&qev);
}
@@ -2292,7 +2375,7 @@ longlong Item_func_benchmark::val_int()
{
switch (args[0]->result_type()) {
case REAL_RESULT:
- (void) args[0]->val();
+ (void) args[0]->val_real();
break;
case INT_RESULT:
(void) args[0]->val_int();
@@ -2346,6 +2429,7 @@ static user_var_entry *get_variable(HASH *hash, LEX_STRING &name,
entry->value=0;
entry->length=0;
entry->update_query_id=0;
+ entry->collation.set(NULL, DERIVATION_NONE);
/*
If we are here, we were called from a SET or a query which sets a
variable. Imagine it is this:
@@ -2380,16 +2464,33 @@ bool Item_func_set_user_var::fix_fields(THD *thd, TABLE_LIST *tables,
/* fix_fields will call Item_func_set_user_var::fix_length_and_dec */
if (Item_func::fix_fields(thd, tables, ref) ||
!(entry= get_variable(&thd->user_vars, name, 1)))
- return 1;
+ return TRUE;
/*
Remember the last query which updated it, this way a query can later know
if this variable is a constant item in the query (it is if update_query_id
is different from query_id).
*/
entry->update_query_id= thd->query_id;
- entry->collation.set(args[0]->collation);
+ /*
+ As it is wrong and confusing to associate any
+ character set with NULL, @a should be latin2
+ after this query sequence:
+
+ SET @a=_latin2'string';
+ SET @a=NULL;
+
+ I.e. the second query should not change the charset
+ to the current default value, but should keep the
+ original value assigned during the first query.
+ In order to do it, we don't copy charset
+ from the argument if the argument is NULL
+ and the variable has previously been initialized.
+ */
+ if (!entry->collation.collation || !args[0]->null_value)
+ entry->collation.set(args[0]->collation);
+ collation.set(entry->collation);
cached_result_type= args[0]->result_type();
- return 0;
+ return FALSE;
}
@@ -2415,7 +2516,6 @@ bool Item_func_set_user_var::update_hash(void *ptr, uint length,
my_free(entry->value,MYF(0));
entry->value=0;
entry->length=0;
- entry->collation.set(cs, dv);
}
else
{
@@ -2548,7 +2648,7 @@ String *user_var_entry::val_str(my_bool *null_value, String *str,
will be catched by thd->net.report_error check in sql_set_variables().
RETURN
- 0 - OK.
+ FALSE OK.
*/
bool
@@ -2559,7 +2659,7 @@ Item_func_set_user_var::check()
switch (cached_result_type) {
case REAL_RESULT:
{
- save_result.vreal= args[0]->val();
+ save_result.vreal= args[0]->val_real();
break;
}
case INT_RESULT:
@@ -2578,7 +2678,7 @@ Item_func_set_user_var::check()
DBUG_ASSERT(0);
break;
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -2640,7 +2740,7 @@ Item_func_set_user_var::update()
}
-double Item_func_set_user_var::val()
+double Item_func_set_user_var::val_real()
{
DBUG_ASSERT(fixed == 1);
check();
@@ -2696,7 +2796,7 @@ Item_func_get_user_var::val_str(String *str)
}
-double Item_func_get_user_var::val()
+double Item_func_get_user_var::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!var_entry)
@@ -3003,8 +3103,9 @@ void Item_func_match::init_search(bool no_order)
if (ft_tmp->charset() != cmp_collation.collation)
{
+ uint dummy_errors;
search_value.copy(ft_tmp->ptr(), ft_tmp->length(), ft_tmp->charset(),
- cmp_collation.collation);
+ cmp_collation.collation, &dummy_errors);
ft_tmp= &search_value;
}
@@ -3040,7 +3141,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
!args[0]->const_during_execution())
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"AGAINST");
- return 1;
+ return TRUE;
}
const_item_cache=0;
@@ -3063,7 +3164,7 @@ bool Item_func_match::fix_fields(THD *thd, TABLE_LIST *tlist, Item **ref)
if (key == NO_SUCH_KEY && !(flags & FT_BOOL))
{
my_error(ER_WRONG_ARGUMENTS,MYF(0),"MATCH");
- return 1;
+ return TRUE;
}
table=((Item_field *)item)->field->table;
table->fulltext_searched=1;
@@ -3145,7 +3246,8 @@ err:
key=NO_SUCH_KEY;
return 0;
}
- my_error(ER_FT_MATCHING_KEY_NOT_FOUND,MYF(0));
+ my_message(ER_FT_MATCHING_KEY_NOT_FOUND,
+ ER(ER_FT_MATCHING_KEY_NOT_FOUND), MYF(0));
return 1;
}
@@ -3166,7 +3268,7 @@ bool Item_func_match::eq(const Item *item, bool binary_cmp) const
}
-double Item_func_match::val()
+double Item_func_match::val_real()
{
DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_func_match::val");
@@ -3274,7 +3376,7 @@ Item *get_system_var(THD *thd, enum_var_type var_type, LEX_STRING name,
{
if (!var->is_struct())
{
- net_printf(thd, ER_VARIABLE_IS_NOT_STRUCT, base_name->str);
+ my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), base_name->str);
return 0;
}
}
@@ -3414,7 +3516,7 @@ Item_func_sp::func_name() const
1 + // .
1 + // end of string
ALIGN_SIZE(1)); // to avoid String reallocation
- String qname((char *)alloc_root(&thd->mem_root, len), len,
+ String qname((char *)alloc_root(thd->mem_root, len), len,
system_charset_info);
qname.length(0);
@@ -3439,8 +3541,7 @@ Item_func_sp::execute(Item **itp)
m_sp= sp_find_function(thd, m_name);
if (! m_sp)
{
- my_printf_error(ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), MYF(0),
- "FUNCTION", m_name->m_qname);
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
DBUG_RETURN(-1);
}
@@ -3462,6 +3563,7 @@ Item_func_sp::execute(Item **itp)
DBUG_RETURN(res);
}
+
enum enum_field_types
Item_func_sp::field_type() const
{
@@ -3474,11 +3576,11 @@ Item_func_sp::field_type() const
DBUG_PRINT("info", ("m_returns = %d", m_sp->m_returns));
DBUG_RETURN(m_sp->m_returns);
}
- my_printf_error(ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), MYF(0),
- "FUNCTION", m_name->m_qname);
- DBUG_RETURN(MYSQL_TYPE_STRING);
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
+ DBUG_RETURN(MYSQL_TYPE_VARCHAR);
}
+
Item_result
Item_func_sp::result_type() const
{
@@ -3491,8 +3593,7 @@ Item_func_sp::result_type() const
{
DBUG_RETURN(m_sp->result());
}
- my_printf_error(ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), MYF(0),
- "FUNCTION", m_name->m_qname);
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
DBUG_RETURN(STRING_RESULT);
}
@@ -3505,8 +3606,7 @@ Item_func_sp::fix_length_and_dec()
m_sp= sp_find_function(current_thd, m_name);
if (! m_sp)
{
- my_printf_error(ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST), MYF(0),
- "FUNCTION", m_name->m_qname);
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", m_name->m_qname.str);
}
else
{
diff --git a/sql/item_func.h b/sql/item_func.h
index 3b941c4a40c..4657ee81dfb 100644
--- a/sql/item_func.h
+++ b/sql/item_func.h
@@ -146,11 +146,12 @@ public:
Item *get_tmp_table_item(THD *thd);
bool agg_arg_collations(DTCollation &c, Item **items, uint nitems,
- bool allow_superset_conversion= FALSE);
+ uint flags= 0);
bool agg_arg_collations_for_comparison(DTCollation &c,
Item **items, uint nitems,
- bool allow_superset_comversion= FALSE);
-
+ uint flags= 0);
+ bool agg_arg_charsets(DTCollation &c, Item **items, uint nitems,
+ uint flags= 0);
bool walk(Item_processor processor, byte *arg);
Item *transform(Item_transformer transformer, byte *arg);
};
@@ -164,7 +165,8 @@ public:
Item_real_func(Item *a,Item *b) :Item_func(a,b) {}
Item_real_func(List<Item> &list) :Item_func(list) {}
String *val_str(String*str);
- longlong val_int() { DBUG_ASSERT(fixed == 1); return (longlong) val(); }
+ longlong val_int()
+ { DBUG_ASSERT(fixed == 1); return (longlong) val_real(); }
enum Item_result result_type () const { return REAL_RESULT; }
void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
};
@@ -178,10 +180,11 @@ public:
Item_num_func(Item *a) :Item_func(a),hybrid_type(REAL_RESULT) {}
Item_num_func(Item *a,Item *b) :Item_func(a,b),hybrid_type(REAL_RESULT) {}
String *val_str(String*str);
- longlong val_int() { DBUG_ASSERT(fixed == 1); return (longlong) val(); }
+ longlong val_int()
+ { DBUG_ASSERT(fixed == 1); return (longlong) val_real(); }
enum Item_result result_type () const { return hybrid_type; }
void fix_length_and_dec() { fix_num_length_and_dec(); }
- bool is_null() { (void) val(); return null_value; }
+ bool is_null() { (void) val_real(); return null_value; }
};
@@ -196,7 +199,7 @@ class Item_num_op :public Item_func
enum Item_result result_type () const { return hybrid_type; }
void fix_length_and_dec() { fix_num_length_and_dec(); find_num_type(); }
void find_num_type(void);
- bool is_null() { (void) val(); return null_value; }
+ bool is_null() { (void) val_real(); return null_value; }
};
@@ -209,7 +212,7 @@ public:
Item_int_func(Item *a,Item *b,Item *c) :Item_func(a,b,c) { max_length=21; }
Item_int_func(List<Item> &list) :Item_func(list) { max_length=21; }
Item_int_func(THD *thd, Item_int_func *item) :Item_func(thd, item) {}
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec() {}
@@ -221,9 +224,9 @@ class Item_func_signed :public Item_int_func
public:
Item_func_signed(Item *a) :Item_int_func(a) {}
const char *func_name() const { return "cast_as_signed"; }
- double val()
+ double val_real()
{
- double tmp= args[0]->val();
+ double tmp= args[0]->val_real();
null_value= args[0]->null_value;
return tmp;
}
@@ -255,7 +258,7 @@ class Item_func_plus :public Item_num_op
public:
Item_func_plus(Item *a,Item *b) :Item_num_op(a,b) {}
const char *func_name() const { return "+"; }
- double val();
+ double val_real();
longlong val_int();
};
@@ -264,7 +267,7 @@ class Item_func_minus :public Item_num_op
public:
Item_func_minus(Item *a,Item *b) :Item_num_op(a,b) {}
const char *func_name() const { return "-"; }
- double val();
+ double val_real();
longlong val_int();
void fix_length_and_dec();
};
@@ -275,7 +278,7 @@ class Item_func_mul :public Item_num_op
public:
Item_func_mul(Item *a,Item *b) :Item_num_op(a,b) {}
const char *func_name() const { return "*"; }
- double val();
+ double val_real();
longlong val_int();
};
@@ -284,7 +287,7 @@ class Item_func_div :public Item_num_op
{
public:
Item_func_div(Item *a,Item *b) :Item_num_op(a,b) {}
- double val();
+ double val_real();
longlong val_int();
const char *func_name() const { return "/"; }
void fix_length_and_dec();
@@ -296,7 +299,7 @@ class Item_func_int_div :public Item_num_op
public:
Item_func_int_div(Item *a,Item *b) :Item_num_op(a,b)
{ hybrid_type=INT_RESULT; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
longlong val_int();
const char *func_name() const { return "DIV"; }
void fix_length_and_dec();
@@ -307,7 +310,7 @@ class Item_func_mod :public Item_num_op
{
public:
Item_func_mod(Item *a,Item *b) :Item_num_op(a,b) {}
- double val();
+ double val_real();
longlong val_int();
const char *func_name() const { return "%"; }
void fix_length_and_dec();
@@ -318,7 +321,7 @@ class Item_func_neg :public Item_num_func
{
public:
Item_func_neg(Item *a) :Item_num_func(a) {}
- double val();
+ double val_real();
longlong val_int();
const char *func_name() const { return "-"; }
void fix_length_and_dec();
@@ -330,7 +333,7 @@ class Item_func_abs :public Item_num_func
public:
Item_func_abs(Item *a) :Item_num_func(a) {}
const char *func_name() const { return "abs"; }
- double val();
+ double val_real();
longlong val_int();
enum Item_result result_type () const
{ return args[0]->result_type() == INT_RESULT ? INT_RESULT : REAL_RESULT; }
@@ -367,7 +370,7 @@ class Item_func_exp :public Item_dec_func
{
public:
Item_func_exp(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "exp"; }
};
@@ -376,7 +379,7 @@ class Item_func_ln :public Item_dec_func
{
public:
Item_func_ln(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "ln"; }
};
@@ -386,7 +389,7 @@ class Item_func_log :public Item_dec_func
public:
Item_func_log(Item *a) :Item_dec_func(a) {}
Item_func_log(Item *a,Item *b) :Item_dec_func(a,b) {}
- double val();
+ double val_real();
const char *func_name() const { return "log"; }
};
@@ -395,7 +398,7 @@ class Item_func_log2 :public Item_dec_func
{
public:
Item_func_log2(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "log2"; }
};
@@ -404,7 +407,7 @@ class Item_func_log10 :public Item_dec_func
{
public:
Item_func_log10(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "log10"; }
};
@@ -413,7 +416,7 @@ class Item_func_sqrt :public Item_dec_func
{
public:
Item_func_sqrt(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "sqrt"; }
};
@@ -422,7 +425,7 @@ class Item_func_pow :public Item_dec_func
{
public:
Item_func_pow(Item *a,Item *b) :Item_dec_func(a,b) {}
- double val();
+ double val_real();
const char *func_name() const { return "pow"; }
};
@@ -431,7 +434,7 @@ class Item_func_acos :public Item_dec_func
{
public:
Item_func_acos(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "acos"; }
};
@@ -439,7 +442,7 @@ class Item_func_asin :public Item_dec_func
{
public:
Item_func_asin(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "asin"; }
};
@@ -448,7 +451,7 @@ class Item_func_atan :public Item_dec_func
public:
Item_func_atan(Item *a) :Item_dec_func(a) {}
Item_func_atan(Item *a,Item *b) :Item_dec_func(a,b) {}
- double val();
+ double val_real();
const char *func_name() const { return "atan"; }
};
@@ -456,7 +459,7 @@ class Item_func_cos :public Item_dec_func
{
public:
Item_func_cos(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "cos"; }
};
@@ -464,7 +467,7 @@ class Item_func_sin :public Item_dec_func
{
public:
Item_func_sin(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "sin"; }
};
@@ -472,7 +475,7 @@ class Item_func_tan :public Item_dec_func
{
public:
Item_func_tan(Item *a) :Item_dec_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "tan"; }
};
@@ -510,7 +513,7 @@ public:
Item_func_round(Item *a,Item *b,bool trunc_arg)
:Item_real_func(a,b),truncate(trunc_arg) {}
const char *func_name() const { return truncate ? "truncate" : "round"; }
- double val();
+ double val_real();
void fix_length_and_dec();
};
@@ -521,7 +524,7 @@ class Item_func_rand :public Item_real_func
public:
Item_func_rand(Item *a) :Item_real_func(a), rand(0) {}
Item_func_rand() :Item_real_func() {}
- double val();
+ double val_real();
const char *func_name() const { return "rand"; }
bool const_item() const { return 0; }
void update_used_tables();
@@ -545,7 +548,7 @@ class Item_func_units :public Item_real_func
public:
Item_func_units(char *name_arg,Item *a,double mul_arg,double add_arg)
:Item_real_func(a),name(name_arg),mul(mul_arg),add(add_arg) {}
- double val();
+ double val_real();
const char *func_name() const { return name; }
void fix_length_and_dec() { decimals=NOT_FIXED_DEC; max_length=float_length(decimals); }
};
@@ -559,7 +562,7 @@ class Item_func_min_max :public Item_func
public:
Item_func_min_max(List<Item> &list,int cmp_sign_arg) :Item_func(list),
cmp_type(INT_RESULT), cmp_sign(cmp_sign_arg) {}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *);
void fix_length_and_dec();
@@ -798,8 +801,11 @@ class Item_func_udf_float :public Item_udf_func
Item_func_udf_float(udf_func *udf_arg, List<Item> &list)
:Item_udf_func(udf_arg,list) {}
longlong val_int()
- { DBUG_ASSERT(fixed == 1); return (longlong) Item_func_udf_float::val(); }
- double val();
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (longlong) Item_func_udf_float::val_real();
+ }
+ double val_real();
String *val_str(String *str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
};
@@ -812,7 +818,7 @@ public:
Item_func_udf_int(udf_func *udf_arg, List<Item> &list)
:Item_udf_func(udf_arg,list) {}
longlong val_int();
- double val() { return (double) Item_func_udf_int::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; }
void fix_length_and_dec() { decimals=0; max_length=21; }
@@ -826,7 +832,7 @@ public:
Item_func_udf_str(udf_func *udf_arg, List<Item> &list)
:Item_udf_func(udf_arg,list) {}
String *val_str(String *);
- double val()
+ double val_real()
{
int err;
String *res; res=val_str(&str_value);
@@ -849,7 +855,7 @@ class Item_func_udf_float :public Item_real_func
public:
Item_func_udf_float(udf_func *udf_arg) :Item_real_func() {}
Item_func_udf_float(udf_func *udf_arg, List<Item> &list) :Item_real_func(list) {}
- double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
};
@@ -869,7 +875,7 @@ public:
Item_func_udf_str(udf_func *udf_arg, List<Item> &list) :Item_func(list) {}
String *val_str(String *)
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
- double val() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.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; }
@@ -944,7 +950,7 @@ public:
Item_func_set_user_var(LEX_STRING a,Item *b)
:Item_func(b), cached_result_type(INT_RESULT), name(a)
{}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
bool update_hash(void *ptr, uint length, enum Item_result type,
@@ -970,7 +976,7 @@ public:
Item_func(), name(a) {}
enum Functype functype() const { return GUSERVAR_FUNC; }
LEX_STRING get_name() { return name; }
- double val();
+ double val_real();
longlong val_int();
String *val_str(String* str);
void fix_length_and_dec();
@@ -980,7 +986,7 @@ public:
We must always return variables as strings to guard against selects of type
select @t1:=1,@t1,@t:="hello",@t from foo where (@t1:= t2.b)
*/
- enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
const char *func_name() const { return "get_user_var"; }
bool const_item() const;
table_map used_tables() const
@@ -1029,11 +1035,7 @@ public:
table->file->ft_handler=0;
table->fulltext_searched=0;
}
- if (concat)
- {
- delete concat;
- concat= 0;
- }
+ concat= 0;
DBUG_VOID_RETURN;
}
enum Functype functype() const { return FT_FUNC; }
@@ -1043,8 +1045,8 @@ public:
bool fix_fields(THD *thd, struct st_table_list *tlist, Item **ref);
bool eq(const Item *, bool binary_cmp) const;
/* The following should be safe, even if we compare doubles */
- longlong val_int() { DBUG_ASSERT(fixed == 1); return val()!=0.0; }
- double val();
+ longlong val_int() { DBUG_ASSERT(fixed == 1); return val_real() != 0.0; }
+ double val_real();
void print(String *str);
bool fix_index();
@@ -1133,10 +1135,10 @@ public:
longlong val_int()
{
- return (longlong)Item_func_sp::val();
+ return (longlong)Item_func_sp::val_real();
}
- double val()
+ double val_real()
{
Item *it;
double d;
@@ -1146,7 +1148,7 @@ public:
null_value= 1;
return 0.0;
}
- d= it->val();
+ d= it->val_real();
null_value= it->null_value;
return d;
}
diff --git a/sql/item_geofunc.cc b/sql/item_geofunc.cc
index 935925c1e83..163260f6428 100644
--- a/sql/item_geofunc.cc
+++ b/sql/item_geofunc.cc
@@ -148,9 +148,9 @@ String *Item_func_geometry_type::val_str(String *str)
swkb->length() - SRID_SIZE)))))
return 0;
/* String will not move */
- str->set(geom->get_class_info()->m_name.str,
- geom->get_class_info()->m_name.length,
- default_charset());
+ str->copy(geom->get_class_info()->m_name.str,
+ geom->get_class_info()->m_name.length,
+ default_charset());
return str;
}
@@ -320,8 +320,8 @@ err:
String *Item_func_point::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double x= args[0]->val();
- double y= args[1]->val();
+ double x= args[0]->val_real();
+ double y= args[1]->val_real();
if ((null_value= (args[0]->null_value ||
args[1]->null_value ||
@@ -628,7 +628,7 @@ longlong Item_func_numpoints::val_int()
}
-double Item_func_x::val()
+double Item_func_x::val_real()
{
DBUG_ASSERT(fixed == 1);
double res= 0.0; // In case of errors
@@ -645,7 +645,7 @@ double Item_func_x::val()
}
-double Item_func_y::val()
+double Item_func_y::val_real()
{
DBUG_ASSERT(fixed == 1);
double res= 0; // In case of errors
@@ -662,7 +662,7 @@ double Item_func_y::val()
}
-double Item_func_area::val()
+double Item_func_area::val_real()
{
DBUG_ASSERT(fixed == 1);
double res= 0; // In case of errors
@@ -679,7 +679,7 @@ double Item_func_area::val()
return res;
}
-double Item_func_glength::val()
+double Item_func_glength::val_real()
{
DBUG_ASSERT(fixed == 1);
double res= 0; // In case of errors
diff --git a/sql/item_geofunc.h b/sql/item_geofunc.h
index 79e4f804a04..e19036cc982 100644
--- a/sql/item_geofunc.h
+++ b/sql/item_geofunc.h
@@ -263,7 +263,7 @@ class Item_func_x: public Item_real_func
String value;
public:
Item_func_x(Item *a): Item_real_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "x"; }
};
@@ -273,7 +273,7 @@ class Item_func_y: public Item_real_func
String value;
public:
Item_func_y(Item *a): Item_real_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "y"; }
};
@@ -316,7 +316,7 @@ class Item_func_area: public Item_real_func
String value;
public:
Item_func_area(Item *a): Item_real_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "area"; }
};
@@ -326,7 +326,7 @@ class Item_func_glength: public Item_real_func
String value;
public:
Item_func_glength(Item *a): Item_real_func(a) {}
- double val();
+ double val_real();
const char *func_name() const { return "glength"; }
};
diff --git a/sql/item_row.cc b/sql/item_row.cc
index 8a020861fef..0c7eae9d920 100644
--- a/sql/item_row.cc
+++ b/sql/item_row.cc
@@ -62,7 +62,7 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
for (arg= items, arg_end= items+arg_count; arg != arg_end ; arg++)
{
if ((*arg)->fix_fields(thd, tabl, arg))
- return 1;
+ return TRUE;
// we can't assign 'item' before, because fix_fields() can change arg
Item *item= *arg;
used_tables_cache |= item->used_tables();
@@ -81,7 +81,7 @@ bool Item_row::fix_fields(THD *thd, TABLE_LIST *tabl, Item **ref)
with_sum_func= with_sum_func || item->with_sum_func;
}
fixed= 1;
- return 0;
+ return FALSE;
}
void Item_row::split_sum_func(THD *thd, Item **ref_pointer_array,
diff --git a/sql/item_row.h b/sql/item_row.h
index ef5856dcdd3..64bd5cbbb44 100644
--- a/sql/item_row.h
+++ b/sql/item_row.h
@@ -41,7 +41,7 @@ public:
{
illegal_method_call((const char*)"make_field");
};
- double val()
+ double val_real()
{
illegal_method_call((const char*)"val");
return 0;
diff --git a/sql/item_strfunc.cc b/sql/item_strfunc.cc
index d015ca36eac..bf172e1744d 100644
--- a/sql/item_strfunc.cc
+++ b/sql/item_strfunc.cc
@@ -42,10 +42,10 @@ String my_empty_string("",default_charset_info);
static void my_coll_agg_error(DTCollation &c1, DTCollation &c2,
const char *fname)
{
- my_error(ER_CANT_AGGREGATE_2COLLATIONS,MYF(0),
- c1.collation->name,c1.derivation_name(),
- c2.collation->name,c2.derivation_name(),
- fname);
+ my_error(ER_CANT_AGGREGATE_2COLLATIONS, MYF(0),
+ c1.collation->name, c1.derivation_name(),
+ c2.collation->name, c2.derivation_name(),
+ fname);
}
uint nr_of_decimals(const char *str)
@@ -59,7 +59,7 @@ uint nr_of_decimals(const char *str)
return 0;
}
-double Item_str_func::val()
+double Item_str_func::val_real()
{
DBUG_ASSERT(fixed == 1);
int err;
@@ -346,7 +346,7 @@ void Item_func_concat::fix_length_and_dec()
{
max_length=0;
- if (agg_arg_collations(collation, args, arg_count))
+ if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV))
return;
for (uint i=0 ; i < arg_count ; i++)
@@ -640,10 +640,15 @@ void Item_func_concat_ws::fix_length_and_dec()
{
max_length=0;
- if (agg_arg_collations(collation, args, arg_count))
+ if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV))
return;
- max_length= arg_count > 1 ? args[0]->max_length * (arg_count - 2) : 0;
+ /*
+ arg_count cannot be less than 2,
+ it is done on parser level in sql_yacc.yy
+ so, (arg_count - 2) is safe here.
+ */
+ max_length= args[0]->max_length * (arg_count - 2);
for (uint i=1 ; i < arg_count ; i++)
max_length+=args[i]->max_length;
@@ -843,7 +848,7 @@ void Item_func_replace::fix_length_and_dec()
maybe_null=1;
}
- if (agg_arg_collations_for_comparison(collation, args, 3))
+ if (agg_arg_charsets(collation, args, 3, MY_COLL_CMP_CONV))
return;
}
@@ -888,11 +893,13 @@ null:
void Item_func_insert::fix_length_and_dec()
{
- if (collation.set(args[0]->collation, args[3]->collation))
- {
- my_coll_agg_error(args[0]->collation, args[3]->collation, func_name());
- return;
- }
+ Item *cargs[2];
+ cargs[0]= args[0];
+ cargs[1]= args[3];
+ if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV))
+ return;
+ args[0]= cargs[0];
+ args[3]= cargs[1];
max_length=args[0]->max_length+args[3]->max_length;
if (max_length > MAX_BLOB_WIDTH)
{
@@ -1058,7 +1065,7 @@ void Item_func_substr_index::fix_length_and_dec()
{
max_length= args[0]->max_length;
- if (agg_arg_collations_for_comparison(collation, args, 2))
+ if (agg_arg_charsets(collation, args, 2, MY_COLL_CMP_CONV))
return;
}
@@ -1350,10 +1357,14 @@ void Item_func_trim::fix_length_and_dec()
remove.set_ascii(" ",1);
}
else
- if (collation.set(args[1]->collation, args[0]->collation) ||
- collation.derivation == DERIVATION_NONE)
{
- my_coll_agg_error(args[1]->collation, args[0]->collation, func_name());
+ Item *cargs[2];
+ cargs[0]= args[1];
+ cargs[1]= args[0];
+ if (agg_arg_charsets(collation, cargs, 2, MY_COLL_CMP_CONV))
+ return;
+ args[0]= cargs[1];
+ args[1]= cargs[0];
}
}
@@ -1618,7 +1629,7 @@ Item_func_format::Item_func_format(Item *org,int dec) :Item_str_func(org)
String *Item_func_format::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double nr =args[0]->val();
+ double nr= args[0]->val_real();
uint32 diff,length,str_length;
uint dec;
if ((null_value=args[0]->null_value))
@@ -1674,7 +1685,7 @@ void Item_func_elt::fix_length_and_dec()
max_length=0;
decimals=0;
- if (agg_arg_collations(collation, args+1, arg_count-1))
+ if (agg_arg_charsets(collation, args+1, arg_count-1, MY_COLL_ALLOW_CONV))
return;
for (uint i= 1 ; i < arg_count ; i++)
@@ -1686,14 +1697,14 @@ void Item_func_elt::fix_length_and_dec()
}
-double Item_func_elt::val()
+double Item_func_elt::val_real()
{
DBUG_ASSERT(fixed == 1);
uint tmp;
null_value=1;
if ((tmp=(uint) args[0]->val_int()) == 0 || tmp >= arg_count)
return 0.0;
- double result= args[tmp]->val();
+ double result= args[tmp]->val_real();
null_value= args[tmp]->null_value;
return result;
}
@@ -1750,7 +1761,7 @@ void Item_func_make_set::fix_length_and_dec()
{
max_length=arg_count-1;
- if (agg_arg_collations(collation, args, arg_count))
+ if (agg_arg_charsets(collation, args, arg_count, MY_COLL_ALLOW_CONV))
return;
for (uint i=0 ; i < arg_count ; i++)
@@ -1958,12 +1969,13 @@ err:
void Item_func_rpad::fix_length_and_dec()
{
- if (collation.set(args[0]->collation, args[2]->collation))
- {
- my_coll_agg_error(args[0]->collation, args[2]->collation, func_name());
+ Item *cargs[2];
+ cargs[0]= args[0];
+ cargs[1]= args[2];
+ if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV))
return;
- }
-
+ args[0]= cargs[0];
+ args[2]= cargs[1];
if (args[1]->const_item())
{
uint32 length= (uint32) args[1]->val_int() * collation.collation->mbmaxlen;
@@ -2042,11 +2054,13 @@ String *Item_func_rpad::val_str(String *str)
void Item_func_lpad::fix_length_and_dec()
{
- if (collation.set(args[0]->collation, args[2]->collation))
- {
- my_coll_agg_error(args[0]->collation, args[2]->collation, func_name());
+ Item *cargs[2];
+ cargs[0]= args[0];
+ cargs[1]= args[2];
+ if (agg_arg_charsets(collation, cargs, 2, MY_COLL_ALLOW_CONV))
return;
- }
+ args[0]= cargs[0];
+ args[2]= cargs[1];
if (args[1]->const_item())
{
@@ -2155,13 +2169,14 @@ String *Item_func_conv_charset::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
String *arg= args[0]->val_str(str);
+ uint dummy_errors;
if (!arg)
{
null_value=1;
return 0;
}
null_value= str_value.copy(arg->ptr(),arg->length(),arg->charset(),
- conv_charset);
+ conv_charset, &dummy_errors);
return null_value ? 0 : &str_value;
}
@@ -2211,8 +2226,8 @@ void Item_func_set_collation::fix_length_and_dec()
if (!set_collation ||
!my_charset_same(args[0]->collation.collation,set_collation))
{
- my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
- colname,args[0]->collation.collation->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ colname, args[0]->collation.collation->csname);
return;
}
collation.set(set_collation, DERIVATION_EXPLICIT);
@@ -2256,11 +2271,12 @@ String *Item_func_charset::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
+ uint dummy_errors;
if ((null_value=(args[0]->null_value || !res->charset())))
return 0;
str->copy(res->charset()->csname,strlen(res->charset()->csname),
- &my_charset_latin1, collation.collation);
+ &my_charset_latin1, collation.collation, &dummy_errors);
return str;
}
@@ -2268,11 +2284,12 @@ String *Item_func_collation::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
String *res = args[0]->val_str(str);
+ uint dummy_errors;
if ((null_value=(args[0]->null_value || !res->charset())))
return 0;
str->copy(res->charset()->name,strlen(res->charset()->name),
- &my_charset_latin1, collation.collation);
+ &my_charset_latin1, collation.collation, &dummy_errors);
return str;
}
@@ -2499,7 +2516,8 @@ void Item_func_export_set::fix_length_and_dec()
uint sep_length=(arg_count > 3 ? args[3]->max_length : 1);
max_length=length*64+sep_length*63;
- if (agg_arg_collations(collation, args+1, min(4,arg_count)-1))
+ if (agg_arg_charsets(collation, args+1, min(4,arg_count)-1),
+ MY_COLL_ALLOW_CONV)
return;
}
@@ -2556,9 +2574,12 @@ String* Item_func_inet_ntoa::val_str(String* str)
This function is very useful when you want to generate SQL statements
- RETURN VALUES
+ NOTE
+ QUOTE(NULL) returns the string 'NULL' (4 letters, without quotes).
+
+ RETURN VALUES
str Quoted string
- NULL Argument to QUOTE() was NULL or out of memory.
+ NULL Out of memory.
*/
#define get_esc_bit(mask, num) (1 & (*((mask) + ((num) >> 3))) >> ((num) & 7))
@@ -2583,7 +2604,12 @@ String *Item_func_quote::val_str(String *str)
String *arg= args[0]->val_str(str);
uint arg_length, new_length;
if (!arg) // Null argument
- goto null;
+ {
+ str->copy("NULL", 4, collation.collation); // Return the string 'NULL'
+ null_value= 0;
+ return str;
+ }
+
arg_length= arg->length();
new_length= arg_length+2; /* for beginning and ending ' signs */
diff --git a/sql/item_strfunc.h b/sql/item_strfunc.h
index afc4b9da0a1..647cf022d79 100644
--- a/sql/item_strfunc.h
+++ b/sql/item_strfunc.h
@@ -32,7 +32,7 @@ public:
Item_str_func(Item *a,Item *b,Item *c,Item *d, Item* e) :Item_func(a,b,c,d,e) {decimals=NOT_FIXED_DEC; }
Item_str_func(List<Item> &list) :Item_func(list) {decimals=NOT_FIXED_DEC; }
longlong val_int();
- double val();
+ double val_real();
enum Item_result result_type () const { return STRING_RESULT; }
void left_right_max_length();
};
@@ -377,7 +377,7 @@ class Item_func_elt :public Item_str_func
{
public:
Item_func_elt(List<Item> &list) :Item_str_func(list) {}
- double val();
+ double val_real();
longlong val_int();
String *val_str(String *str);
void fix_length_and_dec();
diff --git a/sql/item_subselect.cc b/sql/item_subselect.cc
index bafca8acf0f..304c3ed4bbd 100644
--- a/sql/item_subselect.cc
+++ b/sql/item_subselect.cc
@@ -66,7 +66,7 @@ void Item_subselect::init(st_select_lex *select_lex,
parsing_place= unit->item->parsing_place;
unit->item->engine= 0;
unit->item= this;
- engine->change_item(this, result);
+ engine->change_result(this, result);
}
else
{
@@ -133,13 +133,13 @@ Item_subselect::select_transformer(JOIN *join)
bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
{
char const *save_where= thd_param->where;
- int res;
+ bool res;
DBUG_ASSERT(fixed == 0);
engine->set_thd((thd= thd_param));
if (check_stack_overrun(thd, (gptr)&res))
- return 1;
+ return TRUE;
res= engine->prepare();
@@ -171,7 +171,7 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
if (engine->cols() > max_columns)
{
my_error(ER_OPERAND_COLUMNS, MYF(0), 1);
- return 1;
+ return TRUE;
}
fix_length_and_dec();
}
@@ -190,15 +190,16 @@ bool Item_subselect::fix_fields(THD *thd_param, TABLE_LIST *tables, Item **ref)
bool Item_subselect::exec()
{
int res;
- MEM_ROOT *old_root= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
- if (&thd->mem_root != old_root)
- {
- my_pthread_setspecific_ptr(THR_MALLOC, &thd->mem_root);
- res= engine->exec();
- my_pthread_setspecific_ptr(THR_MALLOC, old_root);
- }
- else
- res= engine->exec();
+ MEM_ROOT *old_root= thd->mem_root;
+
+ /*
+ As this is execution, all objects should be allocated through the main
+ mem root
+ */
+ thd->mem_root= &thd->main_mem_root;
+ res= engine->exec();
+ thd->mem_root= old_root;
+
if (engine_changed)
{
engine_changed= 0;
@@ -440,13 +441,13 @@ void Item_singlerow_subselect::bring_value()
exec();
}
-double Item_singlerow_subselect::val()
+double Item_singlerow_subselect::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!exec() && !value->null_value)
{
null_value= 0;
- return value->val();
+ return value->val_real();
}
else
{
@@ -564,7 +565,7 @@ void Item_exists_subselect::fix_length_and_dec()
max_columns= engine->cols();
}
-double Item_exists_subselect::val()
+double Item_exists_subselect::val_real()
{
DBUG_ASSERT(fixed == 1);
if (exec())
@@ -598,7 +599,7 @@ String *Item_exists_subselect::val_str(String *str)
return str;
}
-double Item_in_subselect::val()
+double Item_in_subselect::val_real()
{
DBUG_ASSERT(fixed == 1);
if (exec())
@@ -661,15 +662,10 @@ Item_in_subselect::single_value_transformer(JOIN *join,
}
SELECT_LEX *select_lex= join->select_lex;
- Item_arena *arena= thd->current_arena, backup;
-
+ Item_arena *arena, backup;
+ arena= thd->change_arena_if_needed(&backup);
thd->where= "scalar IN/ALL/ANY subquery";
- if (arena->is_conventional())
- arena= 0; // For easier test
- else
- thd->set_n_backup_item_arena(arena, &backup);
-
/*
Check that the right part of the subselect contains no more than one
column. E.g. in SELECT 1 IN (SELECT * ..) the right part is (SELECT * ...)
@@ -928,11 +924,8 @@ Item_in_subselect::row_value_transformer(JOIN *join)
}
thd->where= "row IN/ALL/ANY subquery";
- Item_arena *arena= thd->current_arena, backup;
- if (arena->is_conventional())
- arena= 0;
- else
- thd->set_n_backup_item_arena(arena, &backup);
+ Item_arena *arena, backup;
+ arena= thd->change_arena_if_needed(&backup);
if (select_lex->item_list.elements != left_expr->cols())
{
@@ -1429,7 +1422,7 @@ void subselect_uniquesubquery_engine::exclude()
table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
{
table_map map= 0;
- for(; table; table= table->next_local)
+ for(; table; table= table->next_leaf)
{
TABLE *tbl= table->table;
if (tbl && tbl->const_table)
@@ -1442,14 +1435,13 @@ table_map subselect_engine::calc_const_tables(TABLE_LIST *table)
table_map subselect_single_select_engine::upper_select_const_tables()
{
return calc_const_tables((TABLE_LIST *) select_lex->outer_select()->
- table_list.first);
+ leaf_tables);
}
table_map subselect_union_engine::upper_select_const_tables()
{
- return calc_const_tables((TABLE_LIST *) unit->outer_select()->
- table_list.first);
+ return calc_const_tables((TABLE_LIST *) unit->outer_select()->leaf_tables);
}
@@ -1511,12 +1503,12 @@ void subselect_indexsubquery_engine::print(String *str)
res new select_result object
RETURN
- 0 OK
- -1 error
+ FALSE OK
+ TRUE error
*/
-int subselect_single_select_engine::change_item(Item_subselect *si,
- select_subselect *res)
+bool subselect_single_select_engine::change_result(Item_subselect *si,
+ select_subselect *res)
{
item= si;
result= res;
@@ -1533,12 +1525,12 @@ int subselect_single_select_engine::change_item(Item_subselect *si,
res new select_result object
RETURN
- 0 OK
- -1 error
+ FALSE OK
+ TRUE error
*/
-int subselect_union_engine::change_item(Item_subselect *si,
- select_subselect *res)
+bool subselect_union_engine::change_result(Item_subselect *si,
+ select_subselect *res)
{
item= si;
int rc= unit->change_result(res, result);
@@ -1556,14 +1548,15 @@ int subselect_union_engine::change_item(Item_subselect *si,
res new select_result object
RETURN
- -1 error
+ FALSE OK
+ TRUE error
*/
-int subselect_uniquesubquery_engine::change_item(Item_subselect *si,
- select_subselect *res)
+bool subselect_uniquesubquery_engine::change_result(Item_subselect *si,
+ select_subselect *res)
{
DBUG_ASSERT(0);
- return -1;
+ return TRUE;
}
diff --git a/sql/item_subselect.h b/sql/item_subselect.h
index 6efb9052115..d0ff3654e48 100644
--- a/sql/item_subselect.h
+++ b/sql/item_subselect.h
@@ -134,7 +134,7 @@ public:
void reset();
trans_res select_transformer(JOIN *join);
void store(uint i, Item* item);
- double val();
+ double val_real();
longlong val_int ();
String *val_str (String *);
enum Item_result result_type() const;
@@ -179,7 +179,7 @@ public:
enum Item_result result_type() const { return INT_RESULT;}
longlong val_int();
- double val();
+ double val_real();
String *val_str(String*);
void fix_length_and_dec();
void print(String *str);
@@ -224,7 +224,7 @@ public:
Comp_creator *func);
trans_res row_value_transformer(JOIN * join);
longlong val_int();
- double val();
+ double val_real();
String *val_str(String*);
void top_level_item() { abort_on_null=1; }
bool test_limit(st_select_lex_unit *unit);
@@ -290,7 +290,7 @@ public:
virtual table_map upper_select_const_tables()= 0;
static table_map calc_const_tables(TABLE_LIST *);
virtual void print(String *str)= 0;
- virtual int change_item(Item_subselect *si, select_subselect *result)= 0;
+ virtual bool change_result(Item_subselect *si, select_subselect *result)= 0;
virtual bool no_tables()= 0;
};
@@ -315,7 +315,7 @@ public:
void exclude();
table_map upper_select_const_tables();
void print (String *str);
- int change_item(Item_subselect *si, select_subselect *result);
+ bool change_result(Item_subselect *si, select_subselect *result);
bool no_tables();
};
@@ -336,7 +336,7 @@ public:
void exclude();
table_map upper_select_const_tables();
void print (String *str);
- int change_item(Item_subselect *si, select_subselect *result);
+ bool change_result(Item_subselect *si, select_subselect *result);
bool no_tables();
};
@@ -366,7 +366,7 @@ public:
void exclude();
table_map upper_select_const_tables() { return 0; }
void print (String *str);
- int change_item(Item_subselect *si, select_subselect *result);
+ bool change_result(Item_subselect *si, select_subselect *result);
bool no_tables();
};
diff --git a/sql/item_sum.cc b/sql/item_sum.cc
index 743b3eee58c..b242698d36e 100644
--- a/sql/item_sum.cc
+++ b/sql/item_sum.cc
@@ -143,7 +143,7 @@ String *
Item_sum_num::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0;
str->set(nr,decimals, &my_charset_bin);
@@ -173,8 +173,9 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!thd->allow_sum_func)
{
- my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
- return 1;
+ my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
+ MYF(0));
+ return TRUE;
}
thd->allow_sum_func=0; // No included group funcs
decimals=0;
@@ -182,7 +183,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
for (uint i=0 ; i < arg_count ; i++)
{
if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
- return 1;
+ return TRUE;
if (decimals < args[i]->decimals)
decimals=args[i]->decimals;
maybe_null |= args[i]->maybe_null;
@@ -193,7 +194,7 @@ Item_sum_num::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
fix_length_and_dec();
thd->allow_sum_func=1; // Allow group functions
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -205,8 +206,9 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
Item *item= args[0];
if (!thd->allow_sum_func)
{
- my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
- return 1;
+ my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
+ MYF(0));
+ return TRUE;
}
thd->allow_sum_func=0; // No included group funcs
@@ -214,21 +216,18 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!item->fixed &&
item->fix_fields(thd, tables, args) ||
(item= args[0])->check_cols(1))
- return 1;
+ return TRUE;
hybrid_type= item->result_type();
if (hybrid_type == INT_RESULT)
{
- cmp_charset= &my_charset_bin;
max_length=20;
}
else if (hybrid_type == REAL_RESULT)
{
- cmp_charset= &my_charset_bin;
max_length=float_length(decimals);
}else
{
- cmp_charset= item->collation.collation;
max_length=item->max_length;
}
decimals=item->decimals;
@@ -245,7 +244,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
else
hybrid_field_type= Item::field_type();
fixed= 1;
- return 0;
+ return FALSE;
}
@@ -255,7 +254,7 @@ Item_sum_hybrid::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
Item *Item_sum_sum::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_sum(thd, this);
+ return new (thd->mem_root) Item_sum_sum(thd, this);
}
@@ -267,14 +266,14 @@ void Item_sum_sum::clear()
bool Item_sum_sum::add()
{
- sum+=args[0]->val();
+ sum+= args[0]->val_real();
if (!args[0]->null_value)
null_value= 0;
return 0;
}
-double Item_sum_sum::val()
+double Item_sum_sum::val_real()
{
DBUG_ASSERT(fixed == 1);
return sum;
@@ -313,7 +312,7 @@ Item_sum_sum_distinct::~Item_sum_sum_distinct()
Item *
Item_sum_sum_distinct::copy_or_same(THD *thd)
{
- return new (&thd->mem_root) Item_sum_sum_distinct(thd, this);
+ return new (thd->mem_root) Item_sum_sum_distinct(thd, this);
}
C_MODE_START
@@ -359,8 +358,8 @@ void Item_sum_sum_distinct::clear()
bool Item_sum_sum_distinct::add()
{
- /* args[0]->val() may reset args[0]->null_value */
- double val= args[0]->val();
+ /* args[0]->val_real() may reset args[0]->null_value */
+ double val= args[0]->val_real();
if (!args[0]->null_value)
{
DBUG_ASSERT(tree);
@@ -383,7 +382,7 @@ static int sum_sum_distinct(void *element, element_count num_of_dups,
C_MODE_END
-double Item_sum_sum_distinct::val()
+double Item_sum_sum_distinct::val_real()
{
/*
We don't have a tree only if 'setup()' hasn't been called;
@@ -399,7 +398,7 @@ double Item_sum_sum_distinct::val()
Item *Item_sum_count::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_count(thd, this);
+ return new (thd->mem_root) Item_sum_count(thd, this);
}
@@ -444,7 +443,7 @@ void Item_sum_count::cleanup()
Item *Item_sum_avg::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_avg(thd, this);
+ return new (thd->mem_root) Item_sum_avg(thd, this);
}
@@ -456,7 +455,7 @@ void Item_sum_avg::clear()
bool Item_sum_avg::add()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value)
{
sum+=nr;
@@ -465,7 +464,7 @@ bool Item_sum_avg::add()
return 0;
}
-double Item_sum_avg::val()
+double Item_sum_avg::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!count)
@@ -482,16 +481,16 @@ double Item_sum_avg::val()
Standard deviation
*/
-double Item_sum_std::val()
+double Item_sum_std::val_real()
{
DBUG_ASSERT(fixed == 1);
- double tmp= Item_sum_variance::val();
+ double tmp= Item_sum_variance::val_real();
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
Item *Item_sum_std::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_std(thd, this);
+ return new (thd->mem_root) Item_sum_std(thd, this);
}
@@ -501,7 +500,7 @@ Item *Item_sum_std::copy_or_same(THD* thd)
Item *Item_sum_variance::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_variance(thd, this);
+ return new (thd->mem_root) Item_sum_variance(thd, this);
}
@@ -513,7 +512,7 @@ void Item_sum_variance::clear()
bool Item_sum_variance::add()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value)
{
sum+=nr;
@@ -523,7 +522,7 @@ bool Item_sum_variance::add()
return 0;
}
-double Item_sum_variance::val()
+double Item_sum_variance::val_real()
{
DBUG_ASSERT(fixed == 1);
if (!count)
@@ -540,7 +539,7 @@ double Item_sum_variance::val()
void Item_sum_variance::reset_field()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
char *res=result_field->ptr;
if (args[0]->null_value)
@@ -565,7 +564,7 @@ void Item_sum_variance::update_field()
float8get(old_sqr, res+sizeof(double));
field_count=sint8korr(res+sizeof(double)*2);
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
old_nr+=nr;
@@ -587,7 +586,7 @@ void Item_sum_hybrid::clear()
null_value= 1;
}
-double Item_sum_hybrid::val()
+double Item_sum_hybrid::val_real()
{
DBUG_ASSERT(fixed == 1);
int err;
@@ -620,7 +619,7 @@ longlong Item_sum_hybrid::val_int()
return 0;
if (hybrid_type == INT_RESULT)
return sum_int;
- return (longlong) Item_sum_hybrid::val();
+ return (longlong) Item_sum_hybrid::val_real();
}
@@ -663,7 +662,7 @@ void Item_sum_hybrid::cleanup()
Item *Item_sum_min::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_min(thd, this);
+ return new (thd->mem_root) Item_sum_min(thd, this);
}
@@ -674,7 +673,7 @@ bool Item_sum_min::add()
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
- (null_value || sortcmp(&value,result,cmp_charset) > 0))
+ (null_value || sortcmp(&value,result,collation.collation) > 0))
{
value.copy(*result);
null_value=0;
@@ -696,7 +695,7 @@ bool Item_sum_min::add()
break;
case REAL_RESULT:
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value && (null_value || nr < sum))
{
sum=nr;
@@ -716,7 +715,7 @@ bool Item_sum_min::add()
Item *Item_sum_max::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_max(thd, this);
+ return new (thd->mem_root) Item_sum_max(thd, this);
}
@@ -727,7 +726,7 @@ bool Item_sum_max::add()
{
String *result=args[0]->val_str(&tmp_value);
if (!args[0]->null_value &&
- (null_value || sortcmp(&value,result,cmp_charset) < 0))
+ (null_value || sortcmp(&value,result,collation.collation) < 0))
{
value.copy(*result);
null_value=0;
@@ -749,7 +748,7 @@ bool Item_sum_max::add()
break;
case REAL_RESULT:
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (!args[0]->null_value && (null_value || nr > sum))
{
sum=nr;
@@ -783,7 +782,7 @@ void Item_sum_bit::clear()
Item *Item_sum_or::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_or(thd, this);
+ return new (thd->mem_root) Item_sum_or(thd, this);
}
@@ -797,7 +796,7 @@ bool Item_sum_or::add()
Item *Item_sum_xor::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_xor(thd, this);
+ return new (thd->mem_root) Item_sum_xor(thd, this);
}
@@ -811,7 +810,7 @@ bool Item_sum_xor::add()
Item *Item_sum_and::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_and(thd, this);
+ return new (thd->mem_root) Item_sum_and(thd, this);
}
@@ -829,7 +828,7 @@ bool Item_sum_and::add()
void Item_sum_num::reset_field()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
char *res=result_field->ptr;
if (maybe_null)
@@ -883,7 +882,7 @@ void Item_sum_hybrid::reset_field()
}
else // REAL_RESULT
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
if (maybe_null)
{
@@ -902,7 +901,7 @@ void Item_sum_hybrid::reset_field()
void Item_sum_sum::reset_field()
{
- double nr=args[0]->val(); // Nulls also return 0
+ double nr= args[0]->val_real(); // Nulls also return 0
float8store(result_field->ptr,nr);
if (args[0]->null_value)
result_field->set_null();
@@ -930,7 +929,7 @@ void Item_sum_count::reset_field()
void Item_sum_avg::reset_field()
{
- double nr=args[0]->val();
+ double nr= args[0]->val_real();
char *res=result_field->ptr;
if (args[0]->null_value)
@@ -968,7 +967,7 @@ void Item_sum_sum::update_field()
char *res=result_field->ptr;
float8get(old_nr,res);
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
old_nr+=nr;
@@ -1005,7 +1004,7 @@ void Item_sum_avg::update_field()
float8get(old_nr,res);
field_count=sint8korr(res+sizeof(double));
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
old_nr+=nr;
@@ -1038,7 +1037,7 @@ Item_sum_hybrid::min_max_update_str_field()
result_field->val_str(&tmp_value);
if (result_field->is_null() ||
- (cmp_sign * sortcmp(res_str,&tmp_value,cmp_charset)) < 0)
+ (cmp_sign * sortcmp(res_str,&tmp_value,collation.collation)) < 0)
result_field->store(res_str->ptr(),res_str->length(),res_str->charset());
result_field->set_notnull();
}
@@ -1051,7 +1050,7 @@ Item_sum_hybrid::min_max_update_real_field()
double nr,old_nr;
old_nr=result_field->val_real();
- nr=args[0]->val();
+ nr= args[0]->val_real();
if (!args[0]->null_value)
{
if (result_field->is_null(0) ||
@@ -1103,7 +1102,7 @@ Item_avg_field::Item_avg_field(Item_sum_avg *item)
}
-double Item_avg_field::val()
+double Item_avg_field::val_real()
{
// fix_fields() never calls for this Item
double nr;
@@ -1124,7 +1123,7 @@ double Item_avg_field::val()
String *Item_avg_field::val_str(String *str)
{
// fix_fields() never calls for this Item
- double nr=Item_avg_field::val();
+ double nr= Item_avg_field::val_real();
if (null_value)
return 0;
str->set(nr,decimals, &my_charset_bin);
@@ -1136,10 +1135,10 @@ Item_std_field::Item_std_field(Item_sum_std *item)
{
}
-double Item_std_field::val()
+double Item_std_field::val_real()
{
// fix_fields() never calls for this Item
- double tmp= Item_variance_field::val();
+ double tmp= Item_variance_field::val_real();
return tmp <= 0.0 ? 0.0 : sqrt(tmp);
}
@@ -1152,7 +1151,7 @@ Item_variance_field::Item_variance_field(Item_sum_variance *item)
maybe_null=1;
}
-double Item_variance_field::val()
+double Item_variance_field::val_real()
{
// fix_fields() never calls for this Item
double sum,sum_sqr;
@@ -1175,7 +1174,7 @@ double Item_variance_field::val()
String *Item_variance_field::val_str(String *str)
{
// fix_fields() never calls for this Item
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0;
str->set(nr,decimals, &my_charset_bin);
@@ -1195,7 +1194,7 @@ int simple_str_key_cmp(void* arg, byte* key1, byte* key2)
uint len=item->key_length;
return cs->coll->strnncollsp(cs,
(const uchar*) key1, len,
- (const uchar*) key2, len);
+ (const uchar*) key2, len, 0);
}
/*
@@ -1345,10 +1344,9 @@ bool Item_sum_count_distinct::setup(THD *thd)
about other fields
*/
Field* field = table->field[0];
- switch(field->type())
- {
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
+ switch (field->type()) {
+ case MYSQL_TYPE_STRING:
+ case MYSQL_TYPE_VAR_STRING:
if (field->binary())
{
compare_key = (qsort_cmp2)simple_raw_key_cmp;
@@ -1449,7 +1447,7 @@ int Item_sum_count_distinct::tree_to_myisam()
Item *Item_sum_count_distinct::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_count_distinct(thd, this);
+ return new (thd->mem_root) Item_sum_count_distinct(thd, this);
}
@@ -1550,10 +1548,10 @@ bool Item_udf_sum::add()
Item *Item_sum_udf_float::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_udf_float(thd, this);
+ return new (thd->mem_root) Item_sum_udf_float(thd, this);
}
-double Item_sum_udf_float::val()
+double Item_sum_udf_float::val_real()
{
DBUG_ASSERT(fixed == 1);
DBUG_ENTER("Item_sum_udf_float::val");
@@ -1565,7 +1563,7 @@ double Item_sum_udf_float::val()
String *Item_sum_udf_float::val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
- double nr=val();
+ double nr= val_real();
if (null_value)
return 0; /* purecov: inspected */
str->set(nr,decimals, &my_charset_bin);
@@ -1575,7 +1573,7 @@ String *Item_sum_udf_float::val_str(String *str)
Item *Item_sum_udf_int::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_udf_int(thd, this);
+ return new (thd->mem_root) Item_sum_udf_int(thd, this);
}
@@ -1613,7 +1611,7 @@ void Item_sum_udf_str::fix_length_and_dec()
Item *Item_sum_udf_str::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_sum_udf_str(thd, this);
+ return new (thd->mem_root) Item_sum_udf_str(thd, this);
}
@@ -1927,7 +1925,7 @@ Item_func_group_concat::~Item_func_group_concat()
Item *Item_func_group_concat::copy_or_same(THD* thd)
{
- return new (&thd->mem_root) Item_func_group_concat(thd, this);
+ return new (thd->mem_root) Item_func_group_concat(thd, this);
}
@@ -2004,8 +2002,9 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
if (!thd->allow_sum_func)
{
- my_error(ER_INVALID_GROUP_FUNC_USE,MYF(0));
- return 1;
+ my_message(ER_INVALID_GROUP_FUNC_USE, ER(ER_INVALID_GROUP_FUNC_USE),
+ MYF(0));
+ return TRUE;
}
thd->allow_sum_func= 0;
@@ -2019,7 +2018,7 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
for (i=0 ; i < arg_count ; i++)
{
if (args[i]->fix_fields(thd, tables, args + i) || args[i]->check_cols(1))
- return 1;
+ return TRUE;
if (i < arg_count_field)
maybe_null|= args[i]->maybe_null;
}
@@ -2029,12 +2028,12 @@ Item_func_group_concat::fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
max_length= group_concat_max_len;
thd->allow_sum_func= 1;
if (!(tmp_table_param= new TMP_TABLE_PARAM))
- return 1;
+ return TRUE;
/* We'll convert all blobs to varchar fields in the temporary table */
tmp_table_param->convert_blob_length= group_concat_max_len;
tables_list= tables;
fixed= 1;
- return 0;
+ return FALSE;
}
diff --git a/sql/item_sum.h b/sql/item_sum.h
index cede5a1e02e..c1352f7ae7d 100644
--- a/sql/item_sum.h
+++ b/sql/item_sum.h
@@ -107,7 +107,10 @@ public:
Item_sum_num(THD *thd, Item_sum_num *item) :Item_sum(thd, item) {}
bool fix_fields(THD *, TABLE_LIST *, Item **);
longlong val_int()
- { DBUG_ASSERT(fixed == 1); return (longlong) val(); } /* Real as default */
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (longlong) val_real(); /* Real as default */
+ }
String *val_str(String*str);
void reset_field();
};
@@ -119,7 +122,7 @@ public:
Item_sum_int(Item *item_par) :Item_sum_num(item_par) {}
Item_sum_int(List<Item> &list) :Item_sum_num(list) {}
Item_sum_int(THD *thd, Item_sum_int *item) :Item_sum_num(thd, item) {}
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
void fix_length_and_dec()
@@ -139,7 +142,7 @@ class Item_sum_sum :public Item_sum_num
enum Sumfunctype sum_func () const {return SUM_FUNC;}
void clear();
bool add();
- double val();
+ double val_real();
void reset_field();
void update_field();
void no_rows_in_result() {}
@@ -169,7 +172,7 @@ public:
bool setup(THD *thd);
void clear();
bool add();
- double val();
+ double val_real();
inline void add(double val) { sum+= val; }
enum Sumfunctype sum_func () const { return SUM_DISTINCT_FUNC; }
@@ -302,8 +305,9 @@ public:
Field *field;
Item_avg_field(Item_sum_avg *item);
enum Type type() const { return FIELD_AVG_ITEM; }
- double val();
- longlong val_int() { /* can't be fix_fields()ed */ return (longlong) val(); }
+ double val_real();
+ longlong val_int()
+ { /* can't be fix_fields()ed */ return (longlong) val_real(); }
bool is_null() { (void) val_int(); return null_value; }
String *val_str(String*);
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
@@ -329,7 +333,7 @@ class Item_sum_avg :public Item_sum_num
enum Sumfunctype sum_func () const {return AVG_FUNC;}
void clear();
bool add();
- double val();
+ double val_real();
void reset_field();
void update_field();
Item *result_item(Field *field)
@@ -347,8 +351,9 @@ public:
Field *field;
Item_variance_field(Item_sum_variance *item);
enum Type type() const {return FIELD_VARIANCE_ITEM; }
- double val();
- longlong val_int() { /* can't be fix_fields()ed */ return (longlong) val(); }
+ double val_real();
+ longlong val_int()
+ { /* can't be fix_fields()ed */ return (longlong) val_real(); }
String *val_str(String*);
bool is_null() { (void) val_int(); return null_value; }
enum_field_types field_type() const { return MYSQL_TYPE_DOUBLE; }
@@ -386,7 +391,7 @@ class Item_sum_variance : public Item_sum_num
enum Sumfunctype sum_func () const { return VARIANCE_FUNC; }
void clear();
bool add();
- double val();
+ double val_real();
void reset_field();
void update_field();
Item *result_item(Field *field)
@@ -403,7 +408,7 @@ class Item_std_field :public Item_variance_field
public:
Item_std_field(Item_sum_std *item);
enum Type type() const { return FIELD_STD_ITEM; }
- double val();
+ double val_real();
};
/*
@@ -418,7 +423,7 @@ class Item_sum_std :public Item_sum_variance
:Item_sum_variance(thd, item)
{}
enum Sumfunctype sum_func () const { return STD_FUNC; }
- double val();
+ double val_real();
Item *result_item(Field *field)
{ return new Item_std_field(this); }
const char *func_name() const { return "std"; }
@@ -437,26 +442,25 @@ class Item_sum_hybrid :public Item_sum
enum_field_types hybrid_field_type;
int cmp_sign;
table_map used_table_cache;
- CHARSET_INFO *cmp_charset;
public:
Item_sum_hybrid(Item *item_par,int sign)
:Item_sum(item_par), sum(0.0), sum_int(0),
hybrid_type(INT_RESULT), hybrid_field_type(FIELD_TYPE_LONGLONG),
- cmp_sign(sign), used_table_cache(~(table_map) 0),
- cmp_charset(&my_charset_bin)
- {}
+ cmp_sign(sign), used_table_cache(~(table_map) 0)
+ { collation.set(&my_charset_bin); }
Item_sum_hybrid(THD *thd, Item_sum_hybrid *item):
Item_sum(thd, item), value(item->value),
sum(item->sum), sum_int(item->sum_int), hybrid_type(item->hybrid_type),
hybrid_field_type(item->hybrid_field_type),cmp_sign(item->cmp_sign),
- used_table_cache(item->used_table_cache), cmp_charset(item->cmp_charset) {}
+ used_table_cache(item->used_table_cache)
+ { collation.set(item->collation); }
bool fix_fields(THD *, TABLE_LIST *, Item **);
table_map used_tables() const { return used_table_cache; }
bool const_item() const { return !used_table_cache; }
void clear();
- double val();
+ double val_real();
longlong val_int();
void reset_field();
String *val_str(String *);
@@ -567,7 +571,7 @@ public:
:Item_sum( list ), udf(udf_arg)
{ quick_group=0;}
Item_udf_sum(THD *thd, Item_udf_sum *item)
- :Item_sum(thd, item), udf(item->udf) {}
+ :Item_sum(thd, item), udf(item->udf) { udf.not_original= TRUE; }
const char *func_name() const { return udf.name(); }
bool fix_fields(THD *thd, TABLE_LIST *tables, Item **ref)
{
@@ -594,8 +598,11 @@ class Item_sum_udf_float :public Item_udf_sum
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
:Item_udf_sum(thd, item) {}
longlong val_int()
- { DBUG_ASSERT(fixed == 1); return (longlong) Item_sum_udf_float::val(); }
- double val();
+ {
+ DBUG_ASSERT(fixed == 1);
+ return (longlong) Item_sum_udf_float::val_real();
+ }
+ double val_real();
String *val_str(String*str);
void fix_length_and_dec() { fix_num_length_and_dec(); }
Item *copy_or_same(THD* thd);
@@ -611,7 +618,7 @@ public:
Item_sum_udf_int(THD *thd, Item_sum_udf_int *item)
:Item_udf_sum(thd, item) {}
longlong val_int();
- double val()
+ double val_real()
{ DBUG_ASSERT(fixed == 1); return (double) Item_sum_udf_int::val_int(); }
String *val_str(String*str);
enum Item_result result_type () const { return INT_RESULT; }
@@ -629,7 +636,7 @@ public:
Item_sum_udf_str(THD *thd, Item_sum_udf_str *item)
:Item_udf_sum(thd, item) {}
String *val_str(String *);
- double val()
+ double val_real()
{
int err;
String *res; res=val_str(&str_value);
@@ -657,7 +664,7 @@ class Item_sum_udf_float :public Item_sum_num
Item_sum_udf_float(THD *thd, Item_sum_udf_float *item)
:Item_sum_num(thd, item) {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
- double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
void clear() {}
bool add() { return 0; }
void update_field() {}
@@ -673,7 +680,7 @@ public:
:Item_sum_num(thd, item) {}
enum Sumfunctype sum_func () const { return UDF_SUM_FUNC; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return 0; }
- double val() { DBUG_ASSERT(fixed == 1); return 0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0; }
void clear() {}
bool add() { return 0; }
void update_field() {}
@@ -689,7 +696,7 @@ public:
:Item_sum_num(thd, item) {}
String *val_str(String *)
{ DBUG_ASSERT(fixed == 1); null_value=1; return 0; }
- double val() { DBUG_ASSERT(fixed == 1); null_value=1; return 0.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; }
@@ -761,7 +768,7 @@ class Item_func_group_concat : public Item_sum
bool setup(THD *thd);
void make_unique();
virtual void update_field() {}
- double val()
+ double val_real()
{
String *res; res=val_str(&str_value);
return res ? my_atof(res->c_ptr()) : 0.0;
diff --git a/sql/item_timefunc.cc b/sql/item_timefunc.cc
index 3a25921d84b..215218a8277 100644
--- a/sql/item_timefunc.cc
+++ b/sql/item_timefunc.cc
@@ -161,23 +161,24 @@ static bool extract_date_time(DATE_TIME_FORMAT *format,
{
int weekday= 0, yearday= 0, daypart= 0;
int week_number= -1;
- CHARSET_INFO *cs= &my_charset_bin;
int error= 0;
+ int strict_week_number_year= -1;
+ int frac_part;
bool usa_time= 0;
bool sunday_first_n_first_week_non_iso;
bool strict_week_number;
- int strict_week_number_year= -1;
bool strict_week_number_year_type;
- int frac_part;
const char *val_begin= val;
const char *val_end= val + length;
const char *ptr= format->format.str;
const char *end= ptr + format->format.length;
+ CHARSET_INFO *cs= &my_charset_bin;
DBUG_ENTER("extract_date_time");
- LINT_INIT(sunday_first_n_first_week_non_iso);
LINT_INIT(strict_week_number);
- LINT_INIT(strict_week_number_year_type);
+ /* Remove valgrind varnings when using gcc 3.3 and -O1 */
+ PURIFY_OR_LINT_INIT(strict_week_number_year_type);
+ PURIFY_OR_LINT_INIT(sunday_first_n_first_week_non_iso);
if (!sub_pattern_end)
bzero((char*) l_time, sizeof(*l_time));
@@ -1606,50 +1607,46 @@ void Item_func_from_unixtime::fix_length_and_dec()
String *Item_func_from_unixtime::val_str(String *str)
{
TIME time_tmp;
- my_time_t tmp;
-
+
DBUG_ASSERT(fixed == 1);
- tmp= (time_t) args[0]->val_int();
- if ((null_value=args[0]->null_value))
- goto null_date;
-
- thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, tmp);
-
+
+ if (get_date(&time_tmp, 0))
+ return 0;
+
if (str->alloc(20*MY_CHARSET_BIN_MB_MAXLEN))
- goto null_date;
+ {
+ null_value= 1;
+ return 0;
+ }
+
make_datetime((DATE_TIME_FORMAT *) 0, &time_tmp, str);
return str;
-
-null_date:
- null_value=1;
- return 0;
}
longlong Item_func_from_unixtime::val_int()
{
TIME time_tmp;
- my_time_t tmp;
-
+
DBUG_ASSERT(fixed == 1);
- tmp= (time_t) (ulong) args[0]->val_int();
- if ((null_value=args[0]->null_value))
+ if (get_date(&time_tmp, 0))
return 0;
-
- current_thd->variables.time_zone->gmt_sec_to_TIME(&time_tmp, tmp);
-
+
return (longlong) TIME_to_ulonglong_datetime(&time_tmp);
}
bool Item_func_from_unixtime::get_date(TIME *ltime,
uint fuzzy_date __attribute__((unused)))
{
- my_time_t tmp=(my_time_t) args[0]->val_int();
- if ((null_value=args[0]->null_value))
+ longlong tmp= args[0]->val_int();
+
+ if ((null_value= (args[0]->null_value ||
+ tmp < TIMESTAMP_MIN_VALUE ||
+ tmp > TIMESTAMP_MAX_VALUE)))
return 1;
-
- current_thd->variables.time_zone->gmt_sec_to_TIME(ltime, tmp);
+
+ thd->variables.time_zone->gmt_sec_to_TIME(ltime, (my_time_t)tmp);
return 0;
}
@@ -1668,7 +1665,7 @@ Item_func_convert_tz::fix_fields(THD *thd_arg, TABLE_LIST *tables_arg, Item **re
{
String str;
if (Item_date_func::fix_fields(thd_arg, tables_arg, ref))
- return 1;
+ return TRUE;
tz_tables= thd_arg->lex->time_zone_tables_used;
@@ -1678,7 +1675,7 @@ Item_func_convert_tz::fix_fields(THD *thd_arg, TABLE_LIST *tables_arg, Item **re
if (args[2]->const_item())
to_tz= my_tz_find(args[2]->val_str(&str), tz_tables);
- return 0;
+ return FALSE;
}
@@ -2140,8 +2137,10 @@ String *Item_char_typecast::val_str(String *str)
else
{
// Convert character set if differ
+ uint dummy_errors;
if (!(res1= args[0]->val_str(&tmp_value)) ||
- str->copy(res1->ptr(), res1->length(),res1->charset(), cast_cs))
+ str->copy(res1->ptr(), res1->length(), res1->charset(),
+ cast_cs, &dummy_errors))
{
null_value= 1;
return 0;
diff --git a/sql/item_timefunc.h b/sql/item_timefunc.h
index 694f2dc583c..dccba7f52b1 100644
--- a/sql/item_timefunc.h
+++ b/sql/item_timefunc.h
@@ -88,7 +88,7 @@ class Item_func_month :public Item_func
public:
Item_func_month(Item *a) :Item_func(a) {}
longlong val_int();
- double val()
+ double val_real()
{ DBUG_ASSERT(fixed == 1); return (double) Item_func_month::val_int(); }
String *val_str(String *str)
{
@@ -250,7 +250,7 @@ public:
Item_func_weekday(Item *a,bool type_arg)
:Item_func(a), odbc_type(type_arg) {}
longlong val_int();
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
String *val_str(String *str)
{
DBUG_ASSERT(fixed == 1);
@@ -326,7 +326,7 @@ public:
enum_field_types field_type() const { return MYSQL_TYPE_DATE; }
String *val_str(String *str);
longlong val_int();
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
const char *func_name() const { return "date"; }
void fix_length_and_dec()
{
@@ -369,7 +369,7 @@ public:
Item_func_curtime(Item *a) :Item_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
enum_field_types field_type() const { return MYSQL_TYPE_TIME; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
String *val_str(String *str);
void fix_length_and_dec();
@@ -452,7 +452,7 @@ public:
Item_func_now() :Item_date_func() {}
Item_func_now(Item *a) :Item_date_func(a) {}
enum Item_result result_type () const { return STRING_RESULT; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) value; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) value; }
longlong val_int() { DBUG_ASSERT(fixed == 1); return value; }
int save_in_field(Field *to, bool no_conversions);
String *val_str(String *str);
@@ -512,7 +512,7 @@ class Item_func_from_unixtime :public Item_date_func
THD *thd;
public:
Item_func_from_unixtime(Item *a) :Item_date_func(a) {}
- double val()
+ double val_real()
{
DBUG_ASSERT(fixed == 1);
return (double) Item_func_from_unixtime::val_int();
@@ -552,7 +552,7 @@ class Item_func_convert_tz :public Item_date_func
Item_func_convert_tz(Item *a, Item *b, Item *c):
Item_date_func(a, b, c) {}
longlong val_int();
- double val() { return (double) val_int(); }
+ double val_real() { return (double) val_int(); }
String *val_str(String *str);
const char *func_name() const { return "convert_tz"; }
bool fix_fields(THD *, struct st_table_list *, Item **);
@@ -565,7 +565,7 @@ class Item_func_sec_to_time :public Item_str_func
{
public:
Item_func_sec_to_time(Item *item) :Item_str_func(item) {}
- double val()
+ double val_real()
{
DBUG_ASSERT(fixed == 1);
return (double) Item_func_sec_to_time::val_int();
@@ -615,7 +615,7 @@ public:
const char *func_name() const { return "date_add_interval"; }
void fix_length_and_dec();
enum_field_types field_type() const { return cached_field_type; }
- double val() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
+ double val_real() { DBUG_ASSERT(fixed == 1); return (double) val_int(); }
longlong val_int();
bool get_date(TIME *res, uint fuzzy_date);
void print(String *str);
diff --git a/sql/item_uniq.h b/sql/item_uniq.h
index 5582537bdbb..e74c09ca3c4 100644
--- a/sql/item_uniq.h
+++ b/sql/item_uniq.h
@@ -27,7 +27,7 @@ class Item_func_unique_users :public Item_real_func
public:
Item_func_unique_users(Item *name_arg,int start,int end,List<Item> &list)
:Item_real_func(list) {}
- double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
void fix_length_and_dec() { decimals=0; max_length=6; }
void print(String *str) { str->append("0.0", 3); }
};
@@ -40,7 +40,7 @@ public:
:Item_sum_num(item_arg) {}
Item_sum_unique_users(THD *thd, Item_sum_unique_users *item)
:Item_sum_num(thd, item) {}
- double val() { DBUG_ASSERT(fixed == 1); return 0.0; }
+ double val_real() { DBUG_ASSERT(fixed == 1); return 0.0; }
enum Sumfunctype sum_func () const {return UNIQUE_USERS_FUNC;}
void clear() {}
bool add() { return 0; }
@@ -50,7 +50,7 @@ public:
{
DBUG_ASSERT(fixed == 0);
fixed= 1;
- return 0;
+ return FALSE;
}
Item *copy_or_same(THD* thd)
{
diff --git a/sql/key.cc b/sql/key.cc
index 15d84b73beb..dfd924f1dc7 100644
--- a/sql/key.cc
+++ b/sql/key.cc
@@ -106,14 +106,21 @@ void key_copy(byte *to_key, byte *from_record, KEY *key_info, uint key_length)
{
char *pos;
ulong blob_length= ((Field_blob*) key_part->field)->get_length();
- key_length-= 2;
+ key_length-= HA_KEY_BLOB_LENGTH;
((Field_blob*) key_part->field)->get_ptr(&pos);
length=min(key_length, key_part->length);
set_if_smaller(blob_length, length);
int2store(to_key, (uint) blob_length);
- to_key+= 2; // Skip length info
+ to_key+= HA_KEY_BLOB_LENGTH; // Skip length info
memcpy(to_key, pos, blob_length);
}
+ else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
+ {
+ key_length-= HA_KEY_BLOB_LENGTH;
+ length= min(key_length, key_part->length);
+ key_part->field->get_key_image(to_key, length, Field::itRAW);
+ to_key+= HA_KEY_BLOB_LENGTH;
+ }
else
{
length= min(key_length, key_part->length);
@@ -166,12 +173,19 @@ void key_restore(byte *to_record, byte *from_key, KEY *key_info,
if (key_part->key_part_flag & HA_BLOB_PART)
{
uint blob_length= uint2korr(from_key);
- from_key+= 2;
- key_length-= 2;
+ from_key+= HA_KEY_BLOB_LENGTH;
+ key_length-= HA_KEY_BLOB_LENGTH;
((Field_blob*) key_part->field)->set_ptr((ulong) blob_length,
(char*) from_key);
length= key_part->length;
}
+ else if (key_part->key_part_flag & HA_VAR_LENGTH_PART)
+ {
+ key_length-= HA_KEY_BLOB_LENGTH;
+ length= min(key_length, key_part->length);
+ key_part->field->set_key_image(from_key, length);
+ from_key+= HA_KEY_BLOB_LENGTH;
+ }
else
{
length= min(key_length, key_part->length);
@@ -226,9 +240,9 @@ bool key_cmp_if_same(TABLE *table,const byte *key,uint idx,uint key_length)
}
key++;
}
- if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH))
+ if (key_part->key_part_flag & (HA_BLOB_PART | HA_VAR_LENGTH_PART))
{
- if (key_part->field->key_cmp(key, key_part->length+ HA_KEY_BLOB_LENGTH))
+ if (key_part->field->key_cmp(key, key_part->length))
return 1;
length=key_part->length+HA_KEY_BLOB_LENGTH;
}
@@ -248,7 +262,7 @@ bool key_cmp_if_same(TABLE *table,const byte *key,uint idx,uint key_length)
}
if (cs->coll->strnncollsp(cs,
(const uchar*) key, length,
- (const uchar*) pos, char_length))
+ (const uchar*) pos, char_length, 0))
return 1;
}
else if (memcmp(key,table->record[0]+key_part->offset,length))
diff --git a/sql/lex.h b/sql/lex.h
index 89daf46218c..cf0059a1397 100644
--- a/sql/lex.h
+++ b/sql/lex.h
@@ -48,7 +48,7 @@ SYM_GROUP sym_group_rtree= {"RTree keys", "HAVE_RTREE_KEYS"};
*/
static SYMBOL symbols[] = {
- { "&&", SYM(AND_SYM)},
+ { "&&", SYM(AND_AND_SYM)},
{ "<", SYM(LT)},
{ "<=", SYM(LE)},
{ "<>", SYM(NE)},
@@ -120,6 +120,7 @@ static SYMBOL symbols[] = {
{ "CONCURRENT", SYM(CONCURRENT)},
{ "CONDITION", SYM(CONDITION_SYM)},
{ "CONNECTION", SYM(CONNECTION_SYM)},
+ { "CONSISTENT", SYM(CONSISTENT_SYM)},
{ "CONSTRAINT", SYM(CONSTRAINT)},
{ "CONTAINS", SYM(CONTAINS_SYM)},
{ "CONTINUE", SYM(CONTINUE_SYM)},
@@ -333,7 +334,7 @@ static SYMBOL symbols[] = {
{ "NEXT", SYM(NEXT_SYM)},
{ "NO", SYM(NO_SYM)},
{ "NONE", SYM(NONE_SYM)},
- { "NOT", SYM(NOT)},
+ { "NOT", SYM(NOT_SYM)},
{ "NO_WRITE_TO_BINLOG", SYM(NO_WRITE_TO_BINLOG)},
{ "NULL", SYM(NULL_SYM)},
{ "NUMERIC", SYM(NUMERIC_SYM)},
@@ -421,6 +422,7 @@ static SYMBOL symbols[] = {
{ "SIGNED", SYM(SIGNED_SYM)},
{ "SIMPLE", SYM(SIMPLE_SYM)},
{ "SLAVE", SYM(SLAVE)},
+ { "SNAPSHOT", SYM(SNAPSHOT_SYM)},
{ "SMALLINT", SYM(SMALLINT)},
{ "SOME", SYM(ANY_SYM)},
{ "SONAME", SYM(UDF_SONAME_SYM)},
@@ -487,6 +489,7 @@ static SYMBOL symbols[] = {
{ "UNICODE", SYM(UNICODE_SYM)},
{ "UNION", SYM(UNION_SYM)},
{ "UNIQUE", SYM(UNIQUE_SYM)},
+ { "UNKNOWN", SYM(UNKNOWN_SYM)},
{ "UNLOCK", SYM(UNLOCK_SYM)},
{ "UNSIGNED", SYM(UNSIGNED)},
{ "UNTIL", SYM(UNTIL_SYM)},
@@ -521,7 +524,7 @@ static SYMBOL symbols[] = {
{ "YEAR", SYM(YEAR_SYM)},
{ "YEAR_MONTH", SYM(YEAR_MONTH_SYM)},
{ "ZEROFILL", SYM(ZEROFILL)},
- { "||", SYM(OR_OR_CONCAT)}
+ { "||", SYM(OR_OR_SYM)}
};
diff --git a/sql/lock.cc b/sql/lock.cc
index 6d5ca5bf6b4..8a3619b57dd 100644
--- a/sql/lock.cc
+++ b/sql/lock.cc
@@ -430,7 +430,7 @@ static MYSQL_LOCK *get_lock_data(THD *thd, TABLE **table_ptr, uint count,
*write_lock_used=table;
if (table->db_stat & HA_READ_ONLY)
{
- my_error(ER_OPEN_AS_READONLY,MYF(0),table->table_name);
+ my_error(ER_OPEN_AS_READONLY, MYF(0), table->table_name);
my_free((gptr) sql_lock,MYF(0));
return 0;
}
@@ -707,15 +707,70 @@ static void print_lock_error(int error)
/****************************************************************************
Handling of global read locks
+ Taking the global read lock is TWO steps (2nd step is optional; without
+ it, COMMIT of existing transactions will be allowed):
+ lock_global_read_lock() THEN make_global_read_lock_block_commit().
+
The global locks are handled through the global variables:
global_read_lock
+ count of threads which have the global read lock (i.e. have completed at
+ least the first step above)
global_read_lock_blocks_commit
- waiting_for_read_lock
+ count of threads which have the global read lock and block
+ commits (i.e. have completed the second step above)
+ waiting_for_read_lock
+ count of threads which want to take a global read lock but cannot
protect_against_global_read_lock
+ count of threads which have set protection against global read lock.
+
+ How blocking of threads by global read lock is achieved: that's
+ advisory. Any piece of code which should be blocked by global read lock must
+ be designed like this:
+ - call to wait_if_global_read_lock(). When this returns 0, no global read
+ lock is owned; if argument abort_on_refresh was 0, none can be obtained.
+ - job
+ - if abort_on_refresh was 0, call to start_waiting_global_read_lock() to
+ allow other threads to get the global read lock. I.e. removal of the
+ protection.
+ (Note: it's a bit like an implementation of rwlock).
+
+ [ I am sorry to mention some SQL syntaxes below I know I shouldn't but found
+ no better descriptive way ]
+
+ Why does FLUSH TABLES WITH READ LOCK need to block COMMIT: because it's used
+ to read a non-moving SHOW MASTER STATUS, and a COMMIT writes to the binary
+ log.
+
+ Why getting the global read lock is two steps and not one. Because FLUSH
+ TABLES WITH READ LOCK needs to insert one other step between the two:
+ flushing tables. So the order is
+ 1) lock_global_read_lock() (prevents any new table write locks, i.e. stalls
+ all new updates)
+ 2) close_cached_tables() (the FLUSH TABLES), which will wait for tables
+ currently opened and being updated to close (so it's possible that there is
+ a moment where all new updates of server are stalled *and* FLUSH TABLES WITH
+ READ LOCK is, too).
+ 3) make_global_read_lock_block_commit().
+ If we have merged 1) and 3) into 1), we would have had this deadlock:
+ imagine thread 1 and 2, in non-autocommit mode, thread 3, and an InnoDB
+ table t.
+ thd1: SELECT * FROM t FOR UPDATE;
+ thd2: UPDATE t SET a=1; # blocked by row-level locks of thd1
+ thd3: FLUSH TABLES WITH READ LOCK; # blocked in close_cached_tables() by the
+ table instance of thd2
+ thd1: COMMIT; # blocked by thd3.
+ thd1 blocks thd2 which blocks thd3 which blocks thd1: deadlock.
+
+ Note that we need to support that one thread does
+ FLUSH TABLES WITH READ LOCK; and then COMMIT;
+ (that's what innobackup does, for some good reason).
+ So in this exceptional case the COMMIT should not be blocked by the FLUSH
+ TABLES WITH READ LOCK.
+
+ TODO in MySQL 5.x: make_global_read_lock_block_commit() should be
+ killable. Normally CPU does not spend a long time in this function (COMMITs
+ are quite fast), but it would still be nice.
- Taking the global read lock is TWO steps (2nd step is optional; without
- it, COMMIT of existing transactions will be allowed):
- lock_global_read_lock() THEN make_global_read_lock_block_commit().
****************************************************************************/
volatile uint global_read_lock=0;
@@ -795,7 +850,8 @@ bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
if (thd->global_read_lock) // This thread had the read locks
{
if (is_not_commit)
- my_error(ER_CANT_UPDATE_WITH_READLOCK,MYF(0));
+ my_message(ER_CANT_UPDATE_WITH_READLOCK,
+ ER(ER_CANT_UPDATE_WITH_READLOCK), MYF(0));
(void) pthread_mutex_unlock(&LOCK_open);
/*
We allow FLUSHer to COMMIT; we assume FLUSHer knows what it does.
@@ -830,6 +886,8 @@ void start_waiting_global_read_lock(THD *thd)
{
bool tmp;
DBUG_ENTER("start_waiting_global_read_lock");
+ if (unlikely(thd->global_read_lock))
+ DBUG_VOID_RETURN;
(void) pthread_mutex_lock(&LOCK_open);
tmp= (!--protect_against_global_read_lock && waiting_for_read_lock);
(void) pthread_mutex_unlock(&LOCK_open);
@@ -839,19 +897,33 @@ void start_waiting_global_read_lock(THD *thd)
}
-void make_global_read_lock_block_commit(THD *thd)
+bool make_global_read_lock_block_commit(THD *thd)
{
+ bool error;
+ const char *old_message;
+ DBUG_ENTER("make_global_read_lock_block_commit");
/*
If we didn't succeed lock_global_read_lock(), or if we already suceeded
make_global_read_lock_block_commit(), do nothing.
*/
if (thd->global_read_lock != GOT_GLOBAL_READ_LOCK)
- return;
+ DBUG_RETURN(1);
pthread_mutex_lock(&LOCK_open);
/* increment this BEFORE waiting on cond (otherwise race cond) */
global_read_lock_blocks_commit++;
- while (protect_against_global_read_lock)
+ /* For testing we set up some blocking, to see if we can be killed */
+ DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
+ protect_against_global_read_lock++;);
+ old_message= thd->enter_cond(&COND_refresh, &LOCK_open,
+ "Waiting for all running commits to finish");
+ while (protect_against_global_read_lock && !thd->killed)
pthread_cond_wait(&COND_refresh, &LOCK_open);
- pthread_mutex_unlock(&LOCK_open);
- thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
+ DBUG_EXECUTE_IF("make_global_read_lock_block_commit_loop",
+ protect_against_global_read_lock--;);
+ if (error= thd->killed)
+ global_read_lock_blocks_commit--; // undo what we did
+ else
+ thd->global_read_lock= MADE_GLOBAL_READ_LOCK_BLOCK_COMMIT;
+ thd->exit_cond(old_message);
+ DBUG_RETURN(error);
}
diff --git a/sql/log.cc b/sql/log.cc
index ef538c3b03f..c659a3ede2e 100644
--- a/sql/log.cc
+++ b/sql/log.cc
@@ -383,8 +383,7 @@ bool MYSQL_LOG::open(const char *log_name, enum_log_type log_type_arg,
master (it has binlog version of the master, event types of the
master), so this is suitable to parse the next relay log's event. It
has been produced by
- Format_description_log_event::Format_description_log_event(char*
- buf,).
+ Format_description_log_event::Format_description_log_event(char* buf,).
Why don't we want to write the description_event_for_queue if this
event is for format<4 (3.23 or 4.x): this is because in that case, the
description_event_for_queue describes the data received from the
@@ -1326,7 +1325,7 @@ bool MYSQL_LOG::write(Log_event* event_info)
(local_db && !db_ok(local_db, binlog_do_db, binlog_ignore_db)))
{
VOID(pthread_mutex_unlock(&LOCK_log));
- DBUG_PRINT("error",("!db_ok"));
+ DBUG_PRINT("error",("!db_ok('%s')", local_db));
DBUG_RETURN(0);
}
#endif /* HAVE_REPLICATION */
@@ -1369,7 +1368,7 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
(uint) thd->variables.collation_connection->number,
(uint) thd->variables.collation_database->number,
(uint) thd->variables.collation_server->number);
- Query_log_event e(thd, buf, written, 0);
+ Query_log_event e(thd, buf, written, 0, FALSE);
if (e.write(file))
goto err;
}
@@ -1384,7 +1383,7 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
char *buf_end= strxmov(buf, "SET ONE_SHOT TIME_ZONE='",
thd->variables.time_zone->get_name()->ptr(),
"'", NullS);
- Query_log_event e(thd, buf, buf_end - buf, 0);
+ Query_log_event e(thd, buf, buf_end - buf, 0, FALSE);
if (e.write(file))
goto err;
}
@@ -1430,7 +1429,7 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
char buf[256], *p;
p= strmov(strmov(buf, "SET CHARACTER SET "),
thd->variables.convert_set->name);
- Query_log_event e(thd, buf, (ulong) (p - buf), 0);
+ Query_log_event e(thd, buf, (ulong) (p - buf), 0, FALSE);
if (e.write(file))
goto err;
}
@@ -1464,7 +1463,8 @@ COLLATION_CONNECTION=%u,COLLATION_DATABASE=%u,COLLATION_SERVER=%u",
if (flush_io_cache(file) || sync_binlog(file))
goto err;
- if (opt_using_transactions && !my_b_tell(&thd->transaction.trans_log))
+ if (opt_using_transactions &&
+ !(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))
{
/*
LOAD DATA INFILE in AUTOCOMMIT=1 mode writes to the binlog
@@ -1515,7 +1515,7 @@ err:
if (error)
{
if (my_errno == EFBIG)
- my_error(ER_TRANS_CACHE_FULL, MYF(0));
+ my_message(ER_TRANS_CACHE_FULL, ER(ER_TRANS_CACHE_FULL), MYF(0));
else
my_error(ER_ERROR_ON_WRITE, MYF(0), name, errno);
write_error=1;
@@ -1610,7 +1610,15 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
we will add the "COMMIT mark and write the buffer to the binlog.
*/
{
- Query_log_event qinfo(thd, "BEGIN", 5, TRUE);
+ Query_log_event qinfo(thd, "BEGIN", 5, TRUE, FALSE);
+ /*
+ Imagine this is rollback due to net timeout, after all statements of
+ the transaction succeeded. Then we want a zero-error code in BEGIN.
+ In other words, if there was a really serious error code it's already
+ in the statement's events.
+ This is safer than thd->clear_error() against kills at shutdown.
+ */
+ qinfo.error_code= 0;
/*
Now this Query_log_event has artificial log_pos 0. It must be adjusted
to reflect the real position in the log. Not doing it would confuse the
@@ -1642,7 +1650,8 @@ bool MYSQL_LOG::write(THD *thd, IO_CACHE *cache, bool commit_or_rollback)
Query_log_event qinfo(thd,
commit_or_rollback ? "COMMIT" : "ROLLBACK",
commit_or_rollback ? 6 : 8,
- TRUE);
+ TRUE, FALSE);
+ qinfo.error_code= 0;
if (qinfo.write(&log_file) || flush_io_cache(&log_file) ||
sync_binlog(&log_file))
goto err;
@@ -1714,12 +1723,19 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
time_t current_time;
if (!is_open())
return 0;
+ DBUG_ENTER("MYSQL_LOG::write");
+
VOID(pthread_mutex_lock(&LOCK_log));
if (is_open())
{ // Safety agains reopen
int tmp_errno=0;
char buff[80],*end;
end=buff;
+ if (!(thd->options & OPTION_UPDATE_LOG))
+ {
+ VOID(pthread_mutex_unlock(&LOCK_log));
+ DBUG_RETURN(0);
+ }
if (!(specialflag & SPECIAL_SHORT_LOG_FORMAT) || query_start_arg)
{
current_time=time(NULL);
@@ -1818,7 +1834,7 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
}
}
VOID(pthread_mutex_unlock(&LOCK_log));
- return error;
+ DBUG_RETURN(error);
}
@@ -1838,16 +1854,19 @@ bool MYSQL_LOG::write(THD *thd,const char *query, uint query_length,
THD::enter_cond() (see NOTES in sql_class.h).
*/
-void MYSQL_LOG:: wait_for_update(THD* thd, bool master_or_slave)
+void MYSQL_LOG::wait_for_update(THD* thd, bool master_or_slave)
{
- const char* old_msg = thd->enter_cond(&update_cond, &LOCK_log,
- master_or_slave ?
- "Has read all relay log; waiting for \
-the slave I/O thread to update it" :
- "Has sent all binlog to slave; \
-waiting for binlog to be updated");
+ const char *old_msg;
+ DBUG_ENTER("wait_for_update");
+ old_msg= thd->enter_cond(&update_cond, &LOCK_log,
+ master_or_slave ?
+ "Has read all relay log; waiting for the slave I/O "
+ "thread to update it" :
+ "Has sent all binlog to slave; waiting for binlog "
+ "to be updated");
pthread_cond_wait(&update_cond, &LOCK_log);
thd->exit_cond(old_msg);
+ DBUG_VOID_RETURN;
}
@@ -2204,6 +2223,15 @@ void MYSQL_LOG::report_pos_in_innodb()
DBUG_VOID_RETURN;
}
+
+void MYSQL_LOG::signal_update()
+{
+ DBUG_ENTER("MYSQL_LOG::signal_update");
+ pthread_cond_broadcast(&update_cond);
+ DBUG_VOID_RETURN;
+}
+
+
#ifdef __NT__
void print_buffer_to_nt_eventlog(enum loglevel level, char *buff,
uint length, int buffLen)
diff --git a/sql/log_event.cc b/sql/log_event.cc
index ee5af6ed1c0..760436592b9 100644
--- a/sql/log_event.cc
+++ b/sql/log_event.cc
@@ -921,7 +921,8 @@ void Query_log_event::pack_info(Protocol *protocol)
if (!(buf= my_malloc(9 + db_len + q_len, MYF(MY_WME))))
return;
pos= buf;
- if (db && db_len)
+ if (!(flags & LOG_EVENT_SUPPRESS_USE_F)
+ && db && db_len)
{
pos= strmov(buf, "use `");
memcpy(pos, db, db_len);
@@ -1077,9 +1078,12 @@ bool Query_log_event::write(IO_CACHE* file)
#ifndef MYSQL_CLIENT
Query_log_event::Query_log_event(THD* thd_arg, const char* query_arg,
- ulong query_length, bool using_trans)
- :Log_event(thd_arg, !thd_arg->tmp_table_used ?
- 0 : LOG_EVENT_THREAD_SPECIFIC_F, using_trans),
+ ulong query_length, bool using_trans,
+ bool suppress_use)
+ :Log_event(thd_arg,
+ ((thd_arg->tmp_table_used ? LOG_EVENT_THREAD_SPECIFIC_F : 0)
+ | (suppress_use ? LOG_EVENT_SUPPRESS_USE_F : 0)),
+ using_trans),
data_buf(0), query(query_arg), catalog(thd_arg->catalog),
db(thd_arg->db), q_len((uint32) query_length),
error_code((thd_arg->killed != THD::NOT_KILLED) ?
@@ -1259,14 +1263,14 @@ void Query_log_event::print(FILE* file, bool short_form,
(ulong) thread_id, (ulong) exec_time, error_code);
}
- if (db)
+ if (!(flags & LOG_EVENT_SUPPRESS_USE_F) && db)
{
- if ((different_db = memcmp(last_event_info->db, db, db_len + 1)))
+ if (different_db= memcmp(last_event_info->db, db, db_len + 1))
memcpy(last_event_info->db, db, db_len + 1);
+ if (db[0] && different_db)
+ fprintf(file, "use %s;\n", db);
}
-
- if (db && db[0] && different_db)
- fprintf(file, "use %s;\n", db);
+
end=int10_to_str((long) when, strmov(buff,"SET TIMESTAMP="),10);
*end++=';';
*end++='\n';
@@ -1362,7 +1366,8 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
Thank you.
*/
thd->catalog= (char*) catalog;
- thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed
+ thd->db_length= db_len;
+ thd->db= (char*) rewrite_db(db, &thd->db_length);
thd->variables.auto_increment_increment= auto_increment_increment;
thd->variables.auto_increment_offset= auto_increment_offset;
@@ -1384,11 +1389,6 @@ int Query_log_event::exec_event(struct st_relay_log_info* rli)
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
thd->set_time((time_t)when);
- /*
- We cannot use db_len from event to fill thd->db_length, because
- rewrite_db() may have changed db.
- */
- thd->db_length= thd->db ? strlen(thd->db) : 0;
thd->query_length= q_len;
thd->query = (char*)query;
VOID(pthread_mutex_lock(&LOCK_thread_count));
@@ -1466,10 +1466,10 @@ START SLAVE; . Query: '%s'", expected_error, thd->query);
Query caused different errors on master and slave. \
Error on master: '%s' (%d), Error on slave: '%s' (%d). \
Default database: '%s'. Query: '%s'",
- ER_SAFE(expected_error),
- expected_error,
- actual_error ? thd->net.last_error: "no error",
- actual_error,
+ ER_SAFE(expected_error),
+ expected_error,
+ actual_error ? thd->net.last_error: "no error",
+ actual_error,
print_slave_db_safe(db), query);
thd->query_error= 1;
}
@@ -1489,9 +1489,9 @@ Default database: '%s'. Query: '%s'",
{
slave_print_error(rli,actual_error,
"Error '%s' on query. Default database: '%s'. Query: '%s'",
- (actual_error ? thd->net.last_error :
- "unexpected success or fatal error"),
- print_slave_db_safe(db), query);
+ (actual_error ? thd->net.last_error :
+ "unexpected success or fatal error"),
+ print_slave_db_safe(thd->db), query);
thd->query_error= 1;
}
@@ -1535,7 +1535,7 @@ end:
thd->query_length= thd->db_length =0;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
close_thread_tables(thd);
- free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
/*
If there was an error we stop. Otherwise we increment positions. Note that
we will not increment group* positions if we are just after a SET
@@ -2388,16 +2388,22 @@ void Load_log_event::print(FILE* file, bool short_form, LAST_EVENT_INFO* last_ev
/*
Load_log_event::set_fields()
+
+ Note that this function can not use the member variable
+ for the database, since LOAD DATA INFILE on the slave
+ can be for a different database than the current one.
+ This is the reason for the affected_db argument to this method.
*/
#ifndef MYSQL_CLIENT
-void Load_log_event::set_fields(List<Item> &field_list)
+void Load_log_event::set_fields(const char* affected_db,
+ List<Item> &field_list)
{
uint i;
const char* field = fields;
for (i= 0; i < num_fields; i++)
{
- field_list.push_back(new Item_field(db, table_name, field));
+ field_list.push_back(new Item_field(affected_db, table_name, field));
field+= field_lens[i] + 1;
}
}
@@ -2435,7 +2441,8 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
bool use_rli_only_for_errors)
{
char *load_data_query= 0;
- thd->db= (char*) rewrite_db(db); // thd->db_length is set later if needed
+ thd->db_length= db_len;
+ thd->db= (char*) rewrite_db(db, &thd->db_length);
DBUG_ASSERT(thd->query == 0);
thd->query_length= 0; // Should not be needed
thd->query_error= 0;
@@ -2467,7 +2474,6 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
if (db_ok(thd->db, replicate_do_db, replicate_ignore_db))
{
thd->set_time((time_t)when);
- thd->db_length= thd->db ? strlen(thd->db) : 0;
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->query_id = query_id++;
VOID(pthread_mutex_unlock(&LOCK_thread_count));
@@ -2550,7 +2556,7 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
ex.skip_lines = skip_lines;
List<Item> field_list;
- set_fields(field_list);
+ set_fields(thd->db,field_list);
thd->variables.pseudo_thread_id= thread_id;
if (net)
{
@@ -2567,13 +2573,13 @@ int Load_log_event::exec_event(NET* net, struct st_relay_log_info* rli,
if (thd->cuted_fields)
{
/* log_pos is the position of the LOAD event in the master log */
- sql_print_error("\
-Slave: load data infile on table '%s' at log position %s in log \
-'%s' produced %ld warning(s). Default database: '%s'",
- (char*) table_name,
- llstr(log_pos,llbuff), RPL_LOG_NAME,
- (ulong) thd->cuted_fields,
- print_slave_db_safe(db));
+ sql_print_warning("Slave: load data infile on table '%s' at "
+ "log position %s in log '%s' produced %ld "
+ "warning(s). Default database: '%s'",
+ (char*) table_name,
+ llstr(log_pos,llbuff), RPL_LOG_NAME,
+ (ulong) thd->cuted_fields,
+ print_slave_db_safe(thd->db));
}
if (net)
net->pkt_nr= thd->net.pkt_nr;
@@ -2591,6 +2597,7 @@ Slave: load data infile on table '%s' at log position %s in log \
}
thd->net.vio = 0;
+ char *save_db= thd->db;
VOID(pthread_mutex_lock(&LOCK_thread_count));
thd->db= thd->catalog= 0;
thd->query= 0;
@@ -2601,7 +2608,7 @@ Slave: load data infile on table '%s' at log position %s in log \
my_afree(load_data_query);
if (thd->query_error)
{
- /* this err/sql_errno code is copy-paste from send_error() */
+ /* this err/sql_errno code is copy-paste from net_send_error() */
const char *err;
int sql_errno;
if ((err=thd->net.last_error)[0])
@@ -2613,17 +2620,17 @@ Slave: load data infile on table '%s' at log position %s in log \
}
slave_print_error(rli,sql_errno,"\
Error '%s' running LOAD DATA INFILE on table '%s'. Default database: '%s'",
- err, (char*)table_name, print_slave_db_safe(db));
- free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ err, (char*)table_name, print_slave_db_safe(save_db));
+ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
return 1;
}
- free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
if (thd->is_fatal_error)
{
slave_print_error(rli,ER_UNKNOWN_ERROR, "\
Fatal error running LOAD DATA INFILE on table '%s'. Default database: '%s'",
- (char*)table_name, print_slave_db_safe(db));
+ (char*)table_name, print_slave_db_safe(save_db));
return 1;
}
@@ -3250,7 +3257,7 @@ int User_var_log_event::exec_event(struct st_relay_log_info* rli)
*/
e.fix_fields(thd, 0, 0);
e.update_hash(val, val_len, type, charset, DERIVATION_NONE);
- free_root(&thd->mem_root,0);
+ free_root(thd->mem_root,0);
rli->inc_event_relay_log_pos();
return 0;
@@ -3608,7 +3615,7 @@ void Create_file_log_event::print(FILE* file, bool short_form,
if (enable_local)
{
- Load_log_event::print(file, 1, last_event_info, !check_fname_outside_temp_buf());
+ Load_log_event::print(file, short_form, last_event_info, !check_fname_outside_temp_buf());
/*
That one is for "file_id: etc" below: in mysqlbinlog we want the #, in
SHOW BINLOG EVENTS we don't.
diff --git a/sql/log_event.h b/sql/log_event.h
index a1c02b0e3c0..390a8c8070d 100644
--- a/sql/log_event.h
+++ b/sql/log_event.h
@@ -329,6 +329,19 @@ struct sql_ex_info
#define OPTIONS_WRITTEN_TO_BIN_LOG (OPTION_AUTO_IS_NULL | \
OPTION_NO_FOREIGN_KEY_CHECKS | OPTION_RELAXED_UNIQUE_CHECKS)
+/*
+ Suppress the generation of 'USE' statements before the actual
+ statement. This flag should be set for any events that does not need
+ the current database set to function correctly. Most notable cases
+ are 'CREATE DATABASE' and 'DROP DATABASE'.
+
+ This flags should only be used in exceptional circumstances, since
+ it introduce a significant change in behaviour regarding the
+ replication logic together with the flags --binlog-do-db and
+ --replicated-do-db.
+ */
+#define LOG_EVENT_SUPPRESS_USE_F 0x8
+
enum Log_event_type
{
/*
@@ -446,8 +459,9 @@ public:
/*
Some 16 flags. Only one is really used now; look above for
- LOG_EVENT_TIME_F, LOG_EVENT_FORCED_ROTATE_F, LOG_EVENT_THREAD_SPECIFIC_F
- for notes.
+ LOG_EVENT_TIME_F, LOG_EVENT_FORCED_ROTATE_F,
+ LOG_EVENT_THREAD_SPECIFIC_F, and LOG_EVENT_SUPPRESS_USE_F for
+ notes.
*/
uint16 flags;
@@ -650,7 +664,7 @@ public:
#ifndef MYSQL_CLIENT
Query_log_event(THD* thd_arg, const char* query_arg, ulong query_length,
- bool using_trans);
+ bool using_trans, bool suppress_use);
const char* get_db() { return db; }
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
@@ -771,7 +785,7 @@ public:
const char* table_name_arg,
List<Item>& fields_arg, enum enum_duplicates handle_dup,
bool using_trans);
- void set_fields(List<Item> &fields_arg);
+ void set_fields(const char* db, List<Item> &fields_arg);
const char* get_db() { return db; }
#ifdef HAVE_REPLICATION
void pack_info(Protocol* protocol);
diff --git a/sql/mysql_priv.h b/sql/mysql_priv.h
index 960f054b3ac..91d15dc1125 100644
--- a/sql/mysql_priv.h
+++ b/sql/mysql_priv.h
@@ -247,6 +247,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
key checks in some cases */
#define OPTION_RELAXED_UNIQUE_CHECKS (1L << 27)
#define SELECT_NO_UNLOCK (1L << 28)
+#define OPTION_SCHEMA_TABLE (1L << 29)
/* The rest of the file is included in the server only */
#ifndef MYSQL_CLIENT
@@ -281,6 +282,7 @@ extern CHARSET_INFO *national_charset_info, *table_alias_charset;
#define MODE_ERROR_FOR_DIVISION_BY_ZERO (MODE_INVALID_DATES*2)
#define MODE_TRADITIONAL (MODE_ERROR_FOR_DIVISION_BY_ZERO*2)
#define MODE_NO_AUTO_CREATE_USER (MODE_TRADITIONAL*2)
+#define MODE_HIGH_NOT_PRECEDENCE (MODE_NO_AUTO_CREATE_USER*2)
#define RAID_BLOCK_SIZE 1024
@@ -376,6 +378,15 @@ typedef struct st_sql_list {
first= save->first;
elements+= save->elements;
}
+ inline void push_back(struct st_sql_list *save)
+ {
+ if (save->first)
+ {
+ *next= save->first;
+ next= save->next;
+ elements+= save->elements;
+ }
+ }
} SQL_LIST;
@@ -405,23 +416,24 @@ typedef Comp_creator* (*chooser_compare_func_creator)(bool invert);
void free_items(Item *item);
void cleanup_items(Item *item);
class THD;
-void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0);
+void close_thread_tables(THD *thd, bool locked=0, bool skip_derived=0,
+ TABLE *stopper= 0);
bool check_one_table_access(THD *thd, ulong privilege,
TABLE_LIST *tables);
bool check_some_access(THD *thd, ulong want_access, TABLE_LIST *table);
bool check_merge_table_access(THD *thd, char *db,
TABLE_LIST *table_list);
-int multi_update_precheck(THD *thd, TABLE_LIST *tables);
-int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count);
-int mysql_multi_update_prepare(THD *thd);
-int mysql_multi_delete_prepare(THD *thd);
-int mysql_insert_select_prepare(THD *thd);
-int insert_select_precheck(THD *thd, TABLE_LIST *tables);
-int update_precheck(THD *thd, TABLE_LIST *tables);
-int delete_precheck(THD *thd, TABLE_LIST *tables);
-int insert_precheck(THD *thd, TABLE_LIST *tables);
-int create_table_precheck(THD *thd, TABLE_LIST *tables,
- TABLE_LIST *create_table);
+bool multi_update_precheck(THD *thd, TABLE_LIST *tables);
+bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count);
+bool mysql_multi_update_prepare(THD *thd);
+bool mysql_multi_delete_prepare(THD *thd);
+bool mysql_insert_select_prepare(THD *thd);
+bool insert_select_precheck(THD *thd, TABLE_LIST *tables);
+bool update_precheck(THD *thd, TABLE_LIST *tables);
+bool delete_precheck(THD *thd, TABLE_LIST *tables);
+bool insert_precheck(THD *thd, TABLE_LIST *tables);
+bool create_table_precheck(THD *thd, TABLE_LIST *tables,
+ TABLE_LIST *create_table);
Item *negate_expression(THD *thd, Item *expr);
#include "sql_class.h"
#include "opt_range.h"
@@ -471,12 +483,12 @@ struct Query_cache_query_flags
#define prepare_execute(A) ((A)->command == COM_EXECUTE)
-int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
-int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
-int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
+bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create, bool silent);
+bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create);
+bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent);
void mysql_binlog_send(THD* thd, char* log_ident, my_off_t pos, ushort flags);
-int 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, my_bool if_exists,
+ my_bool drop_temporary);
int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
bool drop_temporary, bool drop_view, bool log_query);
int mysql_rm_table_part2_with_lock(THD *thd, TABLE_LIST *tables,
@@ -504,7 +516,7 @@ extern "C" pthread_handler_decl(handle_one_connection,arg);
extern "C" pthread_handler_decl(handle_bootstrap,arg);
void end_thread(THD *thd,bool put_in_cache);
void flush_thread_cache();
-int mysql_execute_command(THD *thd);
+bool mysql_execute_command(THD *thd);
bool do_command(THD *thd);
bool dispatch_command(enum enum_server_command command, THD *thd,
char* packet, uint packet_length);
@@ -523,22 +535,22 @@ bool check_table_access(THD *thd, ulong want_access, TABLE_LIST *tables,
bool no_errors);
bool check_global_access(THD *thd, ulong want_access);
-int mysql_backup_table(THD* thd, TABLE_LIST* table_list);
-int mysql_restore_table(THD* thd, TABLE_LIST* table_list);
-
-int mysql_checksum_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_check_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_repair_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
- HA_CHECK_OPT* check_opt);
-int mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
- LEX_STRING *key_cache_name);
-int mysql_preload_keys(THD* thd, TABLE_LIST* table_list);
+bool mysql_backup_table(THD* thd, TABLE_LIST* table_list);
+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_check_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
+bool mysql_repair_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
+bool mysql_analyze_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
+bool mysql_optimize_table(THD* thd, TABLE_LIST* table_list,
+ HA_CHECK_OPT* check_opt);
+bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* table_list,
+ LEX_STRING *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);
@@ -551,21 +563,25 @@ int setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
List<Item> &fields, List<Item> &all_fields, ORDER *order,
bool *hidden_group_fields);
-int handle_select(THD *thd, LEX *lex, select_result *result);
-int mysql_select(THD *thd, Item ***rref_pointer_array,
- TABLE_LIST *tables, uint wild_num, List<Item> &list,
- COND *conds, uint og_num, ORDER *order, ORDER *group,
- Item *having, ORDER *proc_param, ulong select_type,
- select_result *result, SELECT_LEX_UNIT *unit,
- SELECT_LEX *select_lex);
+bool handle_select(THD *thd, LEX *lex, select_result *result);
+bool mysql_select(THD *thd, Item ***rref_pointer_array,
+ TABLE_LIST *tables, uint wild_num, List<Item> &list,
+ COND *conds, uint og_num, ORDER *order, ORDER *group,
+ Item *having, ORDER *proc_param, ulong select_type,
+ select_result *result, SELECT_LEX_UNIT *unit,
+ SELECT_LEX *select_lex);
void free_underlaid_joins(THD *thd, SELECT_LEX *select);
-int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
- select_result *result);
+bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit,
+ select_result *result);
int mysql_explain_select(THD *thd, SELECT_LEX *sl, char const *type,
select_result *result);
-int mysql_union(THD *thd, LEX *lex, select_result *result,
- SELECT_LEX_UNIT *unit);
-int mysql_handle_derived(LEX *lex);
+bool mysql_union(THD *thd, LEX *lex, select_result *result,
+ SELECT_LEX_UNIT *unit);
+int mysql_handle_derived(LEX *lex, int (*processor)(THD *thd,
+ LEX *lex,
+ TABLE_LIST *table));
+int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *t);
+int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *t);
Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
Item ***copy_func, Field **from_field,
bool group, bool modify_item, uint convert_blob_length);
@@ -574,61 +590,61 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
List<Key> &keys, uint &db_options,
handler *file, KEY *&key_info_buffer,
uint &key_count, int select_field_count);
-int mysql_create_table(THD *thd,const char *db, const char *table_name,
- HA_CREATE_INFO *create_info,
- List<create_field> &fields, List<Key> &keys,
- bool tmp_table, uint select_field_count);
+bool mysql_create_table(THD *thd,const char *db, const char *table_name,
+ HA_CREATE_INFO *create_info,
+ List<create_field> &fields, List<Key> &keys,
+ bool tmp_table, uint select_field_count);
TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
TABLE_LIST *create_table,
List<create_field> *extra_fields,
List<Key> *keys,
List<Item> *items,
- MYSQL_LOCK **lock);
-int mysql_alter_table(THD *thd, char *new_db, char *new_name,
- HA_CREATE_INFO *create_info,
- TABLE_LIST *table_list,
- List<create_field> &fields,
- List<Key> &keys,
- uint order_num, ORDER *order,
- enum enum_duplicates handle_duplicates,
- ALTER_INFO *alter_info, bool do_send_ok=1);
-int mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
-int mysql_create_like_table(THD *thd, TABLE_LIST *table,
- HA_CREATE_INFO *create_info,
- Table_ident *src_table);
+ MYSQL_LOCK **lock);
+bool mysql_alter_table(THD *thd, char *new_db, char *new_name,
+ HA_CREATE_INFO *create_info,
+ TABLE_LIST *table_list,
+ List<create_field> &fields,
+ List<Key> &keys,
+ uint order_num, ORDER *order,
+ enum enum_duplicates handle_duplicates,
+ ALTER_INFO *alter_info, bool do_send_ok=1);
+bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list, bool do_send_ok);
+bool mysql_create_like_table(THD *thd, TABLE_LIST *table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *src_table);
bool mysql_rename_table(enum db_type base,
const char *old_db,
const char * old_name,
const char *new_db,
const char * new_name);
-int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
-int mysql_drop_index(THD *thd, TABLE_LIST *table_list,
- ALTER_INFO *alter_info);
-int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
- Item **conds, uint order_num, ORDER *order);
+bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys);
+bool mysql_drop_index(THD *thd, TABLE_LIST *table_list,
+ ALTER_INFO *alter_info);
+bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
+ Item **conds, uint order_num, ORDER *order);
int mysql_update(THD *thd,TABLE_LIST *tables,List<Item> &fields,
List<Item> &values,COND *conds,
- uint order_num, ORDER *order, ha_rows limit,
+ uint order_num, ORDER *order, ha_rows limit,
enum enum_duplicates handle_duplicates);
-int mysql_multi_update(THD *thd, TABLE_LIST *table_list,
- List<Item> *fields, List<Item> *values,
- COND *conds, ulong options,
- enum enum_duplicates handle_duplicates,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
-int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
- List<Item> &fields, List_item *values,
- List<Item> &update_fields,
- List<Item> &update_values, enum_duplicates duplic);
-int mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
- List<List_item> &values, List<Item> &update_fields,
- List<Item> &update_values, enum_duplicates flag);
+bool mysql_multi_update(THD *thd, TABLE_LIST *table_list,
+ List<Item> *fields, List<Item> *values,
+ COND *conds, ulong options,
+ enum enum_duplicates handle_duplicates,
+ SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex);
+bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
+ List<Item> &fields, List_item *values,
+ List<Item> &update_fields,
+ List<Item> &update_values, enum_duplicates duplic);
+bool mysql_insert(THD *thd,TABLE_LIST *table,List<Item> &fields,
+ List<List_item> &values, List<Item> &update_fields,
+ List<Item> &update_values, enum_duplicates flag);
int check_that_all_fields_are_given_values(THD *thd, TABLE *entry);
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
-int mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order,
- ha_rows rows, ulong options);
-int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok);
-int mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create);
+bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds);
+bool mysql_delete(THD *thd, TABLE_LIST *table, COND *conds, SQL_LIST *order,
+ ha_rows rows, ulong options);
+bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok);
+bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create);
TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type update);
TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT* mem,
bool *refresh);
@@ -645,10 +661,15 @@ bool drop_locked_tables(THD *thd,const char *db, const char *table_name);
void abort_locked_tables(THD *thd,const char *db, const char *table_name);
void execute_init_command(THD *thd, sys_var_str *init_command_var,
rw_lock_t *var_mutex);
-extern const Field *not_found_field;
-extern const Field *view_ref_found;
+extern Field *not_found_field;
+extern Field *view_ref_found;
+
+enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
+ IGNORE_ERRORS, REPORT_EXCEPT_NON_UNIQUE,
+ IGNORE_EXCEPT_NON_UNIQUE};
Field *find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
- Item **ref, bool report_error,
+ Item **ref,
+ find_item_error_report_type report_error,
bool check_privileges);
Field *
find_field_in_table(THD *thd, TABLE_LIST *table_list,
@@ -656,7 +677,8 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
uint length, Item **ref,
bool check_grants_table, bool check_grants_view,
bool allow_rowid,
- uint *cached_field_index_ptr);
+ uint *cached_field_index_ptr,
+ bool register_tree_change);
Field *
find_field_in_real_table(THD *thd, TABLE *table, const char *name,
uint length, bool check_grants, bool allow_rowid,
@@ -680,46 +702,57 @@ void free_des_key_file();
#endif /* HAVE_OPENSSL */
/* sql_do.cc */
-int mysql_do(THD *thd, List<Item> &values);
+bool mysql_do(THD *thd, List<Item> &values);
/* sql_show.cc */
-int mysqld_show_dbs(THD *thd,const char *wild);
-int mysqld_show_open_tables(THD *thd,const char *wild);
-int mysqld_show_tables(THD *thd, const char *db, const char *wild,
- bool verbose);
-int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild);
-int mysqld_show_fields(THD *thd,TABLE_LIST *table, const char *wild,
- bool verbose);
-int mysqld_show_keys(THD *thd, TABLE_LIST *table);
-int mysqld_show_logs(THD *thd);
+bool mysqld_show_open_tables(THD *thd,const char *wild);
+bool mysqld_show_logs(THD *thd);
void append_identifier(THD *thd, String *packet, const char *name,
uint length);
int get_quote_char_for_identifier(THD *thd, const char *name, uint length);
void mysqld_list_fields(THD *thd,TABLE_LIST *table, const char *wild);
-int mysqld_dump_create_info(THD *thd, TABLE *table, int fd = -1);
-int mysqld_show_create(THD *thd, TABLE_LIST *table_list);
-int mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
+int mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd = -1);
+bool mysqld_show_create(THD *thd, TABLE_LIST *table_list);
+bool mysqld_show_create_db(THD *thd, char *dbname, HA_CREATE_INFO *create);
void mysqld_list_processes(THD *thd,const char *user,bool verbose);
int mysqld_show_status(THD *thd);
int mysqld_show_variables(THD *thd,const char *wild);
-int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
+bool mysqld_show(THD *thd, const char *wild, show_var_st *variables,
enum enum_var_type value_type,
pthread_mutex_t *mutex,
struct system_status_var *status_var);
int mysql_find_files(THD *thd,List<char> *files, const char *db,
const char *path, const char *wild, bool dir);
-int mysqld_show_charsets(THD *thd,const char *wild);
-int mysqld_show_collations(THD *thd,const char *wild);
-int mysqld_show_storage_engines(THD *thd);
-int mysqld_show_privileges(THD *thd);
-int mysqld_show_column_types(THD *thd);
-int mysqld_help (THD *thd, const char *text);
+bool mysqld_show_storage_engines(THD *thd);
+bool mysqld_show_privileges(THD *thd);
+bool mysqld_show_column_types(THD *thd);
+bool mysqld_help (THD *thd, const char *text);
void calc_sum_of_all_status(STATUS_VAR *to);
+
+
+/* information schema */
+extern LEX_STRING information_schema_name;
+LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str,
+ const char* str, uint length,
+ bool allocate_lex_string= 0);
+ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name);
+ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx);
+int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
+ enum enum_schema_tables schema_table_idx);
+int make_schema_select(THD *thd, SELECT_LEX *sel,
+ enum enum_schema_tables schema_table_idx);
+int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list);
+int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
+int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
+int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
+int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond);
+bool get_schema_tables_result(JOIN *join);
+
/* sql_prepare.cc */
-int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
- LEX_STRING *name=NULL);
+bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
+ LEX_STRING *name=NULL);
void mysql_stmt_execute(THD *thd, char *packet, uint packet_length);
void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name);
void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length);
@@ -734,13 +767,13 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level, uint
void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
uint code, const char *format, ...);
void mysql_reset_errors(THD *thd);
-my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
+bool mysqld_show_warnings(THD *thd, ulong levels_to_show);
/* sql_handler.cc */
-int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0);
-int mysql_ha_close(THD *thd, TABLE_LIST *tables);
-int mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
- List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
+bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen= 0);
+bool mysql_ha_close(THD *thd, TABLE_LIST *tables);
+bool mysql_ha_read(THD *, TABLE_LIST *,enum enum_ha_read_modes,char *,
+ List<Item> *,enum ha_rkey_function,Item *,ha_rows,ha_rows);
int mysql_ha_flush(THD *thd, TABLE_LIST *tables, uint mode_flags);
/* mysql_ha_flush mode_flags bits */
#define MYSQL_HA_CLOSE_FINAL 0x00
@@ -755,7 +788,8 @@ bool add_field_to_list(THD *thd, char *field_name, enum enum_field_types type,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment,
- char *change, TYPELIB *interval,CHARSET_INFO *cs,
+ char *change, List<String> *interval_list,
+ CHARSET_INFO *cs,
uint uint_geom_type);
void store_position_for_column(const char *name);
bool add_to_list(THD *thd, SQL_LIST &list,Item *group,bool asc=0);
@@ -767,9 +801,7 @@ TABLE *unlink_open_table(THD *thd,TABLE *list,TABLE *find);
SQL_SELECT *make_select(TABLE *head, table_map const_tables,
table_map read_tables, COND *conds, int *error,
bool allow_null_cond= false);
-enum find_item_error_report_type {REPORT_ALL_ERRORS, REPORT_EXCEPT_NOT_FOUND,
- IGNORE_ERRORS};
-extern const Item **not_found_item;
+extern Item **not_found_item;
Item ** find_item_in_list(Item *item, List<Item> &items, uint *counter,
find_item_error_report_type report_error,
bool *unaliased);
@@ -779,20 +811,22 @@ bool insert_fields(THD *thd,TABLE_LIST *tables,
const char *db_name, const char *table_name,
List_iterator<Item> *it, bool any_privileges,
bool allocate_view_names);
-bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds);
+bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
+ TABLE_LIST **leaves, bool refresh_only,
+ bool select_insert);
int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list, uint wild_num);
-int setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
- List<Item> &item, bool set_query_id,
- List<Item> *sum_func_list, bool allow_sum_func);
-int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds);
+bool setup_fields(THD *thd, Item** ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &item, bool set_query_id,
+ List<Item> *sum_func_list, bool allow_sum_func);
+int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves,
+ COND **conds);
int setup_ftfuncs(SELECT_LEX* select);
int init_ftfuncs(THD *thd, SELECT_LEX* select, bool no_order);
void wait_for_refresh(THD *thd);
int open_tables(THD *thd, TABLE_LIST *tables, uint *counter);
int simple_open_n_lock_tables(THD *thd,TABLE_LIST *tables);
-int open_and_lock_tables(THD *thd,TABLE_LIST *tables);
-void relink_tables_for_derived(THD *thd);
+bool open_and_lock_tables(THD *thd,TABLE_LIST *tables);
int lock_tables(THD *thd, TABLE_LIST *tables, uint counter);
TABLE *open_temporary_table(THD *thd, const char *path, const char *db,
const char *table_name, bool link_in_list);
@@ -817,8 +851,10 @@ bool remove_table_from_cache(THD *thd, const char *db, const char *table,
bool return_if_owned_by_thd=0);
bool close_cached_tables(THD *thd, bool wait_for_refresh, TABLE_LIST *tables);
void copy_field_from_tmp_record(Field *field,int offset);
-int fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors);
-int fill_record(Field **field,List<Item> &values, bool ignore_errors);
+bool fill_record(THD *thd, List<Item> &fields, List<Item> &values,
+ bool ignore_errors);
+bool fill_record(THD *thd, Field **field, List<Item> &values,
+ bool ignore_errors);
OPEN_TABLE_LIST *list_open_tables(THD *thd, const char *wild);
inline TABLE_LIST *find_table_in_global_list(TABLE_LIST *table,
@@ -842,10 +878,10 @@ inline TABLE_LIST *find_table_in_local_list(TABLE_LIST *table,
bool eval_const_cond(COND *cond);
/* sql_load.cc */
-int mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list,
- List<Item> &fields, enum enum_duplicates handle_duplicates,
- bool local_file, thr_lock_type lock_type,
- bool ignore_check_option_errors);
+bool mysql_load(THD *thd, sql_exchange *ex, TABLE_LIST *table_list,
+ List<Item> &fields, enum enum_duplicates handle_duplicates,
+ bool local_file, thr_lock_type lock_type,
+ bool ignore_check_option_errors);
int write_record(THD *thd, TABLE *table, COPY_INFO *info);
/* sql_manager.cc */
@@ -969,7 +1005,7 @@ extern ulong rpl_recovery_rank, thread_cache_size;
extern ulong back_log;
extern ulong specialflag, current_pid;
extern ulong expire_logs_days, sync_binlog_period, sync_binlog_counter;
-extern my_bool relay_log_purge, opt_innodb_safe_binlog;
+extern my_bool relay_log_purge, opt_innodb_safe_binlog, opt_innodb;
extern uint test_flags,select_errors,ha_open_options;
extern uint protocol_version, mysqld_port, dropping_tables;
extern uint delay_key_write_options, lower_case_table_names;
@@ -994,7 +1030,7 @@ extern char *default_tz_name;
extern MYSQL_LOG mysql_log,mysql_slow_log,mysql_bin_log;
extern FILE *bootstrap_file;
-extern pthread_key(MEM_ROOT*,THR_MALLOC);
+extern pthread_key(MEM_ROOT**,THR_MALLOC);
extern pthread_mutex_t LOCK_mysql_create_db,LOCK_Acl,LOCK_open,
LOCK_thread_count,LOCK_mapped_file,LOCK_user_locks, LOCK_status,
LOCK_error_log, LOCK_delayed_insert, LOCK_uuid_generator,
@@ -1061,7 +1097,7 @@ void unlock_global_read_lock(THD *thd);
bool wait_if_global_read_lock(THD *thd, bool abort_on_refresh,
bool is_not_commit);
void start_waiting_global_read_lock(THD *thd);
-void make_global_read_lock_block_commit(THD *thd);
+bool make_global_read_lock_block_commit(THD *thd);
/* Lock based on name */
int lock_and_wait_for_table_name(THD *thd, TABLE_LIST *table_list);
diff --git a/sql/mysqld.cc b/sql/mysqld.cc
index 3d7ab14f13d..42ae6982eb0 100644
--- a/sql/mysqld.cc
+++ b/sql/mysqld.cc
@@ -37,6 +37,28 @@
#ifdef HAVE_NDBCLUSTER_DB
#include "ha_ndbcluster.h"
#endif
+
+#ifdef HAVE_INNOBASE_DB
+#define OPT_INNODB_DEFAULT 1
+#else
+#define OPT_INNODB_DEFAULT 0
+#endif
+#ifdef HAVE_BERKLEY_DB
+#define OPT_BDB_DEFAULT 1
+#else
+#define OPT_BDB_DEFAULT 0
+#endif
+#ifdef HAVE_ISAM_DB
+#define OPT_ISAM_DEFAULT 1
+#else
+#define OPT_ISAM_DEFAULT 0
+#endif
+#ifdef HAVE_NDBCLUSTER_DB
+#define OPT_NDBCLUSTER_DEFAULT 0
+#else
+#define OPT_NDBCLUSTER_DEFAULT 0
+#endif
+
#include <nisam.h>
#include <thr_alarm.h>
#include <ft_global.h>
@@ -149,6 +171,7 @@ static VolumeID_t datavolid;
static event_handle_t eh;
static Report_t ref;
static void *refneb= NULL;
+my_bool event_flag= FALSE;
static int volumeid= -1;
/* NEB event callback */
@@ -221,7 +244,7 @@ const char *sql_mode_names[] =
"NO_TABLE_OPTIONS", "NO_FIELD_OPTIONS", "MYSQL323", "MYSQL40", "ANSI",
"NO_AUTO_VALUE_ON_ZERO", "NO_BACKSLASH_ESCAPES", "STRICT_TRANS_TABLES", "STRICT_ALL_TABLES",
"NO_ZERO_IN_DATE", "NO_ZERO_DATE", "ALLOW_INVALID_DATES", "ERROR_FOR_DIVISION_BY_ZERO",
- "TRADITIONAL", "NO_AUTO_CREATE_USER",
+ "TRADITIONAL", "NO_AUTO_CREATE_USER", "HIGH_NOT_PRECEDENCE",
NullS
};
TYPELIB sql_mode_typelib= { array_elements(sql_mode_names)-1,"",
@@ -375,7 +398,7 @@ SHOW_COMP_OPTION have_crypt, have_compress;
/* Thread specific variables */
-pthread_key(MEM_ROOT*,THR_MALLOC);
+pthread_key(MEM_ROOT**,THR_MALLOC);
pthread_key(THD*, THR_THD);
pthread_mutex_t LOCK_mysql_create_db, LOCK_Acl, LOCK_open, LOCK_thread_count,
LOCK_mapped_file, LOCK_status,
@@ -469,6 +492,7 @@ Query_cache query_cache;
#ifdef HAVE_SMEM
char *shared_memory_base_name= default_shared_memory_base_name;
bool opt_enable_shared_memory;
+HANDLE smem_event_connect_request= 0;
#endif
#include "sslopt-vars.h"
@@ -543,7 +567,7 @@ static void close_connections(void)
struct timespec abstime;
int error;
LINT_INIT(error);
- DBUG_PRINT("info",("Waiting for select_thread"));
+ DBUG_PRINT("info",("Waiting for select thread"));
#ifndef DONT_USE_THR_ALARM
if (pthread_kill(select_thread,THR_CLIENT_ALARM))
@@ -746,6 +770,15 @@ void kill_mysql(void)
CloseHandle(hEvent);
*/
}
+#ifdef HAVE_SMEM
+ /*
+ Send event to smem_event_connect_request for aborting
+ */
+ if (!SetEvent(smem_event_connect_request))
+ {
+ DBUG_PRINT("error",("Got error: %ld from SetEvent of smem_event_connect_request",GetLastError()));
+ }
+#endif
#endif
#elif defined(OS2)
pthread_cond_signal(&eventShutdown); // post semaphore
@@ -809,7 +842,8 @@ static void __cdecl kill_server(int sig_ptr)
unireg_end();
#ifdef __NETWARE__
- pthread_join(select_thread, NULL); // wait for main thread
+ if(!event_flag)
+ pthread_join(select_thread, NULL); // wait for main thread
#endif /* __NETWARE__ */
pthread_exit(0); /* purecov: deadcode */
@@ -1172,7 +1206,8 @@ static void server_init(void)
WSADATA WsaData;
if (SOCKET_ERROR == WSAStartup (0x0101, &WsaData))
{
- my_message(0,"WSAStartup Failed\n",MYF(0));
+ /* errors are not read yet, so we use test here */
+ my_message(ER_WSAS_FAILED, "WSAStartup Failed", MYF(0));
unireg_abort(1);
}
}
@@ -1334,8 +1369,9 @@ void yyerror(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(ER_SYNTAX_ERROR);
- net_printf(thd,ER_PARSE_ERROR, s, yytext ? (char*) yytext : "",
- thd->lex->yylineno);
+ my_printf_error(ER_PARSE_ERROR, ER(ER_PARSE_ERROR), MYF(0), s,
+ (yytext ? (char*) yytext : ""),
+ thd->lex->yylineno);
}
@@ -1366,7 +1402,7 @@ void close_connection(THD *thd, uint errcode, bool lock)
if ((vio=thd->net.vio) != 0)
{
if (errcode)
- send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
+ net_send_error(thd, errcode, ER(errcode)); /* purecov: inspected */
vio_close(vio); /* vio is freed in delete thd */
}
if (lock)
@@ -1518,20 +1554,20 @@ static void check_data_home(const char *path)
// down server event callback
void mysql_down_server_cb(void *, void *)
{
+ event_flag= TRUE;
kill_server(0);
}
// destroy callback resources
void mysql_cb_destroy(void *)
-{
- UnRegisterEventNotification(eh); // cleanup down event notification
+{
+ UnRegisterEventNotification(eh); // cleanup down event notification
NX_UNWRAP_INTERFACE(ref);
-
- /* Deregister NSS volume deactivation event */
- NX_UNWRAP_INTERFACE(refneb);
+ /* Deregister NSS volume deactivation event */
+ NX_UNWRAP_INTERFACE(refneb);
if (neb_consumer_id)
- UnRegisterConsumer(neb_consumer_id, NULL);
+ UnRegisterConsumer(neb_consumer_id, NULL);
}
@@ -1551,7 +1587,7 @@ void mysql_cb_init()
Register for volume deactivation event
Wrap the callback function, as it is called by non-LibC thread
*/
- (void)NX_WRAP_INTERFACE(neb_event_callback, 1, &refneb);
+ (void *) NX_WRAP_INTERFACE(neb_event_callback, 1, &refneb);
registerwithneb();
NXVmRegisterExitHandler(mysql_cb_destroy, NULL); // clean-up
@@ -1648,7 +1684,9 @@ ulong neb_event_callback(struct EventBlock *eblock)
{
consoleprintf("MySQL data volume is deactivated, shutting down MySQL Server \n");
nw_panic = TRUE;
+ event_flag= TRUE;
kill_server(0);
+
}
}
return 0;
@@ -1722,8 +1760,8 @@ static void init_signals(void)
for (uint i=0 ; i < sizeof(signals)/sizeof(int) ; i++)
signal(signals[i], kill_server);
mysql_cb_init(); // initialize callbacks
-}
+}
static void start_signal_handler(void)
{
@@ -2090,7 +2128,7 @@ extern "C" void *signal_hand(void *arg __attribute__((unused)))
{
reload_acl_and_cache((THD*) 0,
(REFRESH_LOG | REFRESH_TABLES | REFRESH_FAST |
- REFRESH_STATUS | REFRESH_GRANT |
+ REFRESH_GRANT |
REFRESH_THREADS | REFRESH_HOSTS),
(TABLE_LIST*) 0, NULL); // Flush logs
mysql_print_status((THD*) 0); // Send debug some info
@@ -2130,6 +2168,11 @@ extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
THD *thd;
DBUG_ENTER("my_message_sql");
DBUG_PRINT("error", ("error: %u message: '%s'", error, str));
+ /*
+ Put here following assertion when situation with EE_* error codes
+ will be fixed
+ DBUG_ASSERT(error != 0);
+ */
if ((thd= current_thd))
{
if (thd->spcont &&
@@ -2137,6 +2180,9 @@ extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
{
DBUG_RETURN(0);
}
+
+ thd->query_error= 1; // needed to catch query errors during replication
+
/*
thd->lex->current_select == 0 if lex structure is not inited
(not query command (COM_QUERY))
@@ -2155,6 +2201,9 @@ extern "C" int my_message_sql(uint error, const char *str, myf MyFlags)
{
NET *net= &thd->net;
net->report_error= 1;
+#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
+ query_cache_abort(net);
+#endif
if (!net->last_error[0]) // Return only first message
{
strmake(net->last_error, str, sizeof(net->last_error)-1);
@@ -2235,7 +2284,13 @@ extern "C" pthread_handler_decl(handle_shutdown,arg)
#endif
-const char *load_default_groups[]= { "mysqld","server",MYSQL_BASE_VERSION,0,0};
+const char *load_default_groups[]= {
+#ifdef HAVE_NDBCLUSTER_DB
+"mysql_cluster",
+#endif
+"mysqld","server",MYSQL_BASE_VERSION,0,0};
+static const int load_default_groups_sz=
+sizeof(load_default_groups)/sizeof(load_default_groups[0]);
bool open_log(MYSQL_LOG *log, const char *hostname,
const char *opt_name, const char *extension,
@@ -2313,8 +2368,6 @@ bool init_global_datetime_format(timestamp_type format_type,
static int init_common_variables(const char *conf_file_name, int argc,
char **argv, const char **groups)
{
- my_umask=0660; // Default umask for new files
- my_umask_dir=0700; // Default umask for new directories
umask(((~my_umask) & 0666));
tzset(); // Set tzname
@@ -2859,6 +2912,7 @@ int win_main(int argc, char **argv)
int main(int argc, char **argv)
#endif
{
+
DEBUGGER_OFF;
MY_INIT(argv[0]); // init my_sys library & pthreads
@@ -2972,11 +3026,10 @@ we force server id to 2, but this MySQL server will not act as a slave.");
exit(1);
#ifdef __WIN__
-#define MYSQL_ERR_FILE "mysql.err"
if (!opt_console)
{
- freopen(MYSQL_ERR_FILE,"a+",stdout);
- freopen(MYSQL_ERR_FILE,"a+",stderr);
+ freopen(log_error_file,"a+",stdout);
+ freopen(log_error_file,"a+",stderr);
FreeConsole(); // Remove window
}
#endif
@@ -3055,7 +3108,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
#endif /* __NT__ */
/* (void) pthread_attr_destroy(&connection_attrib); */
-
+
DBUG_PRINT("quit",("Exiting main thread"));
#ifndef __WIN__
@@ -3105,6 +3158,7 @@ we force server id to 2, but this MySQL server will not act as a slave.");
#endif
clean_up_mutexes();
my_end(opt_endinfo ? MY_CHECK_ERROR | MY_GIVE_INFO : 0);
+
exit(0);
return(0); /* purecov: deadcode */
}
@@ -3232,7 +3286,7 @@ int main(int argc, char **argv)
and we are now stuck with it.
*/
if (my_strcasecmp(system_charset_info, argv[1],"mysql"))
- load_default_groups[3]= argv[1];
+ load_default_groups[load_default_groups_sz-2]= argv[1];
start_mode= 1;
Service.Init(argv[1], mysql_service);
return 0;
@@ -3253,7 +3307,7 @@ int main(int argc, char **argv)
opt_argv=argv;
start_mode= 1;
if (my_strcasecmp(system_charset_info, argv[2],"mysql"))
- load_default_groups[3]= argv[2];
+ load_default_groups[load_default_groups_sz-2]= argv[2];
Service.Init(argv[2], mysql_service);
return 0;
}
@@ -3431,10 +3485,10 @@ static void create_new_thread(THD *thd)
("Can't create thread to handle request (error %d)",
error));
thread_count--;
- thd->killed= THD::KILL_CONNECTION; // Safety
+ thd->killed= THD::KILL_CONNECTION; // Safety
(void) pthread_mutex_unlock(&LOCK_thread_count);
statistic_increment(aborted_connects,&LOCK_status);
- net_printf(thd,ER_CANT_CREATE_THREAD,error);
+ net_printf_error(thd, ER_CANT_CREATE_THREAD, error);
(void) pthread_mutex_lock(&LOCK_thread_count);
close_connection(thd,0,0);
delete thd;
@@ -3789,7 +3843,6 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
/* file-mapping object, use for create shared memory */
HANDLE handle_connect_file_map= 0;
char *handle_connect_map= 0; // pointer on shared memory
- HANDLE event_connect_request= 0; // for start connection actions
HANDLE event_connect_answer= 0;
ulong smem_buffer_length= shared_memory_buffer_length + 4;
ulong connect_number= 1;
@@ -3810,7 +3863,7 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
*/
suffix_pos= strxmov(tmp,shared_memory_base_name,"_",NullS);
strmov(suffix_pos, "CONNECT_REQUEST");
- if ((event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
+ if ((smem_event_connect_request= CreateEvent(0,FALSE,FALSE,tmp)) == 0)
{
errmsg= "Could not create request event";
goto error;
@@ -3841,7 +3894,13 @@ pthread_handler_decl(handle_connections_shared_memory,arg)
while (!abort_loop)
{
/* Wait a request from client */
- WaitForSingleObject(event_connect_request,INFINITE);
+ WaitForSingleObject(smem_event_connect_request,INFINITE);
+
+ /*
+ it can be after shutdown command
+ */
+ if (abort_loop)
+ goto error;
HANDLE handle_client_file_map= 0;
char *handle_client_map= 0;
@@ -3966,7 +4025,7 @@ error:
if (handle_connect_map) UnmapViewOfFile(handle_connect_map);
if (handle_connect_file_map) CloseHandle(handle_connect_file_map);
if (event_connect_answer) CloseHandle(event_connect_answer);
- if (event_connect_request) CloseHandle(event_connect_request);
+ if (smem_event_connect_request) CloseHandle(smem_event_connect_request);
decrement_handler_count();
DBUG_RETURN(0);
@@ -4031,7 +4090,10 @@ enum options_mysqld
OPT_INNODB_FILE_PER_TABLE, OPT_CRASH_BINLOG_INNODB,
OPT_INNODB_LOCKS_UNSAFE_FOR_BINLOG,
OPT_SAFE_SHOW_DB, OPT_INNODB_SAFE_BINLOG,
- OPT_INNODB, OPT_ISAM, OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, OPT_SKIP_SAFEMALLOC,
+ OPT_INNODB, OPT_ISAM,
+ OPT_NDBCLUSTER, OPT_NDB_CONNECTSTRING, OPT_NDB_USE_EXACT_COUNT,
+ OPT_NDB_FORCE_SEND, OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
+ OPT_SKIP_SAFEMALLOC,
OPT_TEMP_POOL, OPT_TX_ISOLATION,
OPT_SKIP_STACK_TRACE, OPT_SKIP_SYMLINKS,
OPT_MAX_BINLOG_DUMP_EVENTS, OPT_SPORADIC_BINLOG_DUMP_FAIL,
@@ -4157,7 +4219,7 @@ struct my_option my_long_options[] =
0, 0, 0, 0, 0, 0},
{"bdb", OPT_BDB, "Enable Berkeley DB (if this version of MySQL supports it). \
Disable with --skip-bdb (will save memory).",
- (gptr*) &opt_bdb, (gptr*) &opt_bdb, 0, GET_BOOL, NO_ARG, 1, 0, 0,
+ (gptr*) &opt_bdb, (gptr*) &opt_bdb, 0, GET_BOOL, NO_ARG, OPT_BDB_DEFAULT, 0, 0,
0, 0, 0},
#ifdef HAVE_BERKELEY_DB
{"bdb-home", OPT_BDB_HOME, "Berkeley home directory.", (gptr*) &berkeley_home,
@@ -4294,7 +4356,7 @@ Disable with --skip-bdb (will save memory).",
REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"innodb", OPT_INNODB, "Enable InnoDB (if this version of MySQL supports it). \
Disable with --skip-innodb (will save memory).",
- (gptr*) &opt_innodb, (gptr*) &opt_innodb, 0, GET_BOOL, NO_ARG, 1, 0, 0,
+ (gptr*) &opt_innodb, (gptr*) &opt_innodb, 0, GET_BOOL, NO_ARG, OPT_INNODB_DEFAULT, 0, 0,
0, 0, 0},
{"innodb_data_file_path", OPT_INNODB_DATA_FILE_PATH,
"Path to individual files and their sizes.",
@@ -4338,7 +4400,7 @@ Disable with --skip-innodb (will save memory).",
"Percentage of dirty pages allowed in bufferpool.", (gptr*) &srv_max_buf_pool_modified_pct,
(gptr*) &srv_max_buf_pool_modified_pct, 0, GET_ULONG, REQUIRED_ARG, 90, 0, 100, 0, 0, 0},
{"innodb_max_purge_lag", OPT_INNODB_MAX_PURGE_LAG,
- "",
+ "Desired maximum length of the purge queue (0 = no limit)",
(gptr*) &srv_max_purge_lag,
(gptr*) &srv_max_purge_lag, 0, GET_LONG, REQUIRED_ARG, 0, 0, ~0L,
0, 1L, 0},
@@ -4347,14 +4409,14 @@ Disable with --skip-innodb (will save memory).",
(gptr*) &innobase_create_status_file, (gptr*) &innobase_create_status_file,
0, GET_BOOL, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"innodb_table_locks", OPT_INNODB_TABLE_LOCKS,
- "If Innodb should enforce LOCK TABLE",
+ "Enable InnoDB locking in LOCK TABLES",
(gptr*) &global_system_variables.innodb_table_locks,
(gptr*) &global_system_variables.innodb_table_locks,
0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
#endif /* End HAVE_INNOBASE_DB */
{"isam", OPT_ISAM, "Enable ISAM (if this version of MySQL supports it). \
Disable with --skip-isam.",
- (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, 1, 0, 0,
+ (gptr*) &opt_isam, (gptr*) &opt_isam, 0, GET_BOOL, NO_ARG, OPT_ISAM_DEFAULT, 0, 0,
0, 0, 0},
{"language", 'L',
"Client error messages in given language. May be given as a full path.",
@@ -4482,12 +4544,29 @@ master-ssl",
GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
{"ndbcluster", OPT_NDBCLUSTER, "Enable NDB Cluster (if this version of MySQL supports it). \
Disable with --skip-ndbcluster (will save memory).",
- (gptr*) &opt_ndbcluster, (gptr*) &opt_ndbcluster, 0, GET_BOOL, NO_ARG, 1, 0, 0,
- 0, 0, 0},
+ (gptr*) &opt_ndbcluster, (gptr*) &opt_ndbcluster, 0, GET_BOOL, NO_ARG,
+ OPT_NDBCLUSTER_DEFAULT, 0, 0, 0, 0, 0},
#ifdef HAVE_NDBCLUSTER_DB
- {"ndb-connectstring", OPT_NDB_CONNECTSTRING, "Connect string for ndbcluster.",
- (gptr*) &ndbcluster_connectstring, (gptr*) &ndbcluster_connectstring, 0, GET_STR,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"ndb-connectstring", OPT_NDB_CONNECTSTRING,
+ "Connect string for ndbcluster.",
+ (gptr*) &ndbcluster_connectstring, (gptr*) &ndbcluster_connectstring,
+ 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"ndb_autoincrement_prefetch_sz", OPT_NDB_AUTOINCREMENT_PREFETCH_SZ,
+ "Specify number of autoincrement values that are prefetched",
+ (gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
+ (gptr*) &global_system_variables.ndb_autoincrement_prefetch_sz,
+ 0, GET_INT, REQUIRED_ARG, 32, 1, 256, 0, 0, 0},
+ {"ndb_force_send", OPT_NDB_FORCE_SEND,
+ "Force send of buffers to ndb immediately without waiting for other threads",
+ (gptr*) &global_system_variables.ndb_force_send,
+ (gptr*) &global_system_variables.ndb_force_send,
+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
+ {"ndb_use_exact_count", OPT_NDB_USE_EXACT_COUNT,
+ "Use exact records count during query planning and for "
+ "fast select count(*)",
+ (gptr*) &global_system_variables.ndb_use_exact_count,
+ (gptr*) &global_system_variables.ndb_use_exact_count,
+ 0, GET_BOOL, OPT_ARG, 1, 0, 0, 0, 0, 0},
#endif
{"new", 'n', "Use very new possible 'unsafe' functions.",
(gptr*) &global_system_variables.new_mode,
@@ -4831,7 +4910,7 @@ log and this option does nothing anymore.",
"Data file autoextend increment in megabytes",
(gptr*) &srv_auto_extend_increment,
(gptr*) &srv_auto_extend_increment,
- 0, GET_LONG, REQUIRED_ARG, 8L, 1L, ~0L, 0, 1L, 0},
+ 0, GET_LONG, REQUIRED_ARG, 8L, 1L, 1000L, 0, 1L, 0},
{"innodb_buffer_pool_awe_mem_mb", OPT_INNODB_BUFFER_POOL_AWE_MEM_MB,
"If Windows AWE is used, the size of InnoDB buffer pool allocated from the AWE memory.",
(gptr*) &innobase_buffer_pool_awe_mem_mb, (gptr*) &innobase_buffer_pool_awe_mem_mb, 0,
@@ -5132,12 +5211,12 @@ The minimum value for this variable is 4096.",
"Persistent buffer for query parsing and execution",
(gptr*) &global_system_variables.query_prealloc_size,
(gptr*) &max_system_variables.query_prealloc_size, 0, GET_ULONG,
- REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
+ REQUIRED_ARG, QUERY_ALLOC_PREALLOC_SIZE, 16384, ~0L, 0, 1024, 0},
{"range_alloc_block_size", OPT_RANGE_ALLOC_BLOCK_SIZE,
"Allocation block size for storing ranges during optimization",
(gptr*) &global_system_variables.range_alloc_block_size,
(gptr*) &max_system_variables.range_alloc_block_size, 0, GET_ULONG,
- REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 1024, ~0L, 0, 1024, 0},
+ REQUIRED_ARG, RANGE_ALLOC_BLOCK_SIZE, 4096, ~0L, 0, 1024, 0},
{"read_buffer_size", OPT_RECORD_BUFFER,
"Each thread that does a sequential scan allocates a buffer of this size for each table it scans. If you do many sequential scans, you may want to increase this value.",
(gptr*) &global_system_variables.read_buff_size,
@@ -5242,7 +5321,7 @@ The minimum value for this variable is 4096.",
(gptr*) &max_system_variables.trans_prealloc_size, 0, GET_ULONG,
REQUIRED_ARG, TRANS_ALLOC_PREALLOC_SIZE, 1024, ~0L, 0, 1024, 0},
{"updatable_views_with_limit", OPT_UPDATABLE_VIEWS_WITH_LIMIT,
- "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlaying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).",
+ "1 = YES = Don't issue an error message (warning only) if a VIEW without presence of a key of the underlying table is used in queries with a LIMIT clause for updating. 0 = NO = Prohibit update of a VIEW, which does not contain a key of the underlying table and the query uses a LIMIT clause (usually get from GUI tools).",
(gptr*) &global_system_variables.updatable_views_with_limit,
(gptr*) &max_system_variables.updatable_views_with_limit,
0, GET_ULONG, REQUIRED_ARG, 1, 0, 1, 0, 1, 0},
@@ -5392,6 +5471,9 @@ struct show_var_st status_vars[]= {
SHOW_LONG_STATUS},
{"Handler_write", (char*) offsetof(STATUS_VAR, ha_write_count),
SHOW_LONG_STATUS},
+#ifdef HAVE_INNOBASE_DB
+ {"Innodb_", (char*) &innodb_status_variables, SHOW_VARS},
+#endif /*HAVE_INNOBASE_DB*/
{"Key_blocks_not_flushed", (char*) &dflt_key_cache_var.global_blocks_changed,
SHOW_KEY_CACHE_LONG},
{"Key_blocks_unused", (char*) &dflt_key_cache_var.blocks_unused,
@@ -6348,6 +6430,24 @@ static void get_options(int argc,char **argv)
if ((ho_error= handle_options(&argc, &argv, my_long_options,
get_one_option)))
exit(ho_error);
+
+#ifndef HAVE_NDBCLUSTER_DB
+ if (opt_ndbcluster)
+ sql_print_warning("this binary does not contain NDBCLUSTER storage engine");
+#endif
+#ifndef HAVE_INNOBASE_DB
+ if (opt_innodb)
+ sql_print_warning("this binary does not contain INNODB storage engine");
+#endif
+#ifndef HAVE_ISAM
+ if (opt_isam)
+ sql_print_warning("this binary does not contain ISAM storage engine");
+#endif
+#ifndef HAVE_BERKELEY_DB
+ if (opt_bdb)
+ sql_print_warning("this binary does not contain BDB storage engine");
+#endif
+
if (argc > 0)
{
fprintf(stderr, "%s: Too many arguments (first extra is '%s').\nUse --help to get a list of available options\n", my_progname, *argv);
diff --git a/sql/net_serv.cc b/sql/net_serv.cc
index ed4cc6a5942..899733d8639 100644
--- a/sql/net_serv.cc
+++ b/sql/net_serv.cc
@@ -53,19 +53,9 @@
#include <errno.h>
#ifdef EMBEDDED_LIBRARY
-
#undef MYSQL_SERVER
-
-#ifndef MYSQL_CLIENT
+#undef MYSQL_CLIENT
#define MYSQL_CLIENT
-#endif
-
-#undef net_flush
-
-extern "C" {
-my_bool net_flush(NET *net);
-}
-
#endif /*EMBEDDED_LIBRARY */
@@ -110,7 +100,7 @@ extern void query_cache_insert(NET *net, const char *packet, ulong length);
#if !defined(MYSQL_SERVER) || defined(MYSQL_INSTANCE_MANAGER)
#define update_statistics(A)
-#define thd_increment_bytes_sent()
+#define thd_increment_bytes_sent(N)
#endif
#define TEST_BLOCKING 8
diff --git a/sql/opt_range.cc b/sql/opt_range.cc
index 286d0d01842..f9149f10a30 100644
--- a/sql/opt_range.cc
+++ b/sql/opt_range.cc
@@ -724,7 +724,7 @@ QUICK_RANGE_SELECT::QUICK_RANGE_SELECT(THD *thd, TABLE *table, uint key_nr,
{
// Allocates everything through the internal memroot
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
- my_pthread_setspecific_ptr(THR_MALLOC,&alloc);
+ thd->mem_root= &alloc;
}
else
bzero((char*) &alloc,sizeof(alloc));
@@ -1041,7 +1041,7 @@ QUICK_ROR_UNION_SELECT::QUICK_ROR_UNION_SELECT(THD *thd_param,
rowid_length= table->file->ref_length;
record= head->record[0];
init_sql_alloc(&alloc, thd->variables.range_alloc_block_size, 0);
- my_pthread_setspecific_ptr(THR_MALLOC,&alloc);
+ thd_param->mem_root= &alloc;
}
@@ -1360,7 +1360,7 @@ public:
/* Table read plans are allocated on MEM_ROOT and are never deleted */
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
- static void operator delete(void *ptr,size_t size) {}
+ static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
};
class TRP_ROR_INTERSECT;
@@ -1476,7 +1476,8 @@ public:
KEY_PART_INFO *min_max_arg_part_arg,
uint group_prefix_len_arg, uint used_key_parts_arg,
uint group_key_parts_arg, KEY *index_info_arg,
- uint index_arg, uint key_infix_len_arg, byte *key_infix_arg,
+ uint index_arg, uint key_infix_len_arg,
+ byte *key_infix_arg,
SEL_TREE *tree_arg, SEL_ARG *index_tree_arg,
uint param_idx_arg, ha_rows quick_prefix_records_arg)
: have_min(have_min_arg), have_max(have_max_arg),
@@ -1486,12 +1487,10 @@ public:
index(index_arg), key_infix_len(key_infix_len_arg), range_tree(tree_arg),
index_tree(index_tree_arg), param_idx(param_idx_arg),
quick_prefix_records(quick_prefix_records_arg)
-{
- if (key_infix_len)
- memcpy(this->key_infix, key_infix_arg, key_infix_len);
-}
-
-
+ {
+ if (key_infix_len)
+ memcpy(this->key_infix, key_infix_arg, key_infix_len);
+ }
QUICK_SELECT_I *make_quick(PARAM *param, bool retrieve_full_rows,
MEM_ROOT *parent_alloc);
@@ -1649,8 +1648,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
DBUG_RETURN(0); // Can't use range
}
key_parts= param.key_parts;
- old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
- my_pthread_setspecific_ptr(THR_MALLOC,&alloc);
+ old_root= thd->mem_root;
+ thd->mem_root= &alloc;
/*
Make an array with description of all key parts of all table keys.
@@ -1750,8 +1749,10 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
objects are not allowed so don't use ROR-intersection for
table deletes.
*/
- if ((thd->lex->sql_command != SQLCOM_DELETE) )//&&
-// (thd->lex->sql_command != SQLCOM_UPDATE))
+ if ((thd->lex->sql_command != SQLCOM_DELETE))
+#ifdef NOT_USED
+ if ((thd->lex->sql_command != SQLCOM_UPDATE))
+#endif
{
/*
Get best non-covering ROR-intersection plan and prepare data for
@@ -1795,7 +1796,7 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
}
}
- my_pthread_setspecific_ptr(THR_MALLOC, old_root);
+ thd->mem_root= old_root;
/* If we got a read plan, create a quick select from it. */
if (best_trp)
@@ -1809,8 +1810,8 @@ int SQL_SELECT::test_quick_select(THD *thd, key_map keys_to_use,
}
free_mem:
- my_pthread_setspecific_ptr(THR_MALLOC, old_root);
free_root(&alloc,MYF(0)); // Return memory & allocator
+ thd->mem_root= old_root;
thd->no_errors=0;
}
@@ -2717,7 +2718,7 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
double min_cost= read_time;
DBUG_ENTER("get_best_ror_intersect");
- if (tree->n_ror_scans < 2)
+ if ((tree->n_ror_scans < 2) || !param->table->file->records)
DBUG_RETURN(NULL);
/*
@@ -2804,6 +2805,9 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
min_cost= intersect->total_cost;
best_rows= (ha_rows)(intersect->records_fract*
rows2double(param->table->file->records));
+ /* Prevent divisons by zero */
+ if (!best_rows)
+ best_rows= 1;
is_best_covering= intersect->is_covering;
intersect_scans_best= intersect_scans_end;
best_index_scan_costs= intersect->index_scan_costs;
@@ -2848,6 +2852,9 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
min_cost= intersect->total_cost;
best_rows= (ha_rows)(intersect->records_fract*
rows2double(param->table->file->records));
+ /* Prevent divisons by zero */
+ if (!best_rows)
+ best_rows= 1;
is_best_covering= intersect->is_covering;
best_index_scan_costs= intersect->index_scan_costs;
}
@@ -2867,13 +2874,13 @@ TRP_ROR_INTERSECT *get_best_ror_intersect(const PARAM *param, SEL_TREE *tree,
trp->last_scan= trp->first_scan + best_num;
trp->is_covering= is_best_covering;
trp->read_cost= min_cost;
- trp->records= best_rows? best_rows : 1;
+ trp->records= best_rows;
trp->index_scan_costs= best_index_scan_costs;
trp->cpk_scan= cpk_scan;
+ DBUG_PRINT("info",
+ ("Returning non-covering ROR-intersect plan: cost %g, records %lu",
+ trp->read_cost, (ulong) trp->records));
}
- DBUG_PRINT("info",
- ("Returning non-covering ROR-intersect plan: cost %g, records %lu",
- trp->read_cost, (ulong) trp->records));
DBUG_RETURN(trp);
}
@@ -3566,13 +3573,22 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
}
/*
- We can't use an index when comparing strings of
- different collations
+ 1. Usually we can't use an index if the column collation
+ differ from the operation collation.
+
+ 2. However, we can reuse a case insensitive index for
+ the binary searches:
+
+ WHERE latin1_swedish_ci_column = 'a' COLLATE lati1_bin;
+
+ WHERE latin1_swedish_ci_colimn = BINARY 'a '
+
*/
if (field->result_type() == STRING_RESULT &&
value->result_type() == STRING_RESULT &&
key_part->image_type == Field::itRAW &&
- ((Field_str*)field)->charset() != conf_func->compare_collation())
+ ((Field_str*)field)->charset() != conf_func->compare_collation() &&
+ !(conf_func->compare_collation()->state & MY_CS_BINSORT))
DBUG_RETURN(0);
optimize_range= field->optimize_range(param->real_keynr[key_part->key],
@@ -3679,8 +3695,7 @@ get_mm_leaf(PARAM *param, COND *conf_func, Field *field, KEY_PART *key_part,
DBUG_RETURN(0);
if (maybe_null)
*str= (char) field->is_real_null(); // Set to 1 if null
- field->get_key_image(str+maybe_null, key_part->length,
- field->charset(), key_part->image_type);
+ field->get_key_image(str+maybe_null, key_part->length, key_part->image_type);
if (copies == 2)
{
/*
@@ -5220,7 +5235,7 @@ static bool is_key_scan_ror(PARAM *param, uint keynr, uint8 nparts)
NOTES
The caller must call QUICK_SELECT::init for returned quick select
- CAUTION! This function may change THR_MALLOC to a MEM_ROOT which will be
+ CAUTION! This function may change thd->mem_root to a MEM_ROOT which will be
deallocated when the returned quick select is deleted.
RETURN
@@ -5464,7 +5479,8 @@ bool QUICK_ROR_UNION_SELECT::check_if_keys_used(List<Item> *fields)
QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
TABLE_REF *ref)
{
- MEM_ROOT *old_root= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
+ MEM_ROOT *old_root= thd->mem_root;
+ /* The following call may change thd->mem_root */
QUICK_RANGE_SELECT *quick= new QUICK_RANGE_SELECT(thd, table, ref->key, 0);
KEY *key_info = &table->key_info[ref->key];
KEY_PART *key_part;
@@ -5524,12 +5540,11 @@ QUICK_RANGE_SELECT *get_quick_select_for_ref(THD *thd, TABLE *table,
goto err;
}
-ok:
- my_pthread_setspecific_ptr(THR_MALLOC, old_root);
+ thd->mem_root= old_root;
return quick;
err:
- my_pthread_setspecific_ptr(THR_MALLOC, old_root);
+ thd->mem_root= old_root;
delete quick;
return 0;
}
@@ -7488,10 +7503,10 @@ QUICK_GROUP_MIN_MAX_SELECT(TABLE *table, JOIN *join_arg, bool have_min_arg,
if (!parent_alloc)
{
init_sql_alloc(&alloc, join->thd->variables.range_alloc_block_size, 0);
- my_pthread_setspecific_ptr(THR_MALLOC,&alloc);
+ join->thd->mem_root= &alloc;
}
else
- bzero(&alloc, sizeof(MEM_ROOT));
+ bzero(&alloc, sizeof(MEM_ROOT)); // ensure that it's not used
}
@@ -8058,7 +8073,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_min_in_range()
boundary of cur_range, there is no need to check this range.
*/
if (range_idx != 0 && !(cur_range->flag & NO_MAX_RANGE) &&
- (key_cmp(min_max_arg_part, cur_range->max_key, min_max_arg_len) == 1))
+ (key_cmp(min_max_arg_part, (const byte*) cur_range->max_key,
+ min_max_arg_len) == 1))
continue;
if (cur_range->flag & NO_MIN_RANGE)
@@ -8184,7 +8200,8 @@ int QUICK_GROUP_MIN_MAX_SELECT::next_max_in_range()
*/
if (range_idx != min_max_ranges.elements &&
!(cur_range->flag & NO_MIN_RANGE) &&
- (key_cmp(min_max_arg_part, cur_range->min_key, min_max_arg_len) == -1))
+ (key_cmp(min_max_arg_part, (const byte*) cur_range->min_key,
+ min_max_arg_len) == -1))
continue;
if (cur_range->flag & NO_MAX_RANGE)
@@ -8428,7 +8445,7 @@ print_key(KEY_PART *key_part,const char *key,uint used_length)
key++; // Skip null byte
store_length--;
}
- field->set_key_image((char*) key, key_part->length, field->charset());
+ field->set_key_image((char*) key, key_part->length);
field->val_str(&tmp);
fwrite(tmp.ptr(),sizeof(char),tmp.length(),DBUG_FILE);
if (key+store_length < key_end)
diff --git a/sql/opt_sum.cc b/sql/opt_sum.cc
index 30033bc39eb..80226dcfa2c 100644
--- a/sql/opt_sum.cc
+++ b/sql/opt_sum.cc
@@ -59,9 +59,9 @@ static int maxmin_in_range(bool max_fl, Field* field, COND *cond);
SYNOPSIS
opt_sum_query()
- tables Tables in query
- all_fields All fields to be returned
- conds WHERE clause
+ tables list of leaves of join table tree
+ all_fields All fields to be returned
+ conds WHERE clause
NOTE:
This function is only called for queries with sum functions and no
@@ -89,7 +89,7 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
where_tables= conds->used_tables();
/* Don't replace expression on a table that is part of an outer join */
- for (TABLE_LIST *tl= tables; tl; tl= tl->next_local)
+ for (TABLE_LIST *tl= tables; tl; tl= tl->next_leaf)
{
if (tl->on_expr)
{
@@ -128,10 +128,10 @@ int opt_sum_query(TABLE_LIST *tables, List<Item> &all_fields,COND *conds)
{
longlong count= 1;
TABLE_LIST *table;
- for (table= tables; table; table= table->next_local)
+ for (table= tables; table; table= table->next_leaf)
{
if (outer_tables || (table->table->file->table_flags() &
- HA_NOT_EXACT_COUNT))
+ HA_NOT_EXACT_COUNT) || table->schema_table)
{
const_result= 0; // Can't optimize left join
break;
@@ -562,8 +562,7 @@ static bool matching_cond(bool max_fl, TABLE_REF *ref, KEY *keyinfo,
store_val_in_field(part->field, args[between && max_fl ? 2 : 1]);
if (part->null_bit)
*key_ptr++= (byte) test(part->field->is_null());
- part->field->get_key_image((char*) key_ptr, part->length,
- part->field->charset(), Field::itRAW);
+ part->field->get_key_image((char*) key_ptr, part->length, Field::itRAW);
}
if (is_field_part)
{
diff --git a/sql/parse_file.cc b/sql/parse_file.cc
index f548c16d808..6c3a81384a6 100644
--- a/sql/parse_file.cc
+++ b/sql/parse_file.cc
@@ -608,15 +608,13 @@ parse_quoted_escaped_string(char *ptr, char *end,
my_bool
File_parser::parse(gptr base, MEM_ROOT *mem_root,
- struct File_option *parameters, uint required)
+ struct File_option *parameters, uint required)
{
uint first_param= 0, found= 0;
register char *ptr= start;
char *eol;
LEX_STRING *str;
- MEM_ROOT *sql_mem;
List<LEX_STRING> *list;
- bool change_mem;
DBUG_ENTER("File_parser::parse");
while (ptr < end && found < required)
@@ -670,7 +668,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
parameter->offset))))
{
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
- parameter->name.str, line);
+ parameter->name.str, line);
DBUG_RETURN(TRUE);
}
break;
@@ -682,7 +680,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
(base + parameter->offset))))
{
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
- parameter->name.str, line);
+ parameter->name.str, line);
DBUG_RETURN(TRUE);
}
break;
@@ -692,7 +690,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
if (!(eol= strchr(ptr, '\n')))
{
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
- parameter->name.str, line);
+ parameter->name.str, line);
DBUG_RETURN(TRUE);
}
{
@@ -710,7 +708,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
if (ptr[PARSE_FILE_TIMESTAMPLENGTH] != '\n')
{
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
- parameter->name.str, line);
+ parameter->name.str, line);
DBUG_RETURN(TRUE);
}
memcpy(val->str, ptr, PARSE_FILE_TIMESTAMPLENGTH);
@@ -720,18 +718,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
}
case FILE_OPTIONS_STRLIST:
{
- /*
- TODO: remove play with mem_root, when List will be able
- to store MEM_ROOT* pointer for list elements allocation
- FIXME: we can't handle empty lists
- */
- sql_mem= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
- list= (List<LEX_STRING>*)(base + parameter->offset);
- if ((change_mem= (sql_mem != mem_root)))
- {
- change_mem= 1;
- my_pthread_setspecific_ptr(THR_MALLOC, mem_root);
- }
+ list= (List<LEX_STRING>*)(base + parameter->offset);
list->empty();
// list parsing
@@ -739,7 +726,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
{
if (!(str= (LEX_STRING*)alloc_root(mem_root,
sizeof(LEX_STRING))) ||
- list->push_back(str))
+ list->push_back(str, mem_root))
goto list_err;
if(!(ptr= parse_quoted_escaped_string(ptr, end, mem_root, str)))
goto list_err_w_message;
@@ -754,20 +741,15 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
goto list_err_w_message;
}
}
- end_of_list:
+ end_of_list:
if (*(ptr++) != '\n')
goto list_err;
-
- if (change_mem)
- my_pthread_setspecific_ptr(THR_MALLOC, sql_mem);
break;
list_err_w_message:
my_error(ER_FPARSER_ERROR_IN_PARAMETER, MYF(0),
- parameter->name.str, line);
+ parameter->name.str, line);
list_err:
- if (change_mem)
- my_pthread_setspecific_ptr(THR_MALLOC, sql_mem);
DBUG_RETURN(TRUE);
}
default:
@@ -779,8 +761,7 @@ File_parser::parse(gptr base, MEM_ROOT *mem_root,
// skip unknown parameter
if (!(ptr= strchr(ptr, '\n')))
{
- my_error(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER, MYF(0),
- line);
+ my_error(ER_FPARSER_EOF_IN_UNKNOWN_PARAMETER, MYF(0), line);
DBUG_RETURN(TRUE);
}
ptr++;
diff --git a/sql/procedure.cc b/sql/procedure.cc
index 7779f5ce085..420a4f6262b 100644
--- a/sql/procedure.cc
+++ b/sql/procedure.cc
@@ -65,8 +65,7 @@ setup_procedure(THD *thd,ORDER *param,select_result *result,
DBUG_RETURN(proc);
}
}
- my_printf_error(ER_UNKNOWN_PROCEDURE,ER(ER_UNKNOWN_PROCEDURE),MYF(0),
- (*param->item)->name);
+ my_error(ER_UNKNOWN_PROCEDURE, MYF(0), (*param->item)->name);
*error=1;
DBUG_RETURN(0);
}
diff --git a/sql/procedure.h b/sql/procedure.h
index 5365b2e1102..4212a9246a5 100644
--- a/sql/procedure.h
+++ b/sql/procedure.h
@@ -60,7 +60,7 @@ public:
void set(longlong nr) { value=(double) nr; }
void set(const char *str,uint length,CHARSET_INFO *cs)
{ int err; value=my_strntod(cs,(char*) str,length,(char**)0,&err); }
- double val() { return value; }
+ double val_real() { return value; }
longlong val_int() { return (longlong) value; }
String *val_str(String *s) { s->set(value,decimals,default_charset()); return s; }
unsigned int size_of() { return sizeof(*this);}
@@ -78,7 +78,7 @@ public:
void set(longlong nr) { value=nr; }
void set(const char *str,uint length, CHARSET_INFO *cs)
{ int err; value=my_strntoll(cs,str,length,10,NULL,&err); }
- double val() { return (double) value; }
+ double val_real() { return (double) value; }
longlong val_int() { return value; }
String *val_str(String *s) { s->set(value, default_charset()); return s; }
unsigned int size_of() { return sizeof(*this);}
@@ -91,12 +91,12 @@ public:
Item_proc_string(const char *name_par,uint length) :Item_proc(name_par)
{ this->max_length=length; }
enum Item_result result_type () const { return STRING_RESULT; }
- enum_field_types field_type() const { return MYSQL_TYPE_STRING; }
+ enum_field_types field_type() const { return MYSQL_TYPE_VARCHAR; }
void set(double nr) { str_value.set(nr, 2, default_charset()); }
void set(longlong nr) { str_value.set(nr, default_charset()); }
void set(const char *str, uint length, CHARSET_INFO *cs)
{ str_value.copy(str,length,cs); }
- double val()
+ double val_real()
{
int err;
CHARSET_INFO *cs=str_value.charset();
diff --git a/sql/protocol.cc b/sql/protocol.cc
index 051eaaf7bda..d2e63539610 100644
--- a/sql/protocol.cc
+++ b/sql/protocol.cc
@@ -53,14 +53,14 @@ bool Protocol_prep::net_store_data(const char *from, uint length)
/* Send a error string to client */
-void send_error(THD *thd, uint sql_errno, const char *err)
+void net_send_error(THD *thd, uint sql_errno, const char *err)
{
#ifndef EMBEDDED_LIBRARY
uint length;
char buff[MYSQL_ERRMSG_SIZE+2], *pos;
#endif
NET *net= &thd->net;
- DBUG_ENTER("send_error");
+ DBUG_ENTER("net_send_error");
DBUG_PRINT("enter",("sql_errno: %d err: %s", sql_errno,
err ? err : net->last_error[0] ?
net->last_error : "NULL"));
@@ -70,9 +70,6 @@ void send_error(THD *thd, uint sql_errno, const char *err)
{
DBUG_VOID_RETURN;
}
-#ifndef EMBEDDED_LIBRARY /* TODO query cache in embedded library*/
- query_cache_abort(net);
-#endif
thd->query_error= 1; // needed to catch query errors during replication
if (!err)
{
@@ -130,41 +127,10 @@ void send_error(THD *thd, uint sql_errno, const char *err)
thd->net.report_error= 0;
/* Abort multi-result sets */
- thd->lex->found_colon= 0;
thd->server_status&= ~SERVER_MORE_RESULTS_EXISTS;
DBUG_VOID_RETURN;
}
-
-/*
- Send a warning to the end user
-
- SYNOPSIS
- send_warning()
- thd Thread handler
- sql_errno Warning number (error message)
- err Error string. If not set, use ER(sql_errno)
-
- DESCRIPTION
- Register the warning so that the user can get it with mysql_warnings()
- Send an ok (+ warning count) to the end user.
-*/
-
-void send_warning(THD *thd, uint sql_errno, const char *err)
-{
- DBUG_ENTER("send_warning");
- if (thd->spcont &&
- thd->spcont->find_handler(sql_errno, MYSQL_ERROR::WARN_LEVEL_WARN))
- {
- DBUG_VOID_RETURN;
- }
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, sql_errno,
- err ? err : ER(sql_errno));
- send_ok(thd);
- DBUG_VOID_RETURN;
-}
-
-
/*
Write error package and flush to client
It's a little too low level, but I don't want to use another buffer for
@@ -172,7 +138,7 @@ void send_warning(THD *thd, uint sql_errno, const char *err)
*/
void
-net_printf(THD *thd, uint errcode, ...)
+net_printf_error(THD *thd, uint errcode, ...)
{
va_list args;
uint length,offset;
@@ -185,7 +151,7 @@ net_printf(THD *thd, uint errcode, ...)
#endif
NET *net= &thd->net;
- DBUG_ENTER("net_printf");
+ DBUG_ENTER("net_printf_error");
DBUG_PRINT("enter",("message: %u",errcode));
if (thd->spcont && thd->spcont->find_handler(errcode,
@@ -199,8 +165,8 @@ net_printf(THD *thd, uint errcode, ...)
#endif
va_start(args,errcode);
/*
- The following is needed to make net_printf() work with 0 argument for
- errorcode and use the argument after that as the format string. This
+ The following is needed to make net_printf_error() work with 0 argument
+ for errorcode and use the argument after that as the format string. This
is useful for rare errors that are not worth the hassle to put in
errmsg.sys, but at the same time, the message is not fixed text
*/
@@ -486,6 +452,15 @@ void Protocol::init(THD *thd_arg)
}
+bool Protocol::flush()
+{
+#ifndef EMBEDDED_LIBRARY
+ return net_flush(&thd->net);
+#else
+ return 0;
+#endif
+}
+
/*
Send name and type of result to client.
@@ -536,6 +511,11 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
CHARSET_INFO *cs= system_charset_info;
Send_field field;
item->make_field(&field);
+
+ /* Keep things compatible for old clients */
+ if (field.type == MYSQL_TYPE_VARCHAR)
+ field.type= MYSQL_TYPE_VAR_STRING;
+
prot.prepare_for_resend();
if (thd->client_capabilities & CLIENT_PROTOCOL_41)
@@ -618,7 +598,8 @@ bool Protocol::send_fields(List<Item> *list, uint flags)
DBUG_RETURN(prepare_for_send(list));
err:
- send_error(thd,ER_OUT_OF_RESOURCES); /* purecov: inspected */
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
+ MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
@@ -731,7 +712,8 @@ bool Protocol::store_string_aux(const char *from, uint length,
fromcs != &my_charset_bin &&
tocs != &my_charset_bin)
{
- return convert->copy(from, length, fromcs, tocs) ||
+ uint dummy_errors;
+ return convert->copy(from, length, fromcs, tocs, &dummy_errors) ||
net_store_data(convert->ptr(), convert->length());
}
return net_store_data(from, length);
diff --git a/sql/protocol.h b/sql/protocol.h
index 7d390242417..fddd3ceba94 100644
--- a/sql/protocol.h
+++ b/sql/protocol.h
@@ -74,6 +74,7 @@ public:
field_count=item_list->elements;
return 0;
}
+ virtual bool flush();
virtual void prepare_for_resend()=0;
virtual bool store_null()=0;
@@ -172,7 +173,8 @@ public:
};
void send_warning(THD *thd, uint sql_errno, const char *err=0);
-void net_printf(THD *thd,uint sql_errno, ...);
+void net_printf_error(THD *thd, uint sql_errno, ...);
+void net_send_error(THD *thd, uint sql_errno=0, const char *err=0);
void send_ok(THD *thd, ha_rows affected_rows=0L, ulonglong id=0L,
const char *info=0);
void send_eof(THD *thd, bool no_flush=0);
diff --git a/sql/protocol_cursor.cc b/sql/protocol_cursor.cc
index 104457b3bcc..a5bf94469e7 100644
--- a/sql/protocol_cursor.cc
+++ b/sql/protocol_cursor.cc
@@ -84,7 +84,8 @@ bool Protocol_cursor::send_fields(List<Item> *list, uint flags)
DBUG_RETURN(FALSE);
err:
- send_error(thd, ER_OUT_OF_RESOURCES); /* purecov: inspected */
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES),
+ MYF(0)); /* purecov: inspected */
DBUG_RETURN(TRUE); /* purecov: inspected */
}
diff --git a/sql/repl_failsafe.cc b/sql/repl_failsafe.cc
index dc23b014e31..f759be59ffb 100644
--- a/sql/repl_failsafe.cc
+++ b/sql/repl_failsafe.cc
@@ -92,7 +92,7 @@ static int init_failsafe_rpl_thread(THD* thd)
VOID(pthread_sigmask(SIG_UNBLOCK,&set,&thd->block_signals));
#endif
- thd->mem_root.free=thd->mem_root.used=0;
+ thd->mem_root->free= thd->mem_root->used= 0;
if (thd->variables.max_join_size == HA_POS_ERROR)
thd->options|= OPTION_BIG_SELECTS;
@@ -194,7 +194,6 @@ err:
my_message(ER_UNKNOWN_ERROR, "Wrong parameters to function register_slave",
MYF(0));
err2:
- send_error(thd);
return 1;
}
@@ -438,7 +437,7 @@ static Slave_log_event* find_slave_event(IO_CACHE* log,
This function is broken now. See comment for translate_master().
*/
-int show_new_master(THD* thd)
+bool show_new_master(THD* thd)
{
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_new_master");
@@ -451,8 +450,8 @@ int show_new_master(THD* thd)
{
if (errmsg[0])
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
- "SHOW NEW MASTER", errmsg);
- DBUG_RETURN(-1);
+ "SHOW NEW MASTER", errmsg);
+ DBUG_RETURN(TRUE);
}
else
{
@@ -461,14 +460,14 @@ int show_new_master(THD* thd)
MYSQL_TYPE_LONGLONG));
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
protocol->store(lex_mi->log_file_name, &my_charset_bin);
protocol->store((ulonglong) lex_mi->pos);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
}
@@ -631,7 +630,7 @@ err:
}
-int show_slave_hosts(THD* thd)
+bool show_slave_hosts(THD* thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
@@ -653,7 +652,7 @@ int show_slave_hosts(THD* thd)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
pthread_mutex_lock(&LOCK_slave_list);
@@ -674,12 +673,12 @@ int show_slave_hosts(THD* thd)
if (protocol->write())
{
pthread_mutex_unlock(&LOCK_slave_list);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
pthread_mutex_unlock(&LOCK_slave_list);
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -760,7 +759,7 @@ static int fetch_db_tables(THD *thd, MYSQL *mysql, const char *db,
- No active transaction (flush_relay_log_info would not work in this case)
*/
-int load_master_data(THD* thd)
+bool load_master_data(THD* thd)
{
MYSQL mysql;
MYSQL_RES* master_status_res = 0;
@@ -782,16 +781,15 @@ int load_master_data(THD* thd)
(error=terminate_slave_threads(active_mi,restart_thread_mask,
1 /*skip lock*/)))
{
- send_error(thd,error);
+ my_message(error, ER(error), MYF(0));
unlock_slave_threads(active_mi);
pthread_mutex_unlock(&LOCK_active_mi);
- return 1;
+ return TRUE;
}
if (connect_to_master(thd, &mysql, active_mi))
{
- net_printf(thd, error= ER_CONNECT_TO_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_CONNECT_TO_MASTER, MYF(0), mysql_error(&mysql));
goto err;
}
@@ -803,8 +801,7 @@ int load_master_data(THD* thd)
if (mysql_real_query(&mysql, "SHOW DATABASES", 14) ||
!(db_res = mysql_store_result(&mysql)))
{
- net_printf(thd, error = ER_QUERY_ON_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
goto err;
}
@@ -817,7 +814,7 @@ int load_master_data(THD* thd)
if (!(table_res = (MYSQL_RES**)thd->alloc(num_dbs * sizeof(MYSQL_RES*))))
{
- net_printf(thd, error = ER_OUTOFMEMORY);
+ my_message(error = ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0));
goto err;
}
@@ -831,8 +828,7 @@ int load_master_data(THD* thd)
mysql_real_query(&mysql, "SHOW MASTER STATUS",18) ||
!(master_status_res = mysql_store_result(&mysql)))
{
- net_printf(thd, error = ER_QUERY_ON_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
goto err;
}
@@ -877,7 +873,6 @@ int load_master_data(THD* thd)
if (mysql_create_db(thd, db, &create_info, 1))
{
- send_error(thd, 0, 0);
cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
goto err;
}
@@ -886,8 +881,7 @@ int load_master_data(THD* thd)
mysql_real_query(&mysql, "SHOW TABLES", 11) ||
!(*cur_table_res = mysql_store_result(&mysql)))
{
- net_printf(thd, error = ER_QUERY_ON_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
cleanup_mysql_results(db_res, cur_table_res - 1, table_res);
goto err;
}
@@ -923,9 +917,9 @@ int load_master_data(THD* thd)
*/
int error;
- if (init_master_info(active_mi, master_info_file, relay_log_info_file,
- 0))
- send_error(thd, ER_MASTER_INFO);
+ if (init_master_info(active_mi, master_info_file, relay_log_info_file,
+ 0, (SLAVE_IO | SLAVE_SQL)))
+ my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0));
strmake(active_mi->master_log_name, row[0],
sizeof(active_mi->master_log_name));
active_mi->master_log_pos= my_strtoll10(row[1], (char**) 0, &error);
@@ -944,8 +938,7 @@ int load_master_data(THD* thd)
if (mysql_real_query(&mysql, "UNLOCK TABLES", 13))
{
- net_printf(thd, error = ER_QUERY_ON_MASTER,
- mysql_error(&mysql));
+ my_error(error= ER_QUERY_ON_MASTER, MYF(0), mysql_error(&mysql));
goto err;
}
}
@@ -954,10 +947,10 @@ int load_master_data(THD* thd)
0 /* not only reset, but also reinit */,
&errmsg))
{
- send_error(thd, 0, "Failed purging old relay logs");
+ my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
unlock_slave_threads(active_mi);
pthread_mutex_unlock(&LOCK_active_mi);
- return 1;
+ return TRUE;
}
pthread_mutex_lock(&active_mi->rli.data_lock);
active_mi->rli.group_master_log_pos = active_mi->master_log_pos;
diff --git a/sql/repl_failsafe.h b/sql/repl_failsafe.h
index ad0219bb735..dfaacf557e8 100644
--- a/sql/repl_failsafe.h
+++ b/sql/repl_failsafe.h
@@ -38,11 +38,11 @@ int update_slave_list(MYSQL* mysql, MASTER_INFO* mi);
extern HASH slave_list;
-int load_master_data(THD* thd);
+bool load_master_data(THD* thd);
int connect_to_master(THD *thd, MYSQL* mysql, MASTER_INFO* mi);
-int show_new_master(THD* thd);
-int show_slave_hosts(THD* thd);
+bool show_new_master(THD* thd);
+bool show_slave_hosts(THD* thd);
int translate_master(THD* thd, LEX_MASTER_INFO* mi, char* errmsg);
void init_slave_list();
void end_slave_list();
diff --git a/sql/set_var.cc b/sql/set_var.cc
index 8ffed33d442..234ec6617c3 100644
--- a/sql/set_var.cc
+++ b/sql/set_var.cc
@@ -374,6 +374,23 @@ sys_var_thd_bool sys_innodb_table_locks("innodb_table_locks",
sys_var_long_ptr sys_innodb_autoextend_increment("innodb_autoextend_increment",
&srv_auto_extend_increment);
#endif
+#ifdef HAVE_NDBCLUSTER_DB
+// ndb thread specific variable settings
+sys_var_thd_ulong
+sys_ndb_autoincrement_prefetch_sz("ndb_autoincrement_prefetch_sz",
+ &SV::ndb_autoincrement_prefetch_sz);
+sys_var_thd_bool
+sys_ndb_force_send("ndb_force_send",
+ &SV::ndb_force_send);
+sys_var_thd_bool
+sys_ndb_use_exact_count("ndb_use_exact_count",
+ &SV::ndb_use_exact_count);
+sys_var_thd_bool
+sys_ndb_use_transactions("ndb_use_transactions",
+ &SV::ndb_use_transactions);
+// ndb server global variable settings
+// none
+#endif
/* Time/date/datetime formats */
@@ -631,6 +648,12 @@ sys_var *sys_variables[]=
&sys_innodb_table_locks,
&sys_innodb_max_purge_lag,
&sys_innodb_autoextend_increment,
+#endif
+#ifdef HAVE_NDBCLUSTER_DB
+ &sys_ndb_autoincrement_prefetch_sz,
+ &sys_ndb_force_send,
+ &sys_ndb_use_exact_count,
+ &sys_ndb_use_transactions,
#endif
&sys_unique_checks,
&sys_updatable_views_with_limit,
@@ -795,6 +818,13 @@ struct show_var_st init_vars[]= {
#ifdef __NT__
{"named_pipe", (char*) &opt_enable_named_pipe, SHOW_MY_BOOL},
#endif
+#ifdef HAVE_NDBCLUSTER_DB
+ {sys_ndb_autoincrement_prefetch_sz.name,
+ (char*) &sys_ndb_autoincrement_prefetch_sz, SHOW_SYS},
+ {sys_ndb_force_send.name, (char*) &sys_ndb_force_send, SHOW_SYS},
+ {sys_ndb_use_exact_count.name,(char*) &sys_ndb_use_exact_count, SHOW_SYS},
+ {sys_ndb_use_transactions.name,(char*) &sys_ndb_use_transactions, SHOW_SYS},
+#endif
{sys_net_buffer_length.name,(char*) &sys_net_buffer_length, SHOW_SYS},
{sys_net_read_timeout.name, (char*) &sys_net_read_timeout, SHOW_SYS},
{sys_net_retry_count.name, (char*) &sys_net_retry_count, SHOW_SYS},
@@ -899,8 +929,8 @@ bool sys_var_str::check(THD *thd, set_var *var)
return 0;
if ((res=(*check_func)(thd, var)) < 0)
- my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0), name,
- var->value->str_value.ptr());
+ my_error(ER_WRONG_VALUE_FOR_VAR, MYF(0),
+ name, var->value->str_value.ptr());
return res;
}
@@ -1193,7 +1223,7 @@ static void fix_max_connections(THD *thd, enum_var_type type)
static void fix_thd_mem_root(THD *thd, enum_var_type type)
{
if (type != OPT_GLOBAL)
- reset_root_defaults(&thd->mem_root,
+ reset_root_defaults(thd->mem_root,
thd->variables.query_alloc_block_size,
thd->variables.query_prealloc_size);
}
@@ -1537,8 +1567,8 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
{
if (var_type != OPT_DEFAULT)
{
- net_printf(thd, ER_INCORRECT_GLOBAL_LOCAL_VAR,
- name, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
+ my_error(ER_INCORRECT_GLOBAL_LOCAL_VAR, MYF(0),
+ name, var_type == OPT_GLOBAL ? "SESSION" : "GLOBAL");
return 0;
}
/* As there was no local variable, return the global value */
@@ -1581,7 +1611,7 @@ Item *sys_var::item(THD *thd, enum_var_type var_type, LEX_STRING *base)
return tmp;
}
default:
- net_printf(thd, ER_VAR_CANT_BE_READ, name);
+ my_error(ER_VAR_CANT_BE_READ, MYF(0), name);
}
return 0;
}
@@ -1967,8 +1997,8 @@ bool sys_var_character_set_server::check(THD *thd, set_var *var)
(mysql_bin_log.is_open() ||
active_mi->slave_running || active_mi->rli.slave_running))
{
- my_printf_error(0, "Binary logging and replication forbid changing \
-the global server character set or collation", MYF(0));
+ my_error(ER_LOGING_PROHIBIT_CHANGING_OF, MYF(0),
+ "character set, collation");
return 1;
}
return sys_var_character_set::check(thd,var);
@@ -2074,8 +2104,8 @@ bool sys_var_collation_server::check(THD *thd, set_var *var)
(mysql_bin_log.is_open() ||
active_mi->slave_running || active_mi->rli.slave_running))
{
- my_printf_error(0, "Binary logging and replication forbid changing \
-the global server character set or collation", MYF(0));
+ my_error(ER_LOGING_PROHIBIT_CHANGING_OF, MYF(0),
+ "character set, collation");
return 1;
}
return sys_var_collation::check(thd,var);
@@ -2353,7 +2383,7 @@ bool sys_var_slave_skip_counter::check(THD *thd, set_var *var)
pthread_mutex_lock(&active_mi->rli.run_lock);
if (active_mi->rli.slave_running)
{
- my_error(ER_SLAVE_MUST_STOP, MYF(0));
+ my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
result=1;
}
pthread_mutex_unlock(&active_mi->rli.run_lock);
@@ -2424,8 +2454,7 @@ bool sys_var_thd_time_zone::check(THD *thd, set_var *var)
(mysql_bin_log.is_open() ||
active_mi->slave_running || active_mi->rli.slave_running))
{
- my_printf_error(0, "Binary logging and replication forbid changing "
- "of the global server time zone", MYF(0));
+ my_error(ER_LOGING_PROHIBIT_CHANGING_OF, MYF(0), "time zone");
return 1;
}
#endif
@@ -2703,9 +2732,6 @@ void set_var_free()
length Length of variable. zero means that we should use strlen()
on the variable
- NOTE
- We have to use net_printf() as this is called during the parsing stage
-
RETURN VALUES
pointer pointer to variable definitions
0 Unknown variable (error message is given)
@@ -2718,7 +2744,7 @@ sys_var *find_sys_var(const char *str, uint length)
length ? length :
strlen(str));
if (!var)
- net_printf(current_thd, ER_UNKNOWN_SYSTEM_VARIABLE, (char*) str);
+ my_error(ER_UNKNOWN_SYSTEM_VARIABLE, MYF(0), (char*) str);
return var;
}
@@ -2747,21 +2773,25 @@ sys_var *find_sys_var(const char *str, uint length)
int sql_set_variables(THD *thd, List<set_var_base> *var_list)
{
- int error= 0;
+ int error;
List_iterator_fast<set_var_base> it(*var_list);
DBUG_ENTER("sql_set_variables");
set_var_base *var;
while ((var=it++))
{
- if ((error=var->check(thd)))
- DBUG_RETURN(error);
+ if ((error= var->check(thd)))
+ goto err;
}
- if (thd->net.report_error)
- DBUG_RETURN(1);
- it.rewind();
- while ((var=it++))
- error|= var->update(thd); // Returns 0, -1 or 1
+ if (!(error= test(thd->net.report_error)))
+ {
+ it.rewind();
+ while ((var= it++))
+ error|= var->update(thd); // Returns 0, -1 or 1
+ }
+
+err:
+ free_underlaid_joins(thd, &thd->lex->select_lex);
DBUG_RETURN(error);
}
@@ -2804,9 +2834,8 @@ int set_var::check(THD *thd)
{
if (var->check_type(type))
{
- my_error(type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE,
- MYF(0),
- var->name);
+ int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
+ my_error(err, MYF(0), var->name);
return -1;
}
if ((type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL)))
@@ -2849,9 +2878,8 @@ int set_var::light_check(THD *thd)
{
if (var->check_type(type))
{
- my_error(type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE,
- MYF(0),
- var->name);
+ int err= type == OPT_GLOBAL ? ER_LOCAL_VARIABLE : ER_GLOBAL_VARIABLE;
+ my_error(err, MYF(0), var->name);
return -1;
}
if (type == OPT_GLOBAL && check_global_access(thd, SUPER_ACL))
@@ -2917,7 +2945,7 @@ int set_var_user::update(THD *thd)
if (user_var_item->update())
{
/* Give an error if it's not given already */
- my_error(ER_SET_CONSTANTS_ONLY, MYF(0));
+ my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY), MYF(0));
return -1;
}
return 0;
@@ -2979,7 +3007,7 @@ bool sys_var_thd_storage_engine::check(THD *thd, set_var *var)
err:
my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), value);
- return 1;
+ return 1;
}
@@ -3117,9 +3145,9 @@ ulong fix_sql_mode(ulong sql_mode)
MODE_NO_KEY_OPTIONS | MODE_NO_TABLE_OPTIONS |
MODE_NO_FIELD_OPTIONS | MODE_NO_AUTO_CREATE_USER);
if (sql_mode & MODE_MYSQL40)
- sql_mode|= MODE_NO_FIELD_OPTIONS;
+ sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_HIGH_NOT_PRECEDENCE;
if (sql_mode & MODE_MYSQL323)
- sql_mode|= MODE_NO_FIELD_OPTIONS;
+ sql_mode|= MODE_NO_FIELD_OPTIONS | MODE_HIGH_NOT_PRECEDENCE;
if (sql_mode & MODE_TRADITIONAL)
sql_mode|= (MODE_STRICT_TRANS_TABLES | MODE_STRICT_ALL_TABLES |
MODE_NO_ZERO_IN_DATE | MODE_NO_ZERO_DATE |
diff --git a/sql/share/czech/errmsg.txt b/sql/share/czech/errmsg.txt
index e3c08eeca89..e8ea55f0739 100644
--- a/sql/share/czech/errmsg.txt
+++ b/sql/share/czech/errmsg.txt
@@ -296,7 +296,7 @@ character-set=latin2
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -399,3 +399,29 @@ character-set=latin2
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/danish/errmsg.txt b/sql/share/danish/errmsg.txt
index 78610219ade..3664e5ba0ef 100644
--- a/sql/share/danish/errmsg.txt
+++ b/sql/share/danish/errmsg.txt
@@ -287,7 +287,7 @@ character-set=latin1
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -390,3 +390,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/dutch/errmsg.txt b/sql/share/dutch/errmsg.txt
index 051a2a13ab8..cd71ddc3588 100644
--- a/sql/share/dutch/errmsg.txt
+++ b/sql/share/dutch/errmsg.txt
@@ -296,7 +296,7 @@ character-set=latin1
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -399,3 +399,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/english/errmsg.txt b/sql/share/english/errmsg.txt
index bb2a9cb59ba..3050f94936f 100644
--- a/sql/share/english/errmsg.txt
+++ b/sql/share/english/errmsg.txt
@@ -284,7 +284,7 @@ character-set=latin1
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -387,3 +387,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for %.256s",
diff --git a/sql/share/estonian/errmsg.txt b/sql/share/estonian/errmsg.txt
index 14764d764aa..58b032ceb14 100644
--- a/sql/share/estonian/errmsg.txt
+++ b/sql/share/estonian/errmsg.txt
@@ -289,7 +289,7 @@ character-set=latin7
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -392,3 +392,29 @@ character-set=latin7
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/french/errmsg.txt b/sql/share/french/errmsg.txt
index 7c3e833c903..a93a52606a9 100644
--- a/sql/share/french/errmsg.txt
+++ b/sql/share/french/errmsg.txt
@@ -209,7 +209,7 @@ character-set=latin1
"Erreur d'écriture réseau reçue du maître",
"Impossible de trouver un index FULLTEXT correspondant à cette liste de colonnes",
"Impossible d'exécuter la commande car vous avez des tables verrouillées ou une transaction active",
-"Variable système '%-.64' inconnue",
+"Variable système '%-.64s' inconnue",
"La table '%-.64s' est marquée 'crashed' et devrait être réparée",
"La table '%-.64s' est marquée 'crashed' et le dernier 'repair' a échoué",
"Attention: certaines tables ne supportant pas les transactions ont été changées et elles ne pourront pas être restituées",
@@ -284,7 +284,7 @@ character-set=latin1
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -387,3 +387,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/german/errmsg.txt b/sql/share/german/errmsg.txt
index 7cda8bef089..e657f9cb16a 100644
--- a/sql/share/german/errmsg.txt
+++ b/sql/share/german/errmsg.txt
@@ -400,3 +400,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Das Kommando %s scheiterte für %.256s",
diff --git a/sql/share/greek/errmsg.txt b/sql/share/greek/errmsg.txt
index 7b9bf7e967e..0bfcf513001 100644
--- a/sql/share/greek/errmsg.txt
+++ b/sql/share/greek/errmsg.txt
@@ -168,7 +168,7 @@ character-set=greek
"You have an error in your SQL syntax",
"Delayed insert thread couldn't get requested lock for table %-.64s",
"Too many delayed threads in use",
-"Aborted connection %ld to db: '%-.64s' user: '%-32s' (%-.64s)",
+"Aborted connection %ld to db: '%-.64s' user: '%-.32s' (%-.64s)",
"Got a packet bigger than 'max_allowed_packet' bytes",
"Got a read error from the connection pipe",
"Got an error from fcntl()",
@@ -284,7 +284,7 @@ character-set=greek
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -387,3 +387,29 @@ character-set=greek
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/hungarian/errmsg.txt b/sql/share/hungarian/errmsg.txt
index d4e5c5c744f..51338770817 100644
--- a/sql/share/hungarian/errmsg.txt
+++ b/sql/share/hungarian/errmsg.txt
@@ -289,7 +289,7 @@ character-set=latin2
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -392,3 +392,29 @@ character-set=latin2
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/italian/errmsg.txt b/sql/share/italian/errmsg.txt
index c697edb4cd7..f7f553c0eca 100644
--- a/sql/share/italian/errmsg.txt
+++ b/sql/share/italian/errmsg.txt
@@ -284,7 +284,7 @@ character-set=latin1
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -387,3 +387,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/japanese/errmsg.txt b/sql/share/japanese/errmsg.txt
index e1a32f1894b..694447caa48 100644
--- a/sql/share/japanese/errmsg.txt
+++ b/sql/share/japanese/errmsg.txt
@@ -288,7 +288,7 @@ character-set=ujis
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -391,3 +391,29 @@ character-set=ujis
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/korean/errmsg.txt b/sql/share/korean/errmsg.txt
index adb08b67474..3916b10666d 100644
--- a/sql/share/korean/errmsg.txt
+++ b/sql/share/korean/errmsg.txt
@@ -284,7 +284,7 @@ character-set=euckr
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -387,3 +387,29 @@ character-set=euckr
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/norwegian-ny/errmsg.txt b/sql/share/norwegian-ny/errmsg.txt
index 057accd3c5b..8165dc142fe 100644
--- a/sql/share/norwegian-ny/errmsg.txt
+++ b/sql/share/norwegian-ny/errmsg.txt
@@ -286,7 +286,7 @@ character-set=latin1
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -389,3 +389,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/norwegian/errmsg.txt b/sql/share/norwegian/errmsg.txt
index 5506d95592a..477c527968a 100644
--- a/sql/share/norwegian/errmsg.txt
+++ b/sql/share/norwegian/errmsg.txt
@@ -286,7 +286,7 @@ character-set=latin1
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -389,3 +389,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/polish/errmsg.txt b/sql/share/polish/errmsg.txt
index 38cefd45338..5c56730068d 100644
--- a/sql/share/polish/errmsg.txt
+++ b/sql/share/polish/errmsg.txt
@@ -289,7 +289,7 @@ character-set=latin2
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -392,3 +392,29 @@ character-set=latin2
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/portuguese/errmsg.txt b/sql/share/portuguese/errmsg.txt
index 7689db06451..2ccde22a78f 100644
--- a/sql/share/portuguese/errmsg.txt
+++ b/sql/share/portuguese/errmsg.txt
@@ -211,7 +211,7 @@ character-set=latin1
"Erro de rede gravando no 'master'",
"Não pode encontrar um índice para o texto todo que combine com a lista de colunas",
"Não pode executar o comando dado porque você tem tabelas ativas travadas ou uma transação ativa",
-"Variável de sistema '%-.64' desconhecida",
+"Variável de sistema '%-.64s' desconhecida",
"Tabela '%-.64s' está marcada como danificada e deve ser reparada",
"Tabela '%-.64s' está marcada como danificada e a última reparação (automática?) falhou",
"Aviso: Algumas tabelas não-transacionais alteradas não puderam ser reconstituídas (rolled back)",
@@ -286,7 +286,7 @@ character-set=latin1
"Dado truncado para coluna '%s' na linha %ld",
"Usando engine de armazenamento %s para tabela '%s'",
"Combinação ilegal de collations (%s,%s) e (%s,%s) para operação '%s'",
-"Não pode remover um ou mais dos usuários pedidos",
+"Cannot drop one or more of the requested users",
"Não pode revocar todos os privilégios, grant para um ou mais dos usuários pedidos",
"Ilegal combinação de collations (%s,%s), (%s,%s), (%s,%s) para operação '%s'",
"Ilegal combinação de collations para operação '%s'",
@@ -389,3 +389,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/romanian/errmsg.txt b/sql/share/romanian/errmsg.txt
index ad486367ec9..2b2f6aa45a8 100644
--- a/sql/share/romanian/errmsg.txt
+++ b/sql/share/romanian/errmsg.txt
@@ -173,7 +173,7 @@ character-set=latin2
"Aveti o eroare in sintaxa RSQL",
"Thread-ul pentru inserarea aminata nu a putut obtine lacatul (lock) pentru tabela %-.64s",
"Prea multe threaduri aminate care sint in uz",
-"Conectie terminata %ld la baza de date: '%-.64s' utilizator: '%-32s' (%-.64s)",
+"Conectie terminata %ld la baza de date: '%-.64s' utilizator: '%-.32s' (%-.64s)",
"Un packet mai mare decit 'max_allowed_packet' a fost primit",
"Eroare la citire din cauza lui 'connection pipe'",
"Eroare obtinuta de la fcntl()",
@@ -289,7 +289,7 @@ character-set=latin2
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -392,3 +392,29 @@ character-set=latin2
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/russian/errmsg.txt b/sql/share/russian/errmsg.txt
index d057ab53256..58301983b25 100644
--- a/sql/share/russian/errmsg.txt
+++ b/sql/share/russian/errmsg.txt
@@ -289,7 +289,7 @@ character-set=koi8r
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -376,7 +376,7 @@ character-set=koi8r
"View SELECT ÓÏÄÅÒÖÉÔ ÓÓÙÌËÕ ÎÁ ×ÒÅÍÅÎÎÕÀ ÔÁÂÌÉÃÕ '%-.64s'"
"View SELECT É ÓÐÉÓÏË ÐÏÌÅÊ view ÉÍÅÀÔ ÒÁÚÎÏÅ ËÏÌÉÞÅÓÔ×Ï ÓÔÏÌÂÃÏ×"
"áÌÇÏÒÉÔÍ ÓÌÉÑÎÉÑ view ÎÅ ÍÏÖÅÔ ÂÙÔØ ÉÓÐÏÌØÚÏ×ÁÎ ÓÅÊÞÁÓ (ÁÌÇÏÒÉÔÍ ÂÕÄÅÔ ÎÅÏÐÅÒÅÄÅÌÅÎÎÙÍ)"
-"ïÂÎÏ×ÌÑÅÍÙÊ view ÎÅ ÓÏÄÅÒÖÉÔ ËÌÀÞÁ ÉÓÐÏÌØÚÏ×ÁÎÎÏÊ × ÎÅÍ ÔÁÂÌÉÃ(Ù)"
+"ïÂÎÏ×ÌÑÅÍÙÊ view ÎÅ ÓÏÄÅÒÖÉÔ ËÌÀÞÁ ÉÓÐÏÌØÚÏ×ÁÎÎÙÈ(ÏÊ) × ÎÅÍ ÔÁÂÌÉÃ(Ù)"
"View '%-.64s.%-.64s' ÓÓÙÌÁÅÔÓÑ ÎÁ ÎÅÓÕÝÅÓÔ×ÕÀÝÉÅ ÔÁÂÌÉÃÙ ÉÌÉ ÓÔÏÌÂÃÙ"
"Can't drop a %s from within another stored routine"
"GOTO is not allowed in a stored procedure handler"
@@ -392,3 +392,29 @@ character-set=koi8r
"CHECK OPTION ÄÌÑ ÎÅÏÂÎÏ×ÌÑÅÍÏÇÏ VIEW '%-.64s.%-.64s'"
"ÐÒÏ×ÅÒËÁ CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÐÒÏ×ÁÌÉÌÁÓØ"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"ðÒÏ×ÅÒËÁ ËÏÎÔÒÏÌØÎÏÊ ÓÕÍÍÙ ÔÅËÓÔÁ VIEW ÐÒÏ×ÁÌÉÌÁÓØ"
+"îÅÌØÚÑ ÉÚÍÅÎÉÔØ ÂÏÌØÛÅ ÞÅÍ ÏÄÎÕ ÂÁÚÏ×ÕÀ ÔÁÂÌÉÃÕ ÉÓÐÏÌØÚÕÑ ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.64s.%-.64s'"
+"îÅÌØÚÑ ×ÓÔÁ×ÌÑÔØ ÚÁÐÉÓÉ × ÍÎÏÇÏÔÁÂÌÉÞÎÙÊ VIEW '%-.64s.%-.64s' ÂÅÚ ÓÐÉÓËÁ ÐÏÌÅÊ"
+"îÅÌØÚÑ ÕÄÁÌÑÔØ ÉÚ ÍÎÏÇÏÔÁÂÌÉÞÎÏÇÏ VIEW '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/serbian/errmsg.txt b/sql/share/serbian/errmsg.txt
index 6e38b1c3d11..a245da6b677 100644
--- a/sql/share/serbian/errmsg.txt
+++ b/sql/share/serbian/errmsg.txt
@@ -202,7 +202,7 @@ character-set=cp1250
"Greška u slanju mrežnih paketa na glavni server u klasteru",
"Ne mogu da pronaðem 'FULLTEXT' indeks koli odgovara listi kolona",
"Ne mogu da izvršim datu komandu zbog toga što su tabele zakljuèane ili je transakcija u toku",
-"Nepoznata sistemska promenljiva '%-.64'",
+"Nepoznata sistemska promenljiva '%-.64s'",
"Tabela '%-.64s' je markirana kao ošteæena i trebala bi biti popravljena",
"Tabela '%-.64s' je markirana kao ošteæena, a zadnja (automatska?) popravka je bila neuspela",
"Upozorenje: Neke izmenjene tabele ne podržavaju komandu 'ROLLBACK'",
@@ -277,7 +277,7 @@ character-set=cp1250
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -380,3 +380,29 @@ character-set=cp1250
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/slovak/errmsg.txt b/sql/share/slovak/errmsg.txt
index a9667b8ba62..69eddcfa9f6 100644
--- a/sql/share/slovak/errmsg.txt
+++ b/sql/share/slovak/errmsg.txt
@@ -292,7 +292,7 @@ character-set=latin2
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -395,3 +395,29 @@ character-set=latin2
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/spanish/errmsg.txt b/sql/share/spanish/errmsg.txt
index 17600f336c0..0eefed18088 100644
--- a/sql/share/spanish/errmsg.txt
+++ b/sql/share/spanish/errmsg.txt
@@ -238,9 +238,9 @@ character-set=latin1
"No puede adicionar clave extranjera constraint",
"No puede adicionar una línea hijo: falla de clave extranjera constraint",
"No puede deletar una línea padre: falla de clave extranjera constraint",
-"Error de coneccion a master: %-128s",
-"Error executando el query en master: %-128%",
-"Error de %s: %-128%",
+"Error de coneccion a master: %-.128s",
+"Error executando el query en master: %-.128s",
+"Error de %s: %-.128s",
"Equivocado uso de %s y %s",
"El comando SELECT usado tiene diferente número de columnas",
"No puedo ejecutar el query porque usted tiene conflicto de traba de lectura",
@@ -288,7 +288,7 @@ character-set=latin1
"Datos truncados para columna '%s' en la línea %ld",
"Usando motor de almacenamiento %s para tabla '%s'",
"Ilegal mezcla de collations (%s,%s) y (%s,%s) para operación '%s'",
-"No puede remover uno o mas de los usuarios solicitados",
+"Cannot drop one or more of the requested users",
"No puede revocar todos los privilegios, derecho para uno o mas de los usuarios solicitados",
"Ilegal mezcla de collations (%s,%s), (%s,%s), (%s,%s) para operación '%s'",
"Ilegal mezcla de collations para operación '%s'",
@@ -391,3 +391,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/swedish/errmsg.txt b/sql/share/swedish/errmsg.txt
index 8b061ac0eec..be42d3889d0 100644
--- a/sql/share/swedish/errmsg.txt
+++ b/sql/share/swedish/errmsg.txt
@@ -101,7 +101,7 @@ character-set=latin1
"Tabellen '%-.64s' har inget index som motsvarar det angivna i CREATE INDEX. Skapa om tabellen",
"Fältseparatorerna är vad som förväntades. Kontrollera mot manualen",
"Man kan inte använda fast radlängd med blobs. Använd 'fields terminated by'",
-"Textfilen '%' måste finnas i databasbiblioteket eller vara läsbar för alla",
+"Textfilen '%.64s' måste finnas i databasbiblioteket eller vara läsbar för alla",
"Filen '%-.64s' existerar redan",
"Rader: %ld Bortagna: %ld Dubletter: %ld Varningar: %ld",
"Rader: %ld Dubletter: %ld",
@@ -200,7 +200,7 @@ character-set=latin1
"Fick fel %d vid ROLLBACK",
"Fick fel %d vid FLUSH_LOGS",
"Fick fel %d vid CHECKPOINT",
-"Avbröt länken för tråd %ld till db '%-.64s', användare '%-.32s', host '%-.64s' (%.-64s)",
+"Avbröt länken för tråd %ld till db '%-.64s', användare '%-.32s', host '%-.64s' (%-.64s)",
"Tabellhanteraren klarar inte en binär kopiering av tabellen",
"Binärloggen stängdes medan FLUSH MASTER utfördes",
"Failed rebuilding the index of dumped table '%-.64s'",
@@ -284,7 +284,7 @@ character-set=latin1
"Data truncated for column '%s' at row %ld",
"Använder handler %s för tabell '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -387,3 +387,29 @@ character-set=latin1
"CHECK OPTION on non-updatable view '%-.64s.%-.64s'"
"CHECK OPTION failed '%-.64s.%-.64s'"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"View text checksum failed"
+"Can not modify more than one base table through a join view '%-.64s.%-.64s'"
+"Can not insert into join view '%-.64s.%-.64s' without fields list"
+"Can not delete from join view '%-.64s.%-.64s'"
+"Operation %s failed for '%.256s'",
diff --git a/sql/share/ukrainian/errmsg.txt b/sql/share/ukrainian/errmsg.txt
index 317b2d596fa..6d4c37803c7 100644
--- a/sql/share/ukrainian/errmsg.txt
+++ b/sql/share/ukrainian/errmsg.txt
@@ -290,7 +290,7 @@ character-set=koi8u
"Data truncated for column '%s' at row %ld",
"Using storage engine %s for table '%s'",
"Illegal mix of collations (%s,%s) and (%s,%s) for operation '%s'",
-"Can't drop one or more of the requested users",
+"Cannot drop one or more of the requested users",
"Can't revoke all privileges, grant for one or more of the requested users",
"Illegal mix of collations (%s,%s), (%s,%s), (%s,%s) for operation '%s'",
"Illegal mix of collations for operation '%s'",
@@ -391,5 +391,31 @@ character-set=koi8u
"Incorrect %-.32s value: '%-.128s' for column '%.64s' at row %ld",
"Illegal %s '%-.64s' value found during parsing",
"CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÝÏ ÎÅ ÍÏÖÅ ÂÕÔÉ ÏÎÏ×ÌÅÎÎÉÍ"
-"ÐÅÒÅצÒËÁ CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÎÅ ÐÒÏÊÛÌÁ"
+"ðÅÒÅצÒËÁ CHECK OPTION ÄÌÑ VIEW '%-.64s.%-.64s' ÎÅ ÐÒÏÊÛÌÁ"
"Access denied; you are not the procedure/function definer of '%s'"
+"Failed purging old relay logs: %s"
+"Password hash should be a %d-digit hexadecimal number"
+"Target log not found in binlog index"
+"I/O error reading log index file"
+"Server configuration does not permit binlog purge"
+"Failed on fseek()"
+"Fatal error during log purge"
+"A purgeable log is in use, will not purge"
+"Unknown error during log purge"
+"Failed initializing relay log position: %s"
+"You are not using binary logging"
+"The '%-.64s' syntax is reserved for purposes internal to the MySQL server"
+"WSAStartup Failed"
+"Can't handle procedures with differents groups yet"
+"Select must have a group with this procedure"
+"Can't use ORDER clause with this procedure"
+"Binary logging and replication forbid changing the global server %s"
+"Can't map file: %-.64s, errno: %d"
+"Wrong magic in %-.64s"
+"Prepared statement contains too many placeholders"
+"Key part '%-.64s' length cannot be 0"
+"ðÅÒÅצÒËÁ ËÏÎÔÒÏÌØÎϧ ÓÕÍÉ ÔÅËÓÔÕ VIEW ÎÅ ÐÒÏÊÛÌÁ"
+"îÅÍÏÖÌÉ×Ï ÏÎÏ×ÉÔÉ Â¦ÌØÛ ÎÉÖ ÏÄÎÕ ÂÁÚÏ×Õ ÔÁÂÌÉÃÀ ×ÙËÏÒÉÓÔÏ×ÕÀÞÉ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔ¦ÔØ ÄÅË¦ÌØËÁ ÔÁÂÌÉÃØ"
+"îÅÍÏÖÌÉ×Ï ÕÓÔÁ×ÉÔÉ ÒÑÄËÉ Õ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔÉÔØ ÄÅË¦ÌØËÁ ÔÁÂÌÉÃØ, ÂÅÚ ÓÐÉÓËÕ ÓÔÏ×Âæ×"
+"îÅÍÏÖÌÉ×Ï ×ÉÄÁÌÉÔÉ ÒÑÄËÉ Õ VIEW '%-.64s.%-.64s', ÝÏ Í¦ÓÔÉÔØ ÄÅË¦ÌØËÁ ÔÁÂÌÉÃØ"
+"Operation %s failed for '%.256s'",
diff --git a/sql/slave.cc b/sql/slave.cc
index 88dffbd8411..1e38d92ebc5 100644
--- a/sql/slave.cc
+++ b/sql/slave.cc
@@ -160,7 +160,7 @@ int init_slave()
}
if (init_master_info(active_mi,master_info_file,relay_log_info_file,
- !master_host))
+ !master_host, (SLAVE_IO | SLAVE_SQL)))
{
sql_print_error("Failed to initialize the master info structure");
goto err;
@@ -877,7 +877,7 @@ static TABLE_RULE_ENT* find_wild(DYNAMIC_ARRAY *a, const char* key, int len)
1 should be logged/replicated
*/
-int tables_ok(THD* thd, TABLE_LIST* tables)
+bool tables_ok(THD* thd, TABLE_LIST* tables)
{
bool some_tables_updating= 0;
DBUG_ENTER("tables_ok");
@@ -1150,7 +1150,7 @@ bool net_request_file(NET* net, const char* fname)
}
-const char *rewrite_db(const char* db)
+const char *rewrite_db(const char* db, uint32 *new_len)
{
if (replicate_rewrite_db.is_empty() || !db)
return db;
@@ -1160,7 +1160,10 @@ const char *rewrite_db(const char* db)
while ((tmp=it++))
{
if (!strcmp(tmp->key, db))
+ {
+ *new_len= (uint32)strlen(tmp->val);
return tmp->val;
+ }
}
return db;
}
@@ -1174,7 +1177,7 @@ const char *rewrite_db(const char* db)
const char *print_slave_db_safe(const char* db)
{
- return (db ? rewrite_db(db) : "");
+ return (db ? db : "");
}
/*
@@ -1490,7 +1493,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
packet_len= my_net_read(net); // read create table statement
if (packet_len == packet_error)
{
- send_error(thd, ER_MASTER_NET_READ);
+ my_message(ER_MASTER_NET_READ, ER(ER_MASTER_NET_READ), MYF(0));
DBUG_RETURN(1);
}
if (net->read_pos[0] == 255) // error from master
@@ -1499,7 +1502,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
err_msg= (char*) net->read_pos + ((mysql->server_capabilities &
CLIENT_PROTOCOL_41) ?
3+SQLSTATE_LENGTH+1 : 3);
- net_printf(thd, ER_MASTER, err_msg);
+ my_error(ER_MASTER, MYF(0), err_msg);
DBUG_RETURN(1);
}
thd->command = COM_TABLE_DUMP;
@@ -1508,7 +1511,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
if (!(query = thd->strmake((char*) net->read_pos, packet_len)))
{
sql_print_error("create_table_from_dump: out of memory");
- net_printf(thd, ER_GET_ERRNO, "Out of memory");
+ my_message(ER_GET_ERRNO, "Out of memory", MYF(0));
DBUG_RETURN(1);
}
thd->query= query;
@@ -1522,7 +1525,6 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
/* Drop the table if 'overwrite' is true */
if (overwrite && mysql_rm_table(thd,&tables,1,0)) /* drop if exists */
{
- send_error(thd);
sql_print_error("create_table_from_dump: failed to drop the table");
goto err;
}
@@ -1549,7 +1551,6 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
tables.lock_type = TL_WRITE;
if (!open_ltable(thd, &tables, TL_WRITE))
{
- send_error(thd,0,0); // Send error from open_ltable
sql_print_error("create_table_from_dump: could not open created table");
goto err;
}
@@ -1559,7 +1560,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
/* Copy the data file */
if (file->net_read_dump(net))
{
- net_printf(thd, ER_MASTER_NET_READ);
+ my_message(ER_MASTER_NET_READ, ER(ER_MASTER_NET_READ), MYF(0));
sql_print_error("create_table_from_dump: failed in\
handler::net_read_dump()");
goto err;
@@ -1579,7 +1580,7 @@ static int create_table_from_dump(THD* thd, MYSQL *mysql, const char* db,
error=file->repair(thd,&check_opt) != 0;
thd->net.vio = save_vio;
if (error)
- net_printf(thd, ER_INDEX_REBUILD,tables.table->real_name);
+ my_error(ER_INDEX_REBUILD, MYF(0), tables.table->real_name);
err:
close_thread_tables(thd);
@@ -1602,12 +1603,11 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
{
if (!(mysql = mysql_init(NULL)))
{
- send_error(thd); // EOM
DBUG_RETURN(1);
}
if (connect_to_master(thd, mysql, mi))
{
- net_printf(thd, ER_CONNECT_TO_MASTER, mysql_error(mysql));
+ my_error(ER_CONNECT_TO_MASTER, MYF(0), mysql_error(mysql));
mysql_close(mysql);
DBUG_RETURN(1);
}
@@ -1631,7 +1631,7 @@ int fetch_master_table(THD *thd, const char *db_name, const char *table_name,
if (!called_connected)
mysql_close(mysql);
if (errmsg && thd->vio_ok())
- send_error(thd, error, errmsg);
+ my_message(error, errmsg, MYF(0));
DBUG_RETURN(test(error)); // Return 1 on error
}
@@ -1981,7 +1981,8 @@ void clear_until_condition(RELAY_LOG_INFO* rli)
int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
const char* slave_info_fname,
- bool abort_if_no_master_info_file)
+ bool abort_if_no_master_info_file,
+ int thread_mask)
{
int fd,error;
char fname[FN_REFLEN+128];
@@ -1995,8 +1996,16 @@ int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
last time. If this case pos_in_file would be set and we would
get a crash when trying to read the signature for the binary
relay log.
+
+ We only rewind the read position if we are starting the SQL
+ thread. The handle_slave_sql thread assumes that the read
+ position is at the beginning of the file, and will read the
+ "signature" and then fast-forward to the last position read.
*/
- my_b_seek(mi->rli.cur_log, (my_off_t) 0);
+ if (thread_mask & SLAVE_SQL)
+ {
+ my_b_seek(mi->rli.cur_log, (my_off_t) 0);
+ }
DBUG_RETURN(0);
}
@@ -2268,7 +2277,7 @@ void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a)
}
}
-int show_master_info(THD* thd, MASTER_INFO* mi)
+bool show_master_info(THD* thd, MASTER_INFO* mi)
{
// TODO: fix this for multi-master
List<Item> field_list;
@@ -2332,7 +2341,7 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
if (mi->host[0])
{
@@ -2431,10 +2440,10 @@ int show_master_info(THD* thd, MASTER_INFO* mi)
pthread_mutex_unlock(&mi->data_lock);
if (my_net_write(&thd->net, (char*)thd->packet.ptr(), packet->length()))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -2829,7 +2838,7 @@ static int request_dump(MYSQL* mysql, MASTER_INFO* mi,
DBUG_ENTER("request_dump");
// TODO if big log files: Change next to int8store()
- int4store(buf, (longlong) mi->master_log_pos);
+ int4store(buf, (ulong) mi->master_log_pos);
int2store(buf + 4, binlog_flags);
int4store(buf + 6, server_id);
len = (uint) strlen(logname);
diff --git a/sql/slave.h b/sql/slave.h
index 2a9b96b75a1..69d3dc38e78 100644
--- a/sql/slave.h
+++ b/sql/slave.h
@@ -490,11 +490,11 @@ int fetch_master_table(THD* thd, const char* db_name, const char* table_name,
void table_rule_ent_hash_to_str(String* s, HASH* h);
void table_rule_ent_dynamic_array_to_str(String* s, DYNAMIC_ARRAY* a);
-int show_master_info(THD* thd, MASTER_INFO* mi);
-int show_binlog_info(THD* thd);
+bool show_master_info(THD* thd, MASTER_INFO* mi);
+bool show_binlog_info(THD* thd);
/* See if the query uses any tables that should not be replicated */
-int tables_ok(THD* thd, TABLE_LIST* tables);
+bool tables_ok(THD* thd, TABLE_LIST* tables);
/*
Check to see if the database is ok to operate on with respect to the
@@ -508,8 +508,8 @@ int add_table_rule(HASH* h, const char* table_spec);
int add_wild_table_rule(DYNAMIC_ARRAY* a, const char* table_spec);
void init_table_rule_hash(HASH* h, bool* h_inited);
void init_table_rule_array(DYNAMIC_ARRAY* a, bool* a_inited);
-const char *rewrite_db(const char* db);
-const char *print_slave_db_safe(const char* db);
+const char *rewrite_db(const char* db, uint32 *new_db_len);
+const char *print_slave_db_safe(const char *db);
int check_expected_error(THD* thd, RELAY_LOG_INFO* rli, int error_code);
void skip_load_data_infile(NET* net);
void slave_print_error(RELAY_LOG_INFO* rli, int err_code, const char* msg, ...);
@@ -520,7 +520,8 @@ void clear_until_condition(RELAY_LOG_INFO* rli);
void clear_slave_error_timestamp(RELAY_LOG_INFO* rli);
int init_master_info(MASTER_INFO* mi, const char* master_info_fname,
const char* slave_info_fname,
- bool abort_if_no_master_info_file);
+ bool abort_if_no_master_info_file,
+ int thread_mask);
void end_master_info(MASTER_INFO* mi);
int init_relay_log_info(RELAY_LOG_INFO* rli, const char* info_fname);
void end_relay_log_info(RELAY_LOG_INFO* rli);
diff --git a/sql/sp.cc b/sql/sp.cc
index a1e52ee1ca7..9eff1655711 100644
--- a/sql/sp.cc
+++ b/sql/sp.cc
@@ -166,7 +166,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
}
bzero((char *)&chistics, sizeof(chistics));
- if ((ptr= get_field(&thd->mem_root,
+ if ((ptr= get_field(thd->mem_root,
table->field[MYSQL_PROC_FIELD_ACCESS])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
@@ -189,7 +189,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
chistics.daccess= SP_CONTAINS_SQL;
}
- if ((ptr= get_field(&thd->mem_root,
+ if ((ptr= get_field(thd->mem_root,
table->field[MYSQL_PROC_FIELD_DETERMINISTIC])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
@@ -197,7 +197,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
}
chistics.detistic= (ptr[0] == 'N' ? FALSE : TRUE);
- if ((ptr= get_field(&thd->mem_root,
+ if ((ptr= get_field(thd->mem_root,
table->field[MYSQL_PROC_FIELD_SECURITY_TYPE])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
@@ -205,7 +205,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
}
chistics.suid= (ptr[0] == 'I' ? SP_IS_NOT_SUID : SP_IS_SUID);
- if ((params= get_field(&thd->mem_root,
+ if ((params= get_field(thd->mem_root,
table->field[MYSQL_PROC_FIELD_PARAM_LIST])) == NULL)
{
params= "";
@@ -213,14 +213,14 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
if (type == TYPE_ENUM_PROCEDURE)
returns= "";
- else if ((returns= get_field(&thd->mem_root,
+ else if ((returns= get_field(thd->mem_root,
table->field[MYSQL_PROC_FIELD_RETURNS])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
goto done;
}
- if ((body= get_field(&thd->mem_root,
+ if ((body= get_field(thd->mem_root,
table->field[MYSQL_PROC_FIELD_BODY])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
@@ -228,7 +228,7 @@ db_find_routine(THD *thd, int type, sp_name *name, sp_head **sphp)
}
// Get additional information
- if ((definer= get_field(&thd->mem_root,
+ if ((definer= get_field(thd->mem_root,
table->field[MYSQL_PROC_FIELD_DEFINER])) == NULL)
{
ret= SP_GET_FIELD_FAILED;
@@ -511,10 +511,10 @@ print_field_values(THD *thd, TABLE *table,
String name_string;
struct st_used_field *used_field= used_fields;
- if (get_field(&thd->mem_root, used_field->field, &db_string))
+ if (get_field(thd->mem_root, used_field->field, &db_string))
db_string.set_ascii("", 0);
used_field+= 1;
- get_field(&thd->mem_root, used_field->field, &name_string);
+ get_field(thd->mem_root, used_field->field, &name_string);
if (!wild || !wild[0] || !wild_compare(name_string.ptr(), wild, 0))
{
@@ -539,7 +539,7 @@ print_field_values(THD *thd, TABLE *table,
{
String tmp_string;
- get_field(&thd->mem_root, used_field->field, &tmp_string);
+ get_field(thd->mem_root, used_field->field, &tmp_string);
protocol->store(&tmp_string);
}
break;
@@ -575,6 +575,7 @@ db_show_routine_status(THD *thd, int type, const char *wild)
Item *item;
List<Item> field_list;
struct st_used_field *used_field;
+ TABLE_LIST *leaves= 0;
st_used_field used_fields[array_elements(init_fields)];
memcpy((char*) used_fields, (char*) init_fields, sizeof(used_fields));
@@ -607,7 +608,7 @@ db_show_routine_status(THD *thd, int type, const char *wild)
tables is not VIEW for sure => we can pass 0 as condition
*/
- setup_tables(thd, &tables, 0);
+ setup_tables(thd, &tables, 0, &leaves, FALSE, FALSE);
for (used_field= &used_fields[0];
used_field->field_name;
used_field++)
@@ -615,7 +616,7 @@ db_show_routine_status(THD *thd, int type, const char *wild)
Item_field *field= new Item_field("mysql", "proc",
used_field->field_name);
if (!(used_field->field= find_field_in_tables(thd, field, &tables,
- 0, TRUE, 1)))
+ 0, REPORT_ALL_ERRORS, 1)))
{
res= SP_INTERNAL_ERROR;
goto err_case1;
@@ -982,7 +983,7 @@ sp_cache_functions(THD *thd, LEX *lex)
newlex->proc_table= oldlex->proc_table; // hint if mysql.oper is opened
name.m_name.str= strchr(name.m_qname.str, '.');
name.m_db.length= name.m_name.str - name.m_qname.str;
- name.m_db.str= strmake_root(&thd->mem_root,
+ name.m_db.str= strmake_root(thd->mem_root,
name.m_qname.str, name.m_db.length);
name.m_name.str+= 1;
name.m_name.length= name.m_qname.length - name.m_db.length - 1;
@@ -1001,7 +1002,7 @@ sp_cache_functions(THD *thd, LEX *lex)
{
delete newlex;
thd->lex= oldlex;
- net_printf(thd, ER_SP_DOES_NOT_EXIST, "FUNCTION", ls->str);
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "FUNCTION", ls->str);
ret= 1;
break;
}
@@ -1153,7 +1154,6 @@ sp_change_db(THD *thd, char *name, bool no_access_check)
int length, db_length;
char *dbname=my_strdup((char*) name,MYF(MY_WME));
char path[FN_REFLEN];
- ulong db_access;
HA_CREATE_INFO create;
DBUG_ENTER("sp_change_db");
DBUG_PRINT("enter", ("db: %s, no_access_check: %d", name, no_access_check));
@@ -1163,7 +1163,7 @@ sp_change_db(THD *thd, char *name, bool no_access_check)
{
if ((db_length > NAME_LEN) || check_db_name(dbname))
{
- my_printf_error(ER_WRONG_DB_NAME, ER(ER_WRONG_DB_NAME), MYF(0), dbname);
+ my_error(ER_WRONG_DB_NAME, MYF(0), dbname);
x_free(dbname);
DBUG_RETURN(1);
}
@@ -1174,6 +1174,8 @@ sp_change_db(THD *thd, char *name, bool no_access_check)
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (! no_access_check)
{
+ ulong db_access;
+
if (test_all_bits(thd->master_access,DB_ACLS))
db_access=DB_ACLS;
else
@@ -1182,11 +1184,10 @@ sp_change_db(THD *thd, char *name, bool no_access_check)
if (!(db_access & DB_ACLS) &&
(!grant_option || check_grant_db(thd,dbname)))
{
- my_printf_error(ER_DBACCESS_DENIED_ERROR, ER(ER_DBACCESS_DENIED_ERROR),
- MYF(0),
- thd->priv_user,
- thd->priv_host,
- dbname);
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user,
+ thd->priv_host,
+ dbname);
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
thd->priv_user,
thd->priv_host,
@@ -1202,7 +1203,7 @@ sp_change_db(THD *thd, char *name, bool no_access_check)
path[length-1]=0; // remove ending '\'
if (access(path,F_OK))
{
- my_printf_error(ER_BAD_DB_ERROR, ER(ER_BAD_DB_ERROR), MYF(0), dbname);
+ my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
my_free(dbname,MYF(0));
DBUG_RETURN(1);
}
diff --git a/sql/sp_head.cc b/sql/sp_head.cc
index 8de1b6e906a..114ff0d451a 100644
--- a/sql/sp_head.cc
+++ b/sql/sp_head.cc
@@ -134,7 +134,7 @@ sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type)
}
case REAL_RESULT:
{
- double d= it->val();
+ double d= it->val_real();
if (it->null_value)
{
@@ -148,7 +148,7 @@ sp_eval_func_item(THD *thd, Item *it, enum enum_field_types type)
uint8 decimals= it->decimals;
uint32 max_length= it->max_length;
DBUG_PRINT("info", ("REAL_RESULT: %g", d));
- it= new Item_real(it->val());
+ it= new Item_real(it->val_real());
it->decimals= decimals;
it->max_length= max_length;
}
@@ -190,7 +190,7 @@ void
sp_name::init_qname(THD *thd)
{
m_qname.length= m_db.length+m_name.length+1;
- m_qname.str= alloc_root(&thd->mem_root, m_qname.length+1);
+ m_qname.str= thd->alloc(m_qname.length+1);
sprintf(m_qname.str, "%*s.%*s",
m_db.length, (m_db.length ? m_db.str : ""),
m_name.length, m_name.str);
@@ -232,10 +232,9 @@ sp_head::operator new(size_t size)
MEM_ROOT own_root;
sp_head *sp;
- bzero((char *)&own_root, sizeof(own_root));
init_alloc_root(&own_root, MEM_ROOT_BLOCK_SIZE, MEM_ROOT_PREALLOC);
- sp= (sp_head *)alloc_root(&own_root, size);
- sp->mem_root= own_root;
+ sp= (sp_head *) alloc_root(&own_root, size);
+ sp->main_mem_root= own_root;
DBUG_PRINT("info", ("mem_root 0x%lx", (ulong) &sp->mem_root));
DBUG_RETURN(sp);
}
@@ -245,9 +244,10 @@ sp_head::operator delete(void *ptr, size_t size)
{
DBUG_ENTER("sp_head::operator delete");
MEM_ROOT own_root;
- sp_head *sp= (sp_head *)ptr;
+ sp_head *sp= (sp_head *) ptr;
- memcpy(&own_root, (const void *)&sp->mem_root, sizeof(MEM_ROOT));
+ /* Make a copy of main_mem_root as free_root will free the sp */
+ own_root= sp->main_mem_root;
DBUG_PRINT("info", ("mem_root 0x%lx moved to 0x%lx",
(ulong) &sp->mem_root, (ulong) &own_root));
free_root(&own_root, MYF(0));
@@ -275,6 +275,11 @@ sp_head::init(LEX *lex)
DBUG_ENTER("sp_head::init");
lex->spcont= m_pcont= new sp_pcontext(NULL);
+ /*
+ Altough trg_table_fields list is used only in triggers we init for all
+ types of stored procedures to simplify reset_lex()/restore_lex() code.
+ */
+ lex->trg_table_fields.empty();
my_init_dynamic_array(&m_instr, sizeof(sp_instr *), 16, 8);
m_param_begin= m_param_end= m_returns_begin= m_returns_end= m_body_begin= 0;
m_qname.str= m_db.str= m_name.str= m_params.str= m_retstr.str=
@@ -291,7 +296,7 @@ sp_head::init_strings(THD *thd, LEX *lex, sp_name *name)
DBUG_ENTER("sp_head::init_strings");
uint n; /* Counter for nul trimming */
/* During parsing, we must use thd->mem_root */
- MEM_ROOT *root= &thd->mem_root;
+ MEM_ROOT *root= thd->mem_root;
/* We have to copy strings to get them into the right memroot */
if (name)
@@ -494,16 +499,17 @@ sp_head::execute(THD *thd)
case SP_HANDLER_CONTINUE:
ctx->save_variables(hf);
ctx->push_hstack(ip);
- // Fall through
+ // Fall through
default:
ip= hip;
ret= 0;
ctx->clear_handler();
ctx->in_handler= TRUE;
+ thd->clear_error();
continue;
}
}
- } while (ret == 0 && !thd->killed && !thd->query_error);
+ } while (ret == 0 && !thd->killed);
cleanup_items(thd->current_arena->free_list);
thd->current_arena= old_arena;
@@ -512,7 +518,7 @@ sp_head::execute(THD *thd)
DBUG_PRINT("info", ("ret=%d killed=%d query_error=%d",
ret, thd->killed, thd->query_error));
- if (thd->killed || thd->query_error)
+ if (thd->killed)
ret= -1;
/* If the DB has changed, the pointer has changed too, but the
original thd->db will then have been freed */
@@ -543,8 +549,8 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
{
// Need to use my_printf_error here, or it will not terminate the
// invoking query properly.
- my_printf_error(ER_SP_WRONG_NO_OF_ARGS, ER(ER_SP_WRONG_NO_OF_ARGS), MYF(0),
- "FUNCTION", m_name.str, params, argcount);
+ my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0),
+ "FUNCTION", m_name.str, params, argcount);
DBUG_RETURN(-1);
}
@@ -595,8 +601,7 @@ sp_head::execute_function(THD *thd, Item **argp, uint argcount, Item **resp)
*resp= it;
else
{
- my_printf_error(ER_SP_NORETURNEND, ER(ER_SP_NORETURNEND), MYF(0),
- m_name.str);
+ my_error(ER_SP_NORETURNEND, MYF(0), m_name.str);
ret= -1;
}
}
@@ -622,8 +627,8 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (args->elements != params)
{
- net_printf(thd, ER_SP_WRONG_NO_OF_ARGS, "PROCEDURE", m_name.str,
- params, args->elements);
+ my_error(ER_SP_WRONG_NO_OF_ARGS, MYF(0), "PROCEDURE",
+ m_name.str, params, args->elements);
DBUG_RETURN(-1);
}
@@ -694,13 +699,7 @@ sp_head::execute_procedure(THD *thd, List<Item> *args)
if (! ret)
ret= execute(thd);
- // Don't copy back OUT values if we got an error
- if (ret)
- {
- if (thd->net.report_error)
- send_error(thd, 0, NullS);
- }
- else if (csize > 0)
+ if (!ret && csize > 0)
{
List_iterator_fast<Item> li(*args);
Item *it;
@@ -777,7 +776,7 @@ sp_head::reset_lex(THD *thd)
sublex->spcont= oldlex->spcont;
/* And trigger related stuff too */
sublex->trg_chistics= oldlex->trg_chistics;
- sublex->trg_table= oldlex->trg_table;
+ sublex->trg_table_fields.empty();
sublex->sp_lex_in_use= FALSE;
DBUG_VOID_RETURN;
}
@@ -796,6 +795,7 @@ sp_head::restore_lex(THD *thd)
// Update some state in the old one first
oldlex->ptr= sublex->ptr;
oldlex->next_state= sublex->next_state;
+ oldlex->trg_table_fields.push_back(&sublex->trg_table_fields);
// Collect some data from the sub statement lex.
sp_merge_funs(oldlex, sublex);
@@ -898,7 +898,7 @@ sp_head::check_backpatch(THD *thd)
{
if (bp->lab->type == SP_LAB_REF)
{
- net_printf(thd, ER_SP_LILABEL_MISMATCH, "GOTO", bp->lab->name);
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "GOTO", bp->lab->name);
return -1;
}
}
@@ -916,19 +916,19 @@ sp_head::set_info(char *definer, uint definerlen,
if (! p)
p= definer; // Weird...
len= p-definer;
- m_definer_user.str= strmake_root(&mem_root, definer, len);
+ m_definer_user.str= strmake_root(mem_root, definer, len);
m_definer_user.length= len;
len= definerlen-len-1;
- m_definer_host.str= strmake_root(&mem_root, p+1, len);
+ m_definer_host.str= strmake_root(mem_root, p+1, len);
m_definer_host.length= len;
m_created= created;
m_modified= modified;
- m_chistics= (st_sp_chistics *)alloc_root(&mem_root, sizeof(st_sp_chistics));
- memcpy(m_chistics, chistics, sizeof(st_sp_chistics));
+ 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= strmake_root(mem_root,
m_chistics->comment.str,
m_chistics->comment.length);
m_sql_mode= sql_mode;
@@ -939,14 +939,14 @@ sp_head::reset_thd_mem_root(THD *thd)
{
DBUG_ENTER("sp_head::reset_thd_mem_root");
m_thd_root= thd->mem_root;
- thd->mem_root= mem_root;
+ thd->mem_root= &main_mem_root;
DBUG_PRINT("info", ("mem_root 0x%lx moved to thd mem root 0x%lx",
(ulong) &mem_root, (ulong) &thd->mem_root));
free_list= thd->free_list; // Keep the old list
thd->free_list= NULL; // Start a new one
/* Copy the db, since substatements will point to it */
m_thd_db= thd->db;
- thd->db= strmake_root(&thd->mem_root, thd->db, thd->db_length);
+ thd->db= thd->strmake(thd->db, thd->db_length);
m_thd= thd;
DBUG_VOID_RETURN;
}
@@ -1791,7 +1791,7 @@ sp_instr_error::execute(THD *thd, uint *nextp)
{
DBUG_ENTER("sp_instr_error::execute");
- my_error(m_errcode, MYF(0));
+ my_message(m_errcode, ER(m_errcode), MYF(0));
*nextp= m_ip+1;
DBUG_RETURN(-1);
}
diff --git a/sql/sp_head.h b/sql/sp_head.h
index 6aa05838291..c4d2068661c 100644
--- a/sql/sp_head.h
+++ b/sql/sp_head.h
@@ -231,7 +231,7 @@ public:
private:
- MEM_ROOT m_thd_root; // Temp. store for thd's mem_root
+ MEM_ROOT *m_thd_root; // Temp. store for thd's mem_root
THD *m_thd; // Set if we have reset mem_root
char *m_thd_db; // Original thd->db pointer
@@ -439,13 +439,9 @@ public:
virtual void print(String *str);
- bool setup_field(THD *thd, TABLE *table, enum trg_event_type event)
- {
- return trigger_field.setup_field(thd, table, event);
- }
-private:
-
Item_trigger_field trigger_field;
+
+private:
Item *value;
}; // class sp_instr_trigger_field : public sp_instr
diff --git a/sql/sp_pcontext.h b/sql/sp_pcontext.h
index 36e4ed06aa7..66f631f4938 100644
--- a/sql/sp_pcontext.h
+++ b/sql/sp_pcontext.h
@@ -50,7 +50,7 @@ typedef struct sp_label
char *name;
uint ip; // Instruction index
int type; // begin/iter or ref/free
- struct sp_pcontext *ctx; // The label's context
+ sp_pcontext *ctx; // The label's context
} sp_label_t;
typedef struct sp_cond_type
diff --git a/sql/sp_rcontext.cc b/sql/sp_rcontext.cc
index 51a1bb2e550..609882b84c6 100644
--- a/sql/sp_rcontext.cc
+++ b/sql/sp_rcontext.cc
@@ -153,7 +153,8 @@ sp_cursor::pre_open(THD *thd)
{
if (m_isopen)
{
- send_error(thd, ER_SP_CURSOR_ALREADY_OPEN);
+ my_message(ER_SP_CURSOR_ALREADY_OPEN, ER(ER_SP_CURSOR_ALREADY_OPEN),
+ MYF(0));
return NULL;
}
@@ -187,7 +188,7 @@ sp_cursor::close(THD *thd)
{
if (! m_isopen)
{
- send_error(thd, ER_SP_CURSOR_NOT_OPEN);
+ my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
return -1;
}
destroy();
@@ -217,12 +218,12 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
if (! m_isopen)
{
- send_error(thd, ER_SP_CURSOR_NOT_OPEN);
+ my_message(ER_SP_CURSOR_NOT_OPEN, ER(ER_SP_CURSOR_NOT_OPEN), MYF(0));
return -1;
}
if (m_current_row == NULL)
{
- send_error(thd, ER_SP_FETCH_NO_DATA);
+ my_message(ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA), MYF(0));
return -1;
}
@@ -234,7 +235,8 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
if (fldcount >= m_prot->get_field_count())
{
- send_error(thd, ER_SP_WRONG_NO_OF_FETCH_ARGS);
+ my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
+ ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
return -1;
}
s= row[fldcount];
@@ -260,7 +262,8 @@ sp_cursor::fetch(THD *thd, List<struct sp_pvar> *vars)
}
if (fldcount < m_prot->get_field_count())
{
- send_error(thd, ER_SP_WRONG_NO_OF_FETCH_ARGS);
+ my_message(ER_SP_WRONG_NO_OF_FETCH_ARGS,
+ ER(ER_SP_WRONG_NO_OF_FETCH_ARGS), MYF(0));
return -1;
}
m_current_row= m_current_row->next;
diff --git a/sql/spatial.cc b/sql/spatial.cc
index 0668dd2faab..bcfefd9dde8 100644
--- a/sql/spatial.cc
+++ b/sql/spatial.cc
@@ -828,9 +828,7 @@ int Gis_polygon::centroid_xy(double *x, double *y) const
if (!first_loop)
{
- double d_area= res_area - cur_area;
- if (d_area <= 0)
- return 1;
+ double d_area= fabs(res_area - cur_area);
res_cx= (res_area * res_cx - cur_area * cur_cx) / d_area;
res_cy= (res_area * res_cy - cur_area * cur_cy) / d_area;
}
diff --git a/sql/sql_acl.cc b/sql/sql_acl.cc
index bed3130462d..8be915b89e2 100644
--- a/sql/sql_acl.cc
+++ b/sql/sql_acl.cc
@@ -446,7 +446,8 @@ void acl_free(bool end)
SYNOPSIS
acl_reload()
- thd Thread handle
+ thd Thread handle. Note that this may be NULL if we refresh
+ because we got a signal
*/
void acl_reload(THD *thd)
@@ -919,7 +920,7 @@ static void acl_update_user(const char *user, const char *host,
{
if (!acl_user->host.hostname && !host[0] ||
acl_user->host.hostname &&
- !my_strcasecmp(&my_charset_latin1, host, acl_user->host.hostname))
+ !my_strcasecmp(system_charset_info, host, acl_user->host.hostname))
{
acl_user->access=privileges;
if (mqh->bits & 1)
@@ -998,7 +999,7 @@ static void acl_update_db(const char *user, const char *host, const char *db,
{
if (!acl_db->host.hostname && !host[0] ||
acl_db->host.hostname &&
- !my_strcasecmp(&my_charset_latin1, host, acl_db->host.hostname))
+ !my_strcasecmp(system_charset_info, host, acl_db->host.hostname))
{
if (!acl_db->db && !db[0] ||
acl_db->db && !strcmp(db,acl_db->db))
@@ -1052,11 +1053,11 @@ static void acl_insert_db(const char *user, const char *host, const char *db,
ulong acl_get(const char *host, const char *ip,
const char *user, const char *db, my_bool db_is_pattern)
{
- ulong host_access,db_access;
+ ulong host_access= ~0, db_access= 0;
uint i,key_length;
- db_access=0; host_access= ~0;
char key[ACL_KEY_LENGTH],*tmp_db,*end;
acl_entry *entry;
+ DBUG_ENTER("acl_get");
VOID(pthread_mutex_lock(&acl_cache->lock));
end=strmov((tmp_db=strmov(strmov(key, ip ? ip : "")+1,user)+1),db);
@@ -1070,7 +1071,8 @@ ulong acl_get(const char *host, const char *ip,
{
db_access=entry->access;
VOID(pthread_mutex_unlock(&acl_cache->lock));
- return db_access;
+ DBUG_PRINT("exit", ("access: 0x%lx", db_access));
+ DBUG_RETURN(db_access);
}
/*
@@ -1122,7 +1124,8 @@ exit:
acl_cache->add(entry);
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
- return (db_access & host_access);
+ DBUG_PRINT("exit", ("access: 0x%lx", db_access & host_access));
+ DBUG_RETURN(db_access & host_access);
}
/*
@@ -1138,7 +1141,7 @@ static void init_check_host(void)
DBUG_ENTER("init_check_host");
VOID(my_init_dynamic_array(&acl_wild_hosts,sizeof(struct acl_host_and_ip),
acl_users.elements,1));
- VOID(hash_init(&acl_check_hosts,&my_charset_latin1,acl_users.elements,0,0,
+ VOID(hash_init(&acl_check_hosts,system_charset_info,acl_users.elements,0,0,
(hash_get_key) check_get_key,0,0));
if (!allow_all_hosts)
{
@@ -1154,7 +1157,7 @@ static void init_check_host(void)
{ // Check if host already exists
acl_host_and_ip *acl=dynamic_element(&acl_wild_hosts,j,
acl_host_and_ip *);
- if (!my_strcasecmp(&my_charset_latin1,
+ if (!my_strcasecmp(system_charset_info,
acl_user->host.hostname, acl->hostname))
break; // already stored
}
@@ -1225,29 +1228,27 @@ bool check_change_password(THD *thd, const char *host, const char *user,
{
if (!initialized)
{
- net_printf(thd,ER_OPTION_PREVENTS_STATEMENT,
- "--skip-grant-tables");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
return(1);
}
if (!thd->slave_thread &&
(strcmp(thd->user,user) ||
- my_strcasecmp(&my_charset_latin1, host, thd->host_or_ip)))
+ my_strcasecmp(system_charset_info, host, thd->host_or_ip)))
{
if (check_access(thd, UPDATE_ACL, "mysql",0,1,0))
return(1);
}
if (!thd->slave_thread && !thd->user[0])
{
- send_error(thd, ER_PASSWORD_ANONYMOUS_USER);
+ my_message(ER_PASSWORD_ANONYMOUS_USER, ER(ER_PASSWORD_ANONYMOUS_USER),
+ MYF(0));
return(1);
}
uint len=strlen(new_password);
if (len && len != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
len != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{
- net_printf(thd, 0,
- "Password hash should be a %d-digit hexadecimal number",
- SCRAMBLED_PASSWORD_CHAR_LENGTH);
+ my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
return -1;
}
return(0);
@@ -1285,7 +1286,7 @@ bool change_password(THD *thd, const char *host, const char *user,
if (!(acl_user= find_acl_user(host, user)))
{
VOID(pthread_mutex_unlock(&acl_cache->lock));
- send_error(thd, ER_PASSWORD_NO_MATCH);
+ my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0));
DBUG_RETURN(1);
}
/* update loaded acl entry: */
@@ -1298,7 +1299,6 @@ bool change_password(THD *thd, const char *host, const char *user,
new_password, new_password_len))
{
VOID(pthread_mutex_unlock(&acl_cache->lock)); /* purecov: deadcode */
- send_error(thd,0); /* purecov: deadcode */
DBUG_RETURN(1); /* purecov: deadcode */
}
@@ -1313,7 +1313,7 @@ bool change_password(THD *thd, const char *host, const char *user,
acl_user->host.hostname ? acl_user->host.hostname : "",
new_password));
thd->clear_error();
- Query_log_event qinfo(thd, buff, query_length, 0);
+ Query_log_event qinfo(thd, buff, query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
DBUG_RETURN(0);
}
@@ -1402,7 +1402,7 @@ static bool compare_hostname(const acl_host_and_ip *host, const char *hostname,
return (tmp & host->ip_mask) == host->ip;
}
return (!host->hostname ||
- (hostname && !wild_case_compare(&my_charset_latin1,
+ (hostname && !wild_case_compare(system_charset_info,
hostname,host->hostname)) ||
(ip && !wild_compare(ip,host->hostname,0)));
}
@@ -1415,7 +1415,7 @@ bool hostname_requires_resolving(const char *hostname)
int namelen= strlen(hostname);
int lhlen= strlen(my_localhost);
if ((namelen == lhlen) &&
- !my_strnncoll(&my_charset_latin1, (const uchar *)hostname, namelen,
+ !my_strnncoll(system_charset_info, (const uchar *)hostname, namelen,
(const uchar *)my_localhost, strlen(my_localhost)))
return FALSE;
for (; (cur=*hostname); hostname++)
@@ -1437,6 +1437,7 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
TABLE_LIST tables;
TABLE *table;
bool error=1;
+ char user_key[MAX_KEY_LENGTH];
DBUG_ENTER("update_user_table");
DBUG_PRINT("enter",("user: %s host: %s",user,host));
@@ -1464,18 +1465,22 @@ static bool update_user_table(THD *thd, const char *host, const char *user,
if (!(table=open_ltable(thd,&tables,TL_WRITE)))
DBUG_RETURN(1); /* purecov: deadcode */
- table->field[0]->store(host,(uint) strlen(host), &my_charset_latin1);
- table->field[1]->store(user,(uint) strlen(user), &my_charset_latin1);
+ table->field[0]->store(host,(uint) strlen(host), system_charset_info);
+ table->field[1]->store(user,(uint) strlen(user), system_charset_info);
+ key_copy(user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
- if (table->file->index_read_idx(table->record[0],0,
- (byte*) table->field[0]->ptr,0,
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ if (table->file->index_read_idx(table->record[0], 0,
+ user_key, table->key_info->key_length,
HA_READ_KEY_EXACT))
{
- my_error(ER_PASSWORD_NO_MATCH,MYF(0)); /* purecov: deadcode */
+ my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH),
+ MYF(0)); /* purecov: deadcode */
DBUG_RETURN(1); /* purecov: deadcode */
}
store_record(table,record[1]);
- table->field[2]->store(new_password, new_password_len, &my_charset_latin1);
+ table->field[2]->store(new_password, new_password_len, system_charset_info);
if ((error=table->file->update_row(table->record[1],table->record[0])))
{
table->file->print_error(error,MYF(0)); /* purecov: deadcode */
@@ -1527,7 +1532,10 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
const char *password= "";
uint password_len= 0;
char what= (revoke_grant) ? 'N' : 'Y';
+ byte user_key[MAX_KEY_LENGTH];
+ LEX *lex= thd->lex;
DBUG_ENTER("replace_user_table");
+
safe_mutex_assert_owner(&acl_cache->lock);
if (combo.password.str && combo.password.str[0])
@@ -1535,20 +1543,22 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
if (combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH &&
combo.password.length != SCRAMBLED_PASSWORD_CHAR_LENGTH_323)
{
- my_printf_error(ER_UNKNOWN_ERROR,
- "Password hash should be a %d-digit hexadecimal number",
- MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
+ my_error(ER_PASSWD_LENGTH, MYF(0), SCRAMBLED_PASSWORD_CHAR_LENGTH);
DBUG_RETURN(-1);
}
password_len= combo.password.length;
password=combo.password.str;
}
- table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
- table->field[1]->store(combo.user.str,combo.user.length, &my_charset_latin1);
+ table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[1]->store(combo.user.str,combo.user.length, system_charset_info);
+ key_copy(user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
+
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (table->file->index_read_idx(table->record[0], 0,
- (byte*) table->field[0]->ptr,0,
- HA_READ_KEY_EXACT))
+ user_key, table->key_info->key_length,
+ HA_READ_KEY_EXACT))
{
/* what == 'N' means revoke */
if (what == 'N')
@@ -1577,11 +1587,11 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
old_row_exists = 0;
restore_record(table,default_values); // cp empty row from default_values
table->field[0]->store(combo.host.str,combo.host.length,
- &my_charset_latin1);
+ system_charset_info);
table->field[1]->store(combo.user.str,combo.user.length,
- &my_charset_latin1);
+ system_charset_info);
table->field[2]->store(password, password_len,
- &my_charset_latin1);
+ system_charset_info);
}
else
{
@@ -1592,16 +1602,16 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
DBUG_ASSERT(combo.host.str);
if (thd->user && combo.password.str &&
(strcmp(thd->user,combo.user.str) ||
- my_strcasecmp(&my_charset_latin1,
+ my_strcasecmp(system_charset_info,
combo.host.str, thd->host_or_ip)) &&
check_access(thd, UPDATE_ACL, "mysql",0,1,0))
goto end;
old_row_exists = 1;
store_record(table,record[1]); // Save copy for update
if (combo.password.str) // If password given
- table->field[2]->store(password, password_len, &my_charset_latin1);
- else if (!rights && !revoke_grant && thd->lex->ssl_type == SSL_TYPE_NOT_SPECIFIED &&
- !thd->lex->mqh.bits)
+ table->field[2]->store(password, password_len, system_charset_info);
+ else if (!rights && !revoke_grant &&
+ lex->ssl_type == SSL_TYPE_NOT_SPECIFIED && !lex->mqh.bits)
{
DBUG_RETURN(0);
}
@@ -1624,7 +1634,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
if (table->fields >= 31) /* From 4.0.0 we have more fields */
{
/* We write down SSL related ACL stuff */
- switch (thd->lex->ssl_type) {
+ switch (lex->ssl_type) {
case SSL_TYPE_ANY:
table->field[24]->store("ANY",3, &my_charset_latin1);
table->field[25]->store("", 0, &my_charset_latin1);
@@ -1642,15 +1652,15 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
table->field[25]->store("", 0, &my_charset_latin1);
table->field[26]->store("", 0, &my_charset_latin1);
table->field[27]->store("", 0, &my_charset_latin1);
- if (thd->lex->ssl_cipher)
- table->field[25]->store(thd->lex->ssl_cipher,
- strlen(thd->lex->ssl_cipher), &my_charset_latin1);
- if (thd->lex->x509_issuer)
- table->field[26]->store(thd->lex->x509_issuer,
- strlen(thd->lex->x509_issuer), &my_charset_latin1);
- if (thd->lex->x509_subject)
- table->field[27]->store(thd->lex->x509_subject,
- strlen(thd->lex->x509_subject), &my_charset_latin1);
+ if (lex->ssl_cipher)
+ table->field[25]->store(lex->ssl_cipher,
+ strlen(lex->ssl_cipher), system_charset_info);
+ if (lex->x509_issuer)
+ table->field[26]->store(lex->x509_issuer,
+ strlen(lex->x509_issuer), system_charset_info);
+ if (lex->x509_subject)
+ table->field[27]->store(lex->x509_subject,
+ strlen(lex->x509_subject), system_charset_info);
break;
case SSL_TYPE_NOT_SPECIFIED:
break;
@@ -1662,7 +1672,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
break;
}
- USER_RESOURCES mqh= thd->lex->mqh;
+ USER_RESOURCES mqh= lex->mqh;
if (mqh.bits & 1)
table->field[28]->store((longlong) mqh.questions);
if (mqh.bits & 2)
@@ -1677,6 +1687,7 @@ static int replace_user_table(THD *thd, TABLE *table, const LEX_USER &combo,
We should NEVER delete from the user table, as a uses can still
use mysqld even if he doesn't have any privileges in the user table!
*/
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if (cmp_record(table,record[1]) &&
(error=table->file->update_row(table->record[1],table->record[0])))
{ // This should never happen
@@ -1704,19 +1715,19 @@ end:
if (old_row_exists)
acl_update_user(combo.user.str, combo.host.str,
combo.password.str, password_len,
- thd->lex->ssl_type,
- thd->lex->ssl_cipher,
- thd->lex->x509_issuer,
- thd->lex->x509_subject,
- &thd->lex->mqh,
+ lex->ssl_type,
+ lex->ssl_cipher,
+ lex->x509_issuer,
+ lex->x509_subject,
+ &lex->mqh,
rights);
else
acl_insert_user(combo.user.str, combo.host.str, password, password_len,
- thd->lex->ssl_type,
- thd->lex->ssl_cipher,
- thd->lex->x509_issuer,
- thd->lex->x509_subject,
- &thd->lex->mqh,
+ lex->ssl_type,
+ lex->ssl_cipher,
+ lex->x509_issuer,
+ lex->x509_subject,
+ &lex->mqh,
rights);
}
DBUG_RETURN(error);
@@ -1736,6 +1747,7 @@ static int replace_db_table(TABLE *table, const char *db,
bool old_row_exists=0;
int error;
char what= (revoke_grant) ? 'N' : 'Y';
+ byte user_key[MAX_KEY_LENGTH];
DBUG_ENTER("replace_db_table");
if (!initialized)
@@ -1747,15 +1759,20 @@ static int replace_db_table(TABLE *table, const char *db,
/* Check if there is such a user in user table in memory? */
if (!find_acl_user(combo.host.str,combo.user.str))
{
- my_error(ER_PASSWORD_NO_MATCH,MYF(0));
+ my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH), MYF(0));
DBUG_RETURN(-1);
}
- table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
- table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
- table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
- if (table->file->index_read_idx(table->record[0],0,(byte*) table->field[0]->ptr,0,
- HA_READ_KEY_EXACT))
+ table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[1]->store(db,(uint) strlen(db), system_charset_info);
+ table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
+ key_copy(user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
+
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ if (table->file->index_read_idx(table->record[0],0,
+ user_key, table->key_info->key_length,
+ HA_READ_KEY_EXACT))
{
if (what == 'N')
{ // no row, no revoke
@@ -1764,9 +1781,9 @@ static int replace_db_table(TABLE *table, const char *db,
}
old_row_exists = 0;
restore_record(table,default_values); // cp empty row from default_values
- table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
- table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
- table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
+ table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[1]->store(db,(uint) strlen(db), system_charset_info);
+ table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
}
else
{
@@ -1788,6 +1805,7 @@ static int replace_db_table(TABLE *table, const char *db,
/* update old existing row */
if (rights)
{
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
if ((error=table->file->update_row(table->record[1],table->record[0])))
goto table_error; /* purecov: deadcode */
}
@@ -1797,7 +1815,7 @@ static int replace_db_table(TABLE *table, const char *db,
goto table_error; /* purecov: deadcode */
}
}
- else if ((error=table->file->write_row(table->record[0])))
+ else if (rights && (error=table->file->write_row(table->record[0])))
{
if (error && error != HA_ERR_FOUND_DUPP_KEY) /* purecov: inspected */
goto table_error; /* purecov: deadcode */
@@ -1807,6 +1825,7 @@ static int replace_db_table(TABLE *table, const char *db,
if (old_row_exists)
acl_update_db(combo.user.str,combo.host.str,db,rights);
else
+ if (rights)
acl_insert_db(combo.user.str,combo.host.str,db,rights);
DBUG_RETURN(0);
@@ -1852,6 +1871,7 @@ public:
GRANT_TABLE(const char *h, const char *d,const char *u,
const char *t, ulong p, ulong c);
GRANT_TABLE (TABLE *form, TABLE *col_privs);
+ ~GRANT_TABLE();
bool ok() { return privs != 0 || cols != 0; }
};
@@ -1877,7 +1897,7 @@ GRANT_TABLE::GRANT_TABLE(const char *h, const char *d,const char *u,
key_length =(uint) strlen(d)+(uint) strlen(u)+(uint) strlen(t)+3;
hash_key = (char*) alloc_root(&memex,key_length);
strmov(strmov(strmov(hash_key,user)+1,db)+1,tname);
- (void) hash_init(&hash_columns,&my_charset_latin1,
+ (void) hash_init(&hash_columns,system_charset_info,
0,0,0, (hash_get_key) get_key_column,0,0);
}
@@ -1901,7 +1921,8 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
if (!db || !tname)
{
/* Wrong table row; Ignore it */
- privs = cols = 0; /* purecov: inspected */
+ hash_clear(&hash_columns); /* allow for destruction */
+ privs= cols= 0; /* purecov: inspected */
return; /* purecov: inspected */
}
if (lower_case_table_names)
@@ -1918,26 +1939,29 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
privs = fix_rights_for_table(privs);
cols = fix_rights_for_column(cols);
- (void) hash_init(&hash_columns,&my_charset_latin1,
+ (void) hash_init(&hash_columns,system_charset_info,
0,0,0, (hash_get_key) get_key_column,0,0);
if (cols)
{
- int key_len;
+ uint key_prefix_len;
+ KEY_PART_INFO *key_part= col_privs->key_info->key_part;
col_privs->field[0]->store(orig_host,(uint) strlen(orig_host),
- &my_charset_latin1);
- col_privs->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
- col_privs->field[2]->store(user,(uint) strlen(user), &my_charset_latin1);
- col_privs->field[3]->store(tname,(uint) strlen(tname), &my_charset_latin1);
- key_len=(col_privs->field[0]->pack_length()+
- col_privs->field[1]->pack_length()+
- col_privs->field[2]->pack_length()+
- col_privs->field[3]->pack_length());
- key_copy(key,col_privs->record[0],col_privs->key_info,key_len);
+ system_charset_info);
+ col_privs->field[1]->store(db,(uint) strlen(db), system_charset_info);
+ col_privs->field[2]->store(user,(uint) strlen(user), system_charset_info);
+ col_privs->field[3]->store(tname,(uint) strlen(tname), system_charset_info);
+
+ key_prefix_len= (key_part[0].store_length +
+ key_part[1].store_length +
+ key_part[2].store_length +
+ key_part[3].store_length);
+ key_copy(key, col_privs->record[0], col_privs->key_info, key_prefix_len);
col_privs->field[4]->store("",0, &my_charset_latin1);
+
col_privs->file->ha_index_init(0);
if (col_privs->file->index_read(col_privs->record[0],
- (byte*) col_privs->field[0]->ptr,
- key_len, HA_READ_KEY_EXACT))
+ (byte*) key,
+ key_prefix_len, HA_READ_KEY_EXACT))
{
cols = 0; /* purecov: deadcode */
col_privs->file->ha_index_end();
@@ -1959,12 +1983,18 @@ GRANT_TABLE::GRANT_TABLE(TABLE *form, TABLE *col_privs)
}
my_hash_insert(&hash_columns, (byte *) mem_check);
} while (!col_privs->file->index_next(col_privs->record[0]) &&
- !key_cmp_if_same(col_privs,key,0,key_len));
+ !key_cmp_if_same(col_privs,key,0,key_prefix_len));
col_privs->file->ha_index_end();
}
}
+GRANT_TABLE::~GRANT_TABLE()
+{
+ hash_free(&hash_columns);
+}
+
+
static byte* get_grant_table(GRANT_TABLE *buff,uint *length,
my_bool not_used __attribute__((unused)))
{
@@ -2001,15 +2031,15 @@ static GRANT_TABLE *table_hash_search(const char *host,const char* ip,
if (exact)
{
if ((host &&
- !my_strcasecmp(&my_charset_latin1, host, grant_table->host)) ||
+ !my_strcasecmp(system_charset_info, host, grant_table->host)) ||
(ip && !strcmp(ip,grant_table->host)))
return grant_table;
}
else
{
- if (((host && !wild_case_compare(&my_charset_latin1,
+ if (((host && !wild_case_compare(system_charset_info,
host,grant_table->host)) ||
- (ip && !wild_case_compare(&my_charset_latin1,
+ (ip && !wild_case_compare(system_charset_info,
ip,grant_table->host))) &&
(!found || found->sort < grant_table->sort))
found=grant_table; // Host ok
@@ -2034,19 +2064,22 @@ static int replace_column_table(GRANT_TABLE *g_t,
ulong rights, bool revoke_grant)
{
int error=0,result=0;
- uint key_length;
byte key[MAX_KEY_LENGTH];
+ uint key_prefix_length;
+ KEY_PART_INFO *key_part= table->key_info->key_part;
DBUG_ENTER("replace_column_table");
- table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
- table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
- table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
- table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1);
- key_length=(table->field[0]->pack_length()+ table->field[1]->pack_length()+
- table->field[2]->pack_length()+ table->field[3]->pack_length());
- key_copy(key,table->record[0],table->key_info,key_length);
+ table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[1]->store(db,(uint) strlen(db), system_charset_info);
+ table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
+ table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info);
- rights &= COL_ACLS; // Only ACL for columns
+ /* Get length of 3 first key parts */
+ key_prefix_length= (key_part[0].store_length + key_part[1].store_length +
+ key_part[2].store_length + key_part[3].store_length);
+ key_copy(key, table->record[0], table->key_info, key_prefix_length);
+
+ rights&= COL_ACLS; // Only ACL for columns
/* first fix privileges for all columns in column list */
@@ -2057,25 +2090,35 @@ static int replace_column_table(GRANT_TABLE *g_t,
{
ulong privileges = xx->rights;
bool old_row_exists=0;
- key_restore(table->record[0],key,table->key_info,key_length);
- table->field[4]->store(xx->column.ptr(),xx->column.length(),
- &my_charset_latin1);
+ byte user_key[MAX_KEY_LENGTH];
- if (table->file->index_read(table->record[0],(byte*) table->field[0]->ptr,
- 0, HA_READ_KEY_EXACT))
+ key_restore(table->record[0],key,table->key_info,
+ key_prefix_length);
+ table->field[4]->store(xx->column.ptr(),xx->column.length(),
+ system_charset_info);
+ /* Get key for the first 4 columns */
+ key_copy(user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
+
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ if (table->file->index_read(table->record[0], user_key,
+ table->key_info->key_length,
+ HA_READ_KEY_EXACT))
{
if (revoke_grant)
{
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
- combo.user.str, combo.host.str, table_name); /* purecov: inspected */
+ combo.user.str, combo.host.str,
+ table_name); /* purecov: inspected */
result= -1; /* purecov: inspected */
continue; /* purecov: inspected */
}
old_row_exists = 0;
restore_record(table,default_values); // Get empty record
- key_restore(table->record[0],key,table->key_info,key_length);
+ key_restore(table->record[0],key,table->key_info,
+ key_prefix_length);
table->field[4]->store(xx->column.ptr(),xx->column.length(),
- &my_charset_latin1);
+ system_charset_info);
}
else
{
@@ -2130,8 +2173,14 @@ static int replace_column_table(GRANT_TABLE *g_t,
if (revoke_grant)
{
- if (table->file->index_read(table->record[0], (byte*) table->field[0]->ptr,
- key_length, HA_READ_KEY_EXACT))
+ byte user_key[MAX_KEY_LENGTH];
+ key_copy(user_key, table->record[0], table->key_info,
+ key_prefix_length);
+
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ if (table->file->index_read(table->record[0], user_key,
+ key_prefix_length,
+ HA_READ_KEY_EXACT))
goto end;
/* Scan through all rows with the same host,db,user and table */
@@ -2145,7 +2194,8 @@ static int replace_column_table(GRANT_TABLE *g_t,
{
GRANT_COLUMN *grant_column = NULL;
char colum_name_buf[HOSTNAME_LENGTH+1];
- String column_name(colum_name_buf,sizeof(colum_name_buf),&my_charset_latin1);
+ String column_name(colum_name_buf,sizeof(colum_name_buf),
+ system_charset_info);
privileges&= ~rights;
table->field[6]->store((longlong)
@@ -2181,7 +2231,7 @@ static int replace_column_table(GRANT_TABLE *g_t,
}
}
} while (!table->file->index_next(table->record[0]) &&
- !key_cmp_if_same(table,key,0,key_length));
+ !key_cmp_if_same(table, key, 0, key_prefix_length));
}
end:
@@ -2200,6 +2250,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
int old_row_exists = 1;
int error=0;
ulong store_table_rights, store_col_rights;
+ byte user_key[MAX_KEY_LENGTH];
DBUG_ENTER("replace_table_table");
strxmov(grantor, thd->user, "@", thd->host_or_ip, NullS);
@@ -2210,19 +2261,23 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
*/
if (!find_acl_user(combo.host.str,combo.user.str))
{
- my_error(ER_PASSWORD_NO_MATCH,MYF(0)); /* purecov: deadcode */
+ my_message(ER_PASSWORD_NO_MATCH, ER(ER_PASSWORD_NO_MATCH),
+ MYF(0)); /* purecov: deadcode */
DBUG_RETURN(-1); /* purecov: deadcode */
}
restore_record(table,default_values); // Get empty record
- table->field[0]->store(combo.host.str,combo.host.length, &my_charset_latin1);
- table->field[1]->store(db,(uint) strlen(db), &my_charset_latin1);
- table->field[2]->store(combo.user.str,combo.user.length, &my_charset_latin1);
- table->field[3]->store(table_name,(uint) strlen(table_name), &my_charset_latin1);
+ table->field[0]->store(combo.host.str,combo.host.length, system_charset_info);
+ table->field[1]->store(db,(uint) strlen(db), system_charset_info);
+ table->field[2]->store(combo.user.str,combo.user.length, system_charset_info);
+ table->field[3]->store(table_name,(uint) strlen(table_name), system_charset_info);
store_record(table,record[1]); // store at pos 1
+ key_copy(user_key, table->record[0], table->key_info,
+ table->key_info->key_length);
- if (table->file->index_read_idx(table->record[0],0,
- (byte*) table->field[0]->ptr,0,
+ table->file->extra(HA_EXTRA_RETRIEVE_ALL_COLS);
+ if (table->file->index_read_idx(table->record[0], 0,
+ user_key, table->key_info->key_length,
HA_READ_KEY_EXACT))
{
/*
@@ -2234,7 +2289,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
{ // no row, no revoke
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
combo.user.str, combo.host.str,
- table_name); /* purecov: deadcode */
+ table_name); /* purecov: deadcode */
DBUG_RETURN(-1); /* purecov: deadcode */
}
old_row_exists = 0;
@@ -2262,7 +2317,7 @@ static int replace_table_table(THD *thd, GRANT_TABLE *grant_table,
}
}
- table->field[4]->store(grantor,(uint) strlen(grantor), &my_charset_latin1);
+ table->field[4]->store(grantor,(uint) strlen(grantor), system_charset_info);
table->field[6]->store((longlong) store_table_rights);
table->field[7]->store((longlong) store_col_rights);
rights=fix_rights_for_table(store_table_rights);
@@ -2316,11 +2371,11 @@ table_error:
revoke_grant Set to 1 if this is a REVOKE command
RETURN
- 0 ok
- 1 error
+ FALSE ok
+ TRUE error
*/
-int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
+bool mysql_table_grant(THD *thd, TABLE_LIST *table_list,
List <LEX_USER> &user_list,
List <LEX_COLUMN> &columns, ulong rights,
bool revoke_grant)
@@ -2337,12 +2392,13 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-grant-tables"); /* purecov: inspected */
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(TRUE); /* purecov: inspected */
}
if (rights & ~TABLE_ACLS)
{
- my_error(ER_ILLEGAL_GRANT_FOR_TABLE,MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE),
+ MYF(0));
+ DBUG_RETURN(TRUE);
}
if (columns.elements && !revoke_grant)
@@ -2351,8 +2407,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
List_iterator <LEX_COLUMN> column_iter(columns);
int res;
- if ((res= open_and_lock_tables(thd, table_list)))
- DBUG_RETURN(res);
+ if (open_and_lock_tables(thd, table_list))
+ DBUG_RETURN(TRUE);
while ((column = column_iter++))
{
@@ -2360,11 +2416,11 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (!find_field_in_table(thd, table_list, column->column.ptr(),
column->column.ptr(),
column->column.length(), 0, 0, 0, 0,
- &unused_field_idx))
+ &unused_field_idx, FALSE))
{
my_error(ER_BAD_FIELD_ERROR, MYF(0),
column->column.c_ptr(), table_list->alias);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
column_priv|= column->rights;
}
@@ -2379,7 +2435,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (access(buf,F_OK))
{
my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db, table_list->alias);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
@@ -2412,22 +2468,22 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
*/
tables[0].updating= tables[1].updating= tables[2].updating= 1;
if (!tables_ok(0, tables))
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
#endif
if (simple_open_n_lock_tables(thd,tables))
{ // Should never happen
close_thread_tables(thd); /* purecov: deadcode */
- DBUG_RETURN(-1); /* purecov: deadcode */
+ DBUG_RETURN(TRUE); /* purecov: deadcode */
}
if (!revoke_grant)
create_new_users= test_if_create_new_users(thd);
- int result=0;
+ bool result= FALSE;
rw_wrlock(&LOCK_grant);
- MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
- my_pthread_setspecific_ptr(THR_MALLOC,&memex);
+ MEM_ROOT *old_root= thd->mem_root;
+ thd->mem_root= &memex;
while ((Str = str_list++))
{
@@ -2436,8 +2492,9 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
if (Str->host.length > HOSTNAME_LENGTH ||
Str->user.length > USERNAME_LENGTH)
{
- my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0));
- result= -1;
+ my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
+ MYF(0));
+ result= TRUE;
continue;
}
/* Create user if needed */
@@ -2447,7 +2504,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
pthread_mutex_unlock(&acl_cache->lock);
if (error)
{
- result= -1; // Remember error
+ result= TRUE; // Remember error
continue; // Add next user
}
@@ -2467,7 +2524,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
{
my_error(ER_NONEXISTING_TABLE_GRANT, MYF(0),
Str->user.str, Str->host.str, table_list->real_name);
- result= -1;
+ result= TRUE;
continue;
}
grant_table = new GRANT_TABLE (Str->host.str, db_name,
@@ -2476,7 +2533,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
column_priv);
if (!grant_table) // end of memory
{
- result= -1; /* purecov: deadcode */
+ result= TRUE; /* purecov: deadcode */
continue; /* purecov: deadcode */
}
my_hash_insert(&column_priv_hash,(byte*) grant_table);
@@ -2521,7 +2578,7 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
rights, column_priv, revoke_grant))
{
/* Should only happen if table is crashed */
- result= -1; /* purecov: deadcode */
+ result= TRUE; /* purecov: deadcode */
}
else if (tables[2].table)
{
@@ -2530,12 +2587,12 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
db_name, real_name,
rights, revoke_grant)))
{
- result= -1;
+ result= TRUE;
}
}
}
grant_option=TRUE;
- my_pthread_setspecific_ptr(THR_MALLOC,old_root);
+ thd->mem_root= old_root;
rw_unlock(&LOCK_grant);
if (!result)
send_ok(thd);
@@ -2544,8 +2601,8 @@ int mysql_table_grant(THD *thd, TABLE_LIST *table_list,
}
-int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
- ulong rights, bool revoke_grant)
+bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
+ ulong rights, bool revoke_grant)
{
List_iterator <LEX_USER> str_list (list);
LEX_USER *Str;
@@ -2557,7 +2614,7 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0),
"--skip-grant-tables"); /* purecov: tested */
- DBUG_RETURN(-1); /* purecov: tested */
+ DBUG_RETURN(TRUE); /* purecov: tested */
}
if (lower_case_table_names && db)
@@ -2588,14 +2645,14 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
*/
tables[0].updating= tables[1].updating= 1;
if (!tables_ok(0, tables))
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
#endif
if (simple_open_n_lock_tables(thd,tables))
{ // This should never happen
close_thread_tables(thd); /* purecov: deadcode */
- DBUG_RETURN(-1); /* purecov: deadcode */
+ DBUG_RETURN(TRUE); /* purecov: deadcode */
}
if (!revoke_grant)
@@ -2612,7 +2669,8 @@ int mysql_grant(THD *thd, const char *db, List <LEX_USER> &list,
if (Str->host.length > HOSTNAME_LENGTH ||
Str->user.length > USERNAME_LENGTH)
{
- my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0));
+ my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
+ MYF(0));
result= -1;
continue;
}
@@ -2667,13 +2725,14 @@ my_bool grant_init(THD *org_thd)
THD *thd;
TABLE_LIST tables[2];
MYSQL_LOCK *lock;
+ MEM_ROOT *memex_ptr;
my_bool return_val= 1;
TABLE *t_table, *c_table;
bool check_no_resolve= specialflag & SPECIAL_NO_RESOLVE;
DBUG_ENTER("grant_init");
grant_option = FALSE;
- (void) hash_init(&column_priv_hash,&my_charset_latin1,
+ (void) hash_init(&column_priv_hash,system_charset_info,
0,0,0, (hash_get_key) get_grant_table,
(hash_free_key) free_grant_table,0);
init_sql_alloc(&memex, ACL_ALLOC_BLOCK_SIZE, 0);
@@ -2714,7 +2773,8 @@ my_bool grant_init(THD *org_thd)
grant_option= TRUE;
/* Will be restored by org_thd->store_globals() */
- my_pthread_setspecific_ptr(THR_MALLOC,&memex);
+ memex_ptr= &memex;
+ my_pthread_setspecific_ptr(THR_MALLOC, &memex_ptr);
do
{
GRANT_TABLE *mem_check;
@@ -2737,8 +2797,11 @@ my_bool grant_init(THD *org_thd)
}
}
- if (mem_check->ok() && my_hash_insert(&column_priv_hash,(byte*) mem_check))
+ if (! mem_check->ok())
+ delete mem_check;
+ else if (my_hash_insert(&column_priv_hash,(byte*) mem_check))
{
+ delete mem_check;
grant_option= FALSE;
goto end_unlock;
}
@@ -2844,7 +2907,8 @@ bool check_grant(THD *thd, ulong want_access, TABLE_LIST *tables,
for (table= tables; table && number--; table= table->next_global)
{
GRANT_TABLE *grant_table;
- if (!(~table->grant.privilege & want_access) || table->derived)
+ if (!(~table->grant.privilege & want_access) ||
+ table->derived || table->schema_table)
{
/*
It is subquery in the FROM clause. VIEW set table->derived after
@@ -2907,11 +2971,11 @@ err:
command= "create view";
else if (want_access & SHOW_VIEW_ACL)
command= "show create view";
- net_printf(thd,ER_TABLEACCESS_DENIED_ERROR,
- command,
- thd->priv_user,
- thd->host_or_ip,
- table ? table->real_name : "unknown");
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ command,
+ thd->priv_user,
+ thd->host_or_ip,
+ table ? table->real_name : "unknown");
}
DBUG_RETURN(1);
}
@@ -2957,21 +3021,18 @@ bool check_grant_column(THD *thd, GRANT_INFO *grant,
}
#endif
- /* We must use my_printf_error() here! */
err:
rw_unlock(&LOCK_grant);
if (!show_tables)
{
char command[128];
get_privilege_desc(command, sizeof(command), want_access);
- my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
- ER(ER_COLUMNACCESS_DENIED_ERROR),
- MYF(0),
- command,
- thd->priv_user,
- thd->host_or_ip,
- name,
- table_name);
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ command,
+ thd->priv_user,
+ thd->host_or_ip,
+ name,
+ table_name);
}
return 1;
}
@@ -3018,7 +3079,6 @@ bool check_grant_all_columns(THD *thd, ulong want_access, GRANT_INFO *grant,
rw_unlock(&LOCK_grant);
return 0;
- /* We must use my_printf_error() here! */
err:
rw_unlock(&LOCK_grant);
err2:
@@ -3027,14 +3087,12 @@ err2:
command= "select";
else if (want_access & INSERT_ACL)
command= "insert";
- my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
- ER(ER_COLUMNACCESS_DENIED_ERROR),
- MYF(0),
- command,
- thd->priv_user,
- thd->host_or_ip,
- fields->name(),
- table_name);
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ command,
+ thd->priv_user,
+ thd->host_or_ip,
+ fields->name(),
+ table_name);
return 1;
}
@@ -3060,9 +3118,9 @@ bool check_grant_db(THD *thd,const char *db)
idx);
if (len < grant_table->key_length &&
!memcmp(grant_table->hash_key,helping,len) &&
- (thd->host && !wild_case_compare(&my_charset_latin1,
+ (thd->host && !wild_case_compare(system_charset_info,
thd->host,grant_table->host) ||
- (thd->ip && !wild_case_compare(&my_charset_latin1,
+ (thd->ip && !wild_case_compare(system_charset_info,
thd->ip,grant_table->host))))
{
error=0; // Found match
@@ -3173,7 +3231,7 @@ static uint command_lengths[]=
Send to client grant-like strings depicting user@host privileges
*/
-int mysql_show_grants(THD *thd,LEX_USER *lex_user)
+bool mysql_show_grants(THD *thd,LEX_USER *lex_user)
{
ulong want_access;
uint counter,index;
@@ -3188,7 +3246,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (!initialized)
{
my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
if (!lex_user->host.str)
@@ -3199,8 +3257,9 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (lex_user->host.length > HOSTNAME_LENGTH ||
lex_user->user.length > USERNAME_LENGTH)
{
- my_error(ER_GRANT_WRONG_HOST_OR_USER,MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_GRANT_WRONG_HOST_OR_USER, ER(ER_GRANT_WRONG_HOST_OR_USER),
+ MYF(0));
+ DBUG_RETURN(TRUE);
}
for (counter=0 ; counter < acl_users.elements ; counter++)
@@ -3212,14 +3271,14 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (!(host=acl_user->host.hostname))
host= "";
if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host))
+ !my_strcasecmp(system_charset_info, lex_user->host.str, host))
break;
}
if (counter == acl_users.elements)
{
my_error(ER_NONEXISTING_GRANT, MYF(0),
lex_user->user.str, lex_user->host.str);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
Item_string *field=new Item_string("",0,&my_charset_latin1);
@@ -3231,7 +3290,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
field_list.push_back(field);
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
@@ -3266,7 +3325,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
global.append ("'@'",3);
- global.append(lex_user->host.str,lex_user->host.length);
+ global.append(lex_user->host.str,lex_user->host.length,
+ system_charset_info);
global.append ('\'');
if (acl_user->salt_len)
{
@@ -3300,7 +3360,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (ssl_options++)
global.append(' ');
global.append("SUBJECT \'",9);
- global.append(acl_user->x509_subject,strlen(acl_user->x509_subject));
+ global.append(acl_user->x509_subject,strlen(acl_user->x509_subject),
+ system_charset_info);
global.append('\'');
}
if (acl_user->ssl_cipher)
@@ -3308,7 +3369,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
if (ssl_options++)
global.append(' ');
global.append("CIPHER '",8);
- global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher));
+ global.append(acl_user->ssl_cipher,strlen(acl_user->ssl_cipher),
+ system_charset_info);
global.append('\'');
}
}
@@ -3347,7 +3409,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
host= "";
if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(&my_charset_latin1, lex_user->host.str, host))
+ !my_strcasecmp(system_charset_info, lex_user->host.str, host))
{
want_access=acl_db->access;
if (want_access)
@@ -3381,7 +3443,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
db.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
db.append ("'@'",3);
- db.append(lex_user->host.str, lex_user->host.length);
+ db.append(lex_user->host.str, lex_user->host.length,
+ system_charset_info);
db.append ('\'');
if (want_access & GRANT_ACL)
db.append(" WITH GRANT OPTION",18);
@@ -3407,7 +3470,7 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
user= "";
if (!strcmp(lex_user->user.str,user) &&
- !my_strcasecmp(&my_charset_latin1, lex_user->host.str,
+ !my_strcasecmp(system_charset_info, lex_user->host.str,
grant_table->orig_host))
{
ulong table_access= grant_table->privs;
@@ -3487,7 +3550,8 @@ int mysql_show_grants(THD *thd,LEX_USER *lex_user)
global.append(lex_user->user.str, lex_user->user.length,
system_charset_info);
global.append("'@'",3);
- global.append(lex_user->host.str,lex_user->host.length);
+ global.append(lex_user->host.str,lex_user->host.length,
+ system_charset_info);
global.append('\'');
if (table_access & GRANT_ACL)
global.append(" WITH GRANT OPTION",18);
@@ -3547,13 +3611,34 @@ void get_mqh(const char *user, const char *host, USER_CONN *uc)
bzero((char*) &uc->user_resources, sizeof(uc->user_resources));
}
+/*
+ Open the grant tables.
+
+ SYNOPSIS
+ open_grant_tables()
+ thd The current thread.
+ tables (out) The 4 elements array for the opened tables.
+
+ DESCRIPTION
+ Tables are numbered as follows:
+ 0 user
+ 1 db
+ 2 tables_priv
+ 3 columns_priv
+
+ RETURN
+ 1 Skip GRANT handling during replication.
+ 0 OK.
+ < 0 Error.
+*/
+
int open_grant_tables(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("open_grant_tables");
if (!initialized)
{
- net_printf(thd,ER_OPTION_PREVENTS_STATEMENT, "--skip-grant-tables");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--skip-grant-tables");
DBUG_RETURN(-1);
}
@@ -3622,120 +3707,652 @@ ACL_USER *check_acl_user(LEX_USER *user_name,
}
-int mysql_drop_user(THD *thd, List <LEX_USER> &list)
+/*
+ Modify a privilege table.
+
+ SYNOPSIS
+ modify_grant_table()
+ table The table to modify.
+ host_field The host name field.
+ user_field The user name field.
+ user_to The new name for the user if to be renamed,
+ NULL otherwise.
+
+ DESCRIPTION
+ Update user/host in the current record if user_to is not NULL.
+ Delete the current record if user_to is NULL.
+
+ RETURN
+ 0 OK.
+ != 0 Error.
+*/
+
+static int modify_grant_table(TABLE *table, Field *host_field,
+ Field *user_field, LEX_USER *user_to)
{
- uint counter, acl_userd;
- int result;
- ACL_USER *acl_user;
- ACL_DB *acl_db;
- TABLE_LIST tables[4];
+ int error;
+ DBUG_ENTER("modify_grant_table");
- DBUG_ENTER("mysql_drop_user");
+ if (user_to)
+ {
+ /* rename */
+ store_record(table, record[1]);
+ host_field->store(user_to->host.str, user_to->host.length,
+ system_charset_info);
+ user_field->store(user_to->user.str, user_to->user.length,
+ system_charset_info);
+ if ((error= table->file->update_row(table->record[1], table->record[0])))
+ table->file->print_error(error, MYF(0));
+ }
+ else
+ {
+ /* delete */
+ if ((error=table->file->delete_row(table->record[0])))
+ table->file->print_error(error, MYF(0));
+ }
- if ((result= open_grant_tables(thd, tables)))
- DBUG_RETURN(result == 1 ? 0 : 1);
+ DBUG_RETURN(error);
+}
- rw_wrlock(&LOCK_grant);
- VOID(pthread_mutex_lock(&acl_cache->lock));
- LEX_USER *user_name;
- List_iterator <LEX_USER> user_list(list);
- while ((user_name=user_list++))
+/*
+ Handle a privilege table.
+
+ SYNOPSIS
+ handle_grant_table()
+ tables The array with the four open tables.
+ table_no The number of the table to handle (0..3).
+ drop If user_from is to be dropped.
+ user_from The the user to be searched/dropped/renamed.
+ user_to The new name for the user if to be renamed,
+ NULL otherwise.
+
+ DESCRIPTION
+ Scan through all records in a grant table and apply the requested
+ operation. For the "user" table, a single index access is sufficient,
+ since there is an unique index on (host, user).
+ Delete from grant table if drop is true.
+ Update in grant table if drop is false and user_to is not NULL.
+ Search in grant table if drop is false and user_to is NULL.
+ Tables are numbered as follows:
+ 0 user
+ 1 db
+ 2 tables_priv
+ 3 columns_priv
+
+ RETURN
+ > 0 At least one record matched.
+ 0 OK, but no record matched.
+ < 0 Error.
+*/
+
+static int handle_grant_table(TABLE_LIST *tables, uint table_no, bool drop,
+ LEX_USER *user_from, LEX_USER *user_to)
+{
+ int result= 0;
+ int error;
+ TABLE *table= tables[table_no].table;
+ Field *host_field= table->field[0];
+ Field *user_field= table->field[table_no ? 2 : 1];
+ char *host_str= user_from->host.str;
+ char *user_str= user_from->user.str;
+ const char *host;
+ const char *user;
+ byte user_key[MAX_KEY_LENGTH];
+ uint key_prefix_length;
+ DBUG_ENTER("handle_grant_table");
+
+ if (! table_no) // mysql.user table
{
- if (!(acl_user= check_acl_user(user_name, &counter)))
+ /*
+ The 'user' table has an unique index on (host, user).
+ Thus, we can handle everything with a single index access.
+ The host- and user fields are consecutive in the user table records.
+ So we set host- and user fields of table->record[0] and use the
+ pointer to the host field as key.
+ index_read_idx() will replace table->record[0] (its first argument)
+ by the searched record, if it exists.
+ */
+ DBUG_PRINT("info",("read table: '%s' search: '%s'@'%s'",
+ table->real_name, user_str, host_str));
+ host_field->store(host_str, user_from->host.length, system_charset_info);
+ user_field->store(user_str, user_from->user.length, system_charset_info);
+
+ key_prefix_length= (table->key_info->key_part[0].store_length +
+ table->key_info->key_part[1].store_length);
+ key_copy(user_key, table->record[0], table->key_info, key_prefix_length);
+
+ if ((error= table->file->index_read_idx(table->record[0], 0,
+ user_key, key_prefix_length,
+ HA_READ_KEY_EXACT)))
{
- sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; No such user",
- user_name->user.str,
- user_name->host.str);
- result= -1;
- continue;
+ if (error != HA_ERR_KEY_NOT_FOUND)
+ {
+ table->file->print_error(error, MYF(0));
+ result= -1;
+ }
}
- if ((acl_user->access & ~0))
+ else
+ {
+ /* If requested, delete or update the record. */
+ result= ((drop || user_to) &&
+ modify_grant_table(table, host_field, user_field, user_to)) ?
+ -1 : 1; /* Error or found. */
+ }
+ DBUG_PRINT("info",("read result: %d", result));
+ }
+ else
+ {
+ /*
+ The non-'user' table do not have indexes on (host, user).
+ And their host- and user fields are not consecutive.
+ Thus, we need to do a table scan to find all matching records.
+ */
+ if ((error= table->file->ha_rnd_init(1)))
{
- sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Global privileges exists",
- user_name->user.str,
- user_name->host.str);
+ table->file->print_error(error, MYF(0));
result= -1;
- continue;
}
- acl_userd= counter;
+ else
+ {
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("info",("scan table: '%s' search: '%s'@'%s'",
+ table->real_name, user_str, host_str));
+#endif
+ while ((error= table->file->rnd_next(table->record[0])) !=
+ HA_ERR_END_OF_FILE)
+ {
+ if (error)
+ {
+ /* Most probable 'deleted record'. */
+ DBUG_PRINT("info",("scan error: %d", error));
+ continue;
+ }
+ if (! (host= get_field(&mem, host_field)))
+ host= "";
+ if (! (user= get_field(&mem, user_field)))
+ user= "";
+
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("loop",("scan fields: '%s'@'%s' '%s' '%s' '%s'",
+ user, host,
+ get_field(&mem, table->field[1]) /*db*/,
+ get_field(&mem, table->field[3]) /*table*/,
+ get_field(&mem, table->field[4]) /*column*/));
+#endif
+ if (strcmp(user_str, user) ||
+ my_strcasecmp(system_charset_info, host_str, host))
+ continue;
+
+ /* If requested, delete or update the record. */
+ result= ((drop || user_to) &&
+ modify_grant_table(table, host_field, user_field, user_to)) ?
+ -1 : result ? result : 1; /* Error or keep result or found. */
+ /* If search is requested, we do not need to search further. */
+ if (! drop && ! user_to)
+ break ;
+ }
+ (void) table->file->ha_rnd_end();
+ DBUG_PRINT("info",("scan result: %d", result));
+ }
+ }
+
+ DBUG_RETURN(result);
+}
+
- for (counter= 0 ; counter < acl_dbs.elements ; counter++)
+/*
+ Handle an in-memory privilege structure.
+
+ SYNOPSIS
+ handle_grant_struct()
+ struct_no The number of the structure to handle (0..2).
+ drop If user_from is to be dropped.
+ user_from The the user to be searched/dropped/renamed.
+ user_to The new name for the user if to be renamed,
+ NULL otherwise.
+
+ DESCRIPTION
+ Scan through all elements in an in-memory grant structure and apply
+ the requested operation.
+ Delete from grant structure if drop is true.
+ Update in grant structure if drop is false and user_to is not NULL.
+ Search in grant structure if drop is false and user_to is NULL.
+ Structures are numbered as follows:
+ 0 acl_users
+ 1 acl_dbs
+ 2 column_priv_hash
+
+ RETURN
+ > 0 At least one element matched.
+ 0 OK, but no element matched.
+*/
+
+static int handle_grant_struct(uint struct_no, bool drop,
+ LEX_USER *user_from, LEX_USER *user_to)
+{
+ int result= 0;
+ uint idx;
+ uint elements;
+ const char *user;
+ const char *host;
+ ACL_USER *acl_user;
+ ACL_DB *acl_db;
+ GRANT_TABLE *grant_table;
+ DBUG_ENTER("handle_grant_struct");
+ LINT_INIT(acl_user);
+ LINT_INIT(acl_db);
+ LINT_INIT(grant_table);
+ DBUG_PRINT("info",("scan struct: %u search: '%s'@'%s'",
+ struct_no, user_from->user.str, user_from->host.str));
+
+ /* Get the number of elements in the in-memory structure. */
+ switch (struct_no)
+ {
+ case 0:
+ elements= acl_users.elements;
+ break;
+ case 1:
+ elements= acl_dbs.elements;
+ break;
+ default:
+ elements= column_priv_hash.records;
+ }
+
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("loop",("scan struct: %u search user: '%s' host: '%s'",
+ struct_no, user_from->user.str, user_from->host.str));
+#endif
+ /* Loop over all elements. */
+ for (idx= 0; idx < elements; idx++)
+ {
+ /*
+ Get a pointer to the element.
+ Unfortunaltely, the host default differs for the structures.
+ */
+ switch (struct_no)
{
- const char *user,*host;
- acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*);
- if (!(user= acl_db->user))
- user= "";
- if (!(host= acl_db->host.hostname))
- host= "";
+ case 0:
+ acl_user= dynamic_element(&acl_users, idx, ACL_USER*);
+ user= acl_user->user;
+ if (!(host= acl_user->host.hostname))
+ host= "%";
+ break;
- if (!strcmp(user_name->user.str,user) &&
- !my_strcasecmp(system_charset_info, user_name->host.str, host))
- break;
+ case 1:
+ acl_db= dynamic_element(&acl_dbs, idx, ACL_DB*);
+ user= acl_db->user;
+ host= acl_db->host.hostname;
+ break;
+
+ default:
+ grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash, idx);
+ user= grant_table->user;
+ host= grant_table->host;
}
- if (counter != acl_dbs.elements)
- {
- sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Database privileges exists",
- user_name->user.str,
- user_name->host.str);
- result= -1;
+ if (! user)
+ user= "";
+ if (! host)
+ host= "";
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("loop",("scan struct: %u index: %u user: '%s' host: '%s'",
+ struct_no, idx, user, host));
+#endif
+ if (strcmp(user_from->user.str, user) ||
+ my_strcasecmp(system_charset_info, user_from->host.str, host))
continue;
+
+ result= 1; /* At least one element found. */
+ if ( drop )
+ {
+ switch ( struct_no )
+ {
+ case 0:
+ delete_dynamic_element(&acl_users, idx);
+ break;
+
+ case 1:
+ delete_dynamic_element(&acl_dbs, idx);
+ break;
+
+ default:
+ hash_delete(&column_priv_hash, (byte*) grant_table);
+ }
+ elements--;
+ idx--;
}
+ else if ( user_to )
+ {
+ switch ( struct_no )
+ {
+ case 0:
+ acl_user->user= strdup_root(&mem, user_to->user.str);
+ acl_user->host.hostname= strdup_root(&mem, user_to->host.str);
+ break;
- for (counter= 0 ; counter < column_priv_hash.records ; counter++)
+ case 1:
+ acl_db->user= strdup_root(&mem, user_to->user.str);
+ acl_db->host.hostname= strdup_root(&mem, user_to->host.str);
+ break;
+
+ default:
+ grant_table->user= strdup_root(&mem, user_to->user.str);
+ grant_table->host= strdup_root(&mem, user_to->host.str);
+ }
+ }
+ else
{
- const char *user,*host;
- GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
- counter);
- if (!(user=grant_table->user))
- user= "";
- if (!(host=grant_table->host))
- host= "";
+ /* If search is requested, we do not need to search further. */
+ break;
+ }
+ }
+#ifdef EXTRA_DEBUG
+ DBUG_PRINT("loop",("scan struct: %u result %d", struct_no, result));
+#endif
- if (!strcmp(user_name->user.str,user) &&
- !my_strcasecmp(system_charset_info, user_name->host.str, host))
- break;
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Handle all privilege tables and in-memory privilege structures.
+
+ SYNOPSIS
+ handle_grant_data()
+ tables The array with the four open tables.
+ drop If user_from is to be dropped.
+ user_from The the user to be searched/dropped/renamed.
+ user_to The new name for the user if to be renamed,
+ NULL otherwise.
+
+ DESCRIPTION
+ Go through all grant tables and in-memory grant structures and apply
+ the requested operation.
+ Delete from grant data if drop is true.
+ Update in grant data if drop is false and user_to is not NULL.
+ Search in grant data if drop is false and user_to is NULL.
+
+ RETURN
+ > 0 At least one element matched.
+ 0 OK, but no element matched.
+ < 0 Error.
+*/
+
+static int handle_grant_data(TABLE_LIST *tables, bool drop,
+ LEX_USER *user_from, LEX_USER *user_to)
+{
+ int result= 0;
+ int found;
+ DBUG_ENTER("handle_grant_data");
+
+ /* Handle user table. */
+ if ((found= handle_grant_table(tables, 0, drop, user_from, user_to)) < 0)
+ {
+ /* Handle of table failed, don't touch the in-memory array. */
+ result= -1;
+ }
+ else
+ {
+ /* Handle user array. */
+ if ((handle_grant_struct(0, drop, user_from, user_to) && ! result) ||
+ found)
+ {
+ result= 1; /* At least one record/element found. */
+ /* If search is requested, we do not need to search further. */
+ if (! drop && ! user_to)
+ goto end;
+ }
+ }
+
+ /* Handle db table. */
+ if ((found= handle_grant_table(tables, 1, drop, user_from, user_to)) < 0)
+ {
+ /* Handle of table failed, don't touch the in-memory array. */
+ result= -1;
+ }
+ else
+ {
+ /* Handle db array. */
+ if (((handle_grant_struct(1, drop, user_from, user_to) && ! result) ||
+ found) && ! result)
+ {
+ result= 1; /* At least one record/element found. */
+ /* If search is requested, we do not need to search further. */
+ if (! drop && ! user_to)
+ goto end;
+ }
+ }
+
+ /* Handle tables table. */
+ if ((found= handle_grant_table(tables, 2, drop, user_from, user_to)) < 0)
+ {
+ /* Handle of table failed, don't touch columns and in-memory array. */
+ result= -1;
+ }
+ else
+ {
+ if (found && ! result)
+ {
+ result= 1; /* At least one record found. */
+ /* If search is requested, we do not need to search further. */
+ if (! drop && ! user_to)
+ goto end;
}
- if (counter != column_priv_hash.records)
+
+ /* Handle columns table. */
+ if ((found= handle_grant_table(tables, 3, drop, user_from, user_to)) < 0)
{
- sql_print_error("DROP USER: Can't drop user: '%s'@'%s'; Table privileges exists",
- user_name->user.str,
- user_name->host.str);
+ /* Handle of table failed, don't touch the in-memory array. */
result= -1;
+ }
+ else
+ {
+ /* Handle columns hash. */
+ if (((handle_grant_struct(2, drop, user_from, user_to) && ! result) ||
+ found) && ! result)
+ result= 1; /* At least one record/element found. */
+ }
+ }
+ end:
+ DBUG_RETURN(result);
+}
+
+
+static void append_user(String *str, LEX_USER *user)
+{
+ if (str->length())
+ str->append(',');
+ str->append('\'');
+ str->append(user->user.str);
+ str->append("'@'");
+ str->append(user->host.str);
+ str->append('\'');
+}
+
+
+/*
+ Create a list of users.
+
+ SYNOPSIS
+ mysql_create_user()
+ thd The current thread.
+ list The users to create.
+
+ RETURN
+ FALSE OK.
+ TRUE Error.
+*/
+
+bool mysql_create_user(THD *thd, List <LEX_USER> &list)
+{
+ int result;
+ int found;
+ String wrong_users;
+ ulong sql_mode;
+ LEX_USER *user_name;
+ List_iterator <LEX_USER> user_list(list);
+ TABLE_LIST tables[4];
+ DBUG_ENTER("mysql_create_user");
+
+ /* CREATE USER may be skipped on replication client. */
+ if ((result= open_grant_tables(thd, tables)))
+ DBUG_RETURN(result != 1);
+
+ rw_wrlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ while ((user_name= user_list++))
+ {
+ /*
+ Search all in-memory structures and grant tables
+ for a mention of the new user name.
+ */
+ if ((found= handle_grant_data(tables, 0, user_name, NULL)))
+ {
+ append_user(&wrong_users, user_name);
+ result= TRUE;
continue;
}
- tables[0].table->field[0]->store(user_name->host.str,(uint)
- user_name->host.length,
- system_charset_info);
- tables[0].table->field[1]->store(user_name->user.str,(uint)
- user_name->user.length,
- system_charset_info);
- if (!tables[0].table->file->index_read_idx(tables[0].table->record[0],0,
- (byte*) tables[0].table->
- field[0]->ptr,0,
- HA_READ_KEY_EXACT))
- {
- int error;
- if ((error = tables[0].table->file->delete_row(tables[0].table->
- record[0])))
- {
- tables[0].table->file->print_error(error, MYF(0));
- DBUG_RETURN(-1);
- }
- delete_dynamic_element(&acl_users, acl_userd);
+ sql_mode= thd->variables.sql_mode;
+ thd->variables.sql_mode&= ~MODE_NO_AUTO_CREATE_USER;
+ if (replace_user_table(thd, tables[0].table, *user_name, 0, 0, 1))
+ {
+ append_user(&wrong_users, user_name);
+ result= TRUE;
}
+ thd->variables.sql_mode= sql_mode;
}
VOID(pthread_mutex_unlock(&acl_cache->lock));
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
if (result)
- my_error(ER_DROP_USER, MYF(0));
+ my_error(ER_CANNOT_USER, MYF(0), "CREATE USER", wrong_users.c_ptr());
DBUG_RETURN(result);
}
-int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
+
+/*
+ Drop a list of users and all their privileges.
+
+ SYNOPSIS
+ mysql_drop_user()
+ thd The current thread.
+ list The users to drop.
+
+ RETURN
+ FALSE OK.
+ TRUE Error.
+*/
+
+bool mysql_drop_user(THD *thd, List <LEX_USER> &list)
+{
+ int result;
+ int found;
+ String wrong_users;
+ LEX_USER *user_name;
+ List_iterator <LEX_USER> user_list(list);
+ TABLE_LIST tables[4];
+ DBUG_ENTER("mysql_drop_user");
+
+ /* DROP USER may be skipped on replication client. */
+ if ((result= open_grant_tables(thd, tables)))
+ DBUG_RETURN(result != 1);
+
+ rw_wrlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ while ((user_name= user_list++))
+ {
+ if ((found= handle_grant_data(tables, 1, user_name, NULL)) <= 0)
+ {
+ append_user(&wrong_users, user_name);
+ result= TRUE;
+ }
+ }
+
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
+ close_thread_tables(thd);
+ if (result)
+ my_error(ER_CANNOT_USER, MYF(0), "DROP USER", wrong_users.c_ptr());
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Rename a user.
+
+ SYNOPSIS
+ mysql_rename_user()
+ thd The current thread.
+ list The user name pairs: (from, to).
+
+ RETURN
+ FALSE OK.
+ TRUE Error.
+*/
+
+bool mysql_rename_user(THD *thd, List <LEX_USER> &list)
+{
+ int result= 0;
+ int found;
+ String wrong_users;
+ LEX_USER *user_from;
+ LEX_USER *user_to;
+ List_iterator <LEX_USER> user_list(list);
+ TABLE_LIST tables[4];
+ DBUG_ENTER("mysql_rename_user");
+
+ /* RENAME USER may be skipped on replication client. */
+ if ((result= open_grant_tables(thd, tables)))
+ DBUG_RETURN(result != 1);
+
+ rw_wrlock(&LOCK_grant);
+ VOID(pthread_mutex_lock(&acl_cache->lock));
+
+ while ((user_from= user_list++))
+ {
+ user_to= user_list++;
+ DBUG_ASSERT(user_to); /* Syntax enforces pairs of users. */
+
+ /*
+ Search all in-memory structures and grant tables
+ for a mention of the new user name.
+ */
+ if (handle_grant_data(tables, 0, user_to, NULL) ||
+ handle_grant_data(tables, 0, user_from, user_to) <= 0)
+ {
+ append_user(&wrong_users, user_from);
+ result= TRUE;
+ }
+ }
+
+ VOID(pthread_mutex_unlock(&acl_cache->lock));
+ rw_unlock(&LOCK_grant);
+ close_thread_tables(thd);
+ if (result)
+ my_error(ER_CANNOT_USER, MYF(0), "RENAME USER", wrong_users.c_ptr());
+ DBUG_RETURN(result);
+}
+
+
+/*
+ Revoke all privileges from a list of users.
+
+ SYNOPSIS
+ mysql_revoke_all()
+ thd The current thread.
+ list The users to revoke all privileges from.
+
+ RETURN
+ > 0 Error. Error message already sent.
+ 0 OK.
+ < 0 Error. Error message not yet sent.
+*/
+
+bool mysql_revoke_all(THD *thd, List <LEX_USER> &list)
{
uint counter, revoked;
int result;
@@ -3744,7 +4361,7 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
DBUG_ENTER("mysql_revoke_all");
if ((result= open_grant_tables(thd, tables)))
- DBUG_RETURN(result == 1 ? 0 : 1);
+ DBUG_RETURN(result != 1);
rw_wrlock(&LOCK_grant);
VOID(pthread_mutex_lock(&acl_cache->lock));
@@ -3755,9 +4372,8 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
{
if (!check_acl_user(lex_user, &counter))
{
- sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' not exists",
- lex_user->user.str,
- lex_user->host.str);
+ sql_print_error("REVOKE ALL PRIVILEGES, GRANT: User '%s'@'%s' does not "
+ "exists", lex_user->user.str, lex_user->host.str);
result= -1;
continue;
}
@@ -3780,13 +4396,13 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
for (counter= 0, revoked= 0 ; counter < acl_dbs.elements ; )
{
const char *user,*host;
-
+
acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*);
if (!(user=acl_db->user))
user= "";
if (!(host=acl_db->host.hostname))
host= "";
-
+
if (!strcmp(lex_user->user.str,user) &&
!my_strcasecmp(system_charset_info, lex_user->host.str, host))
{
@@ -3817,7 +4433,7 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
user= "";
if (!(host=grant_table->host))
host= "";
-
+
if (!strcmp(lex_user->user.str,user) &&
!my_strcasecmp(system_charset_info, lex_user->host.str, host))
{
@@ -3852,14 +4468,14 @@ int mysql_revoke_all(THD *thd, List <LEX_USER> &list)
}
} while (revoked);
}
-
+
VOID(pthread_mutex_unlock(&acl_cache->lock));
rw_unlock(&LOCK_grant);
close_thread_tables(thd);
-
+
if (result)
- my_error(ER_REVOKE_GRANTS, MYF(0));
-
+ my_message(ER_REVOKE_GRANTS, ER(ER_REVOKE_GRANTS), MYF(0));
+
DBUG_RETURN(result);
}
@@ -3921,6 +4537,229 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
DBUG_RETURN (*str != '\0');
}
+
+void update_schema_privilege(TABLE *table, char *buff, const char* db,
+ const char* t_name, const char* column,
+ uint col_length, const char *priv,
+ uint priv_length, const char* is_grantable)
+{
+ int i= 2;
+ CHARSET_INFO *cs= system_charset_info;
+ restore_record(table, default_values);
+ table->field[0]->store(buff, strlen(buff), cs);
+ if (db)
+ table->field[i++]->store(db, strlen(db), cs);
+ if (t_name)
+ table->field[i++]->store(t_name, strlen(t_name), cs);
+ if (column)
+ table->field[i++]->store(column, col_length, cs);
+ table->field[i++]->store(priv, priv_length, cs);
+ table->field[i]->store(is_grantable, strlen(is_grantable), cs);
+ table->file->write_row(table->record[0]);
+}
+
+
+int fill_schema_user_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint counter;
+ ACL_USER *acl_user;
+ ulong want_access;
+
+ char buff[100];
+ TABLE *table= tables->table;
+ DBUG_ENTER("fill_schema_user_privileges");
+ for (counter=0 ; counter < acl_users.elements ; counter++)
+ {
+ const char *user,*host, *is_grantable="YES";
+ acl_user=dynamic_element(&acl_users,counter,ACL_USER*);
+ if (!(user=acl_user->user))
+ user= "";
+ if (!(host=acl_user->host.hostname))
+ host= "";
+ want_access= acl_user->access;
+ if (!(want_access & GRANT_ACL))
+ is_grantable= "NO";
+
+ strxmov(buff,"'",user,"'@'",host,"'",NullS);
+ if (!(want_access & ~GRANT_ACL))
+ update_schema_privilege(table, buff, 0, 0, 0, 0, "USAGE", 5, is_grantable);
+ else
+ {
+ uint priv_id;
+ ulong j,test_access= want_access & ~GRANT_ACL;
+ for (priv_id=0, j = SELECT_ACL;j <= GLOBAL_ACLS; priv_id++,j <<= 1)
+ {
+ if (test_access & j)
+ update_schema_privilege(table, buff, 0, 0, 0, 0,
+ command_array[priv_id],
+ command_lengths[priv_id], is_grantable);
+ }
+ }
+ }
+ DBUG_RETURN(0);
+#else
+ return(0);
+#endif
+}
+
+
+int fill_schema_schema_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint counter;
+ ACL_DB *acl_db;
+ ulong want_access;
+ char buff[100];
+ TABLE *table= tables->table;
+ DBUG_ENTER("fill_schema_schema_privileges");
+
+ for (counter=0 ; counter < acl_dbs.elements ; counter++)
+ {
+ const char *user, *host, *is_grantable="YES";
+
+ acl_db=dynamic_element(&acl_dbs,counter,ACL_DB*);
+ if (!(user=acl_db->user))
+ user= "";
+ if (!(host=acl_db->host.hostname))
+ host= "";
+
+ want_access=acl_db->access;
+ if (want_access)
+ {
+ if (!(want_access & GRANT_ACL))
+ {
+ is_grantable= "NO";
+ }
+ strxmov(buff,"'",user,"'@'",host,"'",NullS);
+ if (!(want_access & ~GRANT_ACL))
+ update_schema_privilege(table, buff, acl_db->db, 0, 0,
+ 0, "USAGE", 5, is_grantable);
+ else
+ {
+ int cnt;
+ ulong j,test_access= want_access & ~GRANT_ACL;
+ for (cnt=0, j = SELECT_ACL; j <= DB_ACLS; cnt++,j <<= 1)
+ if (test_access & j)
+ update_schema_privilege(table, buff, acl_db->db, 0, 0, 0,
+ command_array[cnt], command_lengths[cnt],
+ is_grantable);
+ }
+ }
+ }
+ DBUG_RETURN(0);
+#else
+ return (0);
+#endif
+}
+
+
+int fill_schema_table_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint index;
+ char buff[100];
+ TABLE *table= tables->table;
+ DBUG_ENTER("fill_schema_table_privileges");
+
+ for (index=0 ; index < column_priv_hash.records ; index++)
+ {
+ const char *user, *is_grantable= "YES";
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ index);
+ if (!(user=grant_table->user))
+ user= "";
+ ulong table_access= grant_table->privs;
+ if (table_access != 0)
+ {
+ ulong test_access= table_access & ~GRANT_ACL;
+ if (!(table_access & GRANT_ACL))
+ is_grantable= "NO";
+
+ strxmov(buff,"'",user,"'@'",grant_table->orig_host,"'",NullS);
+ if (!test_access)
+ update_schema_privilege(table, buff, grant_table->db, grant_table->tname,
+ 0, 0, "USAGE", 5, is_grantable);
+ else
+ {
+ ulong j;
+ int cnt;
+ for (cnt= 0, j= SELECT_ACL; j <= TABLE_ACLS; cnt++, j<<= 1)
+ {
+ if (test_access & j)
+ update_schema_privilege(table, buff, grant_table->db,
+ grant_table->tname, 0, 0, command_array[cnt],
+ command_lengths[cnt], is_grantable);
+ }
+ }
+ }
+ }
+ DBUG_RETURN(0);
+#else
+ return (0);
+#endif
+}
+
+
+int fill_schema_column_privileges(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint index;
+ char buff[100];
+ TABLE *table= tables->table;
+ DBUG_ENTER("fill_schema_table_privileges");
+
+ for (index=0 ; index < column_priv_hash.records ; index++)
+ {
+ const char *user, *is_grantable= "YES";
+ GRANT_TABLE *grant_table= (GRANT_TABLE*) hash_element(&column_priv_hash,
+ index);
+ if (!(user=grant_table->user))
+ user= "";
+ ulong table_access= grant_table->cols;
+ if (table_access != 0)
+ {
+ if (!(grant_table->privs & GRANT_ACL))
+ is_grantable= "NO";
+
+ ulong test_access= table_access & ~GRANT_ACL;
+ strxmov(buff,"'",user,"'@'",grant_table->orig_host,"'",NullS);
+ if (!test_access)
+ continue;
+ else
+ {
+ ulong j;
+ int cnt;
+ for (cnt= 0, j= SELECT_ACL; j <= TABLE_ACLS; cnt++, j<<= 1)
+ {
+ if (test_access & j)
+ {
+ for (uint col_index=0 ;
+ col_index < grant_table->hash_columns.records ;
+ col_index++)
+ {
+ GRANT_COLUMN *grant_column = (GRANT_COLUMN*)
+ hash_element(&grant_table->hash_columns,col_index);
+ if ((grant_column->rights & j) && (table_access & j))
+ update_schema_privilege(table, buff, grant_table->db,
+ grant_table->tname,
+ grant_column->column,
+ grant_column->key_length,
+ command_array[cnt],
+ command_lengths[cnt], is_grantable);
+ }
+ }
+ }
+ }
+ }
+ }
+ DBUG_RETURN(0);
+#else
+ return (0);
+#endif
+}
+
+
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/*
fill effective privileges for table
@@ -3936,15 +4775,22 @@ int wild_case_compare(CHARSET_INFO *cs, const char *str,const char *wildstr)
void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
const char *db, const char *table)
{
+ /* --skip-grants */
+ if (!initialized)
+ {
+ grant->privilege= ~NO_ACCESS; // everything is allowed
+ return;
+ }
+
/* global privileges */
grant->privilege= thd->master_access;
- /* if privileges ignored (--skip-grant-tables) above is enough */
+ /* db privileges */
+ grant->privilege|= acl_get(thd->host, thd->ip, thd->priv_user, db, 0);
+
if (!grant_option)
return;
- /* db privileges */
- grant->privilege|= acl_get(thd->host, thd->ip, thd->priv_user, db, 0);
/* table privileges */
if (grant->version != grant_version)
{
diff --git a/sql/sql_acl.h b/sql/sql_acl.h
index 390106c1546..8f3ee072f43 100644
--- a/sql/sql_acl.h
+++ b/sql/sql_acl.h
@@ -158,11 +158,11 @@ bool check_change_password(THD *thd, const char *host, const char *user,
char *password);
bool change_password(THD *thd, const char *host, const char *user,
char *password);
-int mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
- ulong rights, bool revoke);
-int mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
- List <LEX_COLUMN> &column_list, ulong rights,
- bool revoke);
+bool mysql_grant(THD *thd, const char *db, List <LEX_USER> &user_list,
+ ulong rights, bool revoke);
+bool mysql_table_grant(THD *thd, TABLE_LIST *table, List <LEX_USER> &user_list,
+ List <LEX_COLUMN> &column_list, ulong rights,
+ bool revoke);
my_bool grant_init(THD *thd);
void grant_free(void);
void grant_reload(THD *thd);
@@ -179,11 +179,13 @@ ulong get_table_grant(THD *thd, TABLE_LIST *table);
ulong get_column_grant(THD *thd, GRANT_INFO *grant,
const char *db_name, const char *table_name,
const char *field_name);
-int mysql_show_grants(THD *thd, LEX_USER *user);
+bool mysql_show_grants(THD *thd, LEX_USER *user);
void get_privilege_desc(char *to, uint max_length, ulong access);
void get_mqh(const char *user, const char *host, USER_CONN *uc);
-int mysql_drop_user(THD *thd, List <LEX_USER> &list);
-int mysql_revoke_all(THD *thd, List <LEX_USER> &list);
+bool mysql_create_user(THD *thd, List <LEX_USER> &list);
+bool mysql_drop_user(THD *thd, List <LEX_USER> &list);
+bool mysql_rename_user(THD *thd, List <LEX_USER> &list);
+bool mysql_revoke_all(THD *thd, List <LEX_USER> &list);
void fill_effective_table_privileges(THD *thd, GRANT_INFO *grant,
const char *db, const char *table);
diff --git a/sql/sql_analyse.cc b/sql/sql_analyse.cc
index 1e0aebbc1ec..2259d3bead8 100644
--- a/sql/sql_analyse.cc
+++ b/sql/sql_analyse.cc
@@ -78,7 +78,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
{
// first parameter
if ((*param->item)->type() != Item::INT_ITEM ||
- (*param->item)->val() < 0)
+ (*param->item)->val_real() < 0)
{
delete pc;
my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
@@ -93,7 +93,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
}
// second parameter
if ((*param->item)->type() != Item::INT_ITEM ||
- (*param->item)->val() < 0)
+ (*param->item)->val_real() < 0)
{
delete pc;
my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
@@ -102,7 +102,7 @@ proc_analyse_init(THD *thd, ORDER *param, select_result *result,
pc->max_treemem = (uint) (*param->item)->val_int();
}
else if ((*param->item)->type() != Item::INT_ITEM ||
- (*param->item)->val() < 0)
+ (*param->item)->val_real() < 0)
{
delete pc;
my_error(ER_WRONG_PARAMETERS_TO_PROCEDURE, MYF(0), proc_name);
@@ -364,7 +364,7 @@ void field_str::add()
void field_real::add()
{
char buff[MAX_FIELD_WIDTH], *ptr, *end;
- double num = item->val();
+ double num= item->val_real();
uint length, zero_count, decs;
TREE_ELEMENT *element;
diff --git a/sql/sql_base.cc b/sql/sql_base.cc
index b3be1fc7338..b4a2f368bc2 100644
--- a/sql/sql_base.cc
+++ b/sql/sql_base.cc
@@ -44,6 +44,7 @@ static my_bool open_new_frm(const char *path, const char *alias,
uint db_stat, uint prgflag,
uint ha_open_flags, TABLE *outparam,
TABLE_LIST *table_desc, MEM_ROOT *mem_root);
+static void relink_tables_for_multidelete(THD *thd);
extern "C" byte *table_cache_key(const byte *record,uint *length,
my_bool not_used __attribute__((unused)))
@@ -369,7 +370,8 @@ bool close_cached_tables(THD *thd, bool if_wait_for_refresh,
Put all normal tables used by thread in free list.
*/
-void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
+void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived,
+ TABLE *stopper)
{
bool found_old_table;
DBUG_ENTER("close_thread_tables");
@@ -407,7 +409,7 @@ void close_thread_tables(THD *thd, bool lock_in_use, bool skip_derived)
DBUG_PRINT("info", ("thd->open_tables: %p", thd->open_tables));
found_old_table= 0;
- while (thd->open_tables)
+ while (thd->open_tables != stopper)
found_old_table|=close_thread_table(thd, &thd->open_tables);
thd->some_tables_deleted=0;
@@ -508,7 +510,7 @@ void close_temporary_tables(THD *thd)
*/
query_buf_size+= table->key_length+1;
- if ((query = alloc_root(&thd->mem_root, query_buf_size)))
+ if ((query = alloc_root(thd->mem_root, query_buf_size)))
// Better add "if exists", in case a RESET MASTER has been done
end=strmov(query, "DROP /*!40005 TEMPORARY */ TABLE IF EXISTS ");
@@ -533,7 +535,7 @@ void close_temporary_tables(THD *thd)
{
/* The -1 is to remove last ',' */
thd->clear_error();
- Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0);
+ Query_log_event qinfo(thd, query, (ulong)(end-query)-1, 0, FALSE);
/*
Imagine the thread had created a temp table, then was doing a SELECT, and
the SELECT was killed. Then it's not clever to mark the statement above as
@@ -555,10 +557,10 @@ void close_temporary_tables(THD *thd)
SYNOPSIS
find_table_in_list()
- table Pointer to table list
+ table Pointer to table list
offset Offset to which list in table structure to use
- db_name Data base name
- table_name Table name
+ db_name Data base name
+ table_name Table name
NOTES:
This is called by find_table_in_local_list() and
@@ -578,13 +580,14 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
{
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
{
- if ((!strcmp(table->db, db_name) &&
- !strcmp(table->real_name, table_name)) ||
- (table->view &&
- !my_strcasecmp(table_alias_charset,
- table->table->table_cache_key, db_name) &&
- !my_strcasecmp(table_alias_charset,
- table->table->table_name, table_name)))
+ if ((table->table == 0 || table->table->tmp_table == NO_TMP_TABLE) &&
+ ((!strcmp(table->db, db_name) &&
+ !strcmp(table->real_name, table_name)) ||
+ (table->view &&
+ !my_strcasecmp(table_alias_charset,
+ table->table->table_cache_key, db_name) &&
+ !my_strcasecmp(table_alias_charset,
+ table->table->table_name, table_name))))
break;
}
}
@@ -592,11 +595,12 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
{
for (; table; table= *(TABLE_LIST **) ((char*) table + offset))
{
- if ((!strcmp(table->db, db_name) &&
- !strcmp(table->real_name, table_name)) ||
- (table->view &&
- !strcmp(table->table->table_cache_key, db_name) &&
- !strcmp(table->table->table_name, table_name)))
+ if ((table->table == 0 || table->table->tmp_table == NO_TMP_TABLE) &&
+ ((!strcmp(table->db, db_name) &&
+ !strcmp(table->real_name, table_name)) ||
+ (table->view &&
+ !strcmp(table->table->table_cache_key, db_name) &&
+ !strcmp(table->table->table_name, table_name))))
break;
}
}
@@ -619,9 +623,14 @@ TABLE_LIST *find_table_in_list(TABLE_LIST *table,
TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
{
+ DBUG_ENTER("unique_table");
+ DBUG_PRINT("enter", ("table alias: %s", table->alias));
TABLE_LIST *res;
const char *d_name= table->db, *t_name= table->real_name;
char d_name_buff[MAX_ALIAS_NAME], t_name_buff[MAX_ALIAS_NAME];
+ /* temporary table is always unique */
+ if (table->table && table->table->tmp_table != NO_TMP_TABLE)
+ return 0;
if (table->view)
{
/* it is view and table opened */
@@ -639,19 +648,19 @@ TABLE_LIST* unique_table(TABLE_LIST *table, TABLE_LIST *table_list)
d_name= table->table->table_cache_key;
t_name= table->table->table_name;
}
- if (d_name == 0)
- {
- /* it's temporary table => always unique */
- return 0;
- }
}
- if ((res= find_table_in_global_list(table_list, d_name, t_name)) &&
- res->table && res->table == table->table)
+
+ DBUG_PRINT("info", ("real table: %s.%s", d_name, t_name));
+ for(;;)
{
- // we found entry of this table try again.
- return find_table_in_global_list(res->next_global, d_name, t_name);
+ if (!(res= find_table_in_global_list(table_list, d_name, t_name)) ||
+ !res->table || res->table != table->table)
+ break;
+ /* if we found entry of this table try again. */
+ table_list= res->next_global;
+ DBUG_PRINT("info", ("found same copy of table"));
}
- return res;
+ DBUG_RETURN(res);
}
@@ -815,7 +824,7 @@ TABLE *reopen_name_locked_table(THD* thd, TABLE_LIST* table_list)
pthread_mutex_lock(&LOCK_open);
if (open_unireg_entry(thd, table, db, table_name, table_name, 0,
- &thd->mem_root) ||
+ thd->mem_root) ||
!(table->table_cache_key =memdup_root(&table->mem_root,(char*) key,
key_length)))
{
@@ -883,8 +892,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
{
if (table->query_id == thd->query_id)
{
- my_printf_error(ER_CANT_REOPEN_TABLE,
- ER(ER_CANT_REOPEN_TABLE), MYF(0), table->table_name);
+ my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->table_name);
DBUG_RETURN(0);
}
table->query_id= thd->query_id;
@@ -941,7 +949,7 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
VOID(pthread_mutex_unlock(&LOCK_open));
}
}
- my_printf_error(ER_TABLE_NOT_LOCKED,ER(ER_TABLE_NOT_LOCKED),MYF(0),alias);
+ my_error(ER_TABLE_NOT_LOCKED, MYF(0), alias);
DBUG_RETURN(0);
}
@@ -1042,8 +1050,11 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
table->reginfo.lock_type=TL_READ; /* Assume read */
reset:
+ if (thd->lex->need_correct_ident())
+ table->alias_name_used= my_strcasecmp(table_alias_charset,
+ table->real_name, alias);
/* Fix alias if table name changes */
- if (strcmp(table->table_name,alias))
+ if (strcmp(table->table_name, alias))
{
uint length=(uint) strlen(alias)+1;
table->table_name= (char*) my_realloc(table->table_name,length,
@@ -1052,31 +1063,6 @@ TABLE *open_table(THD *thd, TABLE_LIST *table_list, MEM_ROOT *mem_root,
for (uint i=0 ; i < table->fields ; i++)
table->field[i]->table_name=table->table_name;
}
-#if MYSQL_VERSION_ID < 40100
- /*
- If per-connection "new" variable (represented by variables.new_mode)
- is set then we should pretend that the length of TIMESTAMP field is 19.
- The cheapest (from perfomance viewpoint) way to achieve that is to set
- field_length of all Field_timestamp objects in a table after opening
- it (to 19 if new_mode is true or to original field length otherwise).
- We save value of new_mode variable in TABLE::timestamp_mode to
- not perform this setup if new_mode value is the same between sequential
- table opens.
- */
- my_bool new_mode= thd->variables.new_mode;
- if (table->timestamp_mode != new_mode)
- {
- for (uint i=0 ; i < table->fields ; i++)
- {
- Field *field= table->field[i];
-
- if (field->type() == FIELD_TYPE_TIMESTAMP)
- field->field_length= new_mode ? 19 :
- ((Field_timestamp *)(field))->orig_field_length;
- }
- table->timestamp_mode= new_mode;
- }
-#endif
/* These variables are also set in reopen_table() */
table->tablenr=thd->current_tablenr++;
table->used_fields=0;
@@ -1135,7 +1121,7 @@ bool reopen_table(TABLE *table,bool locked)
safe_mutex_assert_owner(&LOCK_open);
if (open_unireg_entry(table->in_use, &tmp, db, table_name,
- table->table_name, 0, &table->in_use->mem_root))
+ table->table_name, 0, table->in_use->mem_root))
goto end;
free_io_cache(table);
@@ -1254,7 +1240,7 @@ bool reopen_tables(THD *thd,bool get_locks,bool in_refresh)
next=table->next;
if (!tables || (!db_stat && reopen_table(table,1)))
{
- my_error(ER_CANT_REOPEN_TABLE,MYF(0),table->table_name);
+ my_error(ER_CANT_REOPEN_TABLE, MYF(0), table->table_name);
VOID(hash_delete(&open_cache,(byte*) table));
error=1;
}
@@ -1576,7 +1562,7 @@ static int open_unireg_entry(THD *thd, TABLE *entry, const char *db,
{
end = strxmov(strmov(query, "DELETE FROM `"),
db,"`.`",name,"`", NullS);
- Query_log_event qinfo(thd, query, (ulong)(end-query), 0);
+ Query_log_event qinfo(thd, query, (ulong)(end-query), 0, FALSE);
mysql_bin_log.write(&qinfo);
my_free(query, MYF(0));
}
@@ -1648,6 +1634,12 @@ int open_tables(THD *thd, TABLE_LIST *start, uint *counter)
*/
if (tables->derived)
continue;
+ if (tables->schema_table)
+ {
+ if (!mysql_schema_table(thd, thd->lex, tables))
+ continue;
+ DBUG_RETURN(-1);
+ }
(*counter)++;
if (!tables->table &&
!(tables->table= open_table(thd, tables, &new_frm_mem, &refresh)))
@@ -1732,9 +1724,7 @@ static bool check_lock_and_start_stmt(THD *thd, TABLE *table,
if ((int) lock_type >= (int) TL_WRITE_ALLOW_READ &&
(int) table->reginfo.lock_type < (int) TL_WRITE_ALLOW_READ)
{
- my_printf_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,
- ER(ER_TABLE_NOT_LOCKED_FOR_WRITE),
- MYF(0),table->table_name);
+ my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0),table->table_name);
DBUG_RETURN(1);
}
if ((error=table->file->start_stmt(thd)))
@@ -1774,7 +1764,7 @@ TABLE *open_ltable(THD *thd, TABLE_LIST *table_list, thr_lock_type lock_type)
thd->current_tablenr= 0;
/* open_ltable can be used only for BASIC TABLEs */
table_list->required_type= FRMTYPE_TABLE;
- while (!(table= open_table(thd, table_list, &thd->mem_root, &refresh)) &&
+ while (!(table= open_table(thd, table_list, thd->mem_root, &refresh)) &&
refresh)
;
@@ -1845,33 +1835,34 @@ int simple_open_n_lock_tables(THD *thd, TABLE_LIST *tables)
tables - list of tables for open&locking
RETURN
- 0 - ok
- -1 - error
- 1 - error reported to user
+ FALSE - ok
+ TRUE - error
NOTE
The lock will automaticly be freed by close_thread_tables()
*/
-int open_and_lock_tables(THD *thd, TABLE_LIST *tables)
+bool open_and_lock_tables(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("open_and_lock_tables");
uint counter;
- if (open_tables(thd, tables, &counter) ||
+ if (open_tables(thd, tables, &counter) ||
lock_tables(thd, tables, counter) ||
- mysql_handle_derived(thd->lex))
- DBUG_RETURN(thd->net.report_error ? -1 : 1); /* purecov: inspected */
- relink_tables_for_derived(thd);
+ mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
+ (thd->fill_derived_tables() &&
+ mysql_handle_derived(thd->lex, &mysql_derived_filling)))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ relink_tables_for_multidelete(thd);
DBUG_RETURN(0);
}
/*
Let us propagate pointers to open tables from global table list
- to table lists in particular selects if needed.
+ to table lists for multi-delete
*/
-void relink_tables_for_derived(THD *thd)
+static void relink_tables_for_multidelete(THD *thd)
{
if (thd->lex->all_selects_list->next_select_in_list() ||
thd->lex->time_zone_tables_used)
@@ -1925,7 +1916,7 @@ int lock_tables(THD *thd, TABLE_LIST *tables, uint count)
return -1;
for (table= tables; table; table= table->next_global)
{
- if (!table->placeholder())
+ if (!table->placeholder() && !table->schema_table)
*(ptr++)= table->table;
}
if (!(thd->lock=mysql_lock_tables(thd,start, (uint) (ptr - start))))
@@ -2035,8 +2026,8 @@ bool rm_temporary_table(enum db_type base, char *path)
******************************************************************************/
/* Special Field pointers for find_field_in_tables returning */
-const Field *not_found_field= (Field*) 0x1;
-const Field *view_ref_found= (Field*) 0x2;
+Field *not_found_field= (Field*) 0x1;
+Field *view_ref_found= (Field*) 0x2;
#define WRONG_GRANT (Field*) -1
@@ -2059,6 +2050,8 @@ const Field *view_ref_found= (Field*) 0x2;
allow_rowid do allow finding of "_rowid" field?
cached_field_index_ptr cached position in field list (used to
speedup prepared tables field finding)
+ register_tree_change TRUE if ref is not stack variable and we
+ need register changes in item tree
RETURN
0 field is not found
@@ -2072,17 +2065,21 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
uint length, Item **ref,
bool check_grants_table, bool check_grants_view,
bool allow_rowid,
- uint *cached_field_index_ptr)
+ uint *cached_field_index_ptr,
+ bool register_tree_change)
{
+ DBUG_ENTER("find_field_in_table");
+ DBUG_PRINT("enter", ("table:%s name: %s item name %s, ref 0x%lx",
+ table_list->alias, name, item_name, (ulong)ref));
Field *fld;
if (table_list->field_translation)
{
DBUG_ASSERT(ref != 0 && table_list->view != 0);
uint num= table_list->view->select_lex.item_list.elements;
- Item **trans= table_list->field_translation;
+ Field_translator *trans= table_list->field_translation;
for (uint i= 0; i < num; i ++)
{
- if (strcmp(trans[i]->name, name) == 0)
+ if (strcmp(trans[i].name, name) == 0)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (check_grants_view &&
@@ -2090,25 +2087,26 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
table_list->view_db.str,
table_list->view_name.str,
name, length))
- return WRONG_GRANT;
+ DBUG_RETURN(WRONG_GRANT);
#endif
if (thd->lex->current_select->no_wrap_view_item)
- *ref= trans[i];
+ *ref= trans[i].item;
else
{
- Item_ref *item_ref= new Item_ref(trans + i, table_list->view_name.str,
+ Item_ref *item_ref= new Item_ref(&trans[i].item,
+ table_list->view_name.str,
item_name);
/* as far as Item_ref have defined reference it do not need tables */
- if (item_ref)
+ if (register_tree_change && item_ref)
{
thd->change_item_tree(ref, item_ref);
(*ref)->fix_fields(thd, 0, ref);
}
}
- return (Field*) view_ref_found;
+ DBUG_RETURN((Field*) view_ref_found);
}
}
- return 0;
+ DBUG_RETURN(0);
}
fld= find_field_in_real_table(thd, table_list->table, name, length,
check_grants_table, allow_rowid,
@@ -2122,10 +2120,10 @@ find_field_in_table(THD *thd, TABLE_LIST *table_list,
table_list->view_name.str,
name, length))
{
- return WRONG_GRANT;
+ DBUG_RETURN(WRONG_GRANT);
}
#endif
- return fld;
+ DBUG_RETURN(fld);
}
@@ -2214,25 +2212,32 @@ Field *find_field_in_real_table(THD *thd, TABLE *table,
find_field_in_tables()
thd Pointer to current thread structure
item Field item that should be found
- tables Tables for scanning
- ref if view field is found, pointer to view item will
- be returned via this parameter
- report_error If FALSE then do not report error if item not found
- and return not_found_field
+ tables Tables to be searched for item
+ ref If 'item' is resolved to a view field, ref is set to
+ point to the found view field
+ report_error Degree of error reporting:
+ - IGNORE_ERRORS then do not report any error
+ - IGNORE_EXCEPT_NON_UNIQUE report only non-unique
+ fields, suppress all other errors
+ - REPORT_EXCEPT_NON_UNIQUE report all other errors
+ except when non-unique fields were found
+ - REPORT_ALL_ERRORS
check_privileges need to check privileges
RETURN VALUES
- 0 Field is not found or field is not unique- error
- message is reported
- not_found_field Function was called with report_error == FALSE and
- field was not found. no error message reported.
- view_ref_found view field is found, item passed through ref parameter
- found field
+ 0 If error: the found field is not unique, or there are
+ no sufficient access priviliges for the found field,
+ or the field is qualified with non-existing table.
+ not_found_field The function was called with report_error ==
+ (IGNORE_ERRORS || IGNORE_EXCEPT_NON_UNIQUE) and a
+ field was not found.
+ view_ref_found View field is found, item passed through ref parameter
+ found field If a item was resolved to some field
*/
Field *
find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
- Item **ref, bool report_error,
+ Item **ref, find_item_error_report_type report_error,
bool check_privileges)
{
Field *found=0;
@@ -2250,21 +2255,38 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
TABLE_LIST *tables is not changed during query execution (which
is true for all queries except RENAME but luckily RENAME doesn't
use fields...) so we can rely on reusing pointer to its member.
- With this optimisation we also miss case when addition of one more
- field makes some prepared query ambiguous and so erronous, but we
+ With this optimization we also miss case when addition of one more
+ field makes some prepared query ambiguous and so erroneous, but we
accept this trade off.
*/
- found= find_field_in_real_table(thd, item->cached_table->table,
- name, length,
- test(item->cached_table->
- table->grant.want_privilege) &&
- check_privileges,
- 1, &(item->cached_field_index));
+ if (item->cached_table->table)
+ {
+ found= find_field_in_real_table(thd, item->cached_table->table,
+ name, length,
+ test(item->cached_table->
+ table->grant.want_privilege) &&
+ check_privileges,
+ 1, &(item->cached_field_index));
+ }
+ else
+ {
+ TABLE_LIST *table= item->cached_table;
+ Field *find= find_field_in_table(thd, table, name, item->name, length,
+ ref,
+ (table->table &&
+ test(table->table->grant.
+ want_privilege) &&
+ check_privileges),
+ (test(table->grant.want_privilege) &&
+ check_privileges),
+ 1, &(item->cached_field_index),
+ TRUE);
+ }
if (found)
{
if (found == WRONG_GRANT)
- return (Field*) 0;
+ return (Field*) 0;
return found;
}
}
@@ -2272,7 +2294,7 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
if (db && lower_case_table_names)
{
/*
- convert database to lower case for comparision.
+ convert database to lower case for comparison.
We can't do this in Item_field as this would change the
'name' of the item which may be used in the select list
*/
@@ -2292,12 +2314,14 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
found_table=1;
Field *find= find_field_in_table(thd, tables, name, item->name,
length, ref,
- (test(tables->table->grant.
+ (tables->table &&
+ test(tables->table->grant.
want_privilege) &&
check_privileges),
(test(tables->grant.want_privilege) &&
check_privileges),
- 1, &(item->cached_field_index));
+ 1, &(item->cached_field_index),
+ TRUE);
if (find)
{
item->cached_table= tables;
@@ -2309,8 +2333,10 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
return find;
if (found)
{
- my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
- item->full_name(),thd->where);
+ if (report_error == REPORT_ALL_ERRORS ||
+ report_error == IGNORE_EXCEPT_NON_UNIQUE)
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ item->full_name(),thd->where);
return (Field*) 0;
}
found=find;
@@ -2319,7 +2345,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
}
if (found)
return found;
- if (!found_table && report_error)
+ if (!found_table && (report_error == REPORT_ALL_ERRORS ||
+ report_error == REPORT_EXCEPT_NON_UNIQUE))
{
char buff[NAME_LEN*2+1];
if (db && db[0])
@@ -2327,41 +2354,43 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
strxnmov(buff,sizeof(buff)-1,db,".",table_name,NullS);
table_name=buff;
}
- if (report_error)
- {
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- table_name, thd->where);
- }
+ if (report_error == REPORT_ALL_ERRORS ||
+ report_error == REPORT_EXCEPT_NON_UNIQUE)
+ my_error(ER_UNKNOWN_TABLE, MYF(0), table_name, thd->where);
else
return (Field*) not_found_field;
}
else
- if (report_error)
- my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
- item->full_name(),thd->where);
+ if (report_error == REPORT_ALL_ERRORS ||
+ report_error == REPORT_EXCEPT_NON_UNIQUE)
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(),thd->where);
else
return (Field*) not_found_field;
return (Field*) 0;
}
+
bool allow_rowid= tables && !tables->next_local; // Only one table
for (; tables ; tables= tables->next_local)
{
- if (!tables->table)
+ if (!tables->table && !tables->ancestor)
{
- if (report_error)
- my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),MYF(0),
- item->full_name(),thd->where);
+ if (report_error == REPORT_ALL_ERRORS ||
+ report_error == REPORT_EXCEPT_NON_UNIQUE)
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(),thd->where);
return (Field*) not_found_field;
}
Field *field= find_field_in_table(thd, tables, name, item->name,
length, ref,
- (test(tables->table->grant.
+ (tables->table &&
+ test(tables->table->grant.
want_privilege) &&
check_privileges),
(test(tables->grant.want_privilege) &&
check_privileges),
- allow_rowid, &(item->cached_field_index));
+ allow_rowid,
+ &(item->cached_field_index),
+ TRUE);
if (field)
{
if (field == WRONG_GRANT)
@@ -2373,8 +2402,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
{
if (!thd->where) // Returns first found
break;
- my_printf_error(ER_NON_UNIQ_ERROR,ER(ER_NON_UNIQ_ERROR),MYF(0),
- name,thd->where);
+ if (report_error == REPORT_ALL_ERRORS ||
+ report_error == IGNORE_EXCEPT_NON_UNIQUE)
+ my_error(ER_NON_UNIQ_ERROR, MYF(0), name, thd->where);
return (Field*) 0;
}
found=field;
@@ -2382,9 +2412,9 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
}
if (found)
return found;
- if (report_error)
- my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR),
- MYF(0), item->full_name(), thd->where);
+ if (report_error == REPORT_ALL_ERRORS ||
+ report_error == REPORT_EXCEPT_NON_UNIQUE)
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), item->full_name(), thd->where);
else
return (Field*) not_found_field;
return (Field*) 0;
@@ -2421,8 +2451,8 @@ find_field_in_tables(THD *thd, Item_ident *item, TABLE_LIST *tables,
found field
*/
-// Special Item pointer for find_item_in_list returning
-const Item **not_found_item= (const Item**) 0x1;
+/* Special Item pointer to serve as a return value from find_item_in_list(). */
+Item **not_found_item= (Item**) 0x1;
Item **
@@ -2496,8 +2526,8 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
unaliased names only and will have duplicate error anyway.
*/
if (report_error != IGNORE_ERRORS)
- my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR),
- MYF(0), find->full_name(), current_thd->where);
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ find->full_name(), current_thd->where);
return (Item**) 0;
}
found_unaliased= li.ref();
@@ -2521,8 +2551,8 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
if ((*found)->eq(item, 0))
continue; // Same field twice
if (report_error != IGNORE_ERRORS)
- my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR),
- MYF(0), find->full_name(), current_thd->where);
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ find->full_name(), current_thd->where);
return (Item**) 0;
}
found= li.ref();
@@ -2565,8 +2595,8 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
if (found_unaliased_non_uniq)
{
if (report_error != IGNORE_ERRORS)
- my_printf_error(ER_NON_UNIQ_ERROR, ER(ER_NON_UNIQ_ERROR), MYF(0),
- find->full_name(), current_thd->where);
+ my_error(ER_NON_UNIQ_ERROR, MYF(0),
+ find->full_name(), current_thd->where);
return (Item **) 0;
}
if (found_unaliased)
@@ -2581,8 +2611,8 @@ find_item_in_list(Item *find, List<Item> &items, uint *counter,
if (report_error != REPORT_EXCEPT_NOT_FOUND)
{
if (report_error == REPORT_ALL_ERRORS)
- my_printf_error(ER_BAD_FIELD_ERROR, ER(ER_BAD_FIELD_ERROR), MYF(0),
- find->full_name(), current_thd->where);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
+ find->full_name(), current_thd->where);
return (Item **) 0;
}
else
@@ -2597,24 +2627,20 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
List<Item> *sum_func_list,
uint wild_num)
{
- Item *item;
- DBUG_ENTER("setup_wild");
-
if (!wild_num)
- DBUG_RETURN(0);
+ return(0);
- Item_arena *arena= thd->current_arena, backup;
+ Item *item;
+ List_iterator<Item> it(fields);
+ Item_arena *arena, backup;
+ DBUG_ENTER("setup_wild");
/*
Don't use arena if we are not in prepared statements or stored procedures
For PS/SP we have to use arena to remember the changes
*/
- if (arena->is_conventional())
- arena= 0; // For easier test later one
- else
- thd->set_n_backup_item_arena(arena, &backup);
+ arena= thd->change_arena_if_needed(&backup);
- List_iterator<Item> it(fields);
while (wild_num && (item= it++))
{
if (item->type() == Item::FIELD_ITEM &&
@@ -2671,9 +2697,9 @@ int setup_wild(THD *thd, TABLE_LIST *tables, List<Item> &fields,
** Check that all given fields exists and fill struct with current data
****************************************************************************/
-int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
- List<Item> &fields, bool set_query_id,
- List<Item> *sum_func_list, bool allow_sum_func)
+bool setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ List<Item> &fields, bool set_query_id,
+ List<Item> *sum_func_list, bool allow_sum_func)
{
reg2 Item *item;
List_iterator<Item> it(fields);
@@ -2690,8 +2716,7 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
if (!item->fixed && item->fix_fields(thd, tables, it.ref()) ||
(item= *(it.ref()))->check_cols(1))
{
- select_lex->no_wrap_view_item= 0;
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(TRUE); /* purecov: inspected */
}
if (ref)
*(ref++)= item;
@@ -2705,39 +2730,96 @@ int setup_fields(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
/*
+ make list of leaves of join table tree
+
+ SYNOPSIS
+ make_leaves_list()
+ list pointer to pointer on list first element
+ tables table list
+
+ RETURN pointer on pointer to next_leaf of last element
+*/
+
+TABLE_LIST **make_leaves_list(TABLE_LIST **list, TABLE_LIST *tables)
+{
+ for (TABLE_LIST *table= tables; table; table= table->next_local)
+ {
+ if (table->view && !table->table)
+ {
+ /* it is for multi table views only, check it */
+ DBUG_ASSERT(table->ancestor->next_local);
+ list= make_leaves_list(list, table->ancestor);
+ }
+ else
+ {
+ *list= table;
+ list= &table->next_leaf;
+ }
+ }
+ return list;
+}
+
+/*
prepare tables
SYNOPSIS
setup_tables()
- thd Thread handler
- tables Table list
- conds Condition of current SELECT (can be changed by VIEW)
+ thd Thread handler
+ tables Table list
+ conds Condition of current SELECT (can be changed by VIEW)
+ leaves List of join table leaves list
+ refresh It is onle refresh for subquery
+ select_insert It is SELECT ... INSERT command
NOTE
- Remap table numbers if INSERT ... SELECT
Check also that the 'used keys' and 'ignored keys' exists and set up the
table structure accordingly
+ Create leaf tables list
This has to be called for all tables that are used by items, as otherwise
table->map is not set and all Item_field will be regarded as const items.
RETURN
- 0 ok; In this case *map will includes the choosed index
- 1 error
+ FALSE ok; In this case *map will includes the choosed index
+ TRUE error
*/
-bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds)
+bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds,
+ TABLE_LIST **leaves, bool refresh, bool select_insert)
{
DBUG_ENTER("setup_tables");
+ /*
+ this is used for INSERT ... SELECT.
+ For select we setup tables except first (and its underlying tables)
+ */
+ TABLE_LIST *first_select_table= (select_insert ?
+ tables->next_local:
+ 0);
if (!tables || tables->setup_is_done)
DBUG_RETURN(0);
tables->setup_is_done= 1;
- uint tablenr=0;
- for (TABLE_LIST *table_list= tables;
+
+
+ if (!(*leaves))
+ {
+ make_leaves_list(leaves, tables);
+ }
+
+ uint tablenr= 0;
+ for (TABLE_LIST *table_list= *leaves;
table_list;
- table_list= table_list->next_local, tablenr++)
+ table_list= table_list->next_leaf, tablenr++)
{
TABLE *table= table_list->table;
+ if (first_select_table &&
+ (table_list->belong_to_view ?
+ table_list->belong_to_view :
+ table_list) == first_select_table)
+ {
+ /* new counting for SELECT of INSERT ... SELECT command */
+ first_select_table= 0;
+ tablenr= 0;
+ }
setup_table_map(table, table_list, tablenr);
table->used_keys= table->keys_for_keyread;
if (table_list->use_index)
@@ -2757,16 +2839,24 @@ bool setup_tables(THD *thd, TABLE_LIST *tables, Item **conds)
table->keys_in_use_for_query.subtract(map);
}
table->used_keys.intersect(table->keys_in_use_for_query);
- if (table_list->ancestor &&
- table_list->setup_ancestor(thd, conds,
- table_list->effective_with_check))
- DBUG_RETURN(1);
}
if (tablenr > MAX_TABLES)
{
my_error(ER_TOO_MANY_TABLES,MYF(0),MAX_TABLES);
DBUG_RETURN(1);
}
+ if (!refresh)
+ {
+ for (TABLE_LIST *table_list= tables;
+ table_list;
+ table_list= table_list->next_local)
+ {
+ if (table_list->ancestor &&
+ table_list->setup_ancestor(thd, conds,
+ table_list->effective_with_check))
+ DBUG_RETURN(1);
+ }
+ }
DBUG_RETURN(0);
}
@@ -2799,8 +2889,8 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
(pos= find_type(&table->keynames, name->ptr(), name->length(), 1)) <=
0)
{
- my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), name->c_ptr(),
- table->real_name);
+ my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0),
+ name->c_ptr(), table->real_name);
map->set_all();
return 1;
}
@@ -2823,7 +2913,8 @@ bool get_key_map_from_key_list(key_map *map, TABLE *table,
any_privileges 0 If we should ensure that we have SELECT privileges
for all columns
1 If any privilege is ok
- allocate_view_names if true view names will be copied to current Item_arena memory (made for SP/PS)
+ allocate_view_names if true view names will be copied to current Item_arena
+ memory (made for SP/PS)
RETURN
0 ok
'it' is updated to point at last inserted
@@ -2869,9 +2960,12 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
tables->alias) &&
(!db_name || !strcmp(tables->db,db_name))))
{
+ bool view;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
/* Ensure that we have access right to all columns */
- if (!(table->grant.privilege & SELECT_ACL) && !any_privileges)
+ if (!((table && (table->grant.privilege & SELECT_ACL) ||
+ tables->view && (tables->grant.privilege & SELECT_ACL))) &&
+ !any_privileges)
{
if (tables->view)
{
@@ -2882,8 +2976,9 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
&view_iter))
goto err;
}
- else
+ else if (!tables->schema_table)
{
+ DBUG_ASSERT(table != 0);
table_iter.set(tables);
if (check_grant_all_columns(thd, SELECT_ACL, &table->grant,
table->table_cache_key, table->real_name,
@@ -2892,8 +2987,17 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
}
}
#endif
+ if (table)
+ thd->used_tables|= table->map;
+ else
+ {
+ view_iter.set(tables);
+ for (; !view_iter.end_of_fields(); view_iter.next())
+ {
+ thd->used_tables|= view_iter.item(thd)->used_tables();
+ }
+ }
natural_join_table= 0;
- thd->used_tables|= table->map;
last= embedded= tables;
while ((embedding= embedded->embedding) &&
@@ -2920,9 +3024,15 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
natural_join_table= embedding;
}
if (tables->field_translation)
+ {
iterator= &view_iter;
+ view= 1;
+ }
else
+ {
iterator= &table_iter;
+ view= 0;
+ }
iterator->set(tables);
for (; !iterator->end_of_fields(); iterator->next())
@@ -2935,13 +3045,18 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
!find_field_in_table(thd, natural_join_table, field_name,
field_name,
strlen(field_name), &not_used_item, 0, 0, 0,
- &not_used_field_index))
+ &not_used_field_index, TRUE))
{
Item *item= iterator->item(thd);
if (!found++)
(void) it->replace(item); // Replace '*'
else
it->after(item);
+ if (view && !thd->lex->current_select->no_wrap_view_item)
+ {
+ item= new Item_ref(it->ref(), tables->view_name.str,
+ field_name);
+ }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
if (any_privileges)
{
@@ -2962,21 +3077,20 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
db= tables->db;
tab= tables->real_name;
}
- if (!(fld->have_privileges= (get_column_grant(thd,
+ if (!tables->schema_table &&
+ !(fld->have_privileges= (get_column_grant(thd,
&table->grant,
db,
tab,
fld->field_name) &
VIEW_ANY_ACL)))
{
- my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
- ER(ER_COLUMNACCESS_DENIED_ERROR),
- MYF(0),
- "ANY",
- thd->priv_user,
- thd->host_or_ip,
- fld->field_name,
- tab);
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ "ANY",
+ thd->priv_user,
+ thd->host_or_ip,
+ fld->field_name,
+ tab);
goto err;
}
}
@@ -3003,36 +3117,49 @@ insert_fields(THD *thd, TABLE_LIST *tables, const char *db_name,
during cleunup() this item will be put in list to replace
expression from VIEW
*/
- thd->nocheck_register_item_tree_change(it->ref(), item, &thd->mem_root);
+ thd->nocheck_register_item_tree_change(it->ref(), item,
+ thd->mem_root);
}
}
- /* All fields are used */
- table->used_fields=table->fields;
+ /*
+ All fields are used in case if usual tables (in case of view used
+ fields marked in setup_tables during fix_fields of view columns
+ */
+ if (table)
+ table->used_fields=table->fields;
}
}
if (found)
DBUG_RETURN(0);
if (!table_name)
- my_error(ER_NO_TABLES_USED, MYF(0));
+ my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0));
else
my_error(ER_BAD_TABLE_ERROR, MYF(0), table_name);
-
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
err:
+#endif
DBUG_RETURN(1);
}
/*
-** Fix all conditions and outer join expressions
+ Fix all conditions and outer join expressions
+
+ SYNOPSIS
+ setup_conds()
+ thd thread handler
+ tables list of tables for name resolving
+ leaves list of leaves of join table tree
*/
-int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
+int setup_conds(THD *thd, TABLE_LIST *tables, TABLE_LIST *leaves, COND **conds)
{
table_map not_null_tables= 0;
SELECT_LEX *select_lex= thd->lex->current_select;
Item_arena *arena= thd->current_arena, backup;
bool save_wrapper= thd->lex->current_select->no_wrap_view_item;
+ TABLE_LIST *table= NULL; // For HP compilers
DBUG_ENTER("setup_conds");
if (select_lex->conds_processed_with_permanent_arena ||
@@ -3052,7 +3179,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
/* Check if we are using outer joins */
- for (TABLE_LIST *table= tables; table; table= table->next_local)
+ for (table= leaves; table; table= table->next_leaf)
{
TABLE_LIST *embedded;
TABLE_LIST *embedding= table;
@@ -3108,7 +3235,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
}
if (arena)
- thd->set_n_backup_item_arena(arena, &backup);
+ arena= thd->change_arena_if_needed(&backup);
TABLE *t1=tab1->table;
TABLE *t2=tab2->table;
@@ -3116,8 +3243,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
Field_iterator_view view_iter;
Field_iterator *iterator;
Field *t1_field, *t2_field;
- Item *item_t2;
- Item_cond_and *cond_and=new Item_cond_and();
+ Item *item_t2= 0;
+ Item_cond_and *cond_and= new Item_cond_and();
if (!cond_and) // If not out of memory
goto err_no_arena;
@@ -3143,7 +3270,8 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
t1_field_name,
strlen(t1_field_name), &item_t2,
0, 0, 0,
- &not_used_field_index)))
+ &not_used_field_index,
+ FALSE)))
{
if (t2_field != view_ref_found)
{
@@ -3209,7 +3337,7 @@ int setup_conds(THD *thd,TABLE_LIST *tables,COND **conds)
embedding->nested_join->join_list.head() == embedded);
}
- if (arena)
+ if (!thd->current_arena->is_conventional())
{
/*
We are in prepared statement preparation code => we should store
@@ -3237,8 +3365,25 @@ err_no_arena:
** Returns : 1 if some field has wrong type
******************************************************************************/
-int
-fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors)
+
+/*
+ Fill fields with given items.
+
+ SYNOPSIS
+ fill_record()
+ thd thread handler
+ fields Item_fields list to be filled
+ values values to fill with
+ ignore_errors TRUE if we should ignore errors
+
+ RETURN
+ FALSE OK
+ TRUE error occured
+*/
+
+bool
+fill_record(THD * thd, List<Item> &fields, List<Item> &values,
+ bool ignore_errors)
{
List_iterator_fast<Item> f(fields),v(values);
Item *value;
@@ -3253,14 +3398,32 @@ fill_record(List<Item> &fields,List<Item> &values, bool ignore_errors)
if (rfield == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
if ((value->save_in_field(rfield, 0) < 0) && !ignore_errors)
- DBUG_RETURN(1);
+ {
+ my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
+ DBUG_RETURN(TRUE);
+ }
}
- DBUG_RETURN(0);
+ DBUG_RETURN(thd->net.report_error);
}
-int
-fill_record(Field **ptr,List<Item> &values, bool ignore_errors)
+/*
+ Fill field buffer with values from Field list
+
+ SYNOPSIS
+ fill_record()
+ thd thread handler
+ ptr pointer on pointer to record
+ values list of fields
+ ignore_errors TRUE if we should ignore errors
+
+ RETURN
+ FALSE OK
+ TRUE error occured
+*/
+
+bool
+fill_record(THD *thd, Field **ptr, List<Item> &values, bool ignore_errors)
{
List_iterator_fast<Item> v(values);
Item *value;
@@ -3274,9 +3437,12 @@ fill_record(Field **ptr,List<Item> &values, bool ignore_errors)
if (field == table->next_number_field)
table->auto_increment_field_not_null= TRUE;
if ((value->save_in_field(field, 0) < 0) && !ignore_errors)
- DBUG_RETURN(1);
+ {
+ my_message(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR), MYF(0));
+ DBUG_RETURN(TRUE);
+ }
}
- DBUG_RETURN(0);
+ DBUG_RETURN(thd->net.report_error);
}
diff --git a/sql/sql_class.cc b/sql/sql_class.cc
index f5283020b30..cc178a3121b 100644
--- a/sql/sql_class.cc
+++ b/sql/sql_class.cc
@@ -290,6 +290,9 @@ void THD::init(void)
variables.date_format);
variables.datetime_format= date_time_format_copy((THD*) 0,
variables.datetime_format);
+#ifdef HAVE_NDBCLUSTER_DB
+ variables.ndb_use_transactions= 1;
+#endif
pthread_mutex_unlock(&LOCK_global_system_variables);
server_status= SERVER_STATUS_AUTOCOMMIT;
options= thd_startup_options;
@@ -316,7 +319,7 @@ void THD::init_for_queries()
{
ha_enable_transaction(this,TRUE);
- reset_root_defaults(&mem_root, variables.query_alloc_block_size,
+ reset_root_defaults(mem_root, variables.query_alloc_block_size,
variables.query_prealloc_size);
reset_root_defaults(&transaction.mem_root,
variables.trans_alloc_block_size,
@@ -431,7 +434,7 @@ THD::~THD()
dbug_sentry= THD_SENTRY_GONE;
#endif
/* Reset stmt_backup.mem_root to not double-free memory from thd.mem_root */
- clear_alloc_root(&stmt_backup.mem_root);
+ clear_alloc_root(&stmt_backup.main_mem_root);
DBUG_VOID_RETURN;
}
@@ -567,13 +570,14 @@ bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
{
DBUG_ENTER("convert_string");
size_s new_length= to_cs->mbmaxlen * from_length;
+ uint dummy_errors;
if (!(to->str= alloc(new_length+1)))
{
to->length= 0; // Safety fix
DBUG_RETURN(1); // EOM
}
to->length= copy_and_convert((char*) to->str, new_length, to_cs,
- from, from_length, from_cs);
+ from, from_length, from_cs, &dummy_errors);
to->str[to->length]=0; // Safety
DBUG_RETURN(0);
}
@@ -596,7 +600,8 @@ bool THD::convert_string(LEX_STRING *to, CHARSET_INFO *to_cs,
bool THD::convert_string(String *s, CHARSET_INFO *from_cs, CHARSET_INFO *to_cs)
{
- if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs))
+ uint dummy_errors;
+ if (convert_buffer.copy(s->ptr(), s->length(), from_cs, to_cs, &dummy_errors))
return TRUE;
/* If convert_buffer >> s copying is more efficient long term */
if (convert_buffer.alloced_length() >= convert_buffer.length() * 2 ||
@@ -700,7 +705,7 @@ CHANGED_TABLE_LIST* THD::changed_table_dup(const char *key, long key_length)
if (!new_table)
{
my_error(EE_OUTOFMEMORY, MYF(ME_BELL),
- ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
+ ALIGN_SIZE(sizeof(TABLE_LIST)) + key_length + 1);
killed= KILL_CONNECTION;
return 0;
}
@@ -819,7 +824,7 @@ select_result::select_result()
void select_result::send_error(uint errcode,const char *err)
{
- ::send_error(thd, errcode, err);
+ my_message(errcode, err, MYF(0));
}
@@ -923,7 +928,7 @@ bool select_send::send_eof()
void select_to_file::send_error(uint errcode,const char *err)
{
- ::send_error(thd,errcode,err);
+ my_message(errcode, err, MYF(0));
if (file > 0)
{
(void) end_io_cache(&cache);
@@ -1247,7 +1252,7 @@ bool select_dump::send_data(List<Item> &items)
}
if (row_count++ > 1)
{
- my_error(ER_TOO_MANY_ROWS, MYF(0));
+ my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
goto err;
}
while ((item=li++))
@@ -1260,7 +1265,7 @@ bool select_dump::send_data(List<Item> &items)
}
else if (my_b_write(&cache,(byte*) res->ptr(),res->length()))
{
- my_error(ER_ERROR_ON_WRITE,MYF(0), path, my_errno);
+ my_error(ER_ERROR_ON_WRITE, MYF(0), path, my_errno);
goto err;
}
}
@@ -1343,7 +1348,7 @@ bool select_max_min_finder_subselect::send_data(List<Item> &items)
bool select_max_min_finder_subselect::cmp_real()
{
Item *maxmin= ((Item_singlerow_subselect *)item)->el(0);
- double val1= cache->val(), val2= maxmin->val();
+ double val1= cache->val_real(), val2= maxmin->val_real();
if (fmax)
return (cache->null_value && !maxmin->null_value) ||
(!cache->null_value && !maxmin->null_value &&
@@ -1419,7 +1424,8 @@ int select_dumpvar::prepare(List<Item> &list, SELECT_LEX_UNIT *u)
if (var_list.elements != list.elements)
{
- my_error(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT, MYF(0));
+ my_message(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT,
+ ER(ER_WRONG_NUMBER_OF_COLUMNS_IN_SELECT), MYF(0));
return 1;
}
while ((item=li++))
@@ -1463,10 +1469,10 @@ void select_dumpvar::cleanup()
for memory root initialization.
*/
Item_arena::Item_arena(THD* thd)
- :free_list(0),
- state(INITIALIZED)
+ :free_list(0), mem_root(&main_mem_root),
+ state(INITIALIZED)
{
- init_sql_alloc(&mem_root,
+ init_sql_alloc(&main_mem_root,
thd->variables.query_alloc_block_size,
thd->variables.query_prealloc_size);
}
@@ -1489,11 +1495,11 @@ Item_arena::Item_arena(THD* thd)
statements.
*/
Item_arena::Item_arena(bool init_mem_root)
- :free_list(0),
+ :free_list(0), mem_root(&main_mem_root),
state(CONVENTIONAL_EXECUTION)
{
if (init_mem_root)
- init_sql_alloc(&mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
+ init_sql_alloc(&main_mem_root, ALLOC_ROOT_MIN_BLOCK_SIZE, 0);
}
@@ -1624,14 +1630,14 @@ void Item_arena::restore_backup_item_arena(Item_arena *set, Item_arena *backup)
void Item_arena::set_item_arena(Item_arena *set)
{
- mem_root= set->mem_root;
+ mem_root= set->mem_root;
free_list= set->free_list;
state= set->state;
}
Statement::~Statement()
{
- free_root(&mem_root, MYF(0));
+ free_root(&main_mem_root, MYF(0));
}
C_MODE_START
@@ -1720,7 +1726,7 @@ bool select_dumpvar::send_data(List<Item> &items)
}
if (row_count++)
{
- my_error(ER_TOO_MANY_ROWS, MYF(0));
+ my_message(ER_TOO_MANY_ROWS, ER(ER_TOO_MANY_ROWS), MYF(0));
DBUG_RETURN(1);
}
while ((zz=my_li++) && (item=it++))
@@ -1748,7 +1754,8 @@ bool select_dumpvar::send_data(List<Item> &items)
bool select_dumpvar::send_eof()
{
if (! row_count)
- send_warning(thd, ER_SP_FETCH_NO_DATA);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_SP_FETCH_NO_DATA, ER(ER_SP_FETCH_NO_DATA));
::send_ok(thd,row_count);
return 0;
}
@@ -1762,6 +1769,7 @@ void TMP_TABLE_PARAM::init()
field_count= sum_func_count= func_count= hidden_field_count= 0;
group_parts= group_length= group_null_parts= 0;
quick_group= 1;
+ table_charset= 0;
}
diff --git a/sql/sql_class.h b/sql/sql_class.h
index fcaebe64b43..6cec2c2c787 100644
--- a/sql/sql_class.h
+++ b/sql/sql_class.h
@@ -41,6 +41,7 @@ enum enum_check_fields { CHECK_FIELD_IGNORE, CHECK_FIELD_WARN,
CHECK_FIELD_ERROR_FOR_NULL };
extern char internal_table_name[2];
+extern const char **errmesg;
/* log info errors */
#define LOG_INFO_EOF -1
@@ -153,7 +154,7 @@ public:
DBUG_VOID_RETURN;
}
void set_max_size(ulong max_size_arg);
- void signal_update() { pthread_cond_broadcast(&update_cond);}
+ void signal_update();
void wait_for_update(THD* thd, bool master_or_slave);
void set_need_start_event() { need_start_event = 1; }
void init(enum_log_type log_type_arg,
@@ -430,6 +431,12 @@ struct system_variables
#ifdef HAVE_INNOBASE_DB
my_bool innodb_table_locks;
#endif /* HAVE_INNOBASE_DB */
+#ifdef HAVE_NDBCLUSTER_DB
+ ulong ndb_autoincrement_prefetch_sz;
+ my_bool ndb_force_send;
+ my_bool ndb_use_exact_count;
+ my_bool ndb_use_transactions;
+#endif /* HAVE_NDBCLUSTER_DB */
my_bool old_passwords;
/* Only charset part of these variables is sensible */
@@ -515,7 +522,8 @@ public:
itself to the list on creation (see Item::Item() for details))
*/
Item *free_list;
- MEM_ROOT mem_root;
+ MEM_ROOT main_mem_root;
+ MEM_ROOT *mem_root; // Pointer to current memroot
#ifndef DBUG_OFF
bool backup_arena;
#endif
@@ -557,24 +565,24 @@ public:
{ return state == PREPARED || state == EXECUTED; }
inline bool is_conventional() const
{ return state == CONVENTIONAL_EXECUTION; }
- inline gptr alloc(unsigned int size) { return alloc_root(&mem_root,size); }
+ inline gptr alloc(unsigned int size) { return alloc_root(mem_root,size); }
inline gptr calloc(unsigned int size)
{
gptr ptr;
- if ((ptr=alloc_root(&mem_root,size)))
+ if ((ptr=alloc_root(mem_root,size)))
bzero((char*) ptr,size);
return ptr;
}
inline char *strdup(const char *str)
- { return strdup_root(&mem_root,str); }
+ { return strdup_root(mem_root,str); }
inline char *strmake(const char *str, uint size)
- { return strmake_root(&mem_root,str,size); }
+ { return strmake_root(mem_root,str,size); }
inline char *memdup(const char *str, uint size)
- { return memdup_root(&mem_root,str,size); }
+ { return memdup_root(mem_root,str,size); }
inline char *memdup_w_gap(const char *str, uint size, uint gap)
{
gptr ptr;
- if ((ptr=alloc_root(&mem_root,size+gap)))
+ if ((ptr=alloc_root(mem_root,size+gap)))
memcpy(ptr,str,size);
return ptr;
}
@@ -1131,8 +1139,12 @@ public:
{
return command == COM_PREPARE;
}
- inline gptr trans_alloc(unsigned int size)
- {
+ inline bool fill_derived_tables()
+ {
+ return !only_prepare() && !lex->only_view_structure();
+ }
+ inline gptr trans_alloc(unsigned int size)
+ {
return alloc_root(&transaction.mem_root,size);
}
@@ -1152,6 +1164,7 @@ public:
net.last_error[0]= 0;
net.last_errno= 0;
net.report_error= 0;
+ query_error= 0;
}
inline bool vio_ok() const { return net.vio != 0; }
#else
@@ -1167,11 +1180,26 @@ public:
inline CHARSET_INFO *charset() { return variables.character_set_client; }
void update_charset();
+ inline Item_arena *change_arena_if_needed(Item_arena *backup)
+ {
+ /*
+ use new arena if we are in a prepared statements and we have not
+ already changed to use this arena.
+ */
+ if (!current_arena->is_conventional() &&
+ mem_root != &current_arena->main_mem_root)
+ {
+ set_n_backup_item_arena(current_arena, backup);
+ return current_arena;
+ }
+ return 0;
+ }
+
void change_item_tree(Item **place, Item *new_value)
{
/* TODO: check for OOM condition here */
if (!current_arena->is_conventional())
- nocheck_register_item_tree_change(place, *place, &mem_root);
+ nocheck_register_item_tree_change(place, *place, mem_root);
*place= new_value;
}
void nocheck_register_item_tree_change(Item **place, Item *old_value,
@@ -1189,7 +1217,8 @@ public:
}
inline void send_kill_message() const
{
- my_error(killed_errno(), MYF(0));
+ int err= killed_errno();
+ my_message(err, ER(err), MYF(0));
}
/* return TRUE if we will abort query if we make a warning now */
inline bool really_abort_on_warning()
@@ -1201,6 +1230,12 @@ public:
void set_status_var_init();
};
+#define tmp_disable_binlog(A) \
+ ulong save_options= (A)->options; \
+ (A)->options&= ~OPTION_BIN_LOG;
+
+#define reenable_binlog(A) (A)->options= save_options;
+
/* Flags for the THD::system_thread (bitmap) variable */
#define SYSTEM_THREAD_DELAYED_INSERT 1
#define SYSTEM_THREAD_SLAVE_IO 2
@@ -1231,8 +1266,6 @@ public:
class JOIN;
-void send_error(THD *thd, uint sql_errno=0, const char *err=0);
-
class select_result :public Sql_alloc {
protected:
THD *thd;
@@ -1344,6 +1377,7 @@ class select_insert :public select_result_interceptor {
~select_insert();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
+ virtual void store_values(List<Item> &values);
void send_error(uint errcode,const char *err);
bool send_eof();
/* not implemented: select_insert is never re-used in prepared statements */
@@ -1370,7 +1404,8 @@ public:
lock(0)
{}
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
- bool send_data(List<Item> &values);
+ void store_values(List<Item> &values);
+ void send_error(uint errcode,const char *err);
bool send_eof();
void abort();
};
@@ -1404,6 +1439,7 @@ public:
bool using_indirect_summary_function;
/* If >0 convert all blob fields to varchar(convert_blob_length) */
uint convert_blob_length;
+ CHARSET_INFO *table_charset;
TMP_TABLE_PARAM()
:copy_funcs_it(copy_funcs), copy_field(0), group_parts(0),
@@ -1419,7 +1455,7 @@ public:
if (copy_field) /* Fix for Intel compiler */
{
delete [] copy_field;
- copy_field=0;
+ save_copy_field= copy_field= 0;
}
}
};
@@ -1622,7 +1658,9 @@ public:
class multi_update :public select_result_interceptor
{
- TABLE_LIST *all_tables, *update_tables, *table_being_updated;
+ TABLE_LIST *all_tables; /* query/update command tables */
+ TABLE_LIST *leaves; /* list of leves of join table tree */
+ TABLE_LIST *update_tables, *table_being_updated;
THD *thd;
TABLE **tmp_tables, *main_table, *table_to_update;
TMP_TABLE_PARAM *tmp_table_param;
@@ -1635,8 +1673,9 @@ class multi_update :public select_result_interceptor
bool do_update, trans_safe, transactional_tables, log_delayed;
public:
- multi_update(THD *thd_arg, TABLE_LIST *ut, List<Item> *fields,
- List<Item> *values, enum_duplicates handle_duplicates);
+ multi_update(THD *thd_arg, TABLE_LIST *ut, TABLE_LIST *leaves_list,
+ List<Item> *fields, List<Item> *values,
+ enum_duplicates handle_duplicates);
~multi_update();
int prepare(List<Item> &list, SELECT_LEX_UNIT *u);
bool send_data(List<Item> &items);
diff --git a/sql/sql_db.cc b/sql/sql_db.cc
index 982ad4a34a9..3e606029bec 100644
--- a/sql/sql_db.cc
+++ b/sql/sql_db.cc
@@ -31,11 +31,6 @@ const char *del_exts[]= {".frm", ".BAK", ".TMD",".opt", NullS};
static TYPELIB deletable_extentions=
{array_elements(del_exts)-1,"del_exts", del_exts, NULL};
-const char *known_exts[]=
-{".ISM",".ISD",".ISM",".MRG",".MYI",".MYD",".db", ".ibd", NullS};
-static TYPELIB known_extentions=
-{array_elements(known_exts)-1,"known_exts", known_exts, NULL};
-
static long mysql_rm_known_files(THD *thd, MY_DIR *dirp,
const char *db, const char *path,
uint level);
@@ -379,13 +374,13 @@ bool load_db_opt(THD *thd, const char *path, HA_CREATE_INFO *create)
In this case the entry should not be logged.
RETURN VALUES
- 0 ok
- -1 Error
+ FALSE ok
+ TRUE Error
*/
-int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
- bool silent)
+bool mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
+ bool silent)
{
char path[FN_REFLEN+16];
long result= 1;
@@ -413,7 +408,7 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
{
if (!(create_options & HA_LEX_CREATE_IF_NOT_EXISTS))
{
- my_error(ER_DB_CREATE_EXISTS,MYF(0),db);
+ my_error(ER_DB_CREATE_EXISTS, MYF(0), db);
error= -1;
goto exit;
}
@@ -423,12 +418,12 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
{
if (my_errno != ENOENT)
{
- my_error(EE_STAT, MYF(0),path,my_errno);
+ my_error(EE_STAT, MYF(0), path, my_errno);
goto exit;
}
if (my_mkdir(path,0777,MYF(0)) < 0)
{
- my_error(ER_CANT_CREATE_DB,MYF(0),db,my_errno);
+ my_error(ER_CANT_CREATE_DB, MYF(0), db, my_errno);
error= -1;
goto exit;
}
@@ -473,7 +468,29 @@ int mysql_create_db(THD *thd, char *db, HA_CREATE_INFO *create_info,
}
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, query, query_length, 0);
+ Query_log_event qinfo(thd, query, query_length, 0,
+ /* suppress_use */ TRUE);
+
+ /*
+ Write should use the database being created as the "current
+ database" and not the threads current database, which is the
+ default. If we do not change the "current database" to the
+ database being created, the CREATE statement will not be
+ replicated when using --binlog-do-db to select databases to be
+ replicated.
+
+ An example (--binlog-do-db=sisyfos):
+
+ CREATE DATABASE bob; # Not replicated
+ USE bob; # 'bob' is the current database
+ CREATE DATABASE sisyfos; # Not replicated since 'bob' is
+ # current database.
+ USE sisyfos; # Will give error on slave since
+ # database does not exist.
+ */
+ qinfo.db = db;
+ qinfo.db_len = strlen(db);
+
mysql_bin_log.write(&qinfo);
}
send_ok(thd, result);
@@ -489,7 +506,7 @@ exit2:
/* db-name is already validated when we come here */
-int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
+bool mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
{
char path[FN_REFLEN+16];
long result=1;
@@ -522,7 +539,15 @@ int mysql_alter_db(THD *thd, const char *db, HA_CREATE_INFO *create_info)
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0,
+ /* suppress_use */ TRUE);
+
+ // Write should use the database being created as the "current
+ // database" and not the threads current database, which is the
+ // default.
+ qinfo.db = db;
+ qinfo.db_len = strlen(db);
+
thd->clear_error();
mysql_bin_log.write(&qinfo);
}
@@ -532,7 +557,7 @@ exit:
start_waiting_global_read_lock(thd);
exit2:
VOID(pthread_mutex_unlock(&LOCK_mysql_create_db));
- DBUG_RETURN(error ? -1 : 0); /* -1 to delegate send_error() */
+ DBUG_RETURN(error);
}
@@ -548,11 +573,11 @@ exit2:
silent Don't generate errors
RETURN
- 0 ok (Database dropped)
- -1 Error generated
+ FALSE ok (Database dropped)
+ ERROR Error
*/
-int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
+bool mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
{
long deleted=0;
int error= 0;
@@ -582,7 +607,7 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
if (!if_exists)
{
error= -1;
- my_error(ER_DB_DROP_EXISTS,MYF(0),db);
+ my_error(ER_DB_DROP_EXISTS, MYF(0), db);
goto exit;
}
else
@@ -628,7 +653,15 @@ int mysql_rm_db(THD *thd,char *db,bool if_exists, bool silent)
}
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, query, query_length, 0);
+ Query_log_event qinfo(thd, query, query_length, 0,
+ /* suppress_use */ TRUE);
+
+ // Write should use the database being created as the "current
+ // database" and not the threads current database, which is the
+ // default.
+ qinfo.db = db;
+ qinfo.db_len = strlen(db);
+
thd->clear_error();
mysql_bin_log.write(&qinfo);
}
@@ -724,7 +757,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
if ((mysql_rm_known_files(thd, new_dirp, NullS, newpath,1)) < 0)
goto err;
if (!(copy_of_path= thd->memdup(newpath, length+1)) ||
- !(dir= new (&thd->mem_root) String(copy_of_path, length,
+ !(dir= new (thd->mem_root) String(copy_of_path, length,
&my_charset_bin)) ||
raid_dirs.push_back(dir))
goto err;
@@ -755,7 +788,7 @@ static long mysql_rm_known_files(THD *thd, MY_DIR *dirp, const char *db,
extension= fn_ext(file->name);
if (find_type(extension, &deletable_extentions,1+2) <= 0)
{
- if (find_type(extension, &known_extentions,1+2) <= 0)
+ if (find_type(extension, ha_known_exts(),1+2) <= 0)
found_other_files++;
continue;
}
@@ -990,12 +1023,13 @@ bool mysql_change_db(THD *thd, const char *name)
if (!dbname || !(db_length= strlen(dbname)))
{
x_free(dbname); /* purecov: inspected */
- send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
+ MYF(0)); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
if (check_db_name(dbname))
{
- net_printf(thd, ER_WRONG_DB_NAME, dbname);
+ my_error(ER_WRONG_DB_NAME, MYF(0), dbname);
x_free(dbname);
DBUG_RETURN(1);
}
@@ -1008,10 +1042,10 @@ bool mysql_change_db(THD *thd, const char *name)
thd->master_access);
if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
{
- net_printf(thd,ER_DBACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->priv_host,
- dbname);
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user,
+ thd->priv_host,
+ dbname);
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
thd->priv_user,
thd->priv_host,
@@ -1026,7 +1060,7 @@ bool mysql_change_db(THD *thd, const char *name)
path[length-1]=0; // remove ending '\'
if (access(path,F_OK))
{
- net_printf(thd,ER_BAD_DB_ERROR,dbname);
+ my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
my_free(dbname,MYF(0));
DBUG_RETURN(1);
}
diff --git a/sql/sql_delete.cc b/sql/sql_delete.cc
index 37121e64ecc..f4c5b0f8b59 100644
--- a/sql/sql_delete.cc
+++ b/sql/sql_delete.cc
@@ -29,8 +29,8 @@
#include "sp_head.h"
#include "sql_trigger.h"
-int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
- ha_rows limit, ulong options)
+bool mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds,
+ SQL_LIST *order, ha_rows limit, ulong options)
{
int error;
TABLE *table;
@@ -39,32 +39,46 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
bool using_limit=limit != HA_POS_ERROR;
bool transactional_table, log_delayed, safe_update, const_cond;
ha_rows deleted;
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_delete");
- if ((error= open_and_lock_tables(thd, table_list)))
- DBUG_RETURN(error);
- table= table_list->table;
+ if (open_and_lock_tables(thd, table_list))
+ DBUG_RETURN(TRUE);
+ if (!(table= table_list->table))
+ {
+ DBUG_ASSERT(table_list->view &&
+ table_list->ancestor && table_list->ancestor->next_local);
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ DBUG_RETURN(-1);
+ }
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
thd->proc_info="init";
table->map=1;
- if ((error= mysql_prepare_delete(thd, table_list, &conds)))
- DBUG_RETURN(error);
+ if (mysql_prepare_delete(thd, table_list, &conds))
+ DBUG_RETURN(TRUE);
const_cond= (!conds || conds->const_item());
safe_update=test(thd->options & OPTION_SAFE_UPDATES);
if (safe_update && const_cond)
{
- send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
+ DBUG_RETURN(TRUE);
}
if (thd->lex->duplicates == DUP_IGNORE)
- thd->lex->select_lex.no_error= 1;
+ select_lex->no_error= 1;
- /* Test if the user wants to delete all rows */
+ /*
+ Test if the user wants to delete all rows and deletion doesn't have
+ any side-effects (because of triggers), so we can use optimized
+ handler::delete_all_rows() method.
+ */
if (!using_limit && const_cond && (!conds || conds->val_int()) &&
- !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)))
+ !(specialflag & (SPECIAL_NO_NEW_FUNC | SPECIAL_SAFE_MODE)) &&
+ !(table->triggers && table->triggers->has_delete_triggers()))
{
deleted= table->file->records;
if (!(error=table->file->delete_all_rows()))
@@ -85,11 +99,11 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
table->quick_keys.clear_all(); // Can't use 'only index'
select=make_select(table,0,0,conds,&error);
if (error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
if ((select && select->check_quick(thd, safe_update, limit)) || !limit)
{
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, select_lex);
thd->row_count_func= 0;
send_ok(thd,0L);
DBUG_RETURN(0); // Nothing to delete
@@ -102,9 +116,10 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
if (safe_update && !using_limit)
{
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
- send_error(thd,ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE);
- DBUG_RETURN(1);
+ free_underlaid_joins(thd, select_lex);
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
+ DBUG_RETURN(TRUE);
}
}
if (options & OPTION_QUICK)
@@ -124,8 +139,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
table->sort.io_cache = (IO_CACHE *) my_malloc(sizeof(IO_CACHE),
MYF(MY_FAE | MY_ZEROFILL));
- if (thd->lex->select_lex.setup_ref_array(thd, order->elements) ||
- setup_order(thd, thd->lex->select_lex.ref_pointer_array, &tables,
+ if (select_lex->setup_ref_array(thd, order->elements) ||
+ setup_order(thd, select_lex->ref_pointer_array, &tables,
fields, all_fields, (ORDER*) order->first) ||
!(sortorder=make_unireg_sortorder((ORDER*) order->first, &length)) ||
(table->sort.found_records = filesort(thd, table, sortorder, length,
@@ -134,8 +149,8 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
== HA_POS_ERROR)
{
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
- DBUG_RETURN(-1); // This will force out message
+ free_underlaid_joins(thd, select_lex);
+ DBUG_RETURN(TRUE);
}
/*
Filesort has already found and selected the rows we want to delete,
@@ -149,12 +164,12 @@ int mysql_delete(THD *thd, TABLE_LIST *table_list, COND *conds, SQL_LIST *order,
if (select && select->quick && select->quick->reset())
{
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
- DBUG_RETURN(-1); // This will force out message
+ free_underlaid_joins(thd, select_lex);
+ DBUG_RETURN(TRUE);
}
init_read_record(&info,thd,table,select,1,1);
deleted=0L;
- init_ftfuncs(thd, &thd->lex->select_lex, 1);
+ init_ftfuncs(thd, select_lex, 1);
thd->proc_info="updating";
while (!(error=info.read_record(&info)) && !thd->killed &&
!thd->net.report_error)
@@ -234,7 +249,7 @@ cleanup:
if (error <= 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed);
+ log_delayed, FALSE);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
@@ -252,16 +267,14 @@ cleanup:
mysql_unlock_tables(thd, thd->lock);
thd->lock=0;
}
- free_underlaid_joins(thd, &thd->lex->select_lex);
- if (error >= 0 || thd->net.report_error)
- send_error(thd,thd->killed_errno());
- else
+ free_underlaid_joins(thd, select_lex);
+ if (error < 0)
{
thd->row_count_func= deleted;
send_ok(thd,deleted);
DBUG_PRINT("info",("%d records deleted",deleted));
}
- DBUG_RETURN(0);
+ DBUG_RETURN(error >= 0 || thd->net.report_error);
}
@@ -275,31 +288,31 @@ cleanup:
conds - conditions
RETURN VALUE
- 0 - OK
- 1 - error (message is sent to user)
- -1 - error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
+bool mysql_prepare_delete(THD *thd, TABLE_LIST *table_list, Item **conds)
{
SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_prepare_delete");
- if (setup_tables(thd, table_list, conds) ||
- setup_conds(thd, table_list, conds) ||
+ if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables,
+ FALSE, FALSE) ||
+ setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
setup_ftfuncs(select_lex))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
if (!table_list->updatable || check_key_in_view(thd, table_list))
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "DELETE");
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
- if (unique_table(table_list, table_list->next_independent()))
+ if (unique_table(table_list, table_list->next_global))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
select_lex->fix_prepare_information(thd, conds);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -323,16 +336,15 @@ extern "C" int refpos_order_cmp(void* arg, const void *a,const void *b)
thd thread handler
RETURN
- 0 OK
- -1 Error
+ FALSE OK
+ TRUE Error
*/
-int mysql_multi_delete_prepare(THD *thd)
+bool mysql_multi_delete_prepare(THD *thd)
{
LEX *lex= thd->lex;
TABLE_LIST *aux_tables= (TABLE_LIST *)lex->auxilliary_table_list.first;
TABLE_LIST *target_tbl;
- int res= 0;
DBUG_ENTER("mysql_multi_delete_prepare");
/*
@@ -341,8 +353,9 @@ int mysql_multi_delete_prepare(THD *thd)
lex->query_tables also point on local list of DELETE SELECT_LEX
*/
- if (setup_tables(thd, lex->query_tables, &lex->select_lex.where))
- DBUG_RETURN(-1);
+ if (setup_tables(thd, lex->query_tables, &lex->select_lex.where,
+ &lex->select_lex.leaf_tables, FALSE, FALSE))
+ DBUG_RETURN(TRUE);
/* Fix tables-to-be-deleted-from list to point at opened tables */
for (target_tbl= (TABLE_LIST*) aux_tables;
@@ -353,15 +366,15 @@ int mysql_multi_delete_prepare(THD *thd)
if (!target_tbl->correspondent_table->updatable ||
check_key_in_view(thd, target_tbl->correspondent_table))
{
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), target_tbl->real_name,
- "DELETE");
- DBUG_RETURN(-1);
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
+ target_tbl->real_name, "DELETE");
+ DBUG_RETURN(TRUE);
}
/*
Check are deleted table used somewhere inside subqueries.
Multi-delete can't be constructed over-union => we always have
- single SELECT on top and have to check underlaying SELECTs of it
+ single SELECT on top and have to check underlying SELECTs of it
*/
for (SELECT_LEX_UNIT *un= lex->select_lex.first_inner_unit();
un;
@@ -373,12 +386,11 @@ int mysql_multi_delete_prepare(THD *thd)
{
my_error(ER_UPDATE_TABLE_USED, MYF(0),
target_tbl->correspondent_table->real_name);
- res= -1;
- break;
+ DBUG_RETURN(TRUE);
}
}
}
- DBUG_RETURN(res);
+ DBUG_RETURN(FALSE);
}
@@ -524,7 +536,7 @@ void multi_delete::send_error(uint errcode,const char *err)
DBUG_ENTER("multi_delete::send_error");
/* First send error what ever it is ... */
- ::send_error(thd,errcode,err);
+ my_message(errcode, err, MYF(0));
/* If nothing deleted return */
if (!deleted)
@@ -658,7 +670,7 @@ bool multi_delete::send_eof()
if (error <= 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed);
+ log_delayed, FALSE);
if (mysql_bin_log.write(&qinfo) && !normal_tables)
local_error=1; // Log write failed: roll back the SQL statement
}
@@ -670,9 +682,7 @@ bool multi_delete::send_eof()
if (ha_autocommit_or_rollback(thd,local_error > 0))
local_error=1;
- if (local_error)
- ::send_error(thd);
- else
+ if (!local_error)
{
thd->row_count_func= deleted;
::send_ok(thd, deleted);
@@ -697,12 +707,12 @@ bool multi_delete::send_eof()
- If we want to have a name lock on the table on exit without errors.
*/
-int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
+bool mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
{
HA_CREATE_INFO create_info;
char path[FN_REFLEN];
TABLE **table_ptr;
- int error;
+ bool error;
DBUG_ENTER("mysql_truncate");
bzero((char*) &create_info,sizeof(create_info));
@@ -738,9 +748,9 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
db_type table_type;
if ((table_type=get_table_type(path)) == DB_TYPE_UNKNOWN)
{
- my_error(ER_NO_SUCH_TABLE, MYF(0), table_list->db,
- table_list->real_name);
- DBUG_RETURN(-1);
+ my_error(ER_NO_SUCH_TABLE, MYF(0),
+ table_list->db, table_list->real_name);
+ DBUG_RETURN(TRUE);
}
if (!ha_supports_generate(table_type))
{
@@ -753,11 +763,11 @@ int mysql_truncate(THD *thd, TABLE_LIST *table_list, bool dont_send_ok)
DBUG_RETURN(error);
}
if (lock_and_wait_for_table_name(thd, table_list))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
*fn_ext(path)=0; // Remove the .frm extension
- error= ha_create_table(path,&create_info,1) ? -1 : 0;
+ error= ha_create_table(path,&create_info,1);
query_cache_invalidate3(thd, table_list, 0);
end:
@@ -769,7 +779,7 @@ end:
{
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- thd->tmp_table);
+ thd->tmp_table, FALSE);
mysql_bin_log.write(&qinfo);
}
send_ok(thd); // This should return record count
@@ -784,5 +794,5 @@ end:
unlock_table_name(thd, table_list);
VOID(pthread_mutex_unlock(&LOCK_open));
}
- DBUG_RETURN(error ? -1 : 0);
+ DBUG_RETURN(error);
}
diff --git a/sql/sql_derived.cc b/sql/sql_derived.cc
index 0923cf811f5..69511018880 100644
--- a/sql/sql_derived.cc
+++ b/sql/sql_derived.cc
@@ -25,15 +25,15 @@
#include "sql_select.h"
#include "sql_acl.h"
-static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s,
- TABLE_LIST *t);
+
/*
- Resolve derived tables in all queries
+ call given derived table processor (preparing or filling tables)
SYNOPSIS
mysql_handle_derived()
lex LEX for this thread
+ processor procedure of derived table processing
RETURN
0 ok
@@ -42,7 +42,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *s,
*/
int
-mysql_handle_derived(LEX *lex)
+mysql_handle_derived(LEX *lex, int (*processor)(THD*, LEX*, TABLE_LIST*))
{
if (lex->derived_tables)
{
@@ -55,14 +55,8 @@ mysql_handle_derived(LEX *lex)
cursor= cursor->next_local)
{
int res;
- if (cursor->derived && (res= mysql_derived(lex->thd, lex,
- cursor->derived,
- cursor)))
- {
+ if ((res= (*processor)(lex->thd, lex, cursor)))
return res;
- }
- else if (cursor->ancestor)
- cursor->set_ancestor();
}
if (lex->describe)
{
@@ -80,20 +74,16 @@ mysql_handle_derived(LEX *lex)
/*
- Resolve derived tables in all queries
+ Create temporary table structure (but do not fill it)
SYNOPSIS
- mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit, TABLE_LIST *t)
+ mysql_derived_prepare()
thd Thread handle
lex LEX for this thread
- unit node that contains all SELECT's for derived tables
- t TABLE_LIST for the upper SELECT
+ orig_table_list TABLE_LIST for the upper SELECT
IMPLEMENTATION
- Derived table is resolved with temporary table. It is created based on the
- queries defined. After temporary table is created, if this is not EXPLAIN,
- then the entire unit / node is deleted. unit is deleted if UNION is used
- for derived table and node is deleted is it is a simple SELECT.
+ Derived table is resolved with temporary table.
After table creation, the above TABLE_LIST is updated with a new table.
@@ -107,60 +97,126 @@ mysql_handle_derived(LEX *lex)
0 ok
1 Error
-1 Error and error message given
-*/
-
+ */
-static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
- TABLE_LIST *org_table_list)
+int mysql_derived_prepare(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
{
- SELECT_LEX *first_select= unit->first_select();
- TABLE *table;
- int res;
- select_union *derived_result;
- bool is_union= first_select->next_select() &&
- first_select->next_select()->linkage == UNION_TYPE;
- SELECT_LEX *save_current_select= lex->current_select;
- DBUG_ENTER("mysql_derived");
-
- if (!(derived_result= new select_union(0)))
- DBUG_RETURN(1); // out of memory
-
- // st_select_lex_unit::prepare correctly work for single select
- if ((res= unit->prepare(thd, derived_result, 0)))
- goto exit;
-
-
- derived_result->tmp_table_param.init();
- derived_result->tmp_table_param.field_count= unit->types.elements;
- /*
- Temp table is created so that it hounours if UNION without ALL is to be
- processed
- */
- if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
- unit->types, (ORDER*) 0,
- is_union && unit->union_distinct, 1,
- (first_select->options | thd->options |
- TMP_TABLE_ALL_COLUMNS),
- HA_POS_ERROR,
- org_table_list->alias)))
+ SELECT_LEX_UNIT *unit= orig_table_list->derived;
+ int res= 0;
+ DBUG_ENTER("mysql_derived_prepare");
+ if (unit)
{
- res= -1;
- goto exit;
+ SELECT_LEX *first_select= unit->first_select();
+ TABLE *table= 0;
+ select_union *derived_result;
+ bool is_union= first_select->next_select() &&
+ first_select->next_select()->linkage == UNION_TYPE;
+
+ if (!(derived_result= new select_union(0)))
+ DBUG_RETURN(1); // out of memory
+
+ // st_select_lex_unit::prepare correctly work for single select
+ if ((res= unit->prepare(thd, derived_result, 0)))
+ goto exit;
+
+
+ derived_result->tmp_table_param.init();
+ derived_result->tmp_table_param.field_count= unit->types.elements;
+ /*
+ Temp table is created so that it hounours if UNION without ALL is to be
+ processed
+ */
+ if (!(table= create_tmp_table(thd, &derived_result->tmp_table_param,
+ unit->types, (ORDER*) 0,
+ is_union && unit->union_distinct, 1,
+ (first_select->options | thd->options |
+ TMP_TABLE_ALL_COLUMNS),
+ HA_POS_ERROR,
+ orig_table_list->alias)))
+ {
+ res= -1;
+ goto exit;
+ }
+ derived_result->set_table(table);
+
+exit:
+ /*
+ if it is preparation PS only or commands that need only VIEW structure
+ then we do not need real data and we can skip execution (and parameters
+ is not defined, too)
+ */
+ if (res)
+ {
+ if (table)
+ free_tmp_table(thd, table);
+ delete derived_result;
+ }
+ else
+ {
+ if (!thd->fill_derived_tables())
+ delete derived_result;
+ orig_table_list->derived_result= derived_result;
+ orig_table_list->table= table;
+ orig_table_list->real_name= table->real_name;
+ table->derived_select_number= first_select->select_number;
+ table->tmp_table= TMP_TABLE;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ table->grant.privilege= SELECT_ACL;
+#endif
+ orig_table_list->db= (char *)"";
+ // Force read of table stats in the optimizer
+ table->file->info(HA_STATUS_VARIABLE);
+ /* Add new temporary table to list of open derived tables */
+ table->next= thd->derived_tables;
+ thd->derived_tables= table;
+ }
}
- derived_result->set_table(table);
+ else if (orig_table_list->ancestor)
+ orig_table_list->set_ancestor();
+ DBUG_RETURN(res);
+}
+
- /*
- if it is preparation PS only or commands that need only VIEW structure
- then we do not need real data and we can skip execution (and parameters
- is not defined, too)
+/*
+ fill derived table
+
+ SYNOPSIS
+ mysql_derived_filling()
+ thd Thread handle
+ lex LEX for this thread
+ unit node that contains all SELECT's for derived tables
+ orig_table_list TABLE_LIST for the upper SELECT
+
+ IMPLEMENTATION
+ Derived table is resolved with temporary table. It is created based on the
+ queries defined. After temporary table is filled, if this is not EXPLAIN,
+ then the entire unit / node is deleted. unit is deleted if UNION is used
+ for derived table and node is deleted is it is a simple SELECT.
+
+ RETURN
+ 0 ok
+ 1 Error
+ -1 Error and error message given
*/
- if (!thd->only_prepare() && !lex->only_view_structure())
+
+int mysql_derived_filling(THD *thd, LEX *lex, TABLE_LIST *orig_table_list)
+{
+ TABLE *table= orig_table_list->table;
+ SELECT_LEX_UNIT *unit= orig_table_list->derived;
+ int res= 0;
+
+ /*check that table creation pass without problem and it is derived table */
+ if (table && unit)
{
+ SELECT_LEX *first_select= unit->first_select();
+ select_union *derived_result= orig_table_list->derived_result;
+ SELECT_LEX *save_current_select= lex->current_select;
+ bool is_union= first_select->next_select() &&
+ first_select->next_select()->linkage == UNION_TYPE;
if (is_union)
{
// execute union without clean up
- if (!(res= unit->prepare(thd, derived_result, SELECT_NO_UNLOCK)))
- res= unit->exec();
+ res= unit->exec();
}
else
{
@@ -173,7 +229,7 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
first_select->options&= ~OPTION_FOUND_ROWS;
lex->current_select= first_select;
- res= mysql_select(thd, &first_select->ref_pointer_array,
+ res= mysql_select(thd, &first_select->ref_pointer_array,
(TABLE_LIST*) first_select->table_list.first,
first_select->with_wild,
first_select->item_list, first_select->where,
@@ -186,49 +242,27 @@ static int mysql_derived(THD *thd, LEX *lex, SELECT_LEX_UNIT *unit,
SELECT_NO_UNLOCK),
derived_result, unit, first_select);
}
- }
- if (!res)
- {
- /*
- Here we entirely fix both TABLE_LIST and list of SELECT's as
- there were no derived tables
- */
- if (derived_result->flush())
- res= 1;
- else
+ if (!res)
{
- org_table_list->real_name= table->real_name;
- org_table_list->table= table;
- table->derived_select_number= first_select->select_number;
- table->tmp_table= TMP_TABLE;
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- table->grant.privilege= SELECT_ACL;
-#endif
- org_table_list->db= (char *)"";
- // Force read of table stats in the optimizer
- table->file->info(HA_STATUS_VARIABLE);
- }
+ /*
+ Here we entirely fix both TABLE_LIST and list of SELECT's as
+ there were no derived tables
+ */
+ if (derived_result->flush())
+ res= 1;
- if (!lex->describe)
- unit->cleanup();
- if (res)
- free_tmp_table(thd, table);
+ if (!lex->describe)
+ unit->cleanup();
+ }
else
{
- /* Add new temporary table to list of open derived tables */
- table->next= thd->derived_tables;
- thd->derived_tables= table;
+ free_tmp_table(thd, table);
+ unit->cleanup();
}
+ lex->current_select= save_current_select;
+ if (res)
+ free_tmp_table(thd, table);
}
- else
- {
- free_tmp_table(thd, table);
- unit->cleanup();
- }
-
-exit:
- delete derived_result;
- lex->current_select= save_current_select;
- DBUG_RETURN(res);
+ return res;
}
diff --git a/sql/sql_do.cc b/sql/sql_do.cc
index 25a8359f3d2..3f34835c2c9 100644
--- a/sql/sql_do.cc
+++ b/sql/sql_do.cc
@@ -20,16 +20,17 @@
#include "mysql_priv.h"
#include "sql_acl.h"
-int mysql_do(THD *thd, List<Item> &values)
+bool mysql_do(THD *thd, List<Item> &values)
{
List_iterator<Item> li(values);
Item *value;
DBUG_ENTER("mysql_do");
if (setup_fields(thd, 0, 0, values, 0, 0, 0))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
while ((value = li++))
value->val_int();
+ free_underlaid_joins(thd, &thd->lex->select_lex);
thd->clear_error(); // DO always is OK
send_ok(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_error.cc b/sql/sql_error.cc
index c09bfe0aea8..adae481d608 100644
--- a/sql/sql_error.cc
+++ b/sql/sql_error.cc
@@ -133,11 +133,11 @@ MYSQL_ERROR *push_warning(THD *thd, MYSQL_ERROR::enum_warning_level level,
The following code is here to change the allocation to not
use the thd->mem_root, which is freed after each query
*/
- MEM_ROOT *old_root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
- my_pthread_setspecific_ptr(THR_MALLOC, &thd->warn_root);
+ MEM_ROOT *old_root= thd->mem_root;
+ thd->mem_root= &thd->warn_root;
if ((err= new MYSQL_ERROR(thd, code, level, msg)))
thd->warn_list.push_back(err);
- my_pthread_setspecific_ptr(THR_MALLOC, old_root);
+ thd->mem_root= old_root;
}
thd->warn_count[(uint) level]++;
thd->total_warn_count++;
@@ -183,14 +183,14 @@ void push_warning_printf(THD *thd, MYSQL_ERROR::enum_warning_level level,
Takes into account the current LIMIT
RETURN VALUES
- 0 ok
- 1 Error sending data to client
+ FALSE ok
+ TRUE Error sending data to client
*/
static const char *warning_level_names[]= {"Note", "Warning", "Error", "?"};
static int warning_level_length[]= { 4, 7, 5, 1 };
-my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
+bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
{
List<Item> field_list;
DBUG_ENTER("mysqld_show_warnings");
@@ -201,7 +201,7 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
if (thd->protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
MYSQL_ERROR *err;
SELECT_LEX *sel= &thd->lex->select_lex;
@@ -225,10 +225,10 @@ my_bool mysqld_show_warnings(THD *thd, ulong levels_to_show)
protocol->store((uint32) err->code);
protocol->store(err->msg, strlen(err->msg), system_charset_info);
if (protocol->write())
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
if (!--limit)
break;
}
- send_eof(thd);
- DBUG_RETURN(0);
+ send_eof(thd);
+ DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_handler.cc b/sql/sql_handler.cc
index edb895fd24a..853b3dd37c6 100644
--- a/sql/sql_handler.cc
+++ b/sql/sql_handler.cc
@@ -140,11 +140,11 @@ static void mysql_ha_hash_free(TABLE_LIST *tables)
error messages.
RETURN
- 0 ok
- != 0 error
+ FALSE OK
+ TRUE Error
*/
-int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
+bool mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
{
TABLE_LIST *hash_tables;
char *db, *name, *alias;
@@ -173,8 +173,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
{
DBUG_PRINT("info",("duplicate '%s'", tables->alias));
if (! reopen)
- my_printf_error(ER_NONUNIQ_TABLE, ER(ER_NONUNIQ_TABLE),
- MYF(0), tables->alias);
+ my_error(ER_NONUNIQ_TABLE, MYF(0), tables->alias);
goto err;
}
}
@@ -198,7 +197,7 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
if (! (tables->table->file->table_flags() & HA_CAN_SQL_HANDLER))
{
if (! reopen)
- my_printf_error(ER_ILLEGAL_HA,ER(ER_ILLEGAL_HA),MYF(0), tables->alias);
+ my_error(ER_ILLEGAL_HA, MYF(0), tables->alias);
mysql_ha_close(thd, tables);
goto err;
}
@@ -236,11 +235,11 @@ int mysql_ha_open(THD *thd, TABLE_LIST *tables, bool reopen)
if (! reopen)
send_ok(thd);
DBUG_PRINT("exit",("OK"));
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
DBUG_PRINT("exit",("ERROR"));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
@@ -257,11 +256,11 @@ err:
will be closed. Broadcasts a COND_refresh condition.
RETURN
- 0 ok
- != 0 error
+ FALSE ok
+ TRUE error
*/
-int mysql_ha_close(THD *thd, TABLE_LIST *tables)
+bool mysql_ha_close(THD *thd, TABLE_LIST *tables)
{
TABLE_LIST *hash_tables;
TABLE **table_ptr;
@@ -299,15 +298,14 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables)
}
else
{
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- tables->alias, "HANDLER");
+ my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
DBUG_PRINT("exit",("ERROR"));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_ok(thd);
DBUG_PRINT("exit", ("OK"));
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -327,15 +325,15 @@ int mysql_ha_close(THD *thd, TABLE_LIST *tables)
offset_limit
RETURN
- 0 ok
- != 0 error
+ FALSE ok
+ TRUE error
*/
-int mysql_ha_read(THD *thd, TABLE_LIST *tables,
- enum enum_ha_read_modes mode, char *keyname,
- List<Item> *key_expr,
- enum ha_rkey_function ha_rkey_mode, Item *cond,
- ha_rows select_limit,ha_rows offset_limit)
+bool mysql_ha_read(THD *thd, TABLE_LIST *tables,
+ enum enum_ha_read_modes mode, char *keyname,
+ List<Item> *key_expr,
+ enum ha_rkey_function ha_rkey_mode, Item *cond,
+ ha_rows select_limit,ha_rows offset_limit)
{
TABLE_LIST *hash_tables;
TABLE *table;
@@ -403,11 +401,9 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
strxnmov(buff, sizeof(buff), tables->db, ".", tables->real_name, NullS);
else
strncpy(buff, tables->alias, sizeof(buff));
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- buff, "HANDLER");
+ my_error(ER_UNKNOWN_TABLE, MYF(0), buff, "HANDLER");
#else
- my_printf_error(ER_UNKNOWN_TABLE, ER(ER_UNKNOWN_TABLE), MYF(0),
- tables->alias, "HANDLER");
+ my_error(ER_UNKNOWN_TABLE, MYF(0), tables->alias, "HANDLER");
#endif
goto err0;
}
@@ -422,8 +418,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
{
if ((keyno=find_type(keyname, &table->keynames, 1+2)-1)<0)
{
- my_printf_error(ER_KEY_DOES_NOT_EXITS,ER(ER_KEY_DOES_NOT_EXITS),MYF(0),
- keyname,tables->alias);
+ my_error(ER_KEY_DOES_NOT_EXITS, MYF(0), keyname, tables->alias);
goto err0;
}
table->file->ha_index_or_rnd_end();
@@ -491,8 +486,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
KEY_PART_INFO *key_part=keyinfo->key_part;
if (key_expr->elements > keyinfo->key_parts)
{
- my_printf_error(ER_TOO_MANY_KEY_PARTS,ER(ER_TOO_MANY_KEY_PARTS),
- MYF(0),keyinfo->key_parts);
+ my_error(ER_TOO_MANY_KEY_PARTS, MYF(0), keyinfo->key_parts);
goto err;
}
List_iterator<Item> it_ke(*key_expr);
@@ -512,10 +506,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
key_len+=key_part->store_length;
}
if (!(key= (byte*) thd->calloc(ALIGN_SIZE(key_len))))
- {
- send_error(thd,ER_OUTOFMEMORY);
goto err;
- }
key_copy(key, table->record[0], table->key_info + keyno, key_len);
error= table->file->index_read(table->record[0],
key,key_len,ha_rkey_mode);
@@ -523,7 +514,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
break;
}
default:
- send_error(thd,ER_ILLEGAL_HA);
+ my_message(ER_ILLEGAL_HA, ER(ER_ILLEGAL_HA), MYF(0));
goto err;
}
@@ -552,7 +543,7 @@ int mysql_ha_read(THD *thd, TABLE_LIST *tables,
if (item->send(thd->protocol, &buffer))
{
protocol->free(); // Free used
- my_error(ER_OUT_OF_RESOURCES,MYF(0));
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
goto err;
}
}
@@ -564,13 +555,13 @@ ok:
mysql_unlock_tables(thd,lock);
send_eof(thd);
DBUG_PRINT("exit",("OK"));
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
mysql_unlock_tables(thd,lock);
err0:
DBUG_PRINT("exit",("ERROR"));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_help.cc b/sql/sql_help.cc
index b349a09e49e..f71e9a7133a 100644
--- a/sql/sql_help.cc
+++ b/sql/sql_help.cc
@@ -88,7 +88,7 @@ static bool init_fields(THD *thd, TABLE_LIST *tables,
Item_field *field= new Item_field("mysql", find_fields->table_name,
find_fields->field_name);
if (!(find_fields->field= find_field_in_tables(thd, field, tables,
- 0, TRUE, 1)))
+ 0, REPORT_ALL_ERRORS, 1)))
DBUG_RETURN(1);
}
DBUG_RETURN(0);
@@ -126,7 +126,7 @@ void memorize_variant_topic(THD *thd, TABLE *topics, int count,
String *name, String *description, String *example)
{
DBUG_ENTER("memorize_variant_topic");
- MEM_ROOT *mem_root= &thd->mem_root;
+ MEM_ROOT *mem_root= thd->mem_root;
if (count==0)
{
get_field(mem_root,find_fields[help_topic_name].field, name);
@@ -137,7 +137,7 @@ void memorize_variant_topic(THD *thd, TABLE *topics, int count,
{
if (count == 1)
names->push_back(name);
- String *new_name= new (&thd->mem_root) String;
+ String *new_name= new (thd->mem_root) String;
get_field(mem_root,find_fields[help_topic_name].field,new_name);
names->push_back(new_name);
}
@@ -276,7 +276,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
(iindex_relations= find_type((char*) primary_key_name,
&relations->keynames, 1+2)-1)<0)
{
- send_error(thd,ER_CORRUPT_HELP_DB);
+ my_message(ER_CORRUPT_HELP_DB, ER(ER_CORRUPT_HELP_DB), MYF(0));
DBUG_RETURN(-1);
}
rtopic_id= find_fields[help_relation_help_topic_id].field;
@@ -286,8 +286,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
relations->file->ha_index_init(iindex_relations);
rkey_id->store((longlong) key_id);
- rkey_id->get_key_image(buff, rkey_id->pack_length(), rkey_id->charset(),
- Field::itRAW);
+ rkey_id->get_key_image(buff, rkey_id->pack_length(), Field::itRAW);
int key_res= relations->file->index_read(relations->record[0],
(byte *)buff, rkey_id->pack_length(),
HA_READ_KEY_EXACT);
@@ -300,8 +299,7 @@ int get_topics_for_keyword(THD *thd, TABLE *topics, TABLE *relations,
longlong topic_id= rtopic_id->val_int();
Field *field= find_fields[help_topic_help_topic_id].field;
field->store((longlong) topic_id);
- field->get_key_image(topic_id_buff, field->pack_length(), field->charset(),
- Field::itRAW);
+ field->get_key_image(topic_id_buff, field->pack_length(), Field::itRAW);
if (!topics->file->index_read(topics->record[0], (byte *)topic_id_buff,
field->pack_length(), HA_READ_KEY_EXACT))
@@ -350,8 +348,8 @@ int search_categories(THD *thd, TABLE *categories,
{
if (select && !select->cond->val_int())
continue;
- String *lname= new (&thd->mem_root) String;
- get_field(&thd->mem_root,pfname,lname);
+ String *lname= new (thd->mem_root) String;
+ get_field(thd->mem_root,pfname,lname);
if (++count == 1 && res_id)
*res_id= (int16) pcat_id->val_int();
names->push_back(lname);
@@ -384,8 +382,8 @@ void get_all_items_for_category(THD *thd, TABLE *items, Field *pfname,
{
if (!select->cond->val_int())
continue;
- String *name= new (&thd->mem_root) String();
- get_field(&thd->mem_root,pfname,name);
+ String *name= new (thd->mem_root) String();
+ get_field(thd->mem_root,pfname,name);
res->push_back(name);
}
end_read_record(&read_record_info);
@@ -607,18 +605,18 @@ SQL_SELECT *prepare_select_for_name(THD *thd, const char *mask, uint mlen,
thd Thread handler
RETURN VALUES
- 0 Success
- 1 Error and send_error already commited
- -1 error && send_error should be issued (normal case)
+ FALSE Success
+ TRUE Error and send_error already commited
*/
-int mysqld_help(THD *thd, const char *mask)
+bool mysqld_help(THD *thd, const char *mask)
{
Protocol *protocol= thd->protocol;
SQL_SELECT *select;
st_find_field used_fields[array_elements(init_used_fields)];
DBUG_ENTER("mysqld_help");
+ TABLE_LIST *leaves= 0;
TABLE_LIST tables[4];
bzero((gptr)tables,sizeof(tables));
tables[0].alias= tables[0].real_name= (char*) "help_topic";
@@ -638,22 +636,19 @@ int mysqld_help(THD *thd, const char *mask)
String name, description, example;
int res, count_topics, count_categories, error;
uint mlen= strlen(mask);
- MEM_ROOT *mem_root= &thd->mem_root;
+ MEM_ROOT *mem_root= thd->mem_root;
- if ((res= open_and_lock_tables(thd, tables)))
- goto end;
+ if (open_and_lock_tables(thd, tables))
+ goto error;
/*
Init tables and fields to be usable from items
tables do not contain VIEWs => we can pass 0 as conds
*/
- setup_tables(thd, tables, 0);
+ setup_tables(thd, tables, 0, &leaves, FALSE, FALSE);
memcpy((char*) used_fields, (char*) init_used_fields, sizeof(used_fields));
if (init_fields(thd, tables, used_fields, array_elements(used_fields)))
- {
- res= -1;
- goto end;
- }
+ goto error;
size_t i;
for (i=0; i<sizeof(tables)/sizeof(TABLE_LIST); i++)
tables[i].table->file->init_table_handle_for_HANDLER();
@@ -661,12 +656,8 @@ int mysqld_help(THD *thd, const char *mask)
if (!(select=
prepare_select_for_name(thd,mask,mlen,tables,tables[0].table,
used_fields[help_topic_name].field,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
- res= 1;
count_topics= search_topics(thd,tables[0].table,used_fields,
select,&topics_list,
&name, &description, &example);
@@ -678,10 +669,8 @@ int mysqld_help(THD *thd, const char *mask)
if (!(select=
prepare_select_for_name(thd,mask,mlen,tables,tables[3].table,
used_fields[help_keyword_name].field,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
+
count_topics=search_keyword(thd,tables[3].table,used_fields,select,&key_id);
delete select;
count_topics= (count_topics != 1) ? 0 :
@@ -697,10 +686,7 @@ int mysqld_help(THD *thd, const char *mask)
if (!(select=
prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
used_fields[help_category_name].field,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
count_categories= search_categories(thd, tables[1].table, used_fields,
select,
@@ -709,13 +695,13 @@ int mysqld_help(THD *thd, const char *mask)
if (!count_categories)
{
if (send_header_2(protocol,FALSE))
- goto end;
+ goto error;
}
else if (count_categories > 1)
{
if (send_header_2(protocol,FALSE) ||
send_variant_2_list(mem_root,protocol,&categories_list,"Y",0))
- goto end;
+ goto error;
}
else
{
@@ -728,20 +714,14 @@ int mysqld_help(THD *thd, const char *mask)
new Item_int((int32)category_id));
if (!(select= prepare_simple_select(thd,cond_topic_by_cat,
tables,tables[0].table,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
get_all_items_for_category(thd,tables[0].table,
used_fields[help_topic_name].field,
select,&topics_list);
delete select;
if (!(select= prepare_simple_select(thd,cond_cat_by_cat,tables,
tables[1].table,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
get_all_items_for_category(thd,tables[1].table,
used_fields[help_category_name].field,
select,&subcategories_list);
@@ -750,39 +730,36 @@ int mysqld_help(THD *thd, const char *mask)
if (send_header_2(protocol, TRUE) ||
send_variant_2_list(mem_root,protocol,&topics_list, "N",cat) ||
send_variant_2_list(mem_root,protocol,&subcategories_list,"Y",cat))
- goto end;
+ goto error;
}
}
else if (count_topics == 1)
{
if (send_answer_1(protocol,&name,&description,&example))
- goto end;
+ goto error;
}
else
{
/* First send header and functions */
if (send_header_2(protocol, FALSE) ||
send_variant_2_list(mem_root,protocol, &topics_list, "N", 0))
- goto end;
+ goto error;
if (!(select=
prepare_select_for_name(thd,mask,mlen,tables,tables[1].table,
used_fields[help_category_name].field,&error)))
- {
- res= -1;
- goto end;
- }
+ goto error;
search_categories(thd, tables[1].table, used_fields,
select,&categories_list, 0);
delete select;
/* Then send categories */
if (send_variant_2_list(mem_root,protocol, &categories_list, "Y", 0))
- goto end;
+ goto error;
}
- res= 0;
-
send_eof(thd);
end:
- DBUG_RETURN(res);
+ DBUG_RETURN(FALSE);
+error:
+ DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_insert.cc b/sql/sql_insert.cc
index 63e11822f6e..0814c7a747e 100644
--- a/sql/sql_insert.cc
+++ b/sql/sql_insert.cc
@@ -21,6 +21,7 @@
#include "sql_acl.h"
#include "sp_head.h"
#include "sql_trigger.h"
+#include "sql_select.h"
static int check_null_fields(THD *thd,TABLE *entry);
#ifndef EMBEDDED_LIBRARY
@@ -31,6 +32,7 @@ static void end_delayed_insert(THD *thd);
extern "C" pthread_handler_decl(handle_delayed_insert,arg);
static void unlink_blobs(register TABLE *table);
#endif
+static bool check_view_insertability(TABLE_LIST *view, ulong query_id);
/* Define to force use of my_malloc() if the allocated memory block is big */
@@ -54,13 +56,25 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
{
TABLE *table= table_list->table;
+ if (!table_list->updatable)
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
+ return -1;
+ }
+
if (fields.elements == 0 && values.elements != 0)
{
+ if (!table)
+ {
+ DBUG_ASSERT(table_list->view &&
+ table_list->ancestor && table_list->ancestor->next_local);
+ my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ return -1;
+ }
if (values.elements != table->fields)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0),counter);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
return -1;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -82,9 +96,7 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
int res;
if (fields.elements != values.elements)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0),counter);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
return -1;
}
@@ -97,10 +109,28 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
thd->lex->select_lex.no_wrap_view_item= 0;
if (res)
return -1;
+ if (table == 0)
+ {
+ /* it is join view => we need to find table for update */
+ List_iterator_fast<Item> it(fields);
+ Item *item;
+ TABLE_LIST *tbl= 0;
+ table_map map= 0;
+
+ while ((item= it++))
+ map|= item->used_tables();
+ if (table_list->check_single_table(&tbl, map) || tbl == 0)
+ {
+ my_error(ER_VIEW_MULTIUPDATE, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ return -1;
+ }
+ table_list->table= table= tbl->table;
+ }
if (check_unique && thd->dupp_field)
{
- my_error(ER_FIELD_SPECIFIED_TWICE,MYF(0), thd->dupp_field->field_name);
+ my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dupp_field->field_name);
return -1;
}
if (table->timestamp_field && // Don't set timestamp if used
@@ -111,16 +141,25 @@ check_insert_fields(THD *thd, TABLE_LIST *table_list, List<Item> &fields,
#ifndef NO_EMBEDDED_ACCESS_CHECKS
table->grant.want_privilege=(SELECT_ACL & ~table->grant.privilege);
#endif
+
+ if (check_key_in_view(thd, table_list) ||
+ (table_list->view &&
+ check_view_insertability(table_list, thd->query_id)))
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
+ return -1;
+ }
+
return 0;
}
-int mysql_insert(THD *thd,TABLE_LIST *table_list,
- List<Item> &fields,
- List<List_item> &values_list,
- List<Item> &update_fields,
- List<Item> &update_values,
- enum_duplicates duplic)
+bool mysql_insert(THD *thd,TABLE_LIST *table_list,
+ List<Item> &fields,
+ List<List_item> &values_list,
+ List<Item> &update_fields,
+ List<Item> &update_values,
+ enum_duplicates duplic)
{
int error, res;
/*
@@ -135,7 +174,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
ulong counter = 1;
ulonglong id;
COPY_INFO info;
- TABLE *table;
+ TABLE *table= 0;
List_iterator_fast<List_item> its(values_list);
List_item *values;
#ifndef EMBEDDED_LIBRARY
@@ -171,10 +210,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
table_list->db ? table_list->db : thd->db,
table_list->real_name))
{
- my_printf_error(ER_DELAYED_INSERT_TABLE_LOCKED,
- ER(ER_DELAYED_INSERT_TABLE_LOCKED),
- MYF(0), table_list->real_name);
- DBUG_RETURN(-1);
+ my_error(ER_DELAYED_INSERT_TABLE_LOCKED, MYF(0),
+ table_list->real_name);
+ DBUG_RETURN(TRUE);
}
}
if ((table= delayed_get_table(thd,table_list)) && !thd->is_fatal_error)
@@ -200,19 +238,16 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
#endif /* EMBEDDED_LIBRARY */
res= open_and_lock_tables(thd, table_list);
if (res || thd->is_fatal_error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
- table= table_list->table;
thd->proc_info="init";
thd->used_tables=0;
values= its++;
- if (duplic == DUP_UPDATE && !table->insert_values)
+ if (duplic == DUP_UPDATE)
{
/* it should be allocated before Item::fix_fields() */
- table->insert_values=
- (byte *)alloc_root(&thd->mem_root, table->rec_buff_length);
- if (!table->insert_values)
+ if (table_list->set_insert_values(thd->mem_root))
goto abort;
}
@@ -220,6 +255,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
update_fields, update_values, duplic))
goto abort;
+ /* mysql_prepare_insert set table_list->table if it was not set */
+ table= table_list->table;
+
// is table which we are changing used somewhere in other parts of query
value_count= values->elements;
while ((values= its++))
@@ -227,9 +265,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
counter++;
if (values->elements != value_count)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0),counter);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto abort;
}
if (setup_fields(thd, 0, table_list, *values, 0, 0, 0))
@@ -291,13 +327,18 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
if (fields.elements || !value_count)
{
restore_record(table,default_values); // Get empty record
- if (fill_record(fields, *values, 0)|| thd->net.report_error)
+ if (fill_record(thd, fields, *values, 0))
{
if (values_list.elements != 1 && !thd->net.report_error)
{
info.records++;
continue;
}
+ /*
+ TODO: set thd->abort_on_warning if values_list.elements == 1
+ and check that all items return warning in case of problem with
+ storing field.
+ */
error=1;
break;
}
@@ -308,7 +349,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
restore_record(table,default_values); // Get empty record
else
table->record[0][0]=table->default_values[0]; // Fix delete marker
- if (fill_record(table->field,*values, 0) || thd->net.report_error)
+ if (fill_record(thd, table->field, *values, 0))
{
if (values_list.elements != 1 && ! thd->net.report_error)
{
@@ -415,7 +456,7 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
if (error <= 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed);
+ log_delayed, FALSE);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1;
}
@@ -466,9 +507,9 @@ int mysql_insert(THD *thd,TABLE_LIST *table_list,
::send_ok(thd, (ulong) thd->row_count_func, id, buff);
}
free_underlaid_joins(thd, &thd->lex->select_lex);
- table->insert_values=0;
+ table_list->clear_insert_values();
thd->abort_on_warning= 0;
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
abort:
#ifndef EMBEDDED_LIBRARY
@@ -476,9 +517,9 @@ abort:
end_delayed_insert(thd);
#endif
free_underlaid_joins(thd, &thd->lex->select_lex);
- table->insert_values=0;
+ table_list->clear_insert_values();
thd->abort_on_warning= 0;
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
@@ -507,8 +548,9 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
{
uint num= view->view->select_lex.item_list.elements;
TABLE *table= view->table;
- Item **trans_start= view->field_translation, **trans_end=trans_start+num;
- Item **trans;
+ Field_translator *trans_start= view->field_translation,
+ *trans_end= trans_start + num;
+ Field_translator *trans;
Field **field_ptr= table->field;
ulong other_query_id= query_id - 1;
DBUG_ENTER("check_key_in_view");
@@ -521,19 +563,23 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
{
Item_field *field;
/* simple SELECT list entry (field without expression) */
- if (!(field= (*trans)->filed_for_view_update()))
+ if (!(field= trans->item->filed_for_view_update()))
DBUG_RETURN(TRUE);
if (field->field->unireg_check == Field::NEXT_NUMBER)
view->contain_auto_increment= 1;
/* prepare unique test */
field->field->query_id= other_query_id;
- *trans= field; // remove collation if we have it
+ /*
+ remove collation (or other transparent for update function) if we have
+ it
+ */
+ trans->item= field;
}
/* unique test */
for (trans= trans_start; trans != trans_end; trans++)
{
/* Thanks to test above, we know that all columns are of type Item_field */
- Item_field *field= (Item_field *)(*trans);
+ Item_field *field= (Item_field *)trans->item;
if (field->field->query_id == query_id)
DBUG_RETURN(TRUE);
field->field->query_id= query_id;
@@ -552,7 +598,7 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
{
if (trans == trans_end)
DBUG_RETURN(TRUE); // Field was not part of view
- if (((Item_field *)(*trans))->field == *field_ptr)
+ if (((Item_field *)trans->item)->field == *field_ptr)
break; // ok
}
}
@@ -567,39 +613,42 @@ static bool check_view_insertability(TABLE_LIST *view, ulong query_id)
SYNOPSIS
mysql_prepare_insert_check_table()
thd Thread handle
- table_list Table list (only one table)
+ table_list Table list
fields List of fields to be updated
where Pointer to where clause
+ select_insert Check is making for SELECT ... INSERT
RETURN
- 0 ok
- 1 ERROR
+ FALSE ok
+ TRUE ERROR
*/
static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
- List<Item> &fields, COND **where)
+ List<Item> &fields, COND **where,
+ bool select_insert)
{
bool insert_into_view= (table_list->view != 0);
DBUG_ENTER("mysql_prepare_insert_check_table");
- if (setup_tables(thd, table_list, where))
- DBUG_RETURN(1);
+ if (setup_tables(thd, table_list, where, &thd->lex->select_lex.leaf_tables,
+ FALSE, select_insert))
+ DBUG_RETURN(TRUE);
if (insert_into_view && !fields.elements)
{
thd->lex->empty_field_list_on_rset= 1;
- insert_view_fields(&fields, table_list);
+ if (!table_list->table)
+ {
+ DBUG_ASSERT(table_list->view &&
+ table_list->ancestor && table_list->ancestor->next_local);
+ my_error(ER_VIEW_NO_INSERT_FIELD_LIST, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_RETURN(insert_view_fields(&fields, table_list));
}
- if (!table_list->updatable ||
- check_key_in_view(thd, table_list) ||
- (insert_into_view &&
- check_view_insertability(table_list, thd->query_id)))
- {
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "INSERT");
- DBUG_RETURN(1);
- }
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -612,11 +661,11 @@ static bool mysql_prepare_insert_check_table(THD *thd, TABLE_LIST *table_list,
table_list Global/local table list
RETURN VALUE
- 0 OK
- -1 error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
+bool mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
List<Item> &fields, List_item *values,
List<Item> &update_fields, List<Item> &update_values,
enum_duplicates duplic)
@@ -624,30 +673,39 @@ int mysql_prepare_insert(THD *thd, TABLE_LIST *table_list, TABLE *table,
bool insert_into_view= (table_list->view != 0);
/* TODO: use this condition for 'WITH CHECK OPTION' */
Item *unused_conds= 0;
- int res;
+ bool res;
DBUG_ENTER("mysql_prepare_insert");
- if (mysql_prepare_insert_check_table(thd, table_list, fields, &unused_conds))
- DBUG_RETURN(-1);
+ DBUG_PRINT("enter", ("table_list 0x%lx, table 0x%lx, view %d",
+ (ulong)table_list, (ulong)table,
+ (int)insert_into_view));
+ if (mysql_prepare_insert_check_table(thd, table_list, fields, &unused_conds,
+ FALSE))
+ DBUG_RETURN(TRUE);
if (check_insert_fields(thd, table_list, fields, *values, 1,
!insert_into_view) ||
setup_fields(thd, 0, table_list, *values, 0, 0, 0) ||
(duplic == DUP_UPDATE &&
((thd->lex->select_lex.no_wrap_view_item= 1,
- (res= setup_fields(thd, 0, table_list, update_fields, 0, 0, 0)),
+ (res= setup_fields(thd, 0, table_list, update_fields, 1, 0, 0)),
thd->lex->select_lex.no_wrap_view_item= 0,
res) ||
- setup_fields(thd, 0, table_list, update_values, 0, 0, 0))))
- DBUG_RETURN(-1);
+ setup_fields(thd, 0, table_list, update_values, 1, 0, 0))))
+ DBUG_RETURN(TRUE);
- if (unique_table(table_list, table_list->next_independent()))
+ if (!table)
+ table= table_list->table;
+
+ if (unique_table(table_list, table_list->next_global))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
+ if (duplic == DUP_UPDATE || duplic == DUP_REPLACE)
+ table->file->extra(HA_EXTRA_RETRIEVE_PRIMARY_KEY);
thd->lex->select_lex.first_execution= 0;
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -739,7 +797,7 @@ int write_record(THD *thd, TABLE *table,COPY_INFO *info)
*/
store_record(table,insert_values);
restore_record(table,record[1]);
- if (fill_record(*info->update_fields, *info->update_values, 0))
+ if (fill_record(thd, *info->update_fields, *info->update_values, 0))
goto err;
/* CHECK OPTION for VIEW ... ON DUPLICATE KEY UPDATE ... */
@@ -823,9 +881,7 @@ int check_that_all_fields_are_given_values(THD *thd, TABLE *entry)
if ((*field)->query_id != thd->query_id &&
((*field)->flags & NO_DEFAULT_VALUE_FLAG))
{
- my_printf_error(ER_NO_DEFAULT_FOR_FIELD,
- ER(ER_NO_DEFAULT_FOR_FIELD),MYF(0),
- (*field)->field_name);
+ my_error(ER_NO_DEFAULT_FOR_FIELD, MYF(0), (*field)->field_name);
return 1;
}
}
@@ -1001,7 +1057,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
{
delete tmp;
thd->fatal_error();
- my_error(ER_OUT_OF_RESOURCES,MYF(0));
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
pthread_mutex_unlock(&LOCK_delayed_create);
DBUG_RETURN(0);
}
@@ -1021,7 +1077,7 @@ static TABLE *delayed_get_table(THD *thd,TABLE_LIST *table_list)
delete tmp;
thd->fatal_error();
pthread_mutex_unlock(&LOCK_delayed_create);
- net_printf(thd,ER_CANT_CREATE_THREAD,error);
+ my_error(ER_CANT_CREATE_THREAD, MYF(0), error);
DBUG_RETURN(0);
}
@@ -1124,7 +1180,7 @@ TABLE *delayed_insert::get_local_table(THD* client_thd)
found_next_number_field=table->found_next_number_field;
for (org_field=table->field ; *org_field ; org_field++,field++)
{
- if (!(*field= (*org_field)->new_field(&client_thd->mem_root,copy)))
+ if (!(*field= (*org_field)->new_field(client_thd->mem_root,copy)))
return 0;
(*field)->orig_table= copy; // Remove connection
(*field)->move_field(adjust_ptrs); // Point at copy->record[0]
@@ -1559,7 +1615,7 @@ bool delayed_insert::handle_inserts(void)
}
if (row->query && row->log_query && using_bin_log)
{
- Query_log_event qinfo(&thd, row->query, row->query_length,0);
+ Query_log_event qinfo(&thd, row->query, row->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
if (table->blob_fields)
@@ -1649,13 +1705,17 @@ bool delayed_insert::handle_inserts(void)
thd thread handler
RETURN
- 0 OK
- -1 Error
+ FALSE OK
+ TRUE Error
*/
-int mysql_insert_select_prepare(THD *thd)
+bool mysql_insert_select_prepare(THD *thd)
{
LEX *lex= thd->lex;
+ TABLE_LIST* first_select_table=
+ (TABLE_LIST*)lex->select_lex.table_list.first;
+ TABLE_LIST* first_select_leaf_table;
+ int res;
DBUG_ENTER("mysql_insert_select_prepare");
/*
SELECT_LEX do not belong to INSERT statement, so we can't add WHERE
@@ -1664,9 +1724,31 @@ int mysql_insert_select_prepare(THD *thd)
lex->query_tables->no_where_clause= 1;
if (mysql_prepare_insert_check_table(thd, lex->query_tables,
lex->field_list,
- &lex->select_lex.where))
- DBUG_RETURN(-1);
- DBUG_RETURN(0);
+ &lex->select_lex.where,
+ TRUE))
+ DBUG_RETURN(TRUE);
+ /*
+ setup was done in mysql_insert_select_prepare, but we have to mark
+ first local table
+ */
+ if (first_select_table)
+ first_select_table->setup_is_done= 1;
+ /*
+ exclude first table from leaf tables list, because it belong to
+ INSERT
+ */
+ DBUG_ASSERT(lex->select_lex.leaf_tables);
+ lex->leaf_tables_insert= lex->select_lex.leaf_tables;
+ /* skip all leaf tables belonged to view where we are insert */
+ for (first_select_leaf_table= lex->select_lex.leaf_tables->next_leaf;
+ first_select_leaf_table &&
+ first_select_leaf_table->belong_to_view &&
+ first_select_leaf_table->belong_to_view ==
+ lex->leaf_tables_insert->belong_to_view;
+ first_select_leaf_table= first_select_leaf_table->next_leaf)
+ {}
+ lex->select_lex.leaf_tables= first_select_leaf_table;
+ DBUG_RETURN(FALSE);
}
@@ -1694,10 +1776,26 @@ select_insert::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (check_insert_fields(thd, table_list, *fields, values, 1,
!insert_into_view))
DBUG_RETURN(1);
+ /*
+ if it is INSERT into join view then check_insert_fields already found
+ real table for insert
+ */
+ table= table_list->table;
+
+ /*
+ Is table which we are changing used somewhere in other parts of
+ query
+ */
+ if (!(thd->lex->current_select->options & OPTION_BUFFER_RESULT) &&
+ unique_table(table_list, table_list->next_global))
+ {
+ /* Using same table for INSERT and SELECT */
+ thd->lex->current_select->options|= OPTION_BUFFER_RESULT;
+ thd->lex->current_select->join->select_options|= OPTION_BUFFER_RESULT;
+ }
restore_record(table,default_values); // Get empty record
table->next_number_field=table->found_next_number_field;
- thd->count_cuted_fields= CHECK_FIELD_WARN; // calc cuted fields
thd->cuted_fields=0;
if (info.handle_duplicates == DUP_IGNORE ||
info.handle_duplicates == DUP_REPLACE)
@@ -1736,41 +1834,53 @@ select_insert::~select_insert()
bool select_insert::send_data(List<Item> &values)
{
DBUG_ENTER("select_insert::send_data");
+ bool error=0;
if (unit->offset_limit_cnt)
{ // using limit offset,count
unit->offset_limit_cnt--;
DBUG_RETURN(0);
}
- if (fields->elements)
- fill_record(*fields, values, 1);
- else
- fill_record(table->field, values, 1);
- switch (table_list->view_check_option(thd,
- thd->lex->duplicates == DUP_IGNORE))
- {
- case VIEW_CHECK_SKIP:
- DBUG_RETURN(0);
- case VIEW_CHECK_ERROR:
+
+ thd->count_cuted_fields= CHECK_FIELD_WARN; // Calculate cuted fields
+ store_values(values);
+ thd->count_cuted_fields= CHECK_FIELD_IGNORE;
+ if (thd->net.report_error)
DBUG_RETURN(1);
+ if (table_list) // Not CREATE ... SELECT
+ {
+ switch (table_list->view_check_option(thd,
+ thd->lex->duplicates ==
+ DUP_IGNORE)) {
+ case VIEW_CHECK_SKIP:
+ DBUG_RETURN(0);
+ case VIEW_CHECK_ERROR:
+ DBUG_RETURN(1);
+ }
}
- if (thd->net.report_error || write_record(thd, table, &info))
- DBUG_RETURN(1);
- if (table->next_number_field) // Clear for next record
+ if (!(error= write_record(thd, table,&info)) && table->next_number_field)
{
+ /* Clear for next record */
table->next_number_field->reset();
if (! last_insert_id && thd->insert_id_used)
last_insert_id=thd->insert_id();
}
- DBUG_RETURN(0);
+ DBUG_RETURN(error);
}
+void select_insert::store_values(List<Item> &values)
+{
+ if (fields->elements)
+ fill_record(thd, *fields, values, 1);
+ else
+ fill_record(thd, table->field, values, 1);
+}
+
void select_insert::send_error(uint errcode,const char *err)
{
DBUG_ENTER("select_insert::send_error");
- /* TODO error should be sent at the query processing end */
- ::send_error(thd,errcode,err);
+ my_message(errcode, err, MYF(0));
if (!table)
{
@@ -1795,7 +1905,7 @@ void select_insert::send_error(uint errcode,const char *err)
if (mysql_bin_log.is_open())
{
Query_log_event qinfo(thd, thd->query, thd->query_length,
- table->file->has_transactions());
+ table->file->has_transactions(), FALSE);
mysql_bin_log.write(&qinfo);
}
if (!table->tmp_table)
@@ -1838,7 +1948,7 @@ bool select_insert::send_eof()
if (!error)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- table->file->has_transactions());
+ table->file->has_transactions(), FALSE);
mysql_bin_log.write(&qinfo);
}
if ((error2=ha_autocommit_or_rollback(thd,error)) && ! error)
@@ -1846,8 +1956,6 @@ bool select_insert::send_eof()
if (error)
{
table->file->print_error(error,MYF(0));
- //TODO error should be sent at the query processing end
- ::send_error(thd);
DBUG_RETURN(1);
}
char buff[160];
@@ -1880,9 +1988,7 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
if (table->fields < values.elements)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0),1);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), 1);
DBUG_RETURN(-1);
}
@@ -1895,8 +2001,6 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
table->next_number_field=table->found_next_number_field;
restore_record(table,default_values); // Get empty record
- /* Count warnings. This is reset in ~select_insert() */
- thd->count_cuted_fields= CHECK_FIELD_WARN;
thd->cuted_fields=0;
if (info.handle_duplicates == DUP_IGNORE ||
info.handle_duplicates == DUP_REPLACE)
@@ -1911,23 +2015,21 @@ select_create::prepare(List<Item> &values, SELECT_LEX_UNIT *u)
}
-bool select_create::send_data(List<Item> &values)
+void select_create::store_values(List<Item> &values)
{
- if (unit->offset_limit_cnt)
- { // using limit offset,count
- unit->offset_limit_cnt--;
- return 0;
- }
- fill_record(field, values, 1);
- if (thd->net.report_error || write_record(thd, table, &info))
- return 1;
- if (table->next_number_field) // Clear for next record
- {
- table->next_number_field->reset();
- if (! last_insert_id && thd->insert_id_used)
- last_insert_id=thd->insert_id();
- }
- return 0;
+ fill_record(thd, field, values, 1);
+}
+
+
+void select_create::send_error(uint errcode,const char *err)
+{
+ /*
+ Disable binlog, because we "roll back" partial inserts in ::abort
+ by removing the table, even for non-transactional tables.
+ */
+ tmp_disable_binlog(thd);
+ select_insert::send_error(errcode, err);
+ reenable_binlog(thd);
}
@@ -1975,7 +2077,7 @@ void select_create::abort()
enum db_type table_type=table->db_type;
if (!table->tmp_table)
{
- ulong version= table->version;
+ ulong version= table->version;
hash_delete(&open_cache,(byte*) table);
if (!create_info->table_existed)
quick_rm_table(table_type, create_table->db, create_table->real_name);
diff --git a/sql/sql_lex.cc b/sql/sql_lex.cc
index d978cc14f64..12e4d912f15 100644
--- a/sql/sql_lex.cc
+++ b/sql/sql_lex.cc
@@ -144,13 +144,14 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->select_lex.init_order();
lex->select_lex.group_list.empty();
lex->describe= 0;
- lex->derived_tables= FALSE;
+ lex->subqueries= FALSE;
lex->view_prepare_mode= FALSE;
+ lex->derived_tables= 0;
lex->lock_option= TL_READ;
lex->found_colon= 0;
lex->safe_to_cache_query= 1;
lex->time_zone_tables_used= 0;
- lex->proc_table= lex->query_tables= 0;
+ lex->leaf_tables_insert= lex->proc_table= lex->query_tables= 0;
lex->query_tables_last= &lex->query_tables;
lex->variables_used= 0;
lex->select_lex.parent_lex= lex;
@@ -175,13 +176,10 @@ void lex_start(THD *thd, uchar *buf,uint length)
lex->duplicates= DUP_ERROR;
lex->sphead= NULL;
lex->spcont= NULL;
- lex->trg_table= NULL;
-
- extern byte *sp_lex_spfuns_key(const byte *ptr, uint *plen, my_bool first);
- hash_free(&lex->spfuns);
- hash_init(&lex->spfuns, system_charset_info, 0, 0, 0,
- sp_lex_spfuns_key, 0, 0);
+ lex->proc_list.first= 0;
+ if (lex->spfuns.records)
+ hash_reset(&lex->spfuns);
}
void lex_end(LEX *lex)
@@ -202,6 +200,14 @@ static int find_keyword(LEX *lex, uint len, bool function)
lex->yylval->symbol.symbol=symbol;
lex->yylval->symbol.str= (char*) tok;
lex->yylval->symbol.length=len;
+
+ if ((symbol->tok == NOT_SYM) &&
+ (lex->thd->variables.sql_mode & MODE_HIGH_NOT_PRECEDENCE))
+ return NOT2_SYM;
+ if ((symbol->tok == OR_OR_SYM) &&
+ !(lex->thd->variables.sql_mode & MODE_PIPES_AS_CONCAT))
+ return OR2_SYM;
+
return symbol->tok;
}
return 0;
@@ -1043,7 +1049,7 @@ void st_select_lex::init_query()
table_list.empty();
top_join_list.empty();
join_list= &top_join_list;
- embedding= 0;
+ embedding= leaf_tables= 0;
item_list.empty();
join= 0;
where= prep_where= 0;
@@ -1059,6 +1065,7 @@ void st_select_lex::init_query()
first_cond_optimization= 1;
parsing_place= NO_MATTER;
no_wrap_view_item= 0;
+ link_next= 0;
}
void st_select_lex::init_select()
@@ -1310,7 +1317,7 @@ bool st_select_lex::test_limit()
if (select_limit != HA_POS_ERROR)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0),
- "LIMIT & IN/ALL/ANY/SOME subquery");
+ "LIMIT & IN/ALL/ANY/SOME subquery");
return(1);
}
// We need only 1 row to determinate existence
@@ -1637,7 +1644,7 @@ bool st_lex::can_be_merged()
select_lex.group_list.elements == 0 &&
select_lex.having == 0 &&
select_lex.with_sum_func == 0 &&
- select_lex.table_list.elements == 1 &&
+ select_lex.table_list.elements >= 1 &&
!(select_lex.options & SELECT_DISTINCT) &&
select_lex.select_limit == HA_POS_ERROR);
}
@@ -1717,6 +1724,7 @@ bool st_lex::can_not_use_merged()
TRUE yes, we need only structure
FALSE no, we need data
*/
+
bool st_lex::only_view_structure()
{
switch(sql_command)
@@ -1736,6 +1744,32 @@ bool st_lex::only_view_structure()
/*
+ Should Items_ident be printed correctly
+
+ SYNOPSIS
+ need_correct_ident()
+
+ RETURN
+ TRUE yes, we need only structure
+ FALSE no, we need data
+*/
+
+
+bool st_lex::need_correct_ident()
+{
+ switch(sql_command)
+ {
+ case SQLCOM_SHOW_CREATE:
+ case SQLCOM_SHOW_TABLES:
+ case SQLCOM_CREATE_VIEW:
+ return TRUE;
+ default:
+ return FALSE;
+ }
+}
+
+
+/*
initialize limit counters
SYNOPSIS
diff --git a/sql/sql_lex.h b/sql/sql_lex.h
index 2bdc35f35cb..1c0e3e2e02e 100644
--- a/sql/sql_lex.h
+++ b/sql/sql_lex.h
@@ -56,7 +56,7 @@ enum enum_sql_command {
SQLCOM_SHOW_INNODB_STATUS,
SQLCOM_SHOW_PROCESSLIST, SQLCOM_SHOW_MASTER_STAT, SQLCOM_SHOW_SLAVE_STAT,
SQLCOM_SHOW_GRANTS, SQLCOM_SHOW_CREATE, SQLCOM_SHOW_CHARSETS,
- SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB,
+ SQLCOM_SHOW_COLLATIONS, SQLCOM_SHOW_CREATE_DB, SQLCOM_SHOW_TABLE_STATUS,
SQLCOM_LOAD,SQLCOM_SET_OPTION,SQLCOM_LOCK_TABLES,SQLCOM_UNLOCK_TABLES,
SQLCOM_GRANT,
@@ -78,7 +78,8 @@ enum enum_sql_command {
SQLCOM_SHOW_BINLOG_EVENTS, SQLCOM_SHOW_NEW_MASTER, SQLCOM_DO,
SQLCOM_SHOW_WARNS, SQLCOM_EMPTY_QUERY, SQLCOM_SHOW_ERRORS,
SQLCOM_SHOW_COLUMN_TYPES, SQLCOM_SHOW_STORAGE_ENGINES, SQLCOM_SHOW_PRIVILEGES,
- SQLCOM_HELP, SQLCOM_DROP_USER, SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
+ SQLCOM_HELP, SQLCOM_CREATE_USER, SQLCOM_DROP_USER, SQLCOM_RENAME_USER,
+ SQLCOM_REVOKE_ALL, SQLCOM_CHECKSUM,
SQLCOM_CREATE_PROCEDURE, SQLCOM_CREATE_SPFUNCTION, SQLCOM_CALL,
SQLCOM_DROP_PROCEDURE, SQLCOM_ALTER_PROCEDURE,SQLCOM_ALTER_FUNCTION,
SQLCOM_SHOW_CREATE_PROC, SQLCOM_SHOW_CREATE_FUNC,
@@ -282,8 +283,9 @@ public:
}
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
- static void operator delete(void *ptr,size_t size) {}
- static void operator delete(void *ptr,size_t size, MEM_ROOT *mem_root) {}
+ static void operator delete(void *ptr,size_t size) { TRASH(ptr, size); }
+ static void operator delete(void *ptr,size_t size, MEM_ROOT *mem_root)
+ { TRASH(ptr, size); }
st_select_lex_node(): linkage(UNSPECIFIED_TYPE) {}
virtual ~st_select_lex_node() {}
inline st_select_lex_node* get_master() { return master; }
@@ -342,8 +344,8 @@ protected:
TABLE *table; /* temporary table using for appending UNION results */
select_result *result;
- int res;
ulong found_rows_for_union;
+ bool res;
bool prepared, // prepare phase already performed for UNION (unit)
optimized, // optimize phase already performed for UNION (unit)
executed, // already executed
@@ -403,9 +405,9 @@ public:
void exclude_tree();
/* UNION methods */
- int prepare(THD *thd, select_result *result, ulong additional_options);
- int exec();
- int cleanup();
+ bool prepare(THD *thd, select_result *result, ulong additional_options);
+ bool exec();
+ bool cleanup();
inline void unclean() { cleaned= 0; }
void reinit_exec_mechanism();
@@ -413,7 +415,7 @@ public:
void print(String *str);
ulong init_prepare_fake_select_lex(THD *thd);
- int change_result(select_subselect *result, select_subselect *old_result);
+ bool change_result(select_subselect *result, select_subselect *old_result);
void set_limit(st_select_lex *values, st_select_lex *sl);
friend void lex_start(THD *thd, uchar *buf, uint length);
@@ -447,6 +449,7 @@ public:
List<TABLE_LIST> top_join_list; /* join list of the top level */
List<TABLE_LIST> *join_list; /* list for the currently parsed join */
TABLE_LIST *embedding; /* table embedding to the above list */
+ TABLE_LIST *leaf_tables; /* list of leaves in join table tree */
const char *type; /* type of select for EXPLAIN */
SQL_LIST order_list; /* ORDER clause */
@@ -649,7 +652,6 @@ typedef struct st_lex
char *help_arg;
char *backup_dir; /* For RESTORE/BACKUP */
char* to_log; /* For PURGE MASTER LOGS TO */
- time_t purge_time; /* For PURGE MASTER LOGS BEFORE */
char* x509_subject,*x509_issuer,*ssl_cipher;
char* found_colon; /* For multi queries - next query */
String *wild;
@@ -669,6 +671,8 @@ typedef struct st_lex
*/
TABLE_LIST **query_tables_last;
TABLE_LIST *proc_table; /* refer to mysql.proc if it was opened by VIEW */
+ /* store original leaf_tables for INSERT SELECT and PS/SP */
+ TABLE_LIST *leaf_tables_insert;
List<key_part_spec> col_list;
List<key_part_spec> ref_list;
@@ -683,7 +687,6 @@ typedef struct st_lex
List<Item_param> param_list;
List<LEX_STRING> view_list; // view list (list of field names in view)
SQL_LIST proc_list, auxilliary_table_list, save_list;
- TYPELIB *interval;
create_field *last_field;
char *savepoint_name; // Transaction savepoint id
udf_func udf;
@@ -691,8 +694,8 @@ typedef struct st_lex
HA_CREATE_INFO create_info;
LEX_MASTER_INFO mi; // used by CHANGE MASTER
USER_RESOURCES mqh;
- ulong thread_id,type;
- enum_sql_command sql_command;
+ ulong type;
+ enum_sql_command sql_command, orig_sql_command;
thr_lock_type lock_option, multi_lock_option;
enum SSL_type ssl_type; /* defined in violite.h */
enum my_lex_states next_state;
@@ -706,7 +709,8 @@ typedef struct st_lex
uint uint_geom_type;
uint grant, grant_tot_col, which_columns;
uint fk_delete_opt, fk_update_opt, fk_match_option;
- uint slave_thd_opt;
+ uint slave_thd_opt, start_transaction_opt;
+ uint table_count; /* used when usual update transformed in multiupdate */
uint8 describe;
uint8 derived_tables;
uint8 create_view_algorithm;
@@ -716,6 +720,7 @@ typedef struct st_lex
/* special JOIN::prepare mode: changing of query is prohibited */
bool view_prepare_mode;
bool safe_to_cache_query;
+ bool subqueries;
bool variables_used;
ALTER_INFO alter_info;
/* Prepared statements SQL syntax:*/
@@ -750,15 +755,18 @@ typedef struct st_lex
/* Characterstics of trigger being created */
st_trg_chistics trg_chistics;
/*
- Points to table being opened when we are parsing trigger definition
- while opening table. 0 if we are parsing user provided CREATE TRIGGER
- or any other statement. Used for NEW/OLD row field lookup in trigger.
+ List of all items (Item_trigger_field objects) representing fields in
+ old/new version of row in trigger. We use this list for checking whenever
+ all such fields are valid at trigger creation time and for binding these
+ fields to TABLE object at table open (altough for latter pointer to table
+ being opened is probably enough).
*/
- TABLE *trg_table;
+ SQL_LIST trg_table_fields;
- st_lex() :result(0)
+ st_lex() :result(0), sql_command(SQLCOM_END)
{
- bzero((char *)&spfuns, sizeof(spfuns));
+ extern byte *sp_lex_spfuns_key(const byte *ptr, uint *plen, my_bool first);
+ hash_init(&spfuns, system_charset_info, 0, 0, 0, sp_lex_spfuns_key, 0, 0);
}
~st_lex()
@@ -799,6 +807,7 @@ typedef struct st_lex
bool can_use_merged();
bool can_not_use_merged();
bool only_view_structure();
+ bool need_correct_ident();
} LEX;
extern TABLE_LIST fake_time_zone_tables_list;
@@ -812,7 +821,8 @@ struct st_lex_local: public st_lex
{
return (void*) alloc_root(mem_root, (uint) size);
}
- static void operator delete(void *ptr,size_t size) {}
+ static void operator delete(void *ptr,size_t size)
+ { TRASH(ptr, size); }
};
void lex_init(void);
diff --git a/sql/sql_list.h b/sql/sql_list.h
index d8d3719d39d..657943f1e69 100644
--- a/sql/sql_list.h
+++ b/sql/sql_list.h
@@ -21,12 +21,6 @@
/* mysql standard class memory allocator */
-#ifdef SAFEMALLOC
-#define TRASH(XX,YY) bfill((XX), (YY), 0x8F)
-#else
-#define TRASH(XX,YY) /* no-op */
-#endif
-
class Sql_alloc
{
public:
@@ -113,6 +107,16 @@ public:
}
return 1;
}
+ inline bool push_back(void *info, MEM_ROOT *mem_root)
+ {
+ if (((*last)=new (mem_root) list_node(info, &end_of_list)))
+ {
+ last= &(*last)->next;
+ elements++;
+ return 0;
+ }
+ return 1;
+ }
inline bool push_front(void *info)
{
list_node *node=new list_node(info,first);
@@ -284,6 +288,8 @@ public:
inline List() :base_list() {}
inline List(const List<T> &tmp) :base_list(tmp) {}
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); }
inline bool push_front(T *a) { return base_list::push_front(a); }
inline T* head() {return (T*) base_list::head(); }
inline T** head_ref() {return (T**) base_list::head_ref(); }
diff --git a/sql/sql_load.cc b/sql/sql_load.cc
index 1735da6b717..21dd2318504 100644
--- a/sql/sql_load.cc
+++ b/sql/sql_load.cc
@@ -80,7 +80,7 @@ static int read_sep_field(THD *thd, COPY_INFO &info, TABLE_LIST *table_list,
String &enclosed, ulong skip_lines,
bool ignore_check_option_errors);
-int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
+bool mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
List<Item> &fields, enum enum_duplicates handle_duplicates,
bool read_file_from_client,thr_lock_type lock_type,
bool ignore_check_option_errors)
@@ -91,7 +91,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
int error;
String *field_term=ex->field_term,*escaped=ex->escaped;
String *enclosed=ex->enclosed;
- Item *unused_conds;
+ Item *unused_conds= 0;
bool is_fifo=0;
#ifndef EMBEDDED_LIBRARY
LOAD_FILE_INFO lf_info;
@@ -116,17 +116,20 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
my_message(ER_WRONG_FIELD_TERMINATORS,ER(ER_WRONG_FIELD_TERMINATORS),
MYF(0));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
table_list->lock_type= lock_type;
- if ((res= open_and_lock_tables(thd, table_list)))
- DBUG_RETURN(res);
- if (setup_tables(thd, table_list, &unused_conds))
+ if (open_and_lock_tables(thd, table_list))
+ DBUG_RETURN(TRUE);
+ if (setup_tables(thd, table_list, &unused_conds,
+ &thd->lex->select_lex.leaf_tables, FALSE, FALSE))
DBUG_RETURN(-1);
- if (!table_list->updatable || check_key_in_view(thd, table_list))
+ if (!table_list->table || // do not suport join view
+ !table_list->updatable || // and derived tables
+ check_key_in_view(thd, table_list))
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "LOAD");
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
table= table_list->table;
transactional_table= table->file->has_transactions();
@@ -143,16 +146,16 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
thd->dupp_field=0;
/* TODO: use this conds for 'WITH CHECK OPTIONS' */
Item *unused_conds= 0;
- if (setup_tables(thd, table_list, &unused_conds) ||
- setup_fields(thd, 0, table_list, fields, 1, 0, 0))
- DBUG_RETURN(-1);
+ TABLE_LIST *leaves= 0;
+ if (setup_fields(thd, 0, table_list, fields, 1, 0, 0))
+ DBUG_RETURN(TRUE);
if (thd->dupp_field)
{
my_error(ER_FIELD_SPECIFIED_TWICE, MYF(0), thd->dupp_field->field_name);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
if (check_that_all_fields_are_given_values(thd, table))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
uint tot_length=0;
@@ -178,7 +181,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
my_message(ER_BLOBS_AND_NO_TERMINATED,ER(ER_BLOBS_AND_NO_TERMINATED),
MYF(0));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
/* We can't give an error in the middle when using LOCAL files */
@@ -210,7 +213,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
#if !defined(__WIN__) && !defined(OS2) && ! defined(__NETWARE__)
MY_STAT stat_info;
if (!my_stat(name,&stat_info,MYF(MY_WME)))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
// if we are not in slave thread, the file must be:
if (!thd->slave_thread &&
@@ -221,15 +224,15 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
((stat_info.st_mode & S_IFREG) == S_IFREG ||
(stat_info.st_mode & S_IFIFO) == S_IFIFO)))
{
- my_error(ER_TEXTFILE_NOT_READABLE,MYF(0),name);
- DBUG_RETURN(-1);
+ my_error(ER_TEXTFILE_NOT_READABLE, MYF(0), name);
+ DBUG_RETURN(TRUE);
}
if ((stat_info.st_mode & S_IFIFO) == S_IFIFO)
is_fifo = 1;
#endif
}
if ((file=my_open(name,O_RDONLY,MYF(MY_WME))) < 0)
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
COPY_INFO info;
@@ -244,7 +247,7 @@ int mysql_load(THD *thd,sql_exchange *ex,TABLE_LIST *table_list,
{
if (file >= 0)
my_close(file,MYF(0)); // no files in net reading
- DBUG_RETURN(-1); // Can't allocate buffers
+ DBUG_RETURN(TRUE); // Can't allocate buffers
}
#ifndef EMBEDDED_LIBRARY
diff --git a/sql/sql_map.cc b/sql/sql_map.cc
index e7e24f957c6..687e60b7c72 100644
--- a/sql/sql_map.cc
+++ b/sql/sql_map.cc
@@ -47,13 +47,12 @@ mapped_files::mapped_files(const my_string filename,byte *magic,uint magic_lengt
0L)))
{
error=errno;
- my_printf_error(0,"Can't map file: %s, errno: %d",MYF(0),
- (my_string) name,error);
+ my_error(ER_NO_FILE_MAPPING, MYF(0), (my_string) name, error);
}
}
if (map && memcmp(map,magic,magic_length))
{
- my_printf_error(0,"Wrong magic in %s",MYF(0),name);
+ my_error(ER_WRONG_MAGIC, MYF(0), name);
VOID(munmap(map,size));
map=0;
}
@@ -112,8 +111,7 @@ mapped_files *map_file(const my_string name,byte *magic,uint magic_length)
{
map->use_count++;
if (!map->map)
- my_printf_error(0,"Can't map file: %s, error: %d",MYF(0),path,
- map->error);
+ my_error(ER_NO_FILE_MAPPING, MYF(0), path, map->error);
}
VOID(pthread_mutex_unlock(&LOCK_mapped_file));
return map;
diff --git a/sql/sql_olap.cc b/sql/sql_olap.cc
index 20fd7fe2ee0..07271d40492 100644
--- a/sql/sql_olap.cc
+++ b/sql/sql_olap.cc
@@ -153,7 +153,8 @@ int handle_olaps(LEX *lex, SELECT_LEX *select_lex)
if (setup_tables(lex->thd, (TABLE_LIST *)select_lex->table_list.first
- &select_lex->where) ||
+ &select_lex->where, &select_lex->leaf_tables,
+ FALSE, FALSE) ||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
select_lex->item_list, 1, &all_fields,1) ||
setup_fields(lex->thd, 0, (TABLE_LIST *)select_lex->table_list.first,
diff --git a/sql/sql_parse.cc b/sql/sql_parse.cc
index 60f69b578e9..3d4252a2b17 100644
--- a/sql/sql_parse.cc
+++ b/sql/sql_parse.cc
@@ -118,15 +118,20 @@ static void unlock_locked_tables(THD *thd)
static bool end_active_trans(THD *thd)
{
int error=0;
+ DBUG_ENTER("end_active_trans");
if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN |
OPTION_TABLE_LOCK))
{
+ DBUG_PRINT("info",("options: 0x%lx", (ulong) thd->options));
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
+ /* Safety if one did "drop table" on locked tables */
+ if (!thd->locked_tables)
+ thd->options&= ~OPTION_TABLE_LOCK;
thd->server_status&= ~SERVER_STATUS_IN_TRANS;
if (ha_commit(thd))
error=1;
}
- return error;
+ DBUG_RETURN(error);
}
@@ -166,7 +171,7 @@ static int get_or_create_user_conn(THD *thd, const char *user,
my_malloc(sizeof(struct user_conn) + temp_len+1,
MYF(MY_WME)))))
{
- send_error(thd, 0, NullS); // Out of memory
+ net_send_error(thd, 0, NullS); // Out of memory
return_val=1;
goto end;
}
@@ -184,7 +189,7 @@ static int get_or_create_user_conn(THD *thd, const char *user,
if (my_hash_insert(&hash_user_connections, (byte*) uc))
{
my_free((char*) uc,0);
- send_error(thd, 0, NullS); // Out of memory
+ net_send_error(thd, 0, NullS); // Out of memory
return_val=1;
goto end;
}
@@ -259,7 +264,7 @@ int check_user(THD *thd, enum enum_server_command command,
*/
if (opt_secure_auth_local && passwd_len == SCRAMBLE_LENGTH_323)
{
- net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+ net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
mysql_log.write(thd, COM_CONNECT, ER(ER_NOT_SUPPORTED_AUTH_MODE));
DBUG_RETURN(-1);
}
@@ -291,8 +296,8 @@ int check_user(THD *thd, enum enum_server_command command,
NET *net= &thd->net;
if (opt_secure_auth_local)
{
- net_printf(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
- thd->user, thd->host_or_ip);
+ net_printf_error(thd, ER_SERVER_IS_IN_SECURE_AUTH_MODE,
+ thd->user, thd->host_or_ip);
mysql_log.write(thd, COM_CONNECT, ER(ER_SERVER_IS_IN_SECURE_AUTH_MODE),
thd->user, thd->host_or_ip);
DBUG_RETURN(-1);
@@ -331,7 +336,7 @@ int check_user(THD *thd, enum enum_server_command command,
VOID(pthread_mutex_unlock(&LOCK_thread_count));
if (!count_ok)
{ // too many connections
- send_error(thd, ER_CON_COUNT_ERROR);
+ net_send_error(thd, ER_CON_COUNT_ERROR);
DBUG_RETURN(-1);
}
}
@@ -381,14 +386,14 @@ int check_user(THD *thd, enum enum_server_command command,
}
else if (res == 2) // client gave short hash, server has long hash
{
- net_printf(thd, ER_NOT_SUPPORTED_AUTH_MODE);
+ net_printf_error(thd, ER_NOT_SUPPORTED_AUTH_MODE);
mysql_log.write(thd,COM_CONNECT,ER(ER_NOT_SUPPORTED_AUTH_MODE));
DBUG_RETURN(-1);
}
- net_printf(thd, ER_ACCESS_DENIED_ERROR,
- thd->user,
- thd->host_or_ip,
- passwd_len ? ER(ER_YES) : ER(ER_NO));
+ net_printf_error(thd, ER_ACCESS_DENIED_ERROR,
+ thd->user,
+ thd->host_or_ip,
+ passwd_len ? ER(ER_YES) : ER(ER_NO));
mysql_log.write(thd, COM_CONNECT, ER(ER_ACCESS_DENIED_ERROR),
thd->user,
thd->host_or_ip,
@@ -451,16 +456,16 @@ static int check_for_max_user_connections(THD *thd, USER_CONN *uc)
if (max_user_connections &&
max_user_connections < (uint) uc->connections)
{
- net_printf(thd,ER_TOO_MANY_USER_CONNECTIONS, uc->user);
+ net_printf_error(thd, ER_TOO_MANY_USER_CONNECTIONS, uc->user);
error=1;
goto end;
}
if (uc->user_resources.connections &&
uc->user_resources.connections <= uc->conn_per_hour)
{
- net_printf(thd, ER_USER_LIMIT_REACHED, uc->user,
- "max_connections",
- (long) uc->user_resources.connections);
+ net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user,
+ "max_connections",
+ (long) uc->user_resources.connections);
error=1;
goto end;
}
@@ -592,8 +597,8 @@ static bool check_mqh(THD *thd, uint check_command)
if (uc->user_resources.questions &&
uc->questions++ >= uc->user_resources.questions)
{
- net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
- (long) uc->user_resources.questions);
+ net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_questions",
+ (long) uc->user_resources.questions);
error=1;
goto end;
}
@@ -603,8 +608,8 @@ static bool check_mqh(THD *thd, uint check_command)
if (uc->user_resources.updates && uc_update_queries[check_command] &&
uc->updates++ >= uc->user_resources.updates)
{
- net_printf(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
- (long) uc->user_resources.updates);
+ net_printf_error(thd, ER_USER_LIMIT_REACHED, uc->user, "max_updates",
+ (long) uc->user_resources.updates);
error=1;
goto end;
}
@@ -615,7 +620,7 @@ end:
}
-static void reset_mqh(THD *thd, LEX_USER *lu, bool get_them= 0)
+static void reset_mqh(LEX_USER *lu, bool get_them= 0)
{
#ifndef NO_EMBEDDED_ACCESS_CHECKS
(void) pthread_mutex_lock(&LOCK_user_conn);
@@ -899,18 +904,20 @@ static int check_connection(THD *thd)
/* Since 4.1 all database names are stored in utf8 */
if (db)
{
+ uint dummy_errors;
db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
system_charset_info,
db, strlen(db),
- thd->charset())]= 0;
+ thd->charset(), &dummy_errors)]= 0;
db= db_buff;
}
if (user)
{
+ uint dummy_errors;
user_buff[copy_and_convert(user_buff, sizeof(user_buff)-1,
system_charset_info, user, strlen(user),
- thd->charset())]= '\0';
+ thd->charset(), &dummy_errors)]= '\0';
user= user_buff;
}
@@ -1008,7 +1015,7 @@ pthread_handler_decl(handle_one_connection,arg)
if ((error=check_connection(thd)))
{ // Wrong permissions
if (error > 0)
- net_printf(thd,error,thd->host_or_ip);
+ net_printf_error(thd, error, thd->host_or_ip);
#ifdef __NT__
if (vio_type(net->vio) == VIO_TYPE_NAMEDPIPE)
my_sleep(1000); /* must wait after eof() */
@@ -1026,6 +1033,7 @@ pthread_handler_decl(handle_one_connection,arg)
thd->version= refresh_version;
thd->proc_info= 0;
+ thd->command= COM_SLEEP;
thd->set_time();
thd->init_for_queries();
@@ -1055,7 +1063,7 @@ pthread_handler_decl(handle_one_connection,arg)
thd->host_or_ip,
(net->last_errno ? ER(net->last_errno) :
ER(ER_UNKNOWN_ERROR)));
- send_error(thd,net->last_errno,NullS);
+ net_send_error(thd, net->last_errno, NullS);
statistic_increment(aborted_threads,&LOCK_status);
}
else if (thd->killed)
@@ -1124,8 +1132,8 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
uint length=(uint) strlen(buff);
if (buff[length-1]!='\n' && !feof(file))
{
- send_error(thd,ER_NET_PACKET_TOO_LARGE, NullS);
- thd->is_fatal_error= 1;
+ net_send_error(thd, ER_NET_PACKET_TOO_LARGE, NullS);
+ thd->fatal_error();
break;
}
while (length && (my_isspace(thd->charset(), buff[length-1]) ||
@@ -1144,14 +1152,14 @@ extern "C" pthread_handler_decl(handle_bootstrap,arg)
{
thd->net.error = 0;
close_thread_tables(thd); // Free tables
- free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
break;
}
mysql_parse(thd,thd->query,length);
close_thread_tables(thd); // Free tables
if (thd->is_fatal_error)
break;
- free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
free_root(&thd->transaction.mem_root,MYF(MY_KEEP_PREALLOC));
}
@@ -1172,9 +1180,13 @@ end:
void free_items(Item *item)
{
+ Item *next;
DBUG_ENTER("free_items");
- for (; item ; item=item->next)
+ for (; item ; item=next)
+ {
+ next=item->next;
item->delete_self();
+ }
DBUG_VOID_RETURN;
}
@@ -1202,7 +1214,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
if (!db || check_db_name(db))
{
- net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
+ my_error(ER_WRONG_DB_NAME ,MYF(0), db ? db : "NULL");
goto err;
}
if (lower_case_table_names)
@@ -1217,7 +1229,7 @@ int mysql_table_dump(THD* thd, char* db, char* tbl_name, int fd)
thd->free_list = 0;
thd->query_length=(uint) strlen(tbl_name);
thd->query = tbl_name;
- if ((error = mysqld_dump_create_info(thd, table, -1)))
+ if ((error = mysqld_dump_create_info(thd, table_list, -1)))
{
my_error(ER_GET_ERRNO, MYF(0), my_errno);
goto err;
@@ -1278,7 +1290,7 @@ bool do_command(THD *thd)
statistic_increment(aborted_threads,&LOCK_status);
DBUG_RETURN(TRUE); // We have to close it.
}
- send_error(thd,net->last_errno,NullS);
+ net_send_error(thd, net->last_errno, NullS);
net->error= 0;
DBUG_RETURN(FALSE);
}
@@ -1381,8 +1393,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
db= thd->alloc(db_len + tbl_len + 2);
tbl_name= strmake(db, packet + 1, db_len)+1;
strmake(tbl_name, packet + db_len + 2, tbl_len);
- if (mysql_table_dump(thd, db, tbl_name, -1))
- send_error(thd); // dump to NET
+ mysql_table_dump(thd, db, tbl_name, -1);
break;
}
case COM_CHANGE_USER:
@@ -1407,14 +1418,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* Small check for incoming packet */
if ((uint) ((uchar*) db - net->read_pos) > packet_length)
{
- send_error(thd, ER_UNKNOWN_COM_ERROR);
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
break;
}
#endif
/* Convert database name to utf8 */
+ uint dummy_errors;
db_buff[copy_and_convert(db_buff, sizeof(db_buff)-1,
system_charset_info, db, strlen(db),
- thd->charset())]= 0;
+ thd->charset(), &dummy_errors)]= 0;
db= db_buff;
/* Save user and privileges */
@@ -1429,7 +1441,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (!(thd->user= my_strdup(user, MYF(0))))
{
thd->user= save_user;
- send_error(thd, ER_OUT_OF_RESOURCES);
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
break;
}
@@ -1441,7 +1453,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
{
/* authentication failure, we shall restore old user */
if (res > 0)
- send_error(thd, ER_UNKNOWN_COM_ERROR);
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
x_free(thd->user);
thd->user= save_user;
thd->priv_user= save_priv_user;
@@ -1499,7 +1511,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
DBUG_PRINT("query",("%-.4096s",thd->query));
mysql_parse(thd,thd->query, thd->query_length);
- while (!thd->killed && !thd->is_fatal_error && thd->lex->found_colon)
+ while (!thd->killed && thd->lex->found_colon && !thd->net.report_error)
{
char *packet= thd->lex->found_colon;
/*
@@ -1549,7 +1561,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
}
case COM_FIELD_LIST: // This isn't actually needed
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
break;
#else
{
@@ -1562,7 +1575,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
bzero((char*) &table_list,sizeof(table_list));
if (!(table_list.db=thd->db))
{
- send_error(thd,ER_NO_DB_ERROR);
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
break;
}
pend= strend(packet);
@@ -1616,16 +1629,15 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
// null test to handle EOM
if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
{
- net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
+ my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL");
break;
}
if (check_access(thd,CREATE_ACL,db,0,1,0))
break;
mysql_log.write(thd,command,packet);
bzero(&create_info, sizeof(create_info));
- if (mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db),
- &create_info, 0) < 0)
- send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0);
+ mysql_create_db(thd, (lower_case_table_names == 2 ? alias : db),
+ &create_info, 0);
break;
}
case COM_DROP_DB: // QQ: To be removed
@@ -1636,34 +1648,34 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
/* null test to handle EOM */
if (!db || !(alias= thd->strdup(db)) || check_db_name(db))
{
- net_printf(thd,ER_WRONG_DB_NAME, db ? db : "NULL");
+ my_error(ER_WRONG_DB_NAME, MYF(0), db ? db : "NULL");
break;
}
if (check_access(thd,DROP_ACL,db,0,1,0))
break;
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
break;
}
mysql_log.write(thd,command,db);
- if (mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : db),
- 0, 0) < 0)
- send_error(thd, thd->killed ? ER_SERVER_SHUTDOWN : 0);
+ mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : db),
+ 0, 0);
break;
}
#ifndef EMBEDDED_LIBRARY
case COM_BINLOG_DUMP:
{
+ ulong pos;
+ ushort flags;
+ uint32 slave_server_id;
+
statistic_increment(thd->status_var.com_other,&LOCK_status);
thd->slow_command = TRUE;
if (check_global_access(thd, REPL_SLAVE_ACL))
break;
- mysql_log.write(thd,command, 0);
- ulong pos;
- ushort flags;
- uint32 slave_server_id;
/* TODO: The following has to be changed to an 8 byte integer */
pos = uint4korr(packet);
flags = uint2korr(packet + 4);
@@ -1671,6 +1683,9 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if ((slave_server_id= uint4korr(packet+6))) // mysqlbinlog.server_id==0
kill_zombie_dump_threads(slave_server_id);
thd->server_id = slave_server_id;
+
+ mysql_log.write(thd, command, "Log: '%s' Pos: %ld", packet+10,
+ (long) pos);
mysql_binlog_send(thd, thd->strdup(packet + 10), (my_off_t) pos, flags);
unregister_slave(thd,1,1);
/* fake COM_QUIT -- if we get here, the thread needs to terminate */
@@ -1687,9 +1702,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
if (check_global_access(thd,RELOAD_ACL))
break;
mysql_log.write(thd,command,NullS);
- if (reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, NULL))
- send_error(thd, 0);
- else
+ if (!reload_acl_and_cache(thd, options, (TABLE_LIST*) 0, NULL))
send_ok(thd);
break;
}
@@ -1713,7 +1726,6 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
else if (level != SHUTDOWN_WAIT_ALL_BUFFERS)
{
my_error(ER_NOT_SUPPORTED_YET, MYF(0), "this shutdown level");
- send_error(thd);
break;
}
DBUG_PRINT("quit",("Got shutdown command for level %u", level));
@@ -1797,7 +1809,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
send_eof(thd);
break;
default:
- send_error(thd, ER_UNKNOWN_COM_ERROR);
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
break;
}
break;
@@ -1816,7 +1828,7 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
case COM_DELAYED_INSERT:
case COM_END:
default:
- send_error(thd, ER_UNKNOWN_COM_ERROR);
+ my_message(ER_UNKNOWN_COM_ERROR, ER(ER_UNKNOWN_COM_ERROR), MYF(0));
break;
}
if (thd->lock || thd->open_tables || thd->derived_tables)
@@ -1825,8 +1837,11 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
close_thread_tables(thd); /* Free tables */
}
- if (thd->is_fatal_error)
- send_error(thd,0); // End of memory ?
+ /* report error issued during command execution */
+ if (thd->killed_errno() && !thd->net.report_error)
+ thd->send_kill_message();
+ if (thd->net.report_error)
+ net_send_error(thd);
time_t start_of_query=thd->start_time;
thd->end_time(); // Set start time
@@ -1856,11 +1871,116 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
VOID(pthread_mutex_unlock(&LOCK_thread_count));
thd->packet.shrink(thd->variables.net_buffer_length); // Reclaim some memory
- free_root(&thd->mem_root,MYF(MY_KEEP_PREALLOC));
+ free_root(thd->mem_root,MYF(MY_KEEP_PREALLOC));
DBUG_RETURN(error);
}
+int prepare_schema_table(THD *thd, LEX *lex, Table_ident *table_ident,
+ enum enum_schema_tables schema_table_idx)
+{
+ DBUG_ENTER("prepare_schema_table");
+ SELECT_LEX *sel= 0;
+ switch(schema_table_idx) {
+ case SCH_SCHEMATA:
+#if defined(DONT_ALLOW_SHOW_COMMANDS)
+ my_message(ER_NOT_ALLOWED_COMMAND,
+ ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
+ DBUG_RETURN(1);
+#else
+ if ((specialflag & SPECIAL_SKIP_SHOW_DB) &&
+ check_global_access(thd, SHOW_DB_ACL))
+ DBUG_RETURN(1);
+ break;
+#endif
+ case SCH_TABLE_NAMES:
+ case SCH_TABLES:
+ case SCH_VIEWS:
+#ifdef DONT_ALLOW_SHOW_COMMANDS
+ my_message(ER_NOT_ALLOWED_COMMAND,
+ ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
+ DBUG_RETURN(1);
+#else
+ {
+ char *db= lex->select_lex.db ? lex->select_lex.db : thd->db;
+ if (!db)
+ {
+ my_message(ER_NO_DB_ERROR,
+ ER(ER_NO_DB_ERROR), MYF(0)); /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
+ }
+ remove_escape(db); // Fix escaped '_'
+ if (check_db_name(db))
+ {
+ my_error(ER_WRONG_DB_NAME, MYF(0), db);
+ DBUG_RETURN(1);
+ }
+ if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0))
+ DBUG_RETURN(1); /* purecov: inspected */
+ if (!thd->col_access && check_grant_db(thd,db))
+ {
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user, thd->priv_host, db);
+ DBUG_RETURN(1);
+ }
+ lex->select_lex.db= db;
+ break;
+ }
+#endif
+ case SCH_COLUMNS:
+ case SCH_STATISTICS:
+#ifdef DONT_ALLOW_SHOW_COMMANDS
+ my_message(ER_NOT_ALLOWED_COMMAND,
+ ER(ER_NOT_ALLOWED_COMMAND), MYF(0)); /* purecov: inspected */
+ DBUG_RETURN(1);
+#else
+ if (table_ident)
+ {
+ TABLE_LIST **query_tables_last= lex->query_tables_last;
+ sel= new SELECT_LEX();
+ sel->init_query();
+ if(!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
+ (List<String> *) 0, (List<String> *) 0))
+ DBUG_RETURN(1);
+ lex->query_tables_last= query_tables_last;
+ TABLE_LIST *table_list= (TABLE_LIST*) sel->table_list.first;
+ char *db= table_list->db;
+ remove_escape(db); // Fix escaped '_'
+ remove_escape(table_list->real_name);
+ if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
+ &table_list->grant.privilege, 0, 0))
+ DBUG_RETURN(1); /* purecov: inspected */
+ if (grant_option && check_grant(thd, SELECT_ACL, table_list, 2,
+ UINT_MAX, 0))
+ DBUG_RETURN(1);
+ break;
+ }
+#endif
+ case SCH_PROCEDURES:
+ case SCH_CHARSETS:
+ case SCH_COLLATIONS:
+ case SCH_COLLATION_CHARACTER_SET_APPLICABILITY:
+ case SCH_USER_PRIVILEGES:
+ case SCH_SCHEMA_PRIVILEGES:
+ case SCH_TABLE_PRIVILEGES:
+ case SCH_COLUMN_PRIVILEGES:
+ case SCH_TABLE_CONSTRAINTS:
+ case SCH_KEY_COLUMN_USAGE:
+ default:
+ break;
+ }
+
+ SELECT_LEX *select_lex= lex->current_select;
+ if (make_schema_select(thd, select_lex, schema_table_idx))
+ {
+ DBUG_RETURN(1);
+ }
+ TABLE_LIST *table_list= (TABLE_LIST*) select_lex->table_list.first;
+ table_list->schema_select_lex= sel;
+ DBUG_RETURN(0);
+}
+
+
/*
Read query from packet and store in thd->query
Used in COM_QUERY and COM_PREPARE
@@ -1871,8 +1991,8 @@ bool dispatch_command(enum enum_server_command command, THD *thd,
query_length
RETURN VALUES
- 0 ok
- 1 error; In this case thd->fatal_error is set
+ FALSE ok
+ TRUE error; In this case thd->fatal_error is set
*/
bool alloc_query(THD *thd, char *packet, ulong packet_length)
@@ -1897,7 +2017,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
packet_length,
thd->db_length+ 1 +
QUERY_CACHE_FLAGS_SIZE)))
- return 1;
+ return TRUE;
thd->query[packet_length]=0;
thd->query_length= packet_length;
@@ -1907,7 +2027,7 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
if (!(specialflag & SPECIAL_NO_PRIOR))
my_pthread_setprio(pthread_self(),QUERY_PRIOR);
- return 0;
+ return FALSE;
}
/****************************************************************************
@@ -1915,10 +2035,11 @@ bool alloc_query(THD *thd, char *packet, ulong packet_length)
** Execute command saved in thd and current_lex->sql_command
****************************************************************************/
-int
+bool
mysql_execute_command(THD *thd)
{
- int res= 0;
+ bool res= FALSE;
+ int result= 0;
LEX *lex= thd->lex;
/* first SELECT_LEX (have special meaning for many of non-SELECTcommands) */
SELECT_LEX *select_lex= &lex->select_lex;
@@ -1975,7 +2096,7 @@ mysql_execute_command(THD *thd)
if (all_tables_not_ok(thd, all_tables))
{
/* we warn the slave SQL thread */
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
DBUG_RETURN(0);
}
#ifndef TO_BE_DELETED
@@ -1999,7 +2120,6 @@ mysql_execute_command(THD *thd)
if ((tmp= my_tz_get_table_list(thd, &lex->query_tables_last)) ==
&fake_time_zone_tables_list)
{
- send_error(thd, 0);
DBUG_RETURN(-1);
}
lex->time_zone_tables_used= tmp;
@@ -2015,7 +2135,7 @@ mysql_execute_command(THD *thd)
!(thd->slave_thread || (thd->master_access & SUPER_ACL)) &&
(uc_update_queries[lex->sql_command] > 0))
{
- net_printf(thd, ER_OPTION_PREVENTS_STATEMENT, "--read-only");
+ my_error(ER_OPTION_PREVENTS_STATEMENT, MYF(0), "--read-only");
DBUG_RETURN(-1);
}
@@ -2044,20 +2164,14 @@ mysql_execute_command(THD *thd)
lex->exchange ? SELECT_ACL | FILE_ACL : SELECT_ACL,
any_db, 0, 0, 0);
if (res)
- {
- res=0;
- break; // Error message is given
- }
+ goto error;
if (!(res= open_and_lock_tables(thd, all_tables)))
{
if (lex->describe)
{
if (!(result= new select_send()))
- {
- send_error(thd, ER_OUT_OF_RESOURCES);
goto error;
- }
else
thd->send_explain_fields(result);
res= mysql_explain_union(thd, &thd->lex->unit, result);
@@ -2077,10 +2191,7 @@ mysql_execute_command(THD *thd)
else
{
if (!result && !(result= new select_send()))
- {
- res= -1;
- break;
- }
+ goto error;
query_cache_store_query(thd, all_tables);
res= handle_select(thd, lex, result);
if (result != lex->result)
@@ -2121,10 +2232,7 @@ mysql_execute_command(THD *thd)
*/
DBUG_ASSERT(!is_var_null);
if (!pstr)
- {
- res= -1;
- break; // EOM (error should be reported by allocator)
- }
+ goto error;
}
else
{
@@ -2141,15 +2249,16 @@ mysql_execute_command(THD *thd)
query_len= need_conversion? (pstr->length() * to_cs->mbmaxlen) :
pstr->length();
- if (!(query_str= alloc_root(&thd->mem_root, query_len+1)))
+ if (!(query_str= alloc_root(thd->mem_root, query_len+1)))
+ goto error;
+
+ if (need_conversion)
{
- res= -1;
- break; // EOM (error should be reported by allocator)
+ uint dummy_errors;
+ query_len= copy_and_convert(query_str, query_len, to_cs,
+ pstr->ptr(), pstr->length(),
+ pstr->charset(), &dummy_errors);
}
-
- if (need_conversion)
- query_len= copy_and_convert(query_str, query_len, to_cs, pstr->ptr(),
- pstr->length(), pstr->charset());
else
memcpy(query_str, pstr->ptr(), pstr->length());
query_str[query_len]= 0;
@@ -2164,8 +2273,8 @@ mysql_execute_command(THD *thd)
query_len, query_str));
}
thd->command= COM_PREPARE;
- if (!mysql_stmt_prepare(thd, query_str, query_len + 1,
- &lex->prepared_stmt_name))
+ if (!(res= mysql_stmt_prepare(thd, query_str, query_len + 1,
+ &lex->prepared_stmt_name)))
send_ok(thd, 0L, 0L, "Statement prepared");
break;
}
@@ -2191,22 +2300,21 @@ mysql_execute_command(THD *thd)
}
else
{
- res= -1;
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0),
- lex->prepared_stmt_name.length, lex->prepared_stmt_name.str,
+ lex->prepared_stmt_name.length,
+ lex->prepared_stmt_name.str,
"DEALLOCATE PREPARE");
+ goto error;
}
break;
}
case SQLCOM_DO:
if (all_tables &&
- ((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) ||
- (res= open_and_lock_tables(thd, all_tables))))
- break;
+ (check_table_access(thd, SELECT_ACL, all_tables, 0) ||
+ open_and_lock_tables(thd, all_tables)))
+ goto error;
res= mysql_do(thd, *lex->insert_list);
- if (thd->net.report_error)
- res= -1;
break;
case SQLCOM_EMPTY_QUERY:
@@ -2228,10 +2336,24 @@ mysql_execute_command(THD *thd)
}
case SQLCOM_PURGE_BEFORE:
{
+ Item *it;
+
if (check_global_access(thd, SUPER_ACL))
goto error;
/* PURGE MASTER LOGS BEFORE 'data' */
- res = purge_master_logs_before_date(thd, lex->purge_time);
+ it= (Item *)lex->value_list.head();
+ if (it->check_cols(1) || it->fix_fields(lex->thd, 0, &it))
+ {
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "PURGE LOGS BEFORE");
+ goto error;
+ }
+ it= new Item_func_unix_timestamp(it);
+ /*
+ it is OK only emulate fix_fieds, because we need only
+ value of constant
+ */
+ it->quick_fix_field();
+ res = purge_master_logs_before_date(thd, (ulong)it->val_int());
break;
}
#endif
@@ -2256,12 +2378,12 @@ mysql_execute_command(THD *thd)
goto error;
/* This query don't work now. See comment in repl_failsafe.cc */
#ifndef WORKING_NEW_MASTER
- net_printf(thd, ER_NOT_SUPPORTED_YET, "SHOW NEW MASTER");
- res= 1;
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "SHOW NEW MASTER");
+ goto error;
#else
res = show_new_master(thd);
-#endif
break;
+#endif
}
#ifdef HAVE_REPLICATION
@@ -2357,7 +2479,7 @@ mysql_execute_command(THD *thd)
if (check_global_access(thd, SUPER_ACL))
goto error;
if (end_active_trans(thd))
- res= -1;
+ goto error;
else
res = load_master_data(thd);
break;
@@ -2388,7 +2510,7 @@ mysql_execute_command(THD *thd)
}
if (strlen(first_table->real_name) > NAME_LEN)
{
- net_printf(thd, ER_WRONG_TABLE_NAME, first_table->real_name);
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), first_table->real_name);
break;
}
pthread_mutex_lock(&LOCK_active_mi);
@@ -2415,7 +2537,7 @@ mysql_execute_command(THD *thd)
TABLE_LIST *select_tables= lex->query_tables;
if ((res= create_table_precheck(thd, select_tables, create_table)))
- goto unsent_create_error;
+ goto create_error;
#ifndef HAVE_READLINK
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
@@ -2425,10 +2547,7 @@ mysql_execute_command(THD *thd)
create_table->real_name) ||
append_file_to_dir(thd, &lex->create_info.index_file_name,
create_table->real_name))
- {
- res=-1;
- goto unsent_create_error;
- }
+ goto create_error;
#endif
/*
If we are using SET CHARSET without DEFAULT, add an implicit
@@ -2459,7 +2578,7 @@ mysql_execute_command(THD *thd)
if (!(lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) &&
unique_table(create_table, select_tables))
{
- net_printf(thd, ER_UPDATE_TABLE_USED, create_table->real_name);
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), create_table->real_name);
goto create_error;
}
/* If we create merge table, we have to test tables in merge, too */
@@ -2472,7 +2591,7 @@ mysql_execute_command(THD *thd)
{
if (unique_table(tab, select_tables))
{
- net_printf(thd, ER_UPDATE_TABLE_USED, tab->real_name);
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), tab->real_name);
goto create_error;
}
}
@@ -2519,11 +2638,9 @@ mysql_execute_command(THD *thd)
break;
create_error:
- res= 1; //error reported
-unsent_create_error:
/* put tables back for PS rexecuting */
lex->link_first_table_back(create_table, link_to_local);
- break;
+ goto error;
}
case SQLCOM_CREATE_INDEX:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
@@ -2531,7 +2648,7 @@ unsent_create_error:
goto error; /* purecov: inspected */
thd->slow_command=TRUE;
if (end_active_trans(thd))
- res= -1;
+ goto error;
else
res = mysql_create_index(thd, first_table, lex->key_list);
break;
@@ -2560,7 +2677,8 @@ unsent_create_error:
*/
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION, ER(ER_LOCK_OR_ACTIVE_TRANSACTION),
+ MYF(0));
goto error;
}
{
@@ -2574,16 +2692,16 @@ unsent_create_error:
case SQLCOM_ALTER_TABLE:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#if defined(DONT_ALLOW_SHOW_COMMANDS)
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
goto error;
#else
{
ulong priv=0;
if (lex->name && (!lex->name[0] || strlen(lex->name) > NAME_LEN))
{
- net_printf(thd, ER_WRONG_TABLE_NAME, lex->name);
- res= 1;
- break;
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), lex->name);
+ goto error;
}
if (!select_lex->db)
select_lex->db= first_table->db;
@@ -2614,7 +2732,7 @@ unsent_create_error:
lex->create_info.data_file_name=lex->create_info.index_file_name=0;
/* ALTER TABLE ends previous transaction */
if (end_active_trans(thd))
- res= -1;
+ goto error;
else
{
thd->slow_command=TRUE;
@@ -2659,16 +2777,15 @@ unsent_create_error:
}
}
query_cache_invalidate3(thd, first_table, 0);
- if (end_active_trans(thd))
- res= -1;
- else if (mysql_rename_tables(thd, first_table))
- res= -1;
+ if (end_active_trans(thd) || mysql_rename_tables(thd, first_table))
+ goto error;
break;
}
#ifndef EMBEDDED_LIBRARY
case SQLCOM_SHOW_BINLOGS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
goto error;
#else
{
@@ -2682,7 +2799,8 @@ unsent_create_error:
case SQLCOM_SHOW_CREATE:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
goto error;
#else
{
@@ -2716,7 +2834,8 @@ unsent_create_error:
{
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ thd->clear_error(); // No binlog error generated
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
}
@@ -2745,7 +2864,8 @@ unsent_create_error:
{
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ thd->clear_error(); // No binlog error generated
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
}
@@ -2767,7 +2887,8 @@ unsent_create_error:
{
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ thd->clear_error(); // No binlog error generated
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
}
@@ -2777,28 +2898,35 @@ unsent_create_error:
DBUG_ASSERT(first_table == all_tables && first_table != 0);
if (update_precheck(thd, all_tables))
break;
- res= mysql_update(thd, all_tables,
- select_lex->item_list,
- lex->value_list,
- select_lex->where,
- select_lex->order_list.elements,
- (ORDER *) select_lex->order_list.first,
- select_lex->select_limit,
- lex->duplicates);
- if (thd->net.report_error)
- res= -1;
- break;
- case SQLCOM_UPDATE_MULTI:
- {
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
- if ((res= multi_update_precheck(thd, all_tables)))
+ res= (result= mysql_update(thd, all_tables,
+ select_lex->item_list,
+ lex->value_list,
+ select_lex->where,
+ select_lex->order_list.elements,
+ (ORDER *) select_lex->order_list.first,
+ select_lex->select_limit,
+ lex->duplicates));
+ /* mysql_update return 2 if we need to switch to multi-update */
+ if (result != 2)
break;
- res= mysql_multi_update(thd, all_tables,
- &select_lex->item_list,
- &lex->value_list,
- select_lex->where,
- select_lex->options,
- lex->duplicates, unit, select_lex);
+ case SQLCOM_UPDATE_MULTI:
+ {
+ DBUG_ASSERT(first_table == all_tables && first_table != 0);
+ /* if we switched from normal update, rights are checked */
+ if (result != 2)
+ {
+ if ((res= multi_update_precheck(thd, all_tables)))
+ break;
+ }
+ else
+ res= 0;
+
+ res= mysql_multi_update(thd, all_tables,
+ &select_lex->item_list,
+ &lex->value_list,
+ select_lex->where,
+ select_lex->options,
+ lex->duplicates, unit, select_lex);
break;
}
case SQLCOM_REPLACE:
@@ -2811,8 +2939,6 @@ unsent_create_error:
select_lex->item_list, lex->value_list,
(lex->value_list.elements ?
DUP_UPDATE : lex->duplicates));
- if (thd->net.report_error)
- res= -1;
if (first_table->view && !first_table->contain_auto_increment)
thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
break;
@@ -2836,40 +2962,31 @@ unsent_create_error:
if (!(res= open_and_lock_tables(thd, all_tables)))
{
- /*
- Is table which we are changing used somewhere in other parts of
- query
- */
- if (unique_table(first_table, all_tables->next_independent()))
- {
- /* Using same table for INSERT and SELECT */
- select_lex->options |= OPTION_BUFFER_RESULT;
- }
+ /* Skip first table, which is the table we are inserting in */
+ lex->select_lex.table_list.first= (byte*)first_table->next_local;
- if ((res= mysql_insert_select_prepare(thd)))
- break;
- if ((result= new select_insert(first_table, first_table->table,
- &lex->field_list, lex->duplicates,
- lex->duplicates == DUP_IGNORE)))
+ res= mysql_insert_select_prepare(thd);
+ if (!res && (result= new select_insert(first_table, first_table->table,
+ &lex->field_list,
+ lex->duplicates,
+ lex->duplicates == DUP_IGNORE)))
{
- /* Skip first table, which is the table we are inserting in */
- lex->select_lex.table_list.first= (byte*) first_table->next_local;
+ TABLE_LIST *first_select_table;
+
/*
insert/replace from SELECT give its SELECT_LEX for SELECT,
and item_list belong to SELECT
*/
lex->select_lex.resolve_mode= SELECT_LEX::SELECT_MODE;
res= handle_select(thd, lex, result);
- /* revert changes for SP */
- lex->select_lex.table_list.first= (byte*) first_table;
lex->select_lex.resolve_mode= SELECT_LEX::INSERT_MODE;
delete result;
}
- if (thd->net.report_error)
- res= -1;
+ /* revert changes for SP */
+ lex->select_lex.table_list.first= (byte*) first_table;
}
else
- res= -1;
+ res= TRUE;
if (first_table->view && !first_table->contain_auto_increment)
thd->last_insert_id= 0; // do not show last insert ID if VIEW have not it
@@ -2886,7 +3003,8 @@ unsent_create_error:
*/
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION,NullS);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
@@ -2900,8 +3018,6 @@ unsent_create_error:
res = mysql_delete(thd, all_tables, select_lex->where,
&select_lex->order_list,
select_lex->select_limit, select_lex->options);
- if (thd->net.report_error)
- res= -1;
break;
}
case SQLCOM_DELETE_MULTI:
@@ -2919,15 +3035,24 @@ unsent_create_error:
if (select_lex->item_list.elements != 0)
select_lex->item_list.empty();
if (add_item_to_list(thd, new Item_null()))
+ goto error;
+
+ thd->proc_info="init";
+ if ((res= open_and_lock_tables(thd, all_tables)))
+ break;
+
+ if (!first_table->table)
{
+ DBUG_ASSERT(first_table->view &&
+ first_table->ancestor && first_table->ancestor->next_local);
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ first_table->view_db.str, first_table->view_name.str);
res= -1;
break;
}
- thd->proc_info="init";
- if ((res= open_and_lock_tables(thd, all_tables)) ||
- (res= mysql_multi_delete_prepare(thd)))
- break;
+ if ((res= mysql_multi_delete_prepare(thd)))
+ goto error;
if (!thd->is_fatal_error && (result= new multi_delete(thd,aux_tables,
table_count)))
@@ -2942,12 +3067,10 @@ unsent_create_error:
select_lex->options | thd->options |
SELECT_NO_JOIN_CACHE | SELECT_NO_UNLOCK,
result, unit, select_lex);
- if (thd->net.report_error)
- res= -1;
delete result;
}
else
- res= -1; // Error is not sent
+ res= TRUE;
close_thread_tables(thd);
break;
}
@@ -2959,10 +3082,7 @@ unsent_create_error:
if (check_table_access(thd, DROP_ACL, all_tables, 0))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
- {
- res= -1;
- break;
- }
+ goto error;
}
else
{
@@ -2986,21 +3106,10 @@ unsent_create_error:
if (check_one_table_access(thd, INDEX_ACL, all_tables))
goto error; /* purecov: inspected */
if (end_active_trans(thd))
- res= -1;
+ goto error;
else
res = mysql_drop_index(thd, first_table, &lex->alter_info);
break;
- case SQLCOM_SHOW_DATABASES:
-#if defined(DONT_ALLOW_SHOW_COMMANDS)
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- goto error;
-#else
- if ((specialflag & SPECIAL_SKIP_SHOW_DB) &&
- check_global_access(thd, SHOW_DB_ACL))
- goto error;
- res= mysqld_show_dbs(thd, (lex->wild ? lex->wild->ptr() : NullS));
- break;
-#endif
case SQLCOM_SHOW_PROCESSLIST:
if (!thd->priv_user[0] && check_global_access(thd,PROCESS_ACL))
break;
@@ -3038,7 +3147,8 @@ unsent_create_error:
break;
case SQLCOM_SHOW_LOGS:
#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND),
+ MYF(0)); /* purecov: inspected */
goto error;
#else
{
@@ -3048,95 +3158,9 @@ unsent_create_error:
break;
}
#endif
- case SQLCOM_SHOW_TABLES:
- /* FALL THROUGH */
-#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- goto error;
-#else
- {
- char *db=select_lex->db ? select_lex->db : thd->db;
- if (!db)
- {
- send_error(thd,ER_NO_DB_ERROR); /* purecov: inspected */
- goto error; /* purecov: inspected */
- }
- remove_escape(db); // Fix escaped '_'
- if (check_db_name(db))
- {
- net_printf(thd,ER_WRONG_DB_NAME, db);
- goto error;
- }
- if (check_access(thd,SELECT_ACL,db,&thd->col_access,0,0))
- goto error; /* purecov: inspected */
- if (!thd->col_access && check_grant_db(thd,db))
- {
- net_printf(thd, ER_DBACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->priv_host,
- db);
- goto error;
- }
- /* grant is checked in mysqld_show_tables */
- if (lex->describe)
- res= mysqld_extend_show_tables(thd,db,
- (lex->wild ? lex->wild->ptr() : NullS));
- else
- res= mysqld_show_tables(thd, db,
- (lex->wild ? lex->wild->ptr() : NullS),
- lex->verbose);
- break;
- }
-#endif
case SQLCOM_SHOW_OPEN_TABLES:
res= mysqld_show_open_tables(thd,(lex->wild ? lex->wild->ptr() : NullS));
break;
- case SQLCOM_SHOW_CHARSETS:
- res= mysqld_show_charsets(thd,(lex->wild ? lex->wild->ptr() : NullS));
- break;
- case SQLCOM_SHOW_COLLATIONS:
- res= mysqld_show_collations(thd,(lex->wild ? lex->wild->ptr() : NullS));
- break;
- case SQLCOM_SHOW_FIELDS:
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
-#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- goto error;
-#else
- {
- char *db= first_table->db;
- remove_escape(db); // Fix escaped '_'
- remove_escape(first_table->real_name);
- if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
- &first_table->grant.privilege, 0, 0))
- goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd, SELECT_ACL, first_table, 2, UINT_MAX, 0))
- goto error;
- res= mysqld_show_fields(thd, first_table,
- (lex->wild ? lex->wild->ptr() : NullS),
- lex->verbose);
- break;
- }
-#endif
- case SQLCOM_SHOW_KEYS:
- DBUG_ASSERT(first_table == all_tables && first_table != 0);
-#ifdef DONT_ALLOW_SHOW_COMMANDS
- send_error(thd,ER_NOT_ALLOWED_COMMAND); /* purecov: inspected */
- goto error;
-#else
- {
- char *db= first_table->db;
- remove_escape(db); // Fix escaped '_'
- remove_escape(first_table->real_name);
- if (check_access(thd,SELECT_ACL | EXTRA_ACL,db,
- &first_table->grant.privilege, 0, 0))
- goto error; /* purecov: inspected */
- if (grant_option && check_grant(thd, SELECT_ACL, all_tables, 2, UINT_MAX, 0))
- goto error;
- res= mysqld_show_keys(thd, first_table);
- break;
- }
-#endif
case SQLCOM_CHANGE_DB:
mysql_change_db(thd,select_lex->db);
break;
@@ -3157,7 +3181,7 @@ unsent_create_error:
if (!(thd->client_capabilities & CLIENT_LOCAL_FILES) ||
! opt_local_infile)
{
- send_error(thd,ER_NOT_ALLOWED_COMMAND);
+ my_message(ER_NOT_ALLOWED_COMMAND, ER(ER_NOT_ALLOWED_COMMAND), MYF(0));
goto error;
}
if (check_one_table_access(thd, privilege, all_tables))
@@ -3173,15 +3197,13 @@ unsent_create_error:
{
List<set_var_base> *lex_var_list= &lex->var_list;
if (all_tables &&
- ((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) ||
- (res= open_and_lock_tables(thd, all_tables))))
- break;
+ (check_table_access(thd, SELECT_ACL, all_tables, 0) ||
+ open_and_lock_tables(thd, all_tables)))
+ goto error;
if (lex->one_shot_set && not_all_support_one_shot(lex_var_list))
{
- my_printf_error(0, "The SET ONE_SHOT syntax is reserved for \
-purposes internal to the MySQL server", MYF(0));
- res= -1;
- break;
+ my_error(ER_RESERVED_SYNTAX, MYF(0), "SET ONE_SHOT");
+ goto error;
}
if (!(res= sql_set_variables(thd, lex_var_list)))
{
@@ -3192,12 +3214,16 @@ purposes internal to the MySQL server", MYF(0));
thd->one_shot_set|= lex->one_shot_set;
send_ok(thd);
}
- if (thd->net.report_error)
- res= -1;
break;
}
case SQLCOM_UNLOCK_TABLES:
+ /*
+ It is critical for mysqldump --single-transaction --master-data that
+ UNLOCK TABLES does not implicitely commit a connection which has only
+ done FLUSH TABLES WITH READ LOCK + BEGIN. If this assumption becomes
+ false, mysqldump will not work.
+ */
unlock_locked_tables(thd);
if (thd->options & OPTION_TABLE_LOCK)
{
@@ -3236,7 +3262,7 @@ purposes internal to the MySQL server", MYF(0));
char *alias;
if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name))
{
- net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
break;
}
/*
@@ -3251,7 +3277,7 @@ purposes internal to the MySQL server", MYF(0));
(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
!db_ok_with_wild_table(lex->name)))
{
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
@@ -3266,7 +3292,7 @@ purposes internal to the MySQL server", MYF(0));
char *alias;
if (!(alias=thd->strdup(lex->name)) || check_db_name(lex->name))
{
- net_printf(thd, ER_WRONG_DB_NAME, lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
break;
}
/*
@@ -3281,7 +3307,7 @@ purposes internal to the MySQL server", MYF(0));
(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
!db_ok_with_wild_table(lex->name)))
{
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
@@ -3289,7 +3315,8 @@ purposes internal to the MySQL server", MYF(0));
break;
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
res=mysql_rm_db(thd, (lower_case_table_names == 2 ? alias : lex->name),
@@ -3300,7 +3327,7 @@ purposes internal to the MySQL server", MYF(0));
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
- net_printf(thd, ER_WRONG_DB_NAME, lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
break;
}
/*
@@ -3315,7 +3342,7 @@ purposes internal to the MySQL server", MYF(0));
(!db_ok(lex->name, replicate_do_db, replicate_ignore_db) ||
!db_ok_with_wild_table(lex->name)))
{
- my_error(ER_SLAVE_IGNORED_TABLE, MYF(0));
+ my_message(ER_SLAVE_IGNORED_TABLE, ER(ER_SLAVE_IGNORED_TABLE), MYF(0));
break;
}
#endif
@@ -3323,7 +3350,8 @@ purposes internal to the MySQL server", MYF(0));
break;
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
res=mysql_alter_db(thd,lex->name,&lex->create_info);
@@ -3333,14 +3361,15 @@ purposes internal to the MySQL server", MYF(0));
{
if (!strip_sp(lex->name) || check_db_name(lex->name))
{
- net_printf(thd,ER_WRONG_DB_NAME, lex->name);
+ my_error(ER_WRONG_DB_NAME, MYF(0), lex->name);
break;
}
if (check_access(thd,SELECT_ACL,lex->name,0,1,0))
break;
if (thd->locked_tables || thd->active_transaction())
{
- send_error(thd,ER_LOCK_OR_ACTIVE_TRANSACTION);
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
goto error;
}
res=mysqld_show_create_db(thd,lex->name,&lex->create_info);
@@ -3348,23 +3377,37 @@ purposes internal to the MySQL server", MYF(0));
}
case SQLCOM_CREATE_FUNCTION: // UDF function
{
- sp_head *sph;
if (check_access(thd,INSERT_ACL,"mysql",0,1,0))
break;
#ifdef HAVE_DLOPEN
- if ((sph= sp_find_function(thd, lex->spname)))
+ if (sp_find_function(thd, lex->spname))
{
- net_printf(thd, ER_UDF_EXISTS, lex->spname->m_name.str);
+ my_error(ER_UDF_EXISTS, MYF(0), lex->spname->m_name.str);
goto error;
}
- if (!(res = mysql_create_function(thd,&lex->udf)))
+ if (!(res = mysql_create_function(thd, &lex->udf)))
send_ok(thd);
#else
- res= -1;
+ res= TRUE;
#endif
break;
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ case SQLCOM_CREATE_USER:
+ {
+ if (check_access(thd, GRANT_ACL,"mysql",0,1,0))
+ break;
+ if (!(res= mysql_create_user(thd, lex->users_list)))
+ {
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(thd);
+ }
+ break;
+ }
case SQLCOM_DROP_USER:
{
if (check_access(thd, GRANT_ACL,"mysql",0,1,0))
@@ -3373,8 +3416,23 @@ purposes internal to the MySQL server", MYF(0));
{
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
- mysql_bin_log.write(&qinfo);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
+ }
+ send_ok(thd);
+ }
+ break;
+ }
+ case SQLCOM_RENAME_USER:
+ {
+ if (check_access(thd, GRANT_ACL,"mysql",0,1,0))
+ break;
+ if (!(res= mysql_rename_user(thd, lex->users_list)))
+ {
+ if (mysql_bin_log.is_open())
+ {
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
+ mysql_bin_log.write(&qinfo);
}
send_ok(thd);
}
@@ -3388,7 +3446,7 @@ purposes internal to the MySQL server", MYF(0));
{
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
send_ok(thd);
@@ -3431,7 +3489,7 @@ purposes internal to the MySQL server", MYF(0));
mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
}
@@ -3439,8 +3497,9 @@ purposes internal to the MySQL server", MYF(0));
{
if (lex->columns.elements)
{
- send_error(thd,ER_ILLEGAL_GRANT_FOR_TABLE);
- res=1;
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE, ER(ER_ILLEGAL_GRANT_FOR_TABLE),
+ MYF(0));
+ goto error;
}
else
res = mysql_grant(thd, select_lex->db, lex->users_list, lex->grant,
@@ -3450,7 +3509,7 @@ purposes internal to the MySQL server", MYF(0));
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
if (mqh_used && lex->sql_command == SQLCOM_GRANT)
@@ -3458,7 +3517,7 @@ purposes internal to the MySQL server", MYF(0));
List_iterator <LEX_USER> str_list(lex->users_list);
LEX_USER *user;
while ((user=str_list++))
- reset_mqh(thd,user);
+ reset_mqh(user);
}
}
}
@@ -3480,9 +3539,7 @@ purposes internal to the MySQL server", MYF(0));
binlog or not.
*/
bool write_to_binlog;
- if (reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog))
- send_error(thd, 0);
- else
+ if (!reload_acl_and_cache(thd, lex->type, first_table, &write_to_binlog))
{
/*
We WANT to write and we CAN write.
@@ -3492,7 +3549,7 @@ purposes internal to the MySQL server", MYF(0));
{
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
}
@@ -3501,11 +3558,20 @@ purposes internal to the MySQL server", MYF(0));
break;
}
case SQLCOM_KILL:
- kill_one_thread(thd,lex->thread_id, lex->type & ONLY_KILL_QUERY);
+ {
+ Item *it= (Item *)lex->value_list.head();
+
+ if (it->fix_fields(lex->thd, 0, &it) || it->check_cols(1))
+ {
+ my_message(ER_SET_CONSTANTS_ONLY, ER(ER_SET_CONSTANTS_ONLY),
+ MYF(0));
+ goto error;
+ }
+ kill_one_thread(thd, (ulong)it->val_int(), lex->type & ONLY_KILL_QUERY);
break;
+ }
#ifndef NO_EMBEDDED_ACCESS_CHECKS
case SQLCOM_SHOW_GRANTS:
- res=0;
if ((thd->priv_user &&
!strcmp(thd->priv_user,lex->grant_user->user.str)) ||
!check_access(thd, SELECT_ACL, "mysql",0,1,0))
@@ -3549,15 +3615,15 @@ purposes internal to the MySQL server", MYF(0));
close_thread_tables(thd); // Free tables
}
if (end_active_trans(thd))
- {
- res= -1;
- }
+ goto error;
else
{
thd->options= ((thd->options & (ulong) ~(OPTION_STATUS_NO_TRANS_UPDATE)) |
OPTION_BEGIN);
thd->server_status|= SERVER_STATUS_IN_TRANS;
- send_ok(thd);
+ if (!(lex->start_transaction_opt & MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT) ||
+ !(res= ha_start_consistent_snapshot(thd)))
+ send_ok(thd);
}
break;
case SQLCOM_COMMIT:
@@ -3574,7 +3640,7 @@ purposes internal to the MySQL server", MYF(0));
send_ok(thd);
}
else
- res= -1;
+ goto error;
break;
}
case SQLCOM_ROLLBACK:
@@ -3591,46 +3657,45 @@ purposes internal to the MySQL server", MYF(0));
message in the error log, so we don't send it.
*/
if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread)
- send_warning(thd,ER_WARNING_NOT_COMPLETE_ROLLBACK,0);
- else
- send_ok(thd);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NOT_COMPLETE_ROLLBACK,
+ ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
+ send_ok(thd);
}
else
- res= -1;
+ res= TRUE;
thd->options&= ~(ulong) (OPTION_BEGIN | OPTION_STATUS_NO_TRANS_UPDATE);
break;
case SQLCOM_ROLLBACK_TO_SAVEPOINT:
if (!ha_rollback_to_savepoint(thd, lex->savepoint_name))
{
if ((thd->options & OPTION_STATUS_NO_TRANS_UPDATE) && !thd->slave_thread)
- send_warning(thd, ER_WARNING_NOT_COMPLETE_ROLLBACK, 0);
- else
- send_ok(thd);
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN,
+ ER_WARNING_NOT_COMPLETE_ROLLBACK,
+ ER(ER_WARNING_NOT_COMPLETE_ROLLBACK));
+ send_ok(thd);
}
else
- res= -1;
+ goto error;
break;
case SQLCOM_SAVEPOINT:
if (!ha_savepoint(thd, lex->savepoint_name))
send_ok(thd);
else
- res= -1;
+ goto error;
break;
case SQLCOM_CREATE_PROCEDURE:
case SQLCOM_CREATE_SPFUNCTION:
{
uint namelen;
char *name;
+ int result;
- if (!lex->sphead)
- {
- res= -1; // Shouldn't happen
- break;
- }
+ DBUG_ASSERT(lex->sphead);
if (! lex->sphead->m_db.str)
{
- send_error(thd,ER_NO_DB_ERROR);
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR), MYF(0));
delete lex->sphead;
lex->sphead= 0;
goto error;
@@ -3644,7 +3709,7 @@ purposes internal to the MySQL server", MYF(0));
if (udf)
{
- net_printf(thd, ER_UDF_EXISTS, name);
+ my_error(ER_UDF_EXISTS, MYF(0), name);
delete lex->sphead;
lex->sphead= 0;
goto error;
@@ -3654,14 +3719,14 @@ purposes internal to the MySQL server", MYF(0));
if (lex->sphead->m_type == TYPE_ENUM_FUNCTION &&
!lex->sphead->m_has_return)
{
- net_printf(thd, ER_SP_NORETURN, name);
+ my_error(ER_SP_NORETURN, MYF(0), name);
delete lex->sphead;
lex->sphead= 0;
goto error;
}
- res= lex->sphead->create(thd);
- switch (res) {
+ res= (result= lex->sphead->create(thd));
+ switch (result) {
case SP_OK:
send_ok(thd);
lex->unit.cleanup();
@@ -3669,19 +3734,19 @@ purposes internal to the MySQL server", MYF(0));
lex->sphead= 0;
break;
case SP_WRITE_ROW_FAILED:
- net_printf(thd, ER_SP_ALREADY_EXISTS, SP_TYPE_STRING(lex), name);
+ my_error(ER_SP_ALREADY_EXISTS, MYF(0), SP_TYPE_STRING(lex), name);
lex->unit.cleanup();
delete lex->sphead;
lex->sphead= 0;
goto error;
case SP_NO_DB_ERROR:
- net_printf(thd, ER_BAD_DB_ERROR, lex->sphead->m_db.str);
+ my_error(ER_BAD_DB_ERROR, MYF(0), lex->sphead->m_db.str);
lex->unit.cleanup();
delete lex->sphead;
lex->sphead= 0;
goto error;
default:
- net_printf(thd, ER_SP_STORE_FAILED, SP_TYPE_STRING(lex), name);
+ my_error(ER_SP_STORE_FAILED, MYF(0), SP_TYPE_STRING(lex), name);
lex->unit.cleanup();
delete lex->sphead;
lex->sphead= 0;
@@ -3695,8 +3760,8 @@ purposes internal to the MySQL server", MYF(0));
if (!(sp= sp_find_procedure(thd, lex->spname)))
{
- net_printf(thd, ER_SP_DOES_NOT_EXIST, "PROCEDURE",
- lex->spname->m_qname.str);
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0), "PROCEDURE",
+ lex->spname->m_qname.str);
goto error;
}
else
@@ -3710,17 +3775,11 @@ purposes internal to the MySQL server", MYF(0));
/* In case the arguments are subselects... */
if (all_tables &&
- ((res= check_table_access(thd, SELECT_ACL, all_tables, 0)) ||
- (res= open_and_lock_tables(thd, all_tables))))
- {
- break;
- }
+ (check_table_access(thd, SELECT_ACL, all_tables, 0) ||
+ open_and_lock_tables(thd, all_tables)))
+ goto error;
#ifndef EMBEDDED_LIBRARY
- /*
- When executing substatements, they're assumed to send_error when
- it happens, but not to send_ok.
- */
my_bool nsok= thd->net.no_send_ok;
thd->net.no_send_ok= TRUE;
#endif
@@ -3728,7 +3787,7 @@ purposes internal to the MySQL server", MYF(0));
{
if (! (thd->client_capabilities & CLIENT_MULTI_RESULTS))
{
- send_error(thd, ER_SP_BADSELECT);
+ my_message(ER_SP_BADSELECT, ER(ER_SP_BADSELECT), MYF(0));
#ifndef EMBEDDED_LIBRARY
thd->net.no_send_ok= nsok;
#endif
@@ -3761,7 +3820,7 @@ purposes internal to the MySQL server", MYF(0));
thd->server_status &= ~SERVER_MORE_RESULTS_EXISTS;
}
- if (res == 0)
+ if (!res)
send_ok(thd, (ulong) (thd->row_count_func < 0 ? 0 : thd->row_count_func));
else
goto error; // Substatement should already have sent error
@@ -3771,6 +3830,7 @@ purposes internal to the MySQL server", MYF(0));
case SQLCOM_ALTER_PROCEDURE:
case SQLCOM_ALTER_FUNCTION:
{
+ int result;
sp_head *sp;
st_sp_chistics chistics;
@@ -3781,32 +3841,29 @@ purposes internal to the MySQL server", MYF(0));
sp= sp_find_function(thd, lex->spname);
mysql_reset_errors(thd);
if (! sp)
- res= SP_KEY_NOT_FOUND;
+ result= SP_KEY_NOT_FOUND;
else
{
if (check_sp_definer_access(thd, sp))
- {
- res= -1;
- break;
- }
+ goto error;
memcpy(&lex->sp_chistics, &chistics, sizeof(lex->sp_chistics));
if (lex->sql_command == SQLCOM_ALTER_PROCEDURE)
- res= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
+ result= sp_update_procedure(thd, lex->spname, &lex->sp_chistics);
else
- res= sp_update_function(thd, lex->spname, &lex->sp_chistics);
+ result= sp_update_function(thd, lex->spname, &lex->sp_chistics);
}
- switch (res)
+ switch (result)
{
case SP_OK:
send_ok(thd);
break;
case SP_KEY_NOT_FOUND:
- net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),
- lex->spname->m_qname.str);
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_qname.str);
goto error;
default:
- net_printf(thd, ER_SP_CANT_ALTER, SP_COM_STRING(lex),
- lex->spname->m_qname.str);
+ my_error(ER_SP_CANT_ALTER, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_qname.str);
goto error;
}
break;
@@ -3815,46 +3872,45 @@ purposes internal to the MySQL server", MYF(0));
case SQLCOM_DROP_FUNCTION:
{
sp_head *sp;
+ int result;
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
sp= sp_find_procedure(thd, lex->spname);
else
sp= sp_find_function(thd, lex->spname);
mysql_reset_errors(thd);
- if (! sp)
- res= SP_KEY_NOT_FOUND;
- else
+ if (sp)
{
if (check_sp_definer_access(thd, sp))
- {
- res= -1;
- break;
- }
+ goto error;
if (lex->sql_command == SQLCOM_DROP_PROCEDURE)
- res= sp_drop_procedure(thd, lex->spname);
+ result= sp_drop_procedure(thd, lex->spname);
else
- {
- res= sp_drop_function(thd, lex->spname);
+ result= sp_drop_function(thd, lex->spname);
+ }
+ else
+ {
#ifdef HAVE_DLOPEN
- if (res == SP_KEY_NOT_FOUND)
- {
- udf_func *udf = find_udf(lex->spname->m_name.str,
- lex->spname->m_name.length);
- if (udf)
+ if (lex->sql_command == SQLCOM_DROP_FUNCTION)
+ {
+ udf_func *udf = find_udf(lex->spname->m_name.str,
+ lex->spname->m_name.length);
+ if (udf)
+ {
+ if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0))
+ goto error;
+ if (!(res = mysql_drop_function(thd, &lex->spname->m_name)))
{
- if (check_access(thd, DELETE_ACL, "mysql", 0, 1, 0))
- goto error;
- if (!(res = mysql_drop_function(thd,&lex->spname->m_name)))
- {
- send_ok(thd);
- break;
- }
+ send_ok(thd);
+ break;
}
}
-#endif
}
+#endif
+ result= SP_KEY_NOT_FOUND;
}
- switch (res)
+ res= result;
+ switch (result)
{
case SP_OK:
send_ok(thd);
@@ -3865,34 +3921,31 @@ purposes internal to the MySQL server", MYF(0));
push_warning_printf(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_SP_DOES_NOT_EXIST, ER(ER_SP_DOES_NOT_EXIST),
SP_COM_STRING(lex), lex->spname->m_name.str);
- res= 0;
+ res= FALSE;
send_ok(thd);
break;
}
- net_printf(thd, ER_SP_DOES_NOT_EXIST, SP_COM_STRING(lex),
- lex->spname->m_qname.str);
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_qname.str);
goto error;
default:
- net_printf(thd, ER_SP_DROP_FAILED, SP_COM_STRING(lex),
- lex->spname->m_qname.str);
+ my_error(ER_SP_DROP_FAILED, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_qname.str);
goto error;
}
break;
}
case SQLCOM_SHOW_CREATE_PROC:
{
- res= -1;
if (lex->spname->m_name.length > NAME_LEN)
{
- net_printf(thd, ER_TOO_LONG_IDENT, lex->spname->m_name.str);
+ my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
goto error;
}
- res= sp_show_create_procedure(thd, lex->spname);
- if (res != SP_OK)
+ if (sp_show_create_procedure(thd, lex->spname) != SP_OK)
{ /* We don't distinguish between errors for now */
- net_printf(thd, ER_SP_DOES_NOT_EXIST,
- SP_COM_STRING(lex), lex->spname->m_name.str);
- res= 0;
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_name.str);
goto error;
}
break;
@@ -3901,18 +3954,15 @@ purposes internal to the MySQL server", MYF(0));
{
if (lex->spname->m_name.length > NAME_LEN)
{
- net_printf(thd, ER_TOO_LONG_IDENT, lex->spname->m_name.str);
+ my_error(ER_TOO_LONG_IDENT, MYF(0), lex->spname->m_name.str);
goto error;
}
- res= sp_show_create_function(thd, lex->spname);
- if (res != SP_OK)
+ if (sp_show_create_function(thd, lex->spname) != SP_OK)
{ /* We don't distinguish between errors for now */
- net_printf(thd, ER_SP_DOES_NOT_EXIST,
- SP_COM_STRING(lex), lex->spname->m_name.str);
- res= 0;
+ my_error(ER_SP_DOES_NOT_EXIST, MYF(0),
+ SP_COM_STRING(lex), lex->spname->m_name.str);
goto error;
}
- res= 0;
break;
}
case SQLCOM_SHOW_STATUS_PROC:
@@ -3934,23 +3984,19 @@ purposes internal to the MySQL server", MYF(0));
}
case SQLCOM_DROP_VIEW:
{
- if (check_table_access(thd, DROP_ACL, all_tables, 0))
- goto error;
- if (end_active_trans(thd))
- {
- res= -1;
- break;
- }
+ if (check_table_access(thd, DROP_ACL, all_tables, 0) ||
+ end_active_trans(thd))
+ goto error;
res= mysql_drop_view(thd, first_table, thd->lex->drop_mode);
break;
}
case SQLCOM_CREATE_TRIGGER:
{
- /* We don't care much about trigger body at that point */
+ res= mysql_create_or_drop_trigger(thd, all_tables, 1);
+
+ /* We don't care about trigger body after this point */
delete lex->sphead;
lex->sphead= 0;
-
- res= mysql_create_or_drop_trigger(thd, all_tables, 1);
break;
}
case SQLCOM_DROP_TRIGGER:
@@ -4008,17 +4054,10 @@ purposes internal to the MySQL server", MYF(0));
thd->row_count_func= -1;
}
- /*
- We end up here if res == 0 and send_ok() has been done,
- or res != 0 and no send_error() has yet been done.
- */
- if (res < 0)
- send_error(thd,thd->killed_errno());
- DBUG_RETURN(res);
+ DBUG_RETURN(res || thd->net.report_error);
error:
- /* We end up here if send_error() has already been done. */
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
@@ -4097,7 +4136,8 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
{
DBUG_PRINT("error",("No database"));
if (!no_errors)
- send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
+ MYF(0)); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
@@ -4124,10 +4164,12 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
{ // We can never grant this
DBUG_PRINT("error",("No possible access"));
if (!no_errors)
- net_printf(thd,ER_ACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->priv_host,
- thd->password ? ER(ER_YES) : ER(ER_NO));/* purecov: tested */
+ my_error(ER_ACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user,
+ thd->priv_host,
+ (thd->password ?
+ ER(ER_YES) :
+ ER(ER_NO))); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
}
@@ -4154,10 +4196,12 @@ check_access(THD *thd, ulong want_access, const char *db, ulong *save_priv,
DBUG_PRINT("error",("Access denied"));
if (!no_errors)
- net_printf(thd,ER_DBACCESS_DENIED_ERROR,
- thd->priv_user,
- thd->priv_host,
- db ? db : thd->db ? thd->db : "unknown"); /* purecov: tested */
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user,
+ thd->priv_host,
+ (db ? db : (thd->db ?
+ thd->db :
+ "unknown"))); /* purecov: tested */
DBUG_RETURN(TRUE); /* purecov: tested */
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
@@ -4191,8 +4235,7 @@ bool check_global_access(THD *thd, ulong want_access)
if ((thd->master_access & want_access))
return 0;
get_privilege_desc(command, sizeof(command), want_access);
- net_printf(thd,ER_SPECIFIC_ACCESS_DENIED_ERROR,
- command);
+ my_error(ER_SPECIFIC_ACCESS_DENIED_ERROR, MYF(0), command);
return 1;
#endif /* NO_EMBEDDED_ACCESS_CHECKS */
}
@@ -4212,7 +4255,7 @@ check_table_access(THD *thd, ulong want_access,TABLE_LIST *tables,
TABLE_LIST *org_tables=tables;
for (; tables; tables= tables->next_global)
{
- if (tables->derived ||
+ if (tables->derived || tables->schema_table ||
(tables->table && (int)tables->table->tmp_table) ||
my_tz_check_n_skip_implicit_tables(&tables,
thd->lex->time_zone_tables_used))
@@ -4307,7 +4350,8 @@ static bool check_db_used(THD *thd,TABLE_LIST *tables)
{
if (!(tables->db=thd->db))
{
- send_error(thd,ER_NO_DB_ERROR); /* purecov: tested */
+ my_message(ER_NO_DB_ERROR, ER(ER_NO_DB_ERROR),
+ MYF(0)); /* purecov: tested */
return TRUE; /* purecov: tested */
}
}
@@ -4468,11 +4512,12 @@ mysql_init_select(LEX *lex)
SELECT_LEX *select_lex= lex->current_select;
select_lex->init_select();
select_lex->select_limit= HA_POS_ERROR;
+ lex->orig_sql_command= SQLCOM_END;
+ lex->wild= 0;
if (select_lex == &lex->select_lex)
{
DBUG_ASSERT(lex->result == 0);
lex->exchange= 0;
- lex->proc_list.first= 0;
}
}
@@ -4480,8 +4525,8 @@ mysql_init_select(LEX *lex)
bool
mysql_new_select(LEX *lex, bool move_down)
{
- SELECT_LEX *select_lex = new(&lex->thd->mem_root) SELECT_LEX();
- if (!select_lex)
+ SELECT_LEX *select_lex;
+ if (!(select_lex= new(lex->thd->mem_root) SELECT_LEX()))
return 1;
select_lex->select_number= ++lex->thd->select_number;
select_lex->init_query();
@@ -4489,10 +4534,12 @@ mysql_new_select(LEX *lex, bool move_down)
select_lex->parent_lex= lex;
if (move_down)
{
+ lex->subqueries= TRUE;
/* first select_lex of subselect or derived table */
- SELECT_LEX_UNIT *unit= new(&lex->thd->mem_root) SELECT_LEX_UNIT();
- if (!unit)
+ SELECT_LEX_UNIT *unit;
+ if (!(unit= new(lex->thd->mem_root) SELECT_LEX_UNIT()))
return 1;
+
unit->init_query();
unit->init_select();
unit->thd= lex->thd;
@@ -4507,7 +4554,7 @@ mysql_new_select(LEX *lex, bool move_down)
{
if (lex->current_select->order_list.first && !lex->current_select->braces)
{
- net_printf(lex->thd, ER_WRONG_USAGE, "UNION", "ORDER BY");
+ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "ORDER BY");
return 1;
}
select_lex->include_neighbour(lex->current_select);
@@ -4519,7 +4566,8 @@ mysql_new_select(LEX *lex, bool move_down)
as far as we included SELECT_LEX for UNION unit should have
fake SELECT_LEX for UNION processing
*/
- fake= unit->fake_select_lex= new(&lex->thd->mem_root) SELECT_LEX();
+ if (!(fake= unit->fake_select_lex= new(lex->thd->mem_root) SELECT_LEX()))
+ return 1;
fake->include_standalone(unit,
(SELECT_LEX_NODE**)&unit->fake_select_lex);
fake->select_number= INT_MAX;
@@ -4607,7 +4655,6 @@ void mysql_parse(THD *thd, char *inBuf, uint length)
{
if (thd->net.report_error)
{
- send_error(thd, 0, NullS);
if (thd->lex->sphead)
{
if (lex != thd->lex)
@@ -4676,31 +4723,6 @@ bool mysql_test_parse_for_slave(THD *thd, char *inBuf, uint length)
-/*
- Calculate interval lengths.
- Strip trailing spaces from all strings.
- After this function call:
- - ENUM uses max_length
- - SET uses tot_length.
-*/
-void calculate_interval_lengths(THD *thd, TYPELIB *interval,
- uint *max_length, uint *tot_length)
-{
- const char **pos;
- uint *len;
- CHARSET_INFO *cs= thd->variables.character_set_client;
- *max_length= *tot_length= 0;
- for (pos= interval->type_names, len= interval->type_lengths;
- *pos ; pos++, len++)
- {
- *len= (uint) strip_sp((char*) *pos);
- uint length= cs->cset->numchars(cs, *pos, *pos + *len);
- *tot_length+= length;
- set_if_bigger(*max_length, length);
- }
-}
-
-
/*****************************************************************************
** Store field definition for create
** Return 0 if ok
@@ -4711,19 +4733,20 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
uint type_modifier,
Item *default_value, Item *on_update_value,
LEX_STRING *comment,
- char *change, TYPELIB *interval, CHARSET_INFO *cs,
+ char *change,
+ List<String> *interval_list, CHARSET_INFO *cs,
uint uint_geom_type)
{
register create_field *new_field;
LEX *lex= thd->lex;
uint allowed_type_modifier=0;
uint sign_len;
- char warn_buff[MYSQL_ERRMSG_SIZE];
+ ulong max_field_charlength= MAX_FIELD_CHARLENGTH;
DBUG_ENTER("add_field_to_list");
if (strlen(field_name) > NAME_LEN)
{
- net_printf(thd, ER_TOO_LONG_IDENT, field_name); /* purecov: inspected */
+ my_error(ER_TOO_LONG_IDENT, MYF(0), field_name); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
if (type_modifier & PRI_KEY_FLAG)
@@ -4754,7 +4777,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
!(((Item_func*)default_value)->functype() == Item_func::NOW_FUNC &&
type == FIELD_TYPE_TIMESTAMP))
{
- net_printf(thd, ER_INVALID_DEFAULT, field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
DBUG_RETURN(1);
}
else if (default_value->type() == Item::NULL_ITEM)
@@ -4763,20 +4786,20 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
if ((type_modifier & (NOT_NULL_FLAG | AUTO_INCREMENT_FLAG)) ==
NOT_NULL_FLAG)
{
- net_printf(thd,ER_INVALID_DEFAULT,field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
DBUG_RETURN(1);
}
}
else if (type_modifier & AUTO_INCREMENT_FLAG)
{
- net_printf(thd, ER_INVALID_DEFAULT, field_name);
+ my_error(ER_INVALID_DEFAULT, MYF(0), field_name);
DBUG_RETURN(1);
}
}
if (on_update_value && type != FIELD_TYPE_TIMESTAMP)
{
- net_printf(thd, ER_INVALID_ON_UPDATE, field_name);
+ my_error(ER_INVALID_ON_UPDATE, MYF(0), field_name);
DBUG_RETURN(1);
}
@@ -4794,7 +4817,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->length=0;
new_field->change=change;
new_field->interval=0;
- new_field->pack_length=0;
+ new_field->pack_length= new_field->key_length= 0;
new_field->charset=cs;
new_field->geom_type= (Field::geometry_type) uint_geom_type;
@@ -4866,43 +4889,30 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
new_field->length++;
}
break;
- case FIELD_TYPE_STRING:
- case FIELD_TYPE_VAR_STRING:
- if (new_field->length <= MAX_FIELD_CHARLENGTH || default_value)
- break;
- /* Convert long CHAR() and VARCHAR columns to TEXT or BLOB */
- new_field->sql_type= FIELD_TYPE_BLOB;
- sprintf(warn_buff, ER(ER_AUTO_CONVERT), field_name, "CHAR",
- (cs == &my_charset_bin) ? "BLOB" : "TEXT");
- push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
- warn_buff);
- /* fall through */
+ case MYSQL_TYPE_VARCHAR:
+ /*
+ We can't use pack_length as this includes the field length
+ Long VARCHAR's are automaticly converted to blobs in mysql_prepare_table
+ if they don't have a default value
+ */
+ new_field->key_length= new_field->length;
+ max_field_charlength= MAX_FIELD_VARCHARLENGTH;
+ break;
+ case MYSQL_TYPE_STRING:
+ break;
case FIELD_TYPE_BLOB:
case FIELD_TYPE_TINY_BLOB:
case FIELD_TYPE_LONG_BLOB:
case FIELD_TYPE_MEDIUM_BLOB:
case FIELD_TYPE_GEOMETRY:
- if (new_field->length)
- {
- /* The user has given a length to the blob column */
- if (new_field->length < 256)
- type= FIELD_TYPE_TINY_BLOB;
- if (new_field->length < 65536)
- type= FIELD_TYPE_BLOB;
- else if (new_field->length < 256L*256L*256L)
- type= FIELD_TYPE_MEDIUM_BLOB;
- else
- type= FIELD_TYPE_LONG_BLOB;
- new_field->length= 0;
- }
- new_field->sql_type= type;
if (default_value) // Allow empty as default value
{
String str,*res;
res=default_value->val_str(&str);
if (res->length())
{
- net_printf(thd,ER_BLOB_CANT_HAVE_DEFAULT,field_name); /* purecov: inspected */
+ my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0),
+ field_name); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
new_field->def=0;
@@ -4922,7 +4932,7 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
uint tmp_length=new_field->length;
if (tmp_length > PRECISION_FOR_DOUBLE)
{
- net_printf(thd,ER_WRONG_FIELD_SPEC,field_name);
+ my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(1);
}
else if (tmp_length > PRECISION_FOR_FLOAT)
@@ -5017,86 +5027,67 @@ bool add_field_to_list(THD *thd, char *field_name, enum_field_types type,
break;
case FIELD_TYPE_SET:
{
- if (interval->count > sizeof(longlong)*8)
+ if (interval_list->elements > sizeof(longlong)*8)
{
- net_printf(thd,ER_TOO_BIG_SET,field_name); /* purecov: inspected */
- DBUG_RETURN(1); /* purecov: inspected */
+ my_error(ER_TOO_BIG_SET, MYF(0), field_name); /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
}
- new_field->pack_length=(interval->count+7)/8;
+ new_field->pack_length= (interval_list->elements + 7) / 8;
if (new_field->pack_length > 4)
- new_field->pack_length=8;
- new_field->interval=interval;
- uint dummy_max_length;
- calculate_interval_lengths(thd, interval,
- &dummy_max_length, &new_field->length);
- new_field->length+= (interval->count - 1);
- set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1);
- if (default_value)
- {
- char *not_used;
- uint not_used2;
- bool not_used3;
-
- thd->cuted_fields=0;
- String str,*res;
- res=default_value->val_str(&str);
- (void) find_set(interval, res->ptr(), res->length(),
- &my_charset_bin,
- &not_used, &not_used2, &not_used3);
- if (thd->cuted_fields)
- {
- net_printf(thd,ER_INVALID_DEFAULT,field_name);
- DBUG_RETURN(1);
- }
- }
+ new_field->pack_length=8;
+
+ List_iterator<String> it(*interval_list);
+ String *tmp;
+ while ((tmp= it++))
+ new_field->interval_list.push_back(tmp);
+ /*
+ Set fake length to 1 to pass the below conditions.
+ Real length will be set in mysql_prepare_table()
+ when we know the character set of the column
+ */
+ new_field->length= 1;
+ break;
}
- break;
case FIELD_TYPE_ENUM:
{
- new_field->interval=interval;
- new_field->pack_length=interval->count < 256 ? 1 : 2; // Should be safe
+ // Should be safe
+ new_field->pack_length= interval_list->elements < 256 ? 1 : 2;
- uint dummy_tot_length;
- calculate_interval_lengths(thd, interval,
- &new_field->length, &dummy_tot_length);
- set_if_smaller(new_field->length,MAX_FIELD_WIDTH-1);
- if (default_value)
- {
- String str,*res;
- res=default_value->val_str(&str);
- res->strip_sp();
- if (!find_type(interval, res->ptr(), res->length(), 0))
- {
- net_printf(thd,ER_INVALID_DEFAULT,field_name);
- DBUG_RETURN(1);
- }
- }
+ List_iterator<String> it(*interval_list);
+ String *tmp;
+ while ((tmp= it++))
+ new_field->interval_list.push_back(tmp);
+ new_field->length= 1; // See comment for FIELD_TYPE_SET above.
break;
- }
+ }
+ case MYSQL_TYPE_VAR_STRING:
+ DBUG_ASSERT(0); // Impossible
+ break;
}
- if ((new_field->length > MAX_FIELD_CHARLENGTH && type != FIELD_TYPE_SET &&
- type != FIELD_TYPE_ENUM) ||
- (!new_field->length && !(new_field->flags & BLOB_FLAG) &&
- type != FIELD_TYPE_STRING &&
- type != FIELD_TYPE_VAR_STRING && type != FIELD_TYPE_GEOMETRY))
+ if (!(new_field->flags & BLOB_FLAG) &&
+ ((new_field->length > max_field_charlength && type != FIELD_TYPE_SET &&
+ type != FIELD_TYPE_ENUM &&
+ (type != MYSQL_TYPE_VARCHAR || default_value)) ||
+ (!new_field->length &&
+ type != MYSQL_TYPE_STRING &&
+ type != MYSQL_TYPE_VARCHAR && type != FIELD_TYPE_GEOMETRY)))
{
- net_printf(thd,ER_TOO_BIG_FIELDLENGTH,field_name,
- MAX_FIELD_CHARLENGTH); /* purecov: inspected */
+ my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0),
+ field_name, max_field_charlength); /* purecov: inspected */
DBUG_RETURN(1); /* purecov: inspected */
}
type_modifier&= AUTO_INCREMENT_FLAG;
if ((~allowed_type_modifier) & type_modifier)
{
- net_printf(thd,ER_WRONG_FIELD_SPEC,field_name);
+ my_error(ER_WRONG_FIELD_SPEC, MYF(0), field_name);
DBUG_RETURN(1);
}
if (!new_field->pack_length)
- new_field->pack_length=calc_pack_length(new_field->sql_type ==
- FIELD_TYPE_VAR_STRING ?
- FIELD_TYPE_STRING :
- new_field->sql_type,
- new_field->length);
+ new_field->pack_length= calc_pack_length(new_field->sql_type,
+ new_field->length);
+ if (!new_field->key_length)
+ new_field->key_length= new_field->pack_length;
lex->create_list.push_back(new_field);
lex->last_field=new_field;
DBUG_RETURN(0);
@@ -5140,7 +5131,6 @@ static void remove_escape(char *name)
{
#ifdef USE_MB
int l;
-/* if ((l = ismbchar(name, name+MBMAXLEN))) { Wei He: I think it's wrong */
if (use_mb(system_charset_info) &&
(l = my_ismbchar(system_charset_info, name, strend)))
{
@@ -5218,7 +5208,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
if (check_table_name(table->table.str,table->table.length) ||
table->db.str && check_db_name(table->db.str))
{
- net_printf(thd, ER_WRONG_TABLE_NAME, table->table.str);
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), table->table.str);
DBUG_RETURN(0);
}
@@ -5226,7 +5216,8 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
{
if (table->sel)
{
- net_printf(thd,ER_DERIVED_MUST_HAVE_ALIAS);
+ my_message(ER_DERIVED_MUST_HAVE_ALIAS,
+ ER(ER_DERIVED_MUST_HAVE_ALIAS), MYF(0));
DBUG_RETURN(0);
}
if (!(alias_str=thd->memdup(alias_str,table->table.length+1)))
@@ -5263,6 +5254,18 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
ptr->force_index= test(table_options & TL_OPTION_FORCE_INDEX);
ptr->ignore_leaves= test(table_options & TL_OPTION_IGNORE_LEAVES);
ptr->derived= table->sel;
+ if (!my_strcasecmp(system_charset_info, ptr->db,
+ information_schema_name.str))
+ {
+ ST_SCHEMA_TABLE *schema_table= find_schema_table(thd, ptr->real_name);
+ if (!schema_table)
+ {
+ my_error(ER_UNKNOWN_TABLE, MYF(0),
+ ptr->real_name, information_schema_name.str);
+ DBUG_RETURN(0);
+ }
+ ptr->schema_table= schema_table;
+ }
ptr->select_lex= lex->current_select;
ptr->cacheable_table= 1;
if (use_index_arg)
@@ -5282,7 +5285,7 @@ TABLE_LIST *st_select_lex::add_table_to_list(THD *thd,
if (!my_strcasecmp(table_alias_charset, alias_str, tables->alias) &&
!strcmp(ptr->db, tables->db))
{
- net_printf(thd,ER_NONUNIQ_TABLE,alias_str); /* purecov: tested */
+ my_error(ER_NONUNIQ_TABLE, MYF(0), alias_str); /* purecov: tested */
DBUG_RETURN(0); /* purecov: tested */
}
}
@@ -5628,7 +5631,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
acl_reload(thd);
grant_reload(thd);
if (mqh_used)
- reset_mqh(thd,(LEX_USER *) NULL,TRUE);
+ reset_mqh((LEX_USER *) NULL,TRUE);
}
#endif
if (options & REFRESH_LOG)
@@ -5691,7 +5694,12 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
return 1;
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1,
tables);
- make_global_read_lock_block_commit(thd);
+ if (make_global_read_lock_block_commit(thd))
+ {
+ /* Don't leave things in a half-locked state */
+ unlock_global_read_lock(thd);
+ return 1;
+ }
}
else
result=close_cached_tables(thd,(options & REFRESH_FAST) ? 0 : 1, tables);
@@ -5699,7 +5707,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
}
if (options & REFRESH_HOSTS)
hostname_cache_refresh();
- if (options & REFRESH_STATUS)
+ if (thd && (options & REFRESH_STATUS))
refresh_status();
if (options & REFRESH_THREADS)
flush_thread_cache();
@@ -5729,7 +5737,7 @@ bool reload_acl_and_cache(THD *thd, ulong options, TABLE_LIST *tables,
}
#endif
if (options & REFRESH_USER_RESOURCES)
- reset_mqh(thd,(LEX_USER *) NULL);
+ reset_mqh((LEX_USER *) NULL);
if (write_to_binlog)
*write_to_binlog= tmp_write_to_binlog;
return result;
@@ -5778,7 +5786,7 @@ void kill_one_thread(THD *thd, ulong id, bool only_kill_query)
if (!error)
send_ok(thd);
else
- net_printf(thd,error,id);
+ my_error(error, MYF(0), id);
}
/* Clear most status variables */
@@ -5854,12 +5862,13 @@ static bool append_file_to_dir(THD *thd, const char **filename_ptr,
bool check_simple_select()
{
THD *thd= current_thd;
- if (thd->lex->current_select != &thd->lex->select_lex)
+ LEX *lex= thd->lex;
+ if (lex->current_select != &lex->select_lex)
{
char command[80];
- strmake(command, thd->lex->yylval->symbol.str,
- min(thd->lex->yylval->symbol.length, sizeof(command)-1));
- net_printf(thd, ER_CANT_USE_OPTION_HERE, command);
+ strmake(command, lex->yylval->symbol.str,
+ min(lex->yylval->symbol.length, sizeof(command)-1));
+ my_error(ER_CANT_USE_OPTION_HERE, MYF(0), command);
return 1;
}
return 0;
@@ -5947,7 +5956,7 @@ Item * all_any_subquery_creator(Item *left_expr,
One should normally create all indexes with CREATE TABLE or ALTER TABLE.
*/
-int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
+bool mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
{
List<create_field> fields;
ALTER_INFO alter_info;
@@ -5964,7 +5973,7 @@ int mysql_create_index(THD *thd, TABLE_LIST *table_list, List<Key> &keys)
}
-int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
+bool mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
{
List<create_field> fields;
List<Key> keys;
@@ -5991,12 +6000,11 @@ int mysql_drop_index(THD *thd, TABLE_LIST *table_list, ALTER_INFO *alter_info)
tables Global/local table list (have to be the same)
RETURN VALUE
- 0 OK
- 1 Error (message is sent to user)
- -1 Error (message is not sent to user)
+ FALSE OK
+ TRUE Error
*/
-int multi_update_precheck(THD *thd, TABLE_LIST *tables)
+bool multi_update_precheck(THD *thd, TABLE_LIST *tables)
{
const char *msg= 0;
TABLE_LIST *table;
@@ -6006,8 +6014,8 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (select_lex->item_list.elements != lex->value_list.elements)
{
- my_error(ER_WRONG_VALUE_COUNT, MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
+ DBUG_RETURN(TRUE);
}
/*
Ensure that we have UPDATE or SELECT privilege for each table
@@ -6024,7 +6032,7 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
(check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0) ||
grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0)))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
table->table_in_first_from_clause= 1;
}
@@ -6041,7 +6049,7 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (check_access(thd, SELECT_ACL, table->db,
&table->grant.privilege, 0, 0) ||
grant_option && check_grant(thd, SELECT_ACL, table, 0, 1, 0))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
}
@@ -6054,9 +6062,9 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
if (msg)
{
my_error(ER_WRONG_USAGE, MYF(0), "UPDATE", msg);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
/*
@@ -6069,11 +6077,11 @@ int multi_update_precheck(THD *thd, TABLE_LIST *tables)
table_count Pointer to table counter
RETURN VALUE
- 0 OK
- 1 error (message is sent to user)
- -1 error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
+
+bool multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
{
SELECT_LEX *select_lex= &thd->lex->select_lex;
TABLE_LIST *aux_tables=
@@ -6088,11 +6096,12 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
if (check_db_used(thd, tables) || check_db_used(thd,aux_tables) ||
check_table_access(thd,SELECT_ACL, tables,0) ||
check_table_access(thd,DELETE_ACL, aux_tables,0))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
if ((thd->options & OPTION_SAFE_UPDATES) && !select_lex->where)
{
- my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE, MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
+ DBUG_RETURN(TRUE);
}
for (target_tbl= aux_tables; target_tbl; target_tbl= target_tbl->next_local)
{
@@ -6108,14 +6117,14 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
}
if (!walk)
{
- my_error(ER_UNKNOWN_TABLE, MYF(0), target_tbl->real_name,
- "MULTI DELETE");
- DBUG_RETURN(-1);
+ my_error(ER_UNKNOWN_TABLE, MYF(0),
+ target_tbl->real_name, "MULTI DELETE");
+ DBUG_RETURN(TRUE);
}
walk->lock_type= target_tbl->lock_type;
target_tbl->correspondent_table= walk; // Remember corresponding table
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -6128,12 +6137,11 @@ int multi_delete_precheck(THD *thd, TABLE_LIST *tables, uint *table_count)
tables Global table list
RETURN VALUE
- 0 OK
- 1 Error (message is sent to user)
- -1 Error (message is not sent to user)
+ FALSE OK
+ TRUE Error
*/
-int insert_select_precheck(THD *thd, TABLE_LIST *tables)
+bool insert_select_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("insert_select_precheck");
/*
@@ -6142,7 +6150,7 @@ int insert_select_precheck(THD *thd, TABLE_LIST *tables)
*/
ulong privilege= (thd->lex->duplicates == DUP_REPLACE ?
INSERT_ACL | DELETE_ACL : INSERT_ACL);
- DBUG_RETURN(check_one_table_access(thd, privilege, tables) ? 1 : 0);
+ DBUG_RETURN(check_one_table_access(thd, privilege, tables));
}
@@ -6155,21 +6163,20 @@ int insert_select_precheck(THD *thd, TABLE_LIST *tables)
tables Global table list
RETURN VALUE
- 0 OK
- 1 Error (message is sent to user)
- -1 Error (message is not sent to user)
+ FALSE OK
+ TRUE Error
*/
-int update_precheck(THD *thd, TABLE_LIST *tables)
+bool update_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("update_precheck");
if (thd->lex->select_lex.item_list.elements != thd->lex->value_list.elements)
{
- my_error(ER_WRONG_VALUE_COUNT, MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN((check_db_used(thd, tables) ||
- check_one_table_access(thd, UPDATE_ACL, tables)) ? 1 : 0);
+ DBUG_RETURN(check_db_used(thd, tables) ||
+ check_one_table_access(thd, UPDATE_ACL, tables));
}
@@ -6182,19 +6189,18 @@ int update_precheck(THD *thd, TABLE_LIST *tables)
tables Global table list
RETURN VALUE
- 0 OK
- 1 error (message is sent to user)
- -1 error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int delete_precheck(THD *thd, TABLE_LIST *tables)
+bool delete_precheck(THD *thd, TABLE_LIST *tables)
{
DBUG_ENTER("delete_precheck");
if (check_one_table_access(thd, DELETE_ACL, tables))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
/* Set privilege for the WHERE clause */
tables->grant.want_privilege=(SELECT_ACL & ~tables->grant.privilege);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -6207,12 +6213,11 @@ int delete_precheck(THD *thd, TABLE_LIST *tables)
tables Global table list
RETURN VALUE
- 0 OK
- 1 error (message is sent to user)
- -1 error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int insert_precheck(THD *thd, TABLE_LIST *tables)
+bool insert_precheck(THD *thd, TABLE_LIST *tables)
{
LEX *lex= thd->lex;
DBUG_ENTER("insert_precheck");
@@ -6222,14 +6227,14 @@ int insert_precheck(THD *thd, TABLE_LIST *tables)
(lex->value_list.elements ? UPDATE_ACL : 0));
if (check_one_table_access(thd, privilege, tables))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
if (lex->select_lex.item_list.elements != lex->value_list.elements)
{
- my_error(ER_WRONG_VALUE_COUNT, MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_WRONG_VALUE_COUNT, ER(ER_WRONG_VALUE_COUNT), MYF(0));
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -6243,17 +6248,17 @@ int insert_precheck(THD *thd, TABLE_LIST *tables)
create_table Table which will be created
RETURN VALUE
- 0 OK
- 1 Error (message is sent to user)
+ FALSE OK
+ TRUE Error
*/
-int create_table_precheck(THD *thd, TABLE_LIST *tables,
- TABLE_LIST *create_table)
+bool create_table_precheck(THD *thd, TABLE_LIST *tables,
+ TABLE_LIST *create_table)
{
LEX *lex= thd->lex;
SELECT_LEX *select_lex= &lex->select_lex;
ulong want_priv;
- int error= 1; // Error message is given
+ bool error= TRUE; // Error message is given
DBUG_ENTER("create_table_precheck");
want_priv= ((lex->create_info.options & HA_LEX_CREATE_TMP_TABLE) ?
@@ -6287,15 +6292,14 @@ int create_table_precheck(THD *thd, TABLE_LIST *tables,
find_table_in_global_list(tables, create_table->db,
create_table->real_name))
{
- net_printf(thd,ER_UPDATE_TABLE_USED, create_table->real_name);
-
+ error= FALSE;
goto err;
}
}
if (tables && check_table_access(thd, SELECT_ACL, tables,0))
goto err;
}
- error= 0;
+ error= FALSE;
err:
DBUG_RETURN(error);
diff --git a/sql/sql_prepare.cc b/sql/sql_prepare.cc
index bb2362dd562..6d59d465445 100644
--- a/sql/sql_prepare.cc
+++ b/sql/sql_prepare.cc
@@ -72,6 +72,7 @@ Long data handling:
#include "sql_select.h" // for JOIN
#include <m_ctype.h> // for isspace()
#include "sp_head.h"
+#include "sp.h"
#ifdef EMBEDDED_LIBRARY
/* include MYSQL_BIND headers */
#include <mysql.h>
@@ -122,16 +123,13 @@ inline bool is_param_null(const uchar *pos, ulong param_no)
enum { STMT_QUERY_LOG_LENGTH= 8192 };
-enum enum_send_error { DONT_SEND_ERROR= 0, SEND_ERROR };
-
/*
Seek prepared statement in statement map by id: returns zero if statement
was not found, pointer otherwise.
*/
static Prepared_statement *
-find_prepared_statement(THD *thd, ulong id, const char *where,
- enum enum_send_error se)
+find_prepared_statement(THD *thd, ulong id, const char *where)
{
Statement *stmt= thd->stmt_map.find(id);
@@ -139,8 +137,6 @@ find_prepared_statement(THD *thd, ulong id, const char *where,
{
char llbuf[22];
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), 22, llstr(id, llbuf), where);
- if (se == SEND_ERROR)
- send_error(thd);
return 0;
}
return (Prepared_statement *) stmt;
@@ -170,8 +166,7 @@ static bool send_prep_stmt(Prepared_statement *stmt, uint columns)
(stmt->param_count &&
stmt->thd->protocol_simple.send_fields((List<Item> *)
&stmt->lex->param_list,
- Protocol::SEND_EOF)) ||
- net_flush(net));
+ Protocol::SEND_EOF)));
}
#else
static bool send_prep_stmt(Prepared_statement *stmt,
@@ -181,7 +176,7 @@ static bool send_prep_stmt(Prepared_statement *stmt,
thd->client_stmt_id= stmt->id;
thd->client_param_count= stmt->param_count;
- thd->net.last_errno= 0;
+ thd->clear_error();
return 0;
}
@@ -353,12 +348,6 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len)
tm.neg= (bool) to[0];
day= (uint) sint4korr(to+1);
- /*
- Note, that though ranges of hour, minute and second are not checked
- here we rely on them being < 256: otherwise
- we'll get buffer overflow in make_{date,time} functions,
- which are called when time value is converted to string.
- */
tm.hour= (uint) to[5] + day * 24;
tm.minute= (uint) to[6];
tm.second= (uint) to[7];
@@ -373,7 +362,7 @@ static void set_param_time(Item_param *param, uchar **pos, ulong len)
tm.day= tm.year= tm.month= 0;
}
else
- set_zero_time(&tm);
+ set_zero_time(&tm, MYSQL_TIMESTAMP_TIME);
param->set_time(&tm, MYSQL_TIMESTAMP_TIME,
MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
*pos+= length;
@@ -392,11 +381,6 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len)
tm.year= (uint) sint2korr(to);
tm.month= (uint) to[2];
tm.day= (uint) to[3];
- /*
- Note, that though ranges of hour, minute and second are not checked
- here we rely on them being < 256: otherwise
- we'll get buffer overflow in make_{date,time} functions.
- */
if (length > 4)
{
tm.hour= (uint) to[4];
@@ -409,7 +393,7 @@ static void set_param_datetime(Item_param *param, uchar **pos, ulong len)
tm.second_part= (length > 7) ? (ulong) sint4korr(to+7) : 0;
}
else
- set_zero_time(&tm);
+ set_zero_time(&tm, MYSQL_TIMESTAMP_DATETIME);
param->set_time(&tm, MYSQL_TIMESTAMP_DATETIME,
MAX_DATETIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
*pos+= length;
@@ -424,11 +408,7 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len)
if (length >= 4)
{
uchar *to= *pos;
- /*
- Note, that though ranges of hour, minute and second are not checked
- here we rely on them being < 256: otherwise
- we'll get buffer overflow in make_{date,time} functions.
- */
+
tm.year= (uint) sint2korr(to);
tm.month= (uint) to[2];
tm.day= (uint) to[3];
@@ -438,7 +418,7 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len)
tm.neg= 0;
}
else
- set_zero_time(&tm);
+ set_zero_time(&tm, MYSQL_TIMESTAMP_DATE);
param->set_time(&tm, MYSQL_TIMESTAMP_DATE,
MAX_DATE_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
*pos+= length;
@@ -447,8 +427,17 @@ static void set_param_date(Item_param *param, uchar **pos, ulong len)
#else/*!EMBEDDED_LIBRARY*/
void set_param_time(Item_param *param, uchar **pos, ulong len)
{
- MYSQL_TIME *to= (MYSQL_TIME*)*pos;
- param->set_time(to, MYSQL_TIMESTAMP_TIME,
+ MYSQL_TIME tm= *((MYSQL_TIME*)*pos);
+ tm.hour+= tm.day * 24;
+ tm.day= tm.year= tm.month= 0;
+ if (tm.hour > 838)
+ {
+ /* TODO: add warning 'Data truncated' here */
+ tm.hour= 838;
+ tm.minute= 59;
+ tm.second= 59;
+ }
+ param->set_time(&tm, MYSQL_TIMESTAMP_TIME,
MAX_TIME_WIDTH * MY_CHARSET_BIN_MB_MAXLEN);
}
@@ -882,24 +871,23 @@ static bool insert_params_from_vars_with_log(Prepared_statement *stmt,
tables global/local table list
RETURN VALUE
- 0 ok
- 1 error, sent to the client
- -1 error, not sent to client
+ FALSE OK
+ TRUE error
*/
-static int mysql_test_insert(Prepared_statement *stmt,
- TABLE_LIST *table_list,
- List<Item> &fields,
- List<List_item> &values_list,
- List<Item> &update_fields,
- List<Item> &update_values,
- enum_duplicates duplic)
+static bool mysql_test_insert(Prepared_statement *stmt,
+ TABLE_LIST *table_list,
+ List<Item> &fields,
+ List<List_item> &values_list,
+ List<Item> &update_fields,
+ List<Item> &update_values,
+ enum_duplicates duplic)
{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
List_iterator_fast<List_item> its(values_list);
List_item *values;
- int res;
+ bool res;
DBUG_ENTER("mysql_test_insert");
if ((res= insert_precheck(thd, table_list)))
@@ -909,9 +897,9 @@ static int mysql_test_insert(Prepared_statement *stmt,
open temporary memory pool for temporary data allocated by derived
tables & preparation procedure
*/
- if ((res= open_and_lock_tables(thd, table_list)))
+ if (open_and_lock_tables(thd, table_list))
{
- DBUG_RETURN(res);
+ DBUG_RETURN(TRUE);
}
if ((values= its++))
@@ -932,9 +920,7 @@ static int mysql_test_insert(Prepared_statement *stmt,
counter++;
if (values->elements != value_count)
{
- my_printf_error(ER_WRONG_VALUE_COUNT_ON_ROW,
- ER(ER_WRONG_VALUE_COUNT_ON_ROW),
- MYF(0), counter);
+ my_error(ER_WRONG_VALUE_COUNT_ON_ROW, MYF(0), counter);
goto error;
}
if (setup_fields(thd, 0, table_list, *values, 0, 0, 0))
@@ -959,22 +945,44 @@ error:
RETURN VALUE
0 success
- 1 error, sent to client
- -1 error, not sent to client
+ 2 convert to multi_update
+ 1 error
*/
static int mysql_test_update(Prepared_statement *stmt,
- TABLE_LIST *table_list)
+ TABLE_LIST *table_list)
{
int res;
THD *thd= stmt->thd;
+ uint table_count= 0;
SELECT_LEX *select= &stmt->lex->select_lex;
DBUG_ENTER("mysql_test_update");
- if ((res= update_precheck(thd, table_list)))
- DBUG_RETURN(res);
+ if (update_precheck(thd, table_list))
+ DBUG_RETURN(1);
- if (!(res=open_and_lock_tables(thd, table_list)))
+ if (!open_tables(thd, table_list, &table_count))
{
+ if (table_list->ancestor && table_list->ancestor->next_local)
+ {
+ DBUG_ASSERT(table_list->view);
+ DBUG_PRINT("info", ("Switch to multi-update"));
+ /* pass counter value */
+ thd->lex->table_count= table_count;
+ /*
+ give correct value to multi_lock_option, because it will be used
+ in multiupdate
+ */
+ thd->lex->multi_lock_option= table_list->lock_type;
+ /* convert to multiupdate */
+ return 2;
+ }
+
+ if (lock_tables(thd, table_list, table_count) ||
+ mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
+ (thd->fill_derived_tables() &&
+ mysql_handle_derived(thd->lex, &mysql_derived_filling)))
+ DBUG_RETURN(1);
+
if (!(res= mysql_prepare_update(thd, table_list,
&select->where,
select->order_list.elements,
@@ -983,7 +991,7 @@ static int mysql_test_update(Prepared_statement *stmt,
thd->lex->select_lex.no_wrap_view_item= 1;
if (setup_fields(thd, 0, table_list, select->item_list, 1, 0, 0))
{
- res= -1;
+ res= 1;
thd->lex->select_lex.no_wrap_view_item= 0;
}
else
@@ -991,11 +999,13 @@ static int mysql_test_update(Prepared_statement *stmt,
thd->lex->select_lex.no_wrap_view_item= 0;
if (setup_fields(thd, 0, table_list,
stmt->lex->value_list, 0, 0, 0))
- res= -1;
+ res= 1;
}
}
stmt->lex->unit.cleanup();
}
+ else
+ res= 1;
/* TODO: here we should send types of placeholders to the client. */
DBUG_RETURN(res);
}
@@ -1010,28 +1020,36 @@ static int mysql_test_update(Prepared_statement *stmt,
tables list of tables queries
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error
*/
static int mysql_test_delete(Prepared_statement *stmt,
TABLE_LIST *table_list)
{
- int res;
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
DBUG_ENTER("mysql_test_delete");
- if ((res= delete_precheck(thd, table_list)))
- DBUG_RETURN(res);
+ if (delete_precheck(thd, table_list))
+ DBUG_RETURN(TRUE);
- if (!(res=open_and_lock_tables(thd, table_list)))
+ if (!open_and_lock_tables(thd, table_list))
{
- res= mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
+ if (!table_list->table)
+ {
+ DBUG_ASSERT(table_list->view &&
+ table_list->ancestor && table_list->ancestor->next_local);
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ table_list->view_db.str, table_list->view_name.str);
+ DBUG_RETURN(-1);
+ }
+
+ mysql_prepare_delete(thd, table_list, &lex->select_lex.where);
lex->unit.cleanup();
+ DBUG_RETURN(FALSE);
}
/* TODO: here we should send types of placeholders to the client. */
- DBUG_RETURN(res);
+ DBUG_RETURN(TRUE);
}
@@ -1046,9 +1064,8 @@ static int mysql_test_delete(Prepared_statement *stmt,
tables list of tables queries
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, sent to client
*/
static int mysql_test_select(Prepared_statement *stmt,
@@ -1057,7 +1074,7 @@ static int mysql_test_select(Prepared_statement *stmt,
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
SELECT_LEX_UNIT *unit= &lex->unit;
- int result;
+ bool result;
DBUG_ENTER("mysql_test_select");
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -1065,39 +1082,32 @@ static int mysql_test_select(Prepared_statement *stmt,
if (tables)
{
if (check_table_access(thd, privilege, tables,0))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
else if (check_access(thd, privilege, any_db,0,0,0))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
#endif
- if (!lex->result && !(lex->result= new (&stmt->mem_root) select_send))
- {
- send_error(thd);
+ result= TRUE;
+ if (!lex->result && !(lex->result= new (stmt->mem_root) select_send))
goto err;
- }
- if ((result= open_and_lock_tables(thd, tables)))
- {
- result= 1; // Error sent
- send_error(thd);
+ if (open_and_lock_tables(thd, tables))
goto err;
- }
- result= 1;
+
thd->used_tables= 0; // Updated by setup_fields
// JOIN::prepare calls
if (unit->prepare(thd, 0, 0))
{
- send_error(thd);
goto err_prep;
}
if (!text_protocol)
{
if (lex->describe)
{
- if (send_prep_stmt(stmt, 0))
+ if (send_prep_stmt(stmt, 0) || thd->protocol->flush())
goto err_prep;
}
else
@@ -1115,15 +1125,12 @@ static int mysql_test_select(Prepared_statement *stmt,
prepared in unit->prepare call above.
*/
if (send_prep_stmt(stmt, lex->result->field_count(fields)) ||
- lex->result->send_fields(fields, Protocol::SEND_EOF)
-#ifndef EMBEDDED_LIBRARY
- || net_flush(&thd->net)
-#endif
- )
+ lex->result->send_fields(fields, Protocol::SEND_EOF) ||
+ thd->protocol->flush())
goto err_prep;
}
}
- result= 0; // ok
+ result= FALSE; // ok
err_prep:
unit->cleanup();
@@ -1142,30 +1149,27 @@ err:
values list of expressions
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error, sent to client
*/
-static int mysql_test_do_fields(Prepared_statement *stmt,
+static bool mysql_test_do_fields(Prepared_statement *stmt,
TABLE_LIST *tables,
List<Item> *values)
{
DBUG_ENTER("mysql_test_do_fields");
THD *thd= stmt->thd;
- int res= 0;
- if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
- DBUG_RETURN(res);
+ bool res;
+ if (tables && check_table_access(thd, SELECT_ACL, tables, 0))
+ DBUG_RETURN(TRUE);
- if (tables && (res= open_and_lock_tables(thd, tables)))
+ if (tables && open_and_lock_tables(thd, tables))
{
- DBUG_RETURN(res);
+ DBUG_RETURN(TRUE);
}
res= setup_fields(thd, 0, 0, *values, 0, 0, 0);
stmt->lex->unit.cleanup();
- if (res)
- DBUG_RETURN(-1);
- DBUG_RETURN(0);
+ DBUG_RETURN(res);
}
@@ -1179,22 +1183,21 @@ static int mysql_test_do_fields(Prepared_statement *stmt,
values list of expressions
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error
*/
-static int mysql_test_set_fields(Prepared_statement *stmt,
- TABLE_LIST *tables,
- List<set_var_base> *var_list)
+static bool mysql_test_set_fields(Prepared_statement *stmt,
+ TABLE_LIST *tables,
+ List<set_var_base> *var_list)
{
DBUG_ENTER("mysql_test_set_fields");
List_iterator_fast<set_var_base> it(*var_list);
THD *thd= stmt->thd;
set_var_base *var;
- int res= 0;
+ bool res= 0;
- if (tables && (res= check_table_access(thd, SELECT_ACL, tables, 0)))
- DBUG_RETURN(res);
+ if (tables && check_table_access(thd, SELECT_ACL, tables, 0))
+ DBUG_RETURN(TRUE);
if (tables && (res= open_and_lock_tables(thd, tables)))
goto error;
@@ -1203,7 +1206,7 @@ static int mysql_test_set_fields(Prepared_statement *stmt,
if (var->light_check(thd))
{
stmt->lex->unit.cleanup();
- res= -1;
+ res= TRUE;
goto error;
}
}
@@ -1223,20 +1226,22 @@ error:
specific_prepare - function of command specific prepare
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error
*/
-static int select_like_statement_test(Prepared_statement *stmt,
- TABLE_LIST *tables,
- int (*specific_prepare)(THD *thd))
+static bool select_like_statement_test(Prepared_statement *stmt,
+ TABLE_LIST *tables,
+ bool (*specific_prepare)(THD *thd))
{
DBUG_ENTER("select_like_statement_test");
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
- int res= 0;
+ bool res= 0;
- if (tables && (res= open_and_lock_tables(thd, tables)))
+ /* check that tables was not opened during conversion from usual update */
+ if (tables &&
+ (!tables->table && !tables->view) &&
+ (res= open_and_lock_tables(thd, tables)))
goto end;
if (specific_prepare && (res= (*specific_prepare)(thd)))
@@ -1247,7 +1252,7 @@ static int select_like_statement_test(Prepared_statement *stmt,
// JOIN::prepare calls
if (lex->unit.prepare(thd, 0, 0))
{
- res= thd->net.report_error ? -1 : 1;
+ res= TRUE;
}
end:
lex->unit.cleanup();
@@ -1302,19 +1307,25 @@ static int mysql_test_create_table(Prepared_statement *stmt)
mysql_test_multiupdate()
stmt prepared statemen handler
tables list of tables queries
+ converted converted to multi-update from usual update
RETURN VALUE
- 0 success
- 1 error, sent to client
- -1 error, not sent to client
+ FALSE success
+ TRUE error
*/
-static int mysql_test_multiupdate(Prepared_statement *stmt,
- TABLE_LIST *tables)
+
+static bool mysql_test_multiupdate(Prepared_statement *stmt,
+ TABLE_LIST *tables,
+ bool converted)
{
- int res;
- if ((res= multi_update_precheck(stmt->thd, tables)))
- return res;
- return select_like_statement_test(stmt, tables, &mysql_multi_update_prepare);
+ /* if we switched from normal update, rights are checked */
+ if (!converted && multi_update_precheck(stmt->thd, tables))
+ return TRUE;
+ /*
+ here we do not pass tables for opening, tables will be opened and locked
+ by mysql_multi_update_prepare
+ */
+ return select_like_statement_test(stmt, 0, &mysql_multi_update_prepare);
}
@@ -1342,7 +1353,19 @@ static int mysql_test_multidelete(Prepared_statement *stmt,
uint fake_counter;
if ((res= multi_delete_precheck(stmt->thd, tables, &fake_counter)))
return res;
- return select_like_statement_test(stmt, tables, &mysql_multi_delete_prepare);
+ if ((res= select_like_statement_test(stmt, tables,
+ &mysql_multi_delete_prepare)))
+ return res;
+ if (!tables->table)
+ {
+ DBUG_ASSERT(tables->view &&
+ tables->ancestor && tables->ancestor->next_local);
+ my_error(ER_VIEW_DELETE_MERGE_VIEW, MYF(0),
+ tables->view_db.str, tables->view_name.str);
+ return -1;
+ }
+ return 0;
+
}
@@ -1385,30 +1408,54 @@ static int mysql_test_insert_select(Prepared_statement *stmt,
/*
- Send the prepare query results back to client
+ Perform semantic analysis of the parsed tree and send a response packet
+ to the client.
+
SYNOPSIS
- send_prepare_results()
- stmt prepared statement
+ check_prepared_statement()
+ stmt prepared statement
+
+ DESCRIPTION
+ This function
+ - opens all tables and checks access rights
+ - validates semantics of statement columns and SQL functions
+ by calling fix_fields.
+
RETURN VALUE
0 success
1 error, sent to client
*/
-static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
-{
+
+static int check_prepared_statement(Prepared_statement *stmt,
+ bool text_protocol)
+{
THD *thd= stmt->thd;
LEX *lex= stmt->lex;
SELECT_LEX *select_lex= &lex->select_lex;
TABLE_LIST *tables;
enum enum_sql_command sql_command= lex->sql_command;
int res= 0;
- DBUG_ENTER("send_prepare_results");
-
+ DBUG_ENTER("check_prepared_statement");
DBUG_PRINT("enter",("command: %d, param_count: %ld",
sql_command, stmt->param_count));
lex->first_lists_tables_same();
tables= lex->query_tables;
+ /*
+ Preopen 'proc' system table and cache all functions used in this
+ statement. We must do that before we open ordinary tables to avoid
+ deadlocks. We can't open and lock any table once query tables were
+ opened.
+ */
+ if (lex->sql_command != SQLCOM_CREATE_PROCEDURE &&
+ lex->sql_command != SQLCOM_CREATE_SPFUNCTION)
+ {
+ /* the error is print inside */
+ if (sp_cache_functions(thd, lex))
+ DBUG_RETURN(1);
+ }
+
switch (sql_command) {
case SQLCOM_REPLACE:
case SQLCOM_INSERT:
@@ -1420,6 +1467,12 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
case SQLCOM_UPDATE:
res= mysql_test_update(stmt, tables);
+ /* mysql_test_update return 2 if we need to switch to multi-update */
+ if (res != 2)
+ break;
+
+ case SQLCOM_UPDATE_MULTI:
+ res= mysql_test_multiupdate(stmt, tables, res == 2);
break;
case SQLCOM_DELETE:
@@ -1447,12 +1500,9 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
case SQLCOM_DELETE_MULTI:
res= mysql_test_multidelete(stmt, tables);
break;
-
- case SQLCOM_UPDATE_MULTI:
- res= mysql_test_multiupdate(stmt, tables);
- break;
case SQLCOM_INSERT_SELECT:
+ case SQLCOM_REPLACE_SELECT:
res= mysql_test_insert_select(stmt, tables);
break;
@@ -1487,14 +1537,13 @@ static int send_prepare_results(Prepared_statement *stmt, bool text_protocol)
All other is not supported yet
*/
res= -1;
- my_error(ER_UNSUPPORTED_PS, MYF(0));
+ my_message(ER_UNSUPPORTED_PS, ER(ER_UNSUPPORTED_PS), MYF(0));
goto error;
}
if (res == 0)
- DBUG_RETURN(text_protocol? 0 : send_prep_stmt(stmt, 0));
+ DBUG_RETURN(text_protocol? 0 : (send_prep_stmt(stmt, 0) ||
+ thd->protocol->flush()));
error:
- if (res < 0)
- send_error(thd,thd->killed_errno());
DBUG_RETURN(1);
}
@@ -1513,21 +1562,17 @@ static bool init_param_array(Prepared_statement *stmt)
if (stmt->param_count > (uint) UINT_MAX16)
{
/* Error code to be defined in 5.0 */
- send_error(thd, ER_UNKNOWN_ERROR,
- "Prepared statement contains too many placeholders.");
- return 1;
+ my_message(ER_PS_MANY_PARAM, ER(ER_PS_MANY_PARAM), MYF(0));
+ return TRUE;
}
Item_param **to;
List_iterator<Item_param> param_iterator(lex->param_list);
/* Use thd->mem_root as it points at statement mem_root */
stmt->param_array= (Item_param **)
- alloc_root(&stmt->thd->mem_root,
+ alloc_root(stmt->thd->mem_root,
sizeof(Item_param*) * stmt->param_count);
if (!stmt->param_array)
- {
- send_error(thd, ER_OUT_OF_RESOURCES);
- return 1;
- }
+ return TRUE;
for (to= stmt->param_array;
to < stmt->param_array + stmt->param_count;
++to)
@@ -1535,7 +1580,7 @@ static bool init_param_array(Prepared_statement *stmt)
*to= param_iterator++;
}
}
- return 0;
+ return FALSE;
}
@@ -1551,10 +1596,10 @@ static bool init_param_array(Prepared_statement *stmt)
name NULL or statement name. For unnamed statements binary PS
protocol is used, for named statements text protocol is
used.
- RETURN
- 0 OK, statement prepared successfully
- other Error
-
+ RETURN
+ FALSE OK, statement prepared successfully
+ TRUE Error
+
NOTES
This function parses the query and sends the total number of parameters
and resultset metadata information back to client (if any), without
@@ -1568,39 +1613,34 @@ static bool init_param_array(Prepared_statement *stmt)
*/
-int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
- LEX_STRING *name)
+bool mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
+ LEX_STRING *name)
{
LEX *lex;
Prepared_statement *stmt= new Prepared_statement(thd);
- int error;
+ bool error;
DBUG_ENTER("mysql_stmt_prepare");
DBUG_PRINT("prep_query", ("%s", packet));
if (stmt == 0)
- {
- send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_RETURN(1);
- }
+ DBUG_RETURN(TRUE);
if (name)
{
stmt->name.length= name->length;
- if (!(stmt->name.str= memdup_root(&stmt->mem_root, (char*)name->str,
+ if (!(stmt->name.str= memdup_root(stmt->mem_root, (char*)name->str,
name->length)))
{
delete stmt;
- send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
if (thd->stmt_map.insert(stmt))
{
delete stmt;
- send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
thd->set_n_backup_statement(stmt, &thd->stmt_backup);
@@ -1612,8 +1652,7 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
- send_error(thd, ER_OUT_OF_RESOURCES);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
mysql_log.write(thd, COM_PREPARE, "%s", packet);
@@ -1628,8 +1667,8 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
error= yyparse((void *)thd) || thd->is_fatal_error ||
thd->net.report_error || init_param_array(stmt);
/*
- While doing context analysis of the query (in send_prepare_results) we
- allocate a lot of additional memory: for open tables, JOINs, derived
+ While doing context analysis of the query (in check_prepared_statement)
+ we allocate a lot of additional memory: for open tables, JOINs, derived
tables, etc. Let's save a snapshot of current parse tree to the
statement and restore original THD. In cases when some tree
transformation can be reused on execute, we set again thd->mem_root from
@@ -1638,7 +1677,7 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
thd->restore_backup_item_arena(stmt, &thd->stmt_backup);
if (!error)
- error= send_prepare_results(stmt, test(name));
+ error= check_prepared_statement(stmt, test(name));
/* restore to WAIT_PRIOR: QUERY_PRIOR is set inside alloc_query */
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -1663,9 +1702,6 @@ int mysql_stmt_prepare(THD *thd, char *packet, uint packet_length,
/* Statement map deletes statement on erase */
thd->stmt_map.erase(stmt);
stmt= NULL;
- if (thd->net.report_error)
- send_error(thd);
- /* otherwise the error is sent inside yyparse/send_prepare_results */
}
else
{
@@ -1747,8 +1783,15 @@ void reset_stmt_for_execute(THD *thd, LEX *lex)
were closed in the end of previous prepare or execute call.
*/
tables->table= 0;
+ if (tables->nested_join)
+ tables->nested_join->counter= 0;
}
lex->current_select= &lex->select_lex;
+
+ /* restore original list used in INSERT ... SELECT */
+ if (lex->leaf_tables_insert)
+ lex->select_lex.leaf_tables= lex->leaf_tables_insert;
+
if (lex->result)
lex->result->cleanup();
@@ -1801,8 +1844,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
packet+= 9; /* stmt_id + 5 bytes of flags */
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute",
- SEND_ERROR)))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_execute")))
DBUG_VOID_RETURN;
DBUG_PRINT("exec_query:", ("%s", stmt->query));
@@ -1810,7 +1852,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
/* Check if we got an error when sending long data */
if (stmt->state == Item_arena::ERROR)
{
- send_error(thd, stmt->last_errno, stmt->last_error);
+ my_message(stmt->last_errno, stmt->last_error, MYF(0));
DBUG_VOID_RETURN;
}
@@ -1831,11 +1873,8 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{
DBUG_PRINT("info",("Using READ_ONLY cursor"));
if (!stmt->cursor &&
- !(stmt->cursor= new (&stmt->mem_root) Cursor()))
- {
- send_error(thd, ER_OUT_OF_RESOURCES);
+ !(stmt->cursor= new (&stmt->main_mem_root) Cursor()))
DBUG_VOID_RETURN;
- }
/* If lex->result is set, mysql_execute_command will use it */
stmt->lex->result= &stmt->cursor->result;
}
@@ -1883,7 +1922,7 @@ void mysql_stmt_execute(THD *thd, char *packet, uint packet_length)
{
if (stmt->cursor->is_open())
stmt->cursor->init_from_thd(thd);
- thd->set_item_arena(&thd->stmt_backup);
+ stmt->cursor->state= stmt->state;
}
else
{
@@ -1903,7 +1942,6 @@ set_params_data_err:
reset_stmt_params(stmt);
my_error(ER_WRONG_ARGUMENTS, MYF(0), "mysql_stmt_execute");
err:
- send_error(thd);
DBUG_VOID_RETURN;
}
@@ -1929,14 +1967,12 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
{
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), stmt_name->length,
stmt_name->str, "EXECUTE");
- send_error(thd);
DBUG_VOID_RETURN;
}
if (stmt->param_count != thd->lex->prepared_stmt_params.elements)
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
- send_error(thd);
DBUG_VOID_RETURN;
}
@@ -1949,7 +1985,6 @@ void mysql_sql_stmt_execute(THD *thd, LEX_STRING *stmt_name)
&expanded_query))
{
my_error(ER_WRONG_ARGUMENTS, MYF(0), "EXECUTE");
- send_error(thd);
}
execute_stmt(thd, stmt, &expanded_query);
DBUG_VOID_RETURN;
@@ -1980,7 +2015,7 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
alloc_query(thd, (char *)expanded_query->ptr(),
expanded_query->length()+1))
{
- my_error(ER_OUTOFMEMORY, 0, expanded_query->length());
+ my_error(ER_OUTOFMEMORY, MYF(0), expanded_query->length());
DBUG_VOID_RETURN;
}
/*
@@ -2016,7 +2051,12 @@ static void execute_stmt(THD *thd, Prepared_statement *stmt,
/*
COM_FETCH handler: fetches requested amount of rows from cursor
+
SYNOPSIS
+ mysql_stmt_fetch()
+ thd Thread handler
+ packet Packet from client (with stmt_id & num_rows)
+ packet_length Length of packet
*/
void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
@@ -2026,21 +2066,18 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
ulong num_rows= uint4korr(packet+=4);
Statement *stmt;
int error;
-
DBUG_ENTER("mysql_stmt_fetch");
+ thd->current_arena= stmt;
if (!(stmt= thd->stmt_map.find(stmt_id)) ||
!stmt->cursor ||
!stmt->cursor->is_open())
{
my_error(ER_UNKNOWN_STMT_HANDLER, MYF(0), stmt_id, "fetch");
- send_error(thd);
DBUG_VOID_RETURN;
}
- thd->stmt_backup.set_statement(thd);
- thd->stmt_backup.set_item_arena(thd);
- thd->set_statement(stmt);
+ thd->set_n_backup_statement(stmt, &thd->stmt_backup);
stmt->cursor->init_thd(thd);
if (!(specialflag & SPECIAL_NO_PRIOR))
@@ -2055,11 +2092,8 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
/* Restore THD state */
stmt->cursor->reset_thd(thd);
- thd->set_statement(&thd->stmt_backup);
- thd->set_item_arena(&thd->stmt_backup);
-
- if (error && error != -4)
- send_error(thd, ER_OUT_OF_RESOURCES);
+ thd->restore_backup_statement(stmt, &thd->stmt_backup);
+ thd->current_arena= thd;
DBUG_VOID_RETURN;
}
@@ -2070,7 +2104,7 @@ void mysql_stmt_fetch(THD *thd, char *packet, uint packet_length)
SYNOPSIS
mysql_stmt_reset()
thd Thread handle
- packet Packet with stmt id
+ packet Packet with stmt id
DESCRIPTION
This function resets statement to the state it was right after prepare.
@@ -2090,8 +2124,7 @@ void mysql_stmt_reset(THD *thd, char *packet)
DBUG_ENTER("mysql_stmt_reset");
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset",
- SEND_ERROR)))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_reset")))
DBUG_VOID_RETURN;
stmt->state= Item_arena::PREPARED;
@@ -2122,8 +2155,7 @@ void mysql_stmt_free(THD *thd, char *packet)
DBUG_ENTER("mysql_stmt_free");
- if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close",
- DONT_SEND_ERROR)))
+ if (!(stmt= find_prepared_statement(thd, stmt_id, "mysql_stmt_close")))
DBUG_VOID_RETURN;
/* Statement map deletes statement on erase */
@@ -2173,8 +2205,8 @@ void mysql_stmt_get_longdata(THD *thd, char *packet, ulong packet_length)
stmt_id= uint4korr(packet);
packet+= 4;
- if (!(stmt=find_prepared_statement(thd, stmt_id, "mysql_stmt_send_long_data",
- DONT_SEND_ERROR)))
+ if (!(stmt=find_prepared_statement(thd, stmt_id,
+ "mysql_stmt_send_long_data")))
DBUG_VOID_RETURN;
param_number= uint2korr(packet);
diff --git a/sql/sql_rename.cc b/sql/sql_rename.cc
index 3298eb68a91..1640fc1a634 100644
--- a/sql/sql_rename.cc
+++ b/sql/sql_rename.cc
@@ -44,7 +44,8 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
if (thd->locked_tables || thd->active_transaction())
{
- my_error(ER_LOCK_OR_ACTIVE_TRANSACTION,MYF(0));
+ my_message(ER_LOCK_OR_ACTIVE_TRANSACTION,
+ ER(ER_LOCK_OR_ACTIVE_TRANSACTION), MYF(0));
DBUG_RETURN(1);
}
@@ -83,7 +84,7 @@ bool mysql_rename_tables(THD *thd, TABLE_LIST *table_list)
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
send_ok(thd);
@@ -156,7 +157,7 @@ rename_tables(THD *thd, TABLE_LIST *table_list, bool skip_error)
unpack_filename(name, name);
if (!access(name,F_OK))
{
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_alias);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
DBUG_RETURN(ren_table); // This can't be skipped
}
sprintf(name,"%s/%s/%s%s",mysql_data_home,
diff --git a/sql/sql_repl.cc b/sql/sql_repl.cc
index 10f0c23f54d..0d1a7f3890d 100644
--- a/sql/sql_repl.cc
+++ b/sql/sql_repl.cc
@@ -276,41 +276,39 @@ bool log_in_use(const char* log_name)
return result;
}
-int purge_error_message(THD* thd, int res)
+bool purge_error_message(THD* thd, int res)
{
- const char *errmsg= 0;
+ uint errmsg= 0;
switch (res) {
case 0: break;
- case LOG_INFO_EOF: errmsg= "Target log not found in binlog index"; break;
- case LOG_INFO_IO: errmsg= "I/O error reading log index file"; break;
- case LOG_INFO_INVALID:
- errmsg= "Server configuration does not permit binlog purge"; break;
- case LOG_INFO_SEEK: errmsg= "Failed on fseek()"; break;
- case LOG_INFO_MEM: errmsg= "Out of memory"; break;
- case LOG_INFO_FATAL: errmsg= "Fatal error during purge"; break;
- case LOG_INFO_IN_USE: errmsg= "A purgeable log is in use, will not purge";
- break;
- default: errmsg= "Unknown error during purge"; break;
+ case LOG_INFO_EOF: errmsg= ER_UNKNOWN_TARGET_BINLOG; break;
+ case LOG_INFO_IO: errmsg= ER_IO_ERR_LOG_INDEX_READ; break;
+ case LOG_INFO_INVALID:errmsg= ER_BINLOG_PURGE_PROHIBITED; break;
+ case LOG_INFO_SEEK: errmsg= ER_FSEEK_FAIL; break;
+ case LOG_INFO_MEM: errmsg= ER_OUT_OF_RESOURCES; break;
+ case LOG_INFO_FATAL: errmsg= ER_BINLOG_PURGE_FATAL_ERR; break;
+ case LOG_INFO_IN_USE: errmsg= ER_LOG_IN_USE; break;
+ default: errmsg= ER_LOG_PURGE_UNKNOWN_ERR; break;
}
if (errmsg)
{
- send_error(thd, 0, errmsg);
- return 1;
+ my_message(errmsg, ER(errmsg), MYF(0));
+ return TRUE;
}
send_ok(thd);
- return 0;
+ return FALSE;
}
-int purge_master_logs(THD* thd, const char* to_log)
+bool purge_master_logs(THD* thd, const char* to_log)
{
char search_file_name[FN_REFLEN];
if (!mysql_bin_log.is_open())
{
send_ok(thd);
- return 0;
+ return FALSE;
}
mysql_bin_log.make_log_name(search_file_name, to_log);
@@ -320,7 +318,7 @@ int purge_master_logs(THD* thd, const char* to_log)
}
-int purge_master_logs_before_date(THD* thd, time_t purge_time)
+bool purge_master_logs_before_date(THD* thd, time_t purge_time)
{
if (!mysql_bin_log.is_open())
{
@@ -756,7 +754,7 @@ err:
pthread_mutex_unlock(&LOCK_thread_count);
if (file >= 0)
(void) my_close(file, MYF(MY_WME));
- send_error(thd, my_errno, errmsg);
+ my_message(my_errno, errmsg, MYF(0));
DBUG_VOID_RETURN;
}
@@ -781,7 +779,8 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
thread_mask&= thd->lex->slave_thd_opt;
if (thread_mask) //some threads are stopped, start them
{
- if (init_master_info(mi,master_info_file,relay_log_info_file, 0))
+ if (init_master_info(mi,master_info_file,relay_log_info_file, 0,
+ thread_mask))
slave_errno=ER_MASTER_INFO;
else if (server_id_supplied && *mi->host)
{
@@ -872,7 +871,7 @@ int start_slave(THD* thd , MASTER_INFO* mi, bool net_report)
if (slave_errno)
{
if (net_report)
- send_error(thd, slave_errno);
+ my_message(slave_errno, ER(slave_errno), MYF(0));
DBUG_RETURN(1);
}
else if (net_report)
@@ -922,7 +921,7 @@ int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report )
if (slave_errno)
{
if (net_report)
- send_error(thd, slave_errno);
+ my_message(slave_errno, ER(slave_errno), MYF(0));
return 1;
}
else if (net_report)
@@ -1003,7 +1002,7 @@ int reset_slave(THD *thd, MASTER_INFO* mi)
err:
unlock_slave_threads(mi);
- if (error)
+ if (error)
my_error(sql_errno, MYF(0), errmsg);
DBUG_RETURN(error);
}
@@ -1057,7 +1056,7 @@ void kill_zombie_dump_threads(uint32 slave_server_id)
}
-int change_master(THD* thd, MASTER_INFO* mi)
+bool change_master(THD* thd, MASTER_INFO* mi)
{
int thread_mask;
const char* errmsg= 0;
@@ -1068,19 +1067,20 @@ int change_master(THD* thd, MASTER_INFO* mi)
init_thread_mask(&thread_mask,mi,0 /*not inverse*/);
if (thread_mask) // We refuse if any slave thread is running
{
- net_printf(thd,ER_SLAVE_MUST_STOP);
+ my_message(ER_SLAVE_MUST_STOP, ER(ER_SLAVE_MUST_STOP), MYF(0));
unlock_slave_threads(mi);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
thd->proc_info = "Changing master";
LEX_MASTER_INFO* lex_mi= &thd->lex->mi;
// TODO: see if needs re-write
- if (init_master_info(mi, master_info_file, relay_log_info_file, 0))
+ if (init_master_info(mi, master_info_file, relay_log_info_file, 0,
+ thread_mask))
{
- send_error(thd, ER_MASTER_INFO);
+ my_message(ER_MASTER_INFO, ER(ER_MASTER_INFO), MYF(0));
unlock_slave_threads(mi);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
/*
@@ -1197,9 +1197,9 @@ int change_master(THD* thd, MASTER_INFO* mi)
0 /* not only reset, but also reinit */,
&errmsg))
{
- net_printf(thd, 0, "Failed purging old relay logs: %s",errmsg);
+ my_error(ER_RELAY_LOG_FAIL, MYF(0), errmsg);
unlock_slave_threads(mi);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
else
@@ -1213,9 +1213,9 @@ int change_master(THD* thd, MASTER_INFO* mi)
0 /*no data lock*/,
&msg, 0))
{
- net_printf(thd,0,"Failed initializing relay log position: %s",msg);
+ my_error(ER_RELAY_LOG_INIT, MYF(0), msg);
unlock_slave_threads(mi);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
mi->rli.group_master_log_pos = mi->master_log_pos;
@@ -1257,14 +1257,15 @@ int change_master(THD* thd, MASTER_INFO* mi)
unlock_slave_threads(mi);
thd->proc_info = 0;
send_ok(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
int reset_master(THD* thd)
{
if (!mysql_bin_log.is_open())
{
- my_error(ER_FLUSH_MASTER_BINLOG_CLOSED, MYF(ME_BELL+ME_WAITTANG));
+ my_message(ER_FLUSH_MASTER_BINLOG_CLOSED,
+ ER(ER_FLUSH_MASTER_BINLOG_CLOSED), MYF(ME_BELL+ME_WAITTANG));
return 1;
}
return mysql_bin_log.reset_logs(thd);
@@ -1288,7 +1289,7 @@ int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
}
-int show_binlog_events(THD* thd)
+bool show_binlog_events(THD* thd)
{
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_events");
@@ -1302,7 +1303,7 @@ int show_binlog_events(THD* thd)
Log_event::init_show_field_list(&field_list);
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
if (mysql_bin_log.is_open())
{
@@ -1407,19 +1408,19 @@ err:
if (errmsg)
{
my_error(ER_ERROR_WHEN_EXECUTING_COMMAND, MYF(0),
- "SHOW BINLOG EVENTS", errmsg);
- DBUG_RETURN(-1);
+ "SHOW BINLOG EVENTS", errmsg);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
pthread_mutex_lock(&LOCK_thread_count);
thd->current_linfo = 0;
pthread_mutex_unlock(&LOCK_thread_count);
- DBUG_RETURN(0);
+ DBUG_RETURN(TRUE);
}
-int show_binlog_info(THD* thd)
+bool show_binlog_info(THD* thd)
{
Protocol *protocol= thd->protocol;
DBUG_ENTER("show_binlog_info");
@@ -1432,7 +1433,7 @@ int show_binlog_info(THD* thd)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
if (mysql_bin_log.is_open())
@@ -1445,10 +1446,10 @@ int show_binlog_info(THD* thd)
protocol->store(&binlog_do_db);
protocol->store(&binlog_ignore_db);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -1460,11 +1461,11 @@ int show_binlog_info(THD* thd)
thd Thread specific variable
RETURN VALUES
- 0 ok
- 1 error (Error message sent to client)
+ FALSE OK
+ TRUE error
*/
-int show_binlogs(THD* thd)
+bool show_binlogs(THD* thd)
{
IO_CACHE *index_file;
char fname[FN_REFLEN];
@@ -1475,15 +1476,14 @@ int show_binlogs(THD* thd)
if (!mysql_bin_log.is_open())
{
- //TODO: Replace with ER() error message
- send_error(thd, 0, "You are not using binary logging");
+ my_message(ER_NO_BINARY_LOGGING, ER(ER_NO_BINARY_LOGGING), MYF(0));
return 1;
}
field_list.push_back(new Item_empty_string("Log_name", 255));
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
mysql_bin_log.lock_index();
index_file=mysql_bin_log.get_index_file();
@@ -1501,11 +1501,11 @@ int show_binlogs(THD* thd)
}
mysql_bin_log.unlock_index();
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
mysql_bin_log.unlock_index();
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_repl.h b/sql/sql_repl.h
index 66fdfb4c022..71b25548da4 100644
--- a/sql/sql_repl.h
+++ b/sql/sql_repl.h
@@ -43,17 +43,17 @@ File open_binlog(IO_CACHE *log, const char *log_file_name,
int start_slave(THD* thd, MASTER_INFO* mi, bool net_report);
int stop_slave(THD* thd, MASTER_INFO* mi, bool net_report);
-int change_master(THD* thd, MASTER_INFO* mi);
-int show_binlog_events(THD* thd);
+bool change_master(THD* thd, MASTER_INFO* mi);
+bool show_binlog_events(THD* thd);
int cmp_master_pos(const char* log_file_name1, ulonglong log_pos1,
const char* log_file_name2, ulonglong log_pos2);
int reset_slave(THD *thd, MASTER_INFO* mi);
int reset_master(THD* thd);
-int purge_master_logs(THD* thd, const char* to_log);
-int purge_master_logs_before_date(THD* thd, time_t purge_time);
+bool purge_master_logs(THD* thd, const char* to_log);
+bool purge_master_logs_before_date(THD* thd, time_t purge_time);
bool log_in_use(const char* log_name);
void adjust_linfo_offsets(my_off_t purge_offset);
-int show_binlogs(THD* thd);
+bool show_binlogs(THD* thd);
extern int init_master_info(MASTER_INFO* mi);
void kill_zombie_dump_threads(uint32 slave_server_id);
int check_binlog_magic(IO_CACHE* log, const char** errmsg);
diff --git a/sql/sql_select.cc b/sql/sql_select.cc
index 2e1429feb3e..ed3606856a0 100644
--- a/sql/sql_select.cc
+++ b/sql/sql_select.cc
@@ -38,7 +38,7 @@ const key_map key_map_empty(0);
const key_map key_map_full(~0);
static void optimize_keyuse(JOIN *join, DYNAMIC_ARRAY *keyuse_array);
-static bool make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
+static bool make_join_statistics(JOIN *join, TABLE_LIST *leaves, COND *conds,
DYNAMIC_ARRAY *keyuse);
static bool update_ref_and_keys(THD *thd, DYNAMIC_ARRAY *keyuse,
JOIN_TAB *join_tab,
@@ -192,6 +192,7 @@ static void init_tmptable_sum_functions(Item_sum **func);
static void update_tmptable_sum_func(Item_sum **func,TABLE *tmp_table);
static void copy_sum_funcs(Item_sum **func_ptr);
static bool add_ref_to_table_cond(THD *thd, JOIN_TAB *join_tab);
+static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr);
static bool init_sum_functions(Item_sum **func, Item_sum **end);
static bool update_sum_func(Item_sum **func);
static void select_describe(JOIN *join, bool need_tmp_table,bool need_order,
@@ -204,9 +205,9 @@ static void add_group_and_distinct_keys(JOIN *join, JOIN_TAB *join_tab);
This handles SELECT with and without UNION
*/
-int handle_select(THD *thd, LEX *lex, select_result *result)
+bool handle_select(THD *thd, LEX *lex, select_result *result)
{
- int res;
+ bool res;
register SELECT_LEX *select_lex = &lex->select_lex;
DBUG_ENTER("handle_select");
@@ -231,11 +232,14 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
}
DBUG_PRINT("info",("res: %d report_error: %d", res,
thd->net.report_error));
- if (thd->net.report_error || res < 0)
+ res|= thd->net.report_error;
+ if (unlikely(res))
{
- result->send_error(0, NullS);
+ /*
+ If we have real error reported erly then this will be ignored
+ */
+ result->send_error(ER_UNKNOWN_ERROR, ER(ER_UNKNOWN_ERROR));
result->abort();
- res= 1; // Error sent to client
}
DBUG_RETURN(res);
}
@@ -246,6 +250,7 @@ int handle_select(THD *thd, LEX *lex, select_result *result)
*/
inline int setup_without_group(THD *thd, Item **ref_pointer_array,
TABLE_LIST *tables,
+ TABLE_LIST *leaves,
List<Item> &fields,
List<Item> &all_fields,
COND **conds,
@@ -258,11 +263,13 @@ inline int setup_without_group(THD *thd, Item **ref_pointer_array,
save_allow_sum_func= thd->allow_sum_func;
thd->allow_sum_func= 0;
- res= (setup_conds(thd, tables, conds) ||
- setup_order(thd, ref_pointer_array, tables, fields, all_fields,
- order) ||
- setup_group(thd, ref_pointer_array, tables, fields, all_fields,
- group, hidden_group_fields));
+ res= setup_conds(thd, tables, leaves, conds);
+ thd->allow_sum_func= save_allow_sum_func;
+ res= res || setup_order(thd, ref_pointer_array, tables, fields, all_fields,
+ order);
+ thd->allow_sum_func= 0;
+ res= res || setup_group(thd, ref_pointer_array, tables, fields, all_fields,
+ group, hidden_group_fields);
thd->allow_sum_func= save_allow_sum_func;
DBUG_RETURN(res);
}
@@ -305,13 +312,15 @@ JOIN::prepare(Item ***rref_pointer_array,
/* Check that all tables, fields, conds and order are ok */
- if (setup_tables(thd, tables_list, &conds) ||
+ if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
+ FALSE, FALSE) ||
setup_wild(thd, tables_list, fields_list, &all_fields, wild_num) ||
select_lex->setup_ref_array(thd, og_num) ||
setup_fields(thd, (*rref_pointer_array), tables_list, fields_list, 1,
&all_fields, 1) ||
- setup_without_group(thd, (*rref_pointer_array), tables_list, fields_list,
- all_fields, &conds, order, group_list,
+ setup_without_group(thd, (*rref_pointer_array), tables_list,
+ select_lex->leaf_tables, fields_list,
+ all_fields, &conds, order, group_list,
&hidden_group_fields))
DBUG_RETURN(-1); /* purecov: inspected */
@@ -373,12 +382,15 @@ JOIN::prepare(Item ***rref_pointer_array,
}
if (flag == 3)
{
- my_error(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,MYF(0));
+ my_message(ER_MIX_OF_GROUP_FUNC_AND_FIELDS,
+ ER(ER_MIX_OF_GROUP_FUNC_AND_FIELDS), MYF(0));
DBUG_RETURN(-1);
}
}
TABLE_LIST *table_ptr;
- for (table_ptr= tables_list; table_ptr; table_ptr= table_ptr->next_local)
+ for (table_ptr= select_lex->leaf_tables;
+ table_ptr;
+ table_ptr= table_ptr->next_leaf)
tables++;
}
{
@@ -400,21 +412,22 @@ JOIN::prepare(Item ***rref_pointer_array,
{
if (!test_if_subpart(procedure->group,group_list))
{ /* purecov: inspected */
- my_message(0,"Can't handle procedures with differents groups yet",
- MYF(0)); /* purecov: inspected */
+ my_message(ER_DIFF_GROUPS_PROC, ER(ER_DIFF_GROUPS_PROC),
+ MYF(0)); /* purecov: inspected */
goto err; /* purecov: inspected */
}
}
#ifdef NOT_NEEDED
else if (!group_list && procedure->flags & PROC_GROUP)
{
- my_message(0,"Select must have a group with this procedure",MYF(0));
+ my_message(ER_NO_GROUP_FOR_PROC, MYF(0));
goto err;
}
#endif
if (order && (procedure->flags & PROC_NO_SORT))
{ /* purecov: inspected */
- my_message(0,"Can't use order with this procedure",MYF(0)); /* purecov: inspected */
+ my_message(ER_ORDER_WITH_PROC, ER(ER_ORDER_WITH_PROC),
+ MYF(0)); /* purecov: inspected */
goto err; /* purecov: inspected */
}
}
@@ -579,7 +592,7 @@ JOIN::optimize()
opt_sum_query() returns -1 if no rows match to the WHERE conditions,
or 1 if all items were resolved, or 0, or an error number HA_ERR_...
*/
- if ((res=opt_sum_query(tables_list, all_fields, conds)))
+ if ((res=opt_sum_query(select_lex->leaf_tables, all_fields, conds)))
{
if (res > 1)
{
@@ -605,11 +618,11 @@ JOIN::optimize()
DBUG_RETURN(0);
}
error= -1; // Error is sent to client
- sort_by_table= get_sort_by_table(order, group_list, tables_list);
+ sort_by_table= get_sort_by_table(order, group_list, select_lex->leaf_tables);
/* Calculate how to do the join */
thd->proc_info= "statistics";
- if (make_join_statistics(this, tables_list, conds, &keyuse) ||
+ if (make_join_statistics(this, select_lex->leaf_tables, conds, &keyuse) ||
thd->is_fatal_error)
{
DBUG_PRINT("error",("Error: make_join_statistics() failed"));
@@ -990,13 +1003,15 @@ JOIN::optimize()
if (create_sort_index(thd, this, group_list,
HA_POS_ERROR, HA_POS_ERROR) ||
alloc_group_fields(this, group_list) ||
- make_sum_func_list(all_fields, fields_list, 1))
+ make_sum_func_list(all_fields, fields_list, 1) ||
+ setup_sum_funcs(thd, sum_funcs))
DBUG_RETURN(1);
group_list=0;
}
else
{
- if (make_sum_func_list(all_fields, fields_list, 0))
+ if (make_sum_func_list(all_fields, fields_list, 0) ||
+ setup_sum_funcs(thd, sum_funcs))
DBUG_RETURN(1);
if (!group_list && ! exec_tmp_table1->distinct && order && simple_order)
{
@@ -1035,7 +1050,7 @@ JOIN::optimize()
}
}
- if (select_lex->master_unit()->uncacheable)
+ if (thd->lex->subqueries)
{
if (!(tmp_join= (JOIN*)thd->alloc(sizeof(JOIN))))
DBUG_RETURN(-1);
@@ -1069,7 +1084,8 @@ JOIN::reinit()
if (tables_list)
{
tables_list->setup_is_done= 0;
- if (setup_tables(thd, tables_list, &conds))
+ if (setup_tables(thd, tables_list, &conds, &select_lex->leaf_tables,
+ TRUE, FALSE))
DBUG_RETURN(1);
}
@@ -1174,7 +1190,7 @@ JOIN::exec()
if (zero_result_cause)
{
- (void) return_zero_rows(this, result, tables_list, fields_list,
+ (void) return_zero_rows(this, result, select_lex->leaf_tables, fields_list,
send_row_on_empty_set(),
select_options,
zero_result_cause,
@@ -1218,6 +1234,12 @@ JOIN::exec()
List<Item> *curr_fields_list= &fields_list;
TABLE *curr_tmp_table= 0;
+ if ((curr_join->select_lex->options & OPTION_SCHEMA_TABLE) &&
+ get_schema_tables_result(curr_join))
+ {
+ DBUG_VOID_RETURN;
+ }
+
/* Create a tmp table if distinct or if the sort is too complicated */
if (need_tmp)
{
@@ -1227,7 +1249,7 @@ JOIN::exec()
/* Copy data to the temporary table */
thd->proc_info= "Copying to tmp table";
-
+ DBUG_PRINT("info", ("%s", thd->proc_info));
if ((tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table, 0)))
{
error= tmp_error;
@@ -1355,6 +1377,7 @@ JOIN::exec()
}
thd->proc_info="Copying to group table";
+ DBUG_PRINT("info", ("%s", thd->proc_info));
tmp_error= -1;
if (curr_join != this)
{
@@ -1372,6 +1395,7 @@ JOIN::exec()
}
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
1, TRUE) ||
+ setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
(tmp_error= do_select(curr_join, (List<Item> *) 0, curr_tmp_table,
0)))
{
@@ -1459,7 +1483,9 @@ JOIN::exec()
set_items_ref_array(items3);
if (curr_join->make_sum_func_list(*curr_all_fields, *curr_fields_list,
- 1, TRUE) || thd->is_fatal_error)
+ 1, TRUE) ||
+ setup_sum_funcs(curr_join->thd, curr_join->sum_funcs) ||
+ thd->is_fatal_error)
DBUG_VOID_RETURN;
}
if (curr_join->group_list || curr_join->order)
@@ -1590,6 +1616,7 @@ JOIN::exec()
else
{
thd->proc_info="Sending data";
+ DBUG_PRINT("info", ("%s", thd->proc_info));
error= do_select(curr_join, curr_fields_list, NULL, procedure);
thd->limit_found_rows= curr_join->send_records;
thd->examined_row_count= curr_join->examined_rows;
@@ -1652,9 +1679,13 @@ Cursor::init_from_thd(THD *thd)
/*
We need to save and reset thd->mem_root, otherwise it'll be freed
later in mysql_parse.
+
+ We can't just change the thd->mem_root here as we want to keep the things
+ that is already allocated in thd->mem_root for Cursor::fetch()
*/
- mem_root= thd->mem_root;
- init_sql_alloc(&thd->mem_root,
+ main_mem_root= *thd->mem_root;
+ /* Allocate new memory root for thd */
+ init_sql_alloc(thd->mem_root,
thd->variables.query_alloc_block_size,
thd->variables.query_prealloc_size);
@@ -1668,7 +1699,7 @@ Cursor::init_from_thd(THD *thd)
open_tables= thd->open_tables;
lock= thd->lock;
query_id= thd->query_id;
- free_list= thd->free_list;
+ free_list= thd->free_list;
reset_thd(thd);
/*
XXX: thd->locked_tables is not changed.
@@ -1683,8 +1714,6 @@ Cursor::init_from_thd(THD *thd)
void
Cursor::init_thd(THD *thd)
{
- thd->mem_root= mem_root;
-
DBUG_ASSERT(thd->derived_tables == 0);
thd->derived_tables= derived_tables;
@@ -1694,7 +1723,6 @@ Cursor::init_thd(THD *thd)
DBUG_ASSERT(thd->lock== 0);
thd->lock= lock;
thd->query_id= query_id;
- thd->free_list= free_list;
}
@@ -1772,13 +1800,15 @@ int
Cursor::fetch(ulong num_rows)
{
THD *thd= join->thd;
- JOIN_TAB *join_tab= join->join_tab + join->const_tables;;
+ JOIN_TAB *join_tab= join->join_tab + join->const_tables;
COND *on_expr= *join_tab->on_expr_ref;
COND *select_cond= join_tab->select_cond;
READ_RECORD *info= &join_tab->read_record;
-
int error= 0;
+ /* save references to memory, allocated during fetch */
+ thd->set_n_backup_item_arena(this, &thd->stmt_backup);
+
join->fetch_limit+= num_rows;
/*
@@ -1794,7 +1824,7 @@ Cursor::fetch(ulong num_rows)
if (thd->killed) /* Aborted by user */
{
- my_error(ER_SERVER_SHUTDOWN,MYF(0));
+ my_message(ER_SERVER_SHUTDOWN, ER(ER_SERVER_SHUTDOWN), MYF(0));
return -1;
}
@@ -1843,53 +1873,36 @@ Cursor::fetch(ulong num_rows)
if (thd->net.report_error)
error= -1;
- switch (error) {
+ if (error == -3) /* LIMIT clause worked */
+ error= 0;
+
+#ifdef USING_TRANSACTIONS
+ ha_release_temporary_latches(thd);
+#endif
+
+ thd->restore_backup_item_arena(this, &thd->stmt_backup);
+ if (error == -4)
+ {
/* Fetch limit worked, possibly more rows are there */
- case -4:
- if (thd->transaction.all.innobase_tid)
- ha_release_temporary_latches(thd);
thd->server_status|= SERVER_STATUS_CURSOR_EXISTS;
::send_eof(thd);
thd->server_status&= ~SERVER_STATUS_CURSOR_EXISTS;
- /* save references to memory, allocated during fetch */
- mem_root= thd->mem_root;
- free_list= thd->free_list;
- break;
- /* Limit clause worked: this is the same as 'no more rows' */
- case -3: /* LIMIT clause worked */
- error= 0;
- /* fallthrough */
- case 0: /* No more rows */
- if (thd->transaction.all.innobase_tid)
- ha_release_temporary_latches(thd);
- close();
- thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
- ::send_eof(thd);
- thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
- join= 0;
- unit= 0;
- free_items(thd->free_list);
- thd->free_list= free_list= 0;
- /*
- Must be last, as some memory might be allocated for free purposes,
- like in free_tmp_table() (TODO: fix this issue)
- */
- mem_root= thd->mem_root;
- free_root(&mem_root, MYF(0));
- break;
- default:
+ }
+ else
+ {
close();
- join= 0;
- unit= 0;
- free_items(thd->free_list);
- thd->free_list= free_list= 0;
- /*
- Must be last, as some memory might be allocated for free purposes,
- like in free_tmp_table() (TODO: fix this issue)
- */
- mem_root= thd->mem_root;
- free_root(&mem_root, MYF(0));
- break;
+ if (error == 0)
+ {
+ thd->server_status|= SERVER_STATUS_LAST_ROW_SENT;
+ ::send_eof(thd);
+ thd->server_status&= ~SERVER_STATUS_LAST_ROW_SENT;
+ }
+ else
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
+ /* free cursor memory */
+ free_items(free_list);
+ free_list= 0;
+ free_root(&main_mem_root, MYF(0));
}
return error;
}
@@ -1899,6 +1912,8 @@ void
Cursor::close()
{
THD *thd= join->thd;
+ DBUG_ENTER("Cursor::close");
+
join->join_free(0);
if (unit)
{
@@ -1927,6 +1942,9 @@ Cursor::close()
thd->derived_tables= tmp_derived_tables;
thd->lock= tmp_lock;
}
+ join= 0;
+ unit= 0;
+ DBUG_VOID_RETURN;
}
@@ -1939,13 +1957,13 @@ Cursor::~Cursor()
Must be last, as some memory might be allocated for free purposes,
like in free_tmp_table() (TODO: fix this issue)
*/
- free_root(&mem_root, MYF(0));
+ free_root(&main_mem_root, MYF(0));
}
/*********************************************************************/
-int
+bool
mysql_select(THD *thd, Item ***rref_pointer_array,
TABLE_LIST *tables, uint wild_num, List<Item> &fields,
COND *conds, uint og_num, ORDER *order, ORDER *group,
@@ -1953,7 +1971,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
select_result *result, SELECT_LEX_UNIT *unit,
SELECT_LEX *select_lex)
{
- int err;
+ bool err;
bool free_join= 1;
DBUG_ENTER("mysql_select");
@@ -1961,7 +1979,10 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
if (select_lex->join != 0)
{
join= select_lex->join;
- // is it single SELECT in derived table, called in derived table creation
+ /*
+ is it single SELECT in derived table, called in derived table
+ creation
+ */
if (select_lex->linkage != DERIVED_TABLE_TYPE ||
(select_options & SELECT_DESCRIBE))
{
@@ -1970,7 +1991,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
//here is EXPLAIN of subselect or derived table
if (join->change_result(result))
{
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
else
@@ -1989,7 +2010,7 @@ mysql_select(THD *thd, Item ***rref_pointer_array,
else
{
if (!(join= new JOIN(thd, fields, select_options, result)))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
thd->proc_info="init";
thd->used_tables=0; // Updated by setup_fields
if (join->prepare(rref_pointer_array, tables, wild_num,
@@ -2037,10 +2058,8 @@ err:
{
thd->proc_info="end";
err= join->cleanup();
- if (thd->net.report_error)
- err= -1;
delete join;
- DBUG_RETURN(err);
+ DBUG_RETURN(err || thd->net.report_error);
}
DBUG_RETURN(join->error);
}
@@ -2083,7 +2102,7 @@ static ha_rows get_quick_record_count(THD *thd, SQL_SELECT *select,
*/
static bool
-make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
+make_join_statistics(JOIN *join, TABLE_LIST *tables, COND *conds,
DYNAMIC_ARRAY *keyuse_array)
{
int error;
@@ -2113,7 +2132,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
for (s= stat, i= 0;
tables;
- s++, tables= tables->next_local, i++)
+ s++, tables= tables->next_leaf, i++)
{
TABLE_LIST *embedding= tables->embedding;
stat_vector[i]=s;
@@ -2134,6 +2153,8 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
s->dependent= tables->dep_tables;
s->key_dependent= 0;
+ if (tables->schema_table)
+ table->file->records= 2;
s->on_expr_ref= &tables->on_expr;
if (*s->on_expr_ref)
@@ -2197,7 +2218,7 @@ make_join_statistics(JOIN *join,TABLE_LIST *tables,COND *conds,
if (s->dependent & s->table->map)
{
join->tables=0; // Don't use join->table
- my_error(ER_WRONG_OUTER_JOIN,MYF(0));
+ my_message(ER_WRONG_OUTER_JOIN, ER(ER_WRONG_OUTER_JOIN), MYF(0));
DBUG_RETURN(1);
}
s->key_dependent= s->dependent;
@@ -2618,11 +2639,7 @@ add_key_field(KEY_FIELD **key_fields, uint and_level, COND *cond,
bool is_const=1;
for (uint i=0; i<num_values; i++)
- /*
- TODO: This looks like a bug. It should be
- is_const&= (value[i])->const_item();
- */
- is_const&= (*value)->const_item();
+ is_const&= value[i]->const_item();
if (is_const)
stat[0].const_keys.merge(possible_keys);
/*
@@ -2941,14 +2958,14 @@ add_ft_keys(DYNAMIC_ARRAY *keyuse_array,
Item_func *arg0=(Item_func *)(func->arguments()[0]),
*arg1=(Item_func *)(func->arguments()[1]);
if (arg1->const_item() &&
- ((functype == Item_func::GE_FUNC && arg1->val()> 0) ||
- (functype == Item_func::GT_FUNC && arg1->val()>=0)) &&
+ ((functype == Item_func::GE_FUNC && arg1->val_real() > 0) ||
+ (functype == Item_func::GT_FUNC && arg1->val_real() >=0)) &&
arg0->type() == Item::FUNC_ITEM &&
arg0->functype() == Item_func::FT_FUNC)
cond_func=(Item_func_match *) arg0;
else if (arg0->const_item() &&
- ((functype == Item_func::LE_FUNC && arg0->val()> 0) ||
- (functype == Item_func::LT_FUNC && arg0->val()>=0)) &&
+ ((functype == Item_func::LE_FUNC && arg0->val_real() > 0) ||
+ (functype == Item_func::LT_FUNC && arg0->val_real() >=0)) &&
arg1->type() == Item::FUNC_ITEM &&
arg1->functype() == Item_func::FT_FUNC)
cond_func=(Item_func_match *) arg1;
@@ -3452,7 +3469,7 @@ best_access_path(JOIN *join,
{
/*
Assume that the first key part matches 1% of the file
- and that the hole key matches 10 (duplicates) or 1
+ and that the whole key matches 10 (duplicates) or 1
(unique) records.
Assume also that more key matches proportionally more
records
@@ -3460,7 +3477,7 @@ best_access_path(JOIN *join,
records = (x * (b-a) + a*c-b)/(c-1)
b = records matched by whole key
- a = records matched by first key part (10% of all records?)
+ a = records matched by first key part (1% of all records?)
c = number of key parts in key
x = used key parts (1 <= x <= c)
*/
@@ -3476,9 +3493,12 @@ best_access_path(JOIN *join,
else
{
double a=s->records*0.01;
- tmp = (max_key_part * (rec_per_key - a) +
- a*keyinfo->key_parts - rec_per_key)/
- (keyinfo->key_parts-1);
+ if (keyinfo->key_parts > 1)
+ tmp= (max_key_part * (rec_per_key - a) +
+ a*keyinfo->key_parts - rec_per_key)/
+ (keyinfo->key_parts-1);
+ else
+ tmp= a;
set_if_bigger(tmp,1.0);
}
records = (ulong) tmp;
@@ -4409,7 +4429,7 @@ find_best(JOIN *join,table_map rest_tables,uint idx,double record_count,
{
/*
Assume that the first key part matches 1% of the file
- and that the hole key matches 10 (duplicates) or 1
+ and that the whole key matches 10 (duplicates) or 1
(unique) records.
Assume also that more key matches proportionally more
records
@@ -4703,11 +4723,12 @@ get_best_combination(JOIN *join)
KEYUSE *keyuse;
uint table_count;
THD *thd=join->thd;
+ DBUG_ENTER("get_best_combination");
table_count=join->tables;
if (!(join->join_tab=join_tab=
(JOIN_TAB*) thd->alloc(sizeof(JOIN_TAB)*table_count)))
- return TRUE;
+ DBUG_RETURN(TRUE);
join->full_join=0;
@@ -4721,6 +4742,7 @@ get_best_combination(JOIN *join)
form->reginfo.join_tab=j;
if (!*j->on_expr_ref)
form->reginfo.not_exists_optimize=0; // Only with LEFT JOIN
+ DBUG_PRINT("info",("type: %d", j->type));
if (j->type == JT_CONST)
continue; // Handled in make_join_stat..
@@ -4736,13 +4758,13 @@ get_best_combination(JOIN *join)
join->full_join=1;
}
else if (create_ref_for_key(join, j, keyuse, used_tables))
- return TRUE; // Something went wrong
+ DBUG_RETURN(TRUE); // Something went wrong
}
for (i=0 ; i < table_count ; i++)
join->map2table[join->join_tab[i].table->tablenr]=join->join_tab+i;
update_depend_map(join);
- return 0;
+ DBUG_RETURN(0);
}
@@ -4755,6 +4777,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
uint keyparts,length,key;
TABLE *table;
KEY *keyinfo;
+ DBUG_ENTER("create_ref_for_key");
/* Use best key from find_best */
table=j->table;
@@ -4804,7 +4827,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
(keyparts+1)))) ||
!(j->ref.items= (Item**) thd->alloc(sizeof(Item*)*keyparts)))
{
- return TRUE;
+ DBUG_RETURN(TRUE);
}
j->ref.key_buff2=j->ref.key_buff+ALIGN_SIZE(length);
j->ref.key_err=1;
@@ -4817,7 +4840,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
{
j->ref.items[0]=((Item_func*)(keyuse->val))->key_item();
if (keyuse->used_tables)
- return TRUE; // not supported yet. SerG
+ DBUG_RETURN(TRUE); // not supported yet. SerG
j->type=JT_FT;
}
@@ -4841,7 +4864,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
maybe_null ? (char*) key_buff : 0,
keyinfo->key_part[i].length, keyuse->val);
if (thd->is_fatal_error)
- return TRUE;
+ DBUG_RETURN(TRUE);
tmp.copy();
}
else
@@ -4861,7 +4884,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
} /* not ftkey */
*ref_key=0; // end_marker
if (j->type == JT_FT)
- return 0;
+ DBUG_RETURN(0);
if (j->type == JT_CONST)
j->table->const_table= 1;
else if (((keyinfo->flags & (HA_NOSAME | HA_NULL_PART_KEY |
@@ -4885,7 +4908,7 @@ static bool create_ref_for_key(JOIN *join, JOIN_TAB *j, KEYUSE *org_keyuse,
}
else
j->type=JT_EQ_REF;
- return 0;
+ DBUG_RETURN(0);
}
@@ -4948,10 +4971,11 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
{
TABLE **tableptr;
JOIN_TAB *join_tab;
+ DBUG_ENTER("make_simple_join");
if (!(tableptr=(TABLE**) join->thd->alloc(sizeof(TABLE*))) ||
!(join_tab=(JOIN_TAB*) join->thd->alloc(sizeof(JOIN_TAB))))
- return TRUE;
+ DBUG_RETURN(TRUE);
join->join_tab=join_tab;
join->table=tableptr; tableptr[0]=tmp_table;
join->tables=1;
@@ -4981,10 +5005,11 @@ make_simple_join(JOIN *join,TABLE *tmp_table)
join_tab->not_used_in_distinct=0;
join_tab->read_first_record= join_init_read_record;
join_tab->join=join;
+ join_tab->ref.key_parts= 0;
bzero((char*) &join_tab->read_record,sizeof(join_tab->read_record));
tmp_table->status=0;
tmp_table->null_row=0;
- return FALSE;
+ DBUG_RETURN(FALSE);
}
@@ -5018,7 +5043,7 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
{
tmp= new Item_func_trig_cond(tmp, &tab->found);
}
- if (!tmp)
+ if (tmp)
tmp->quick_fix_field();
return tmp;
}
@@ -5070,6 +5095,7 @@ add_found_match_trig_cond(JOIN_TAB *tab, COND *cond, JOIN_TAB *root_tab)
static void
make_outerjoin_info(JOIN *join)
{
+ DBUG_ENTER("make_outerjoin_info");
for (uint i=join->const_tables ; i < join->tables ; i++)
{
JOIN_TAB *tab=join->join_tab+i;
@@ -5113,6 +5139,7 @@ make_outerjoin_info(JOIN *join)
nested_join->first_nested->last_inner= tab;
}
}
+ DBUG_VOID_RETURN;
}
@@ -5215,7 +5242,9 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
in the ON part of an OUTER JOIN. In this case we want the code
below to check if we should use 'quick' instead.
*/
+ DBUG_PRINT("info", ("Item_int"));
tmp= new Item_int((longlong) 1,1); // Always true
+ DBUG_PRINT("info", ("Item_int 0x%lx", (ulong)tmp));
}
}
@@ -5292,8 +5321,17 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
/* Join with outer join condition */
COND *orig_cond=sel->cond;
sel->cond= and_conds(sel->cond, *tab->on_expr_ref);
+
+ /*
+ We can't call sel->cond->fix_fields,
+ as it will break tab->on_expr if it's AND condition
+ (fix_fields currently removes extra AND/OR levels).
+ Yet attributes of the just built condition are not needed.
+ Thus we call sel->cond->quick_fix_field for safety.
+ */
if (sel->cond && !sel->cond->fixed)
- sel->cond->fix_fields(join->thd, 0, &sel->cond);
+ sel->cond->quick_fix_field();
+
if (sel->test_quick_select(join->thd, tab->keys,
used_tables & ~ current_map,
(join->select_options &
@@ -5395,13 +5433,18 @@ make_join_select(JOIN *join,SQL_SELECT *select,COND *cond)
Now add the guard turning the predicate off for
the null complemented row.
*/
+ DBUG_PRINT("info", ("Item_func_trig_cond"));
tmp= new Item_func_trig_cond(tmp,
&first_inner_tab->not_null_compl);
+ DBUG_PRINT("info", ("Item_func_trig_cond 0x%lx", (ulong) tmp));
if (tmp)
tmp->quick_fix_field();
/* Add the predicate to other pushed down predicates */
+ DBUG_PRINT("info", ("Item_cond_and"));
cond_tab->select_cond= !cond_tab->select_cond ? tmp :
new Item_cond_and(cond_tab->select_cond,tmp);
+ DBUG_PRINT("info", ("Item_cond_and 0x%lx",
+ (ulong)cond_tab->select_cond));
if (!cond_tab->select_cond)
DBUG_RETURN(1);
cond_tab->select_cond->quick_fix_field();
@@ -5610,7 +5653,8 @@ bool error_if_full_join(JOIN *join)
{
if (tab->type == JT_ALL && (!tab->select || !tab->select->quick))
{
- my_error(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,MYF(0));
+ my_message(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE,
+ ER(ER_UPDATE_WITHOUT_KEY_IN_SAFE_MODE), MYF(0));
return(1);
}
}
@@ -5668,7 +5712,9 @@ JOIN::join_free(bool full)
JOIN_TAB *tab,*end;
DBUG_ENTER("JOIN::join_free");
- full= full || !select_lex->uncacheable;
+ full= full || (!select_lex->uncacheable &&
+ !thd->lex->subqueries &&
+ !thd->lex->describe); // do not cleanup too early on EXPLAIN
if (table)
{
@@ -5697,6 +5743,7 @@ JOIN::join_free(bool full)
for (tab= join_tab, end= tab+tables; tab != end; tab++)
tab->cleanup();
table= 0;
+ tables= 0;
}
else
{
@@ -5953,7 +6000,7 @@ return_zero_rows(JOIN *join, select_result *result,TABLE_LIST *tables,
if (send_row)
{
- for (TABLE_LIST *table= tables; table; table= table->next_local)
+ for (TABLE_LIST *table= tables; table; table= table->next_leaf)
mark_as_null_row(table->table); // All fields are NULL
if (having && having->val_int() == 0)
send_row=0;
@@ -5994,9 +6041,13 @@ static void clear_tables(JOIN *join)
class COND_CMP :public ilink {
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
static void operator delete(void *ptr __attribute__((unused)),
- size_t size __attribute__((unused))) {} /*lint -e715 */
+ size_t size __attribute__((unused)))
+ { TRASH(ptr, size); }
Item *and_level;
Item_func *cmp_func;
@@ -6641,10 +6692,7 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
List<Item> eq_list;
Item_func_eq *eq_item= 0;
if (((Item *) item_equal)->const_item() && !item_equal->val_int())
- {
- cond= new Item_int((char*) "FALSE",0,1);
- return cond;
- }
+ return new Item_int((longlong) 0,1);
Item *item_const= item_equal->get_const();
Item_equal_iterator it(*item_equal);
Item *head;
@@ -6687,9 +6735,14 @@ static Item *eliminate_item_equal(COND *cond, COND_EQUAL *upper_levels,
}
if (!cond && !eq_list.head())
+ {
+ if (!eq_item)
+ return new Item_int((longlong) 1,1);
return eq_item;
+ }
- eq_list.push_back(eq_item);
+ if (eq_item)
+ eq_list.push_back(eq_item);
if (!cond)
cond= new Item_cond_and(eq_list);
else
@@ -7486,11 +7539,12 @@ static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
Field *new_field;
if (convert_blob_length && org_field->flags & BLOB_FLAG)
- new_field= new Field_varstring(convert_blob_length, org_field->maybe_null(),
+ new_field= new Field_varstring(convert_blob_length,
+ org_field->maybe_null(),
org_field->field_name, table,
org_field->charset());
else
- new_field= org_field->new_field(&thd->mem_root, table);
+ new_field= org_field->new_field(thd->mem_root, table);
if (new_field)
{
if (modify_item)
@@ -7499,7 +7553,8 @@ static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
new_field->field_name= item->name;
if (org_field->maybe_null())
new_field->flags&= ~NOT_NULL_FLAG; // Because of outer join
- if (org_field->type() == FIELD_TYPE_VAR_STRING)
+ if (org_field->type() == MYSQL_TYPE_VAR_STRING ||
+ org_field->type() == MYSQL_TYPE_VARCHAR)
table->db_create_options|= HA_OPTION_PACK_RECORD;
}
return new_field;
@@ -7529,7 +7584,8 @@ static Field* create_tmp_field_from_field(THD *thd, Field* org_field,
0 on error
new_created field
*/
-static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
+
+static Field *create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
Item ***copy_func, bool modify_item,
uint convert_blob_length)
{
@@ -7547,19 +7603,12 @@ static Field* create_tmp_field_from_item(THD *thd, Item *item, TABLE *table,
item->name, table, item->unsigned_flag);
break;
case STRING_RESULT:
- if (item->max_length > 255)
- {
- if (convert_blob_length)
- new_field= new Field_varstring(convert_blob_length, maybe_null,
- item->name, table,
- item->collation.collation);
- else
- new_field= new Field_blob(item->max_length, maybe_null, item->name,
- table, item->collation.collation);
- }
+ if (item->max_length > 255 && convert_blob_length)
+ new_field= new Field_varstring(convert_blob_length, maybe_null,
+ item->name, table,
+ item->collation.collation);
else
- new_field= new Field_string(item->max_length, maybe_null, item->name,
- table, item->collation.collation);
+ new_field= item->make_string_field(table);
break;
case ROW_RESULT:
default:
@@ -7640,18 +7689,11 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
return new Field_longlong(item_sum->max_length,maybe_null,
item->name,table,item->unsigned_flag);
case STRING_RESULT:
- if (item_sum->max_length > 255)
- {
- if (convert_blob_length)
- return new Field_varstring(convert_blob_length, maybe_null,
- item->name, table,
- item->collation.collation);
- else
- return new Field_blob(item_sum->max_length, maybe_null, item->name,
- table, item->collation.collation);
- }
- return new Field_string(item_sum->max_length,maybe_null,
- item->name,table,item->collation.collation);
+ if (item_sum->max_length > 255 && convert_blob_length)
+ return new Field_varstring(convert_blob_length, maybe_null,
+ item->name, table,
+ item->collation.collation);
+ return item_sum->make_string_field(table);
case ROW_RESULT:
default:
// This case should never be choosen
@@ -7706,6 +7748,11 @@ Field *create_tmp_field(THD *thd, TABLE *table,Item *item, Item::Type type,
for send_fields
*/
+#define STRING_TOTAL_LENGTH_TO_PACK_ROWS 128
+#define AVG_STRING_LENGTH_TO_PACK_ROWS 64
+#define RATIO_TO_PACK_ROWS 2
+#define MIN_STRING_LENGTH_TO_PACK_ROWS 10
+
TABLE *
create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
ORDER *group, bool distinct, bool save_sum_fields,
@@ -7713,12 +7760,15 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
char *table_alias)
{
TABLE *table;
- uint i,field_count,reclength,null_count,null_pack_length,
- hidden_null_count, hidden_null_pack_length, hidden_field_count,
- blob_count,group_null_items;
- bool using_unique_constraint=0;
+ uint i,field_count,null_count,null_pack_length;
+ uint hidden_null_count, hidden_null_pack_length, hidden_field_count;
+ uint blob_count,group_null_items, string_count;
+ uint temp_pool_slot=MY_BIT_NONE;
+ ulong reclength, string_total_length;
+ bool using_unique_constraint= 0;
+ bool use_packed_rows= 0;
bool not_all_columns= !(select_options & TMP_TABLE_ALL_COLUMNS);
- char *tmpname,path[FN_REFLEN];
+ char *tmpname,path[FN_REFLEN], filename[FN_REFLEN];
byte *pos,*group_buff;
uchar *null_flags;
Field **reg_field, **from_field, **blob_field;
@@ -7727,8 +7777,6 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
KEY_PART_INFO *key_part_info;
Item **copy_func;
MI_COLUMNDEF *recinfo;
- uint temp_pool_slot=MY_BIT_NONE;
-
DBUG_ENTER("create_tmp_table");
DBUG_PRINT("enter",("distinct: %d save_sum_fields: %d rows_limit: %lu group: %d",
(int) distinct, (int) save_sum_fields,
@@ -7740,14 +7788,15 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
temp_pool_slot = bitmap_set_next(&temp_pool);
if (temp_pool_slot != MY_BIT_NONE) // we got a slot
- sprintf(path, "%s%s_%lx_%i", mysql_tmpdir, tmp_file_prefix,
- current_pid, temp_pool_slot);
+ sprintf(filename, "%s_%lx_%i", tmp_file_prefix,
+ current_pid, temp_pool_slot);
else // if we run out of slots or we are not using tempool
- sprintf(path,"%s%s%lx_%lx_%x",mysql_tmpdir,tmp_file_prefix,current_pid,
+ sprintf(filename,"%s%lx_%lx_%x",tmp_file_prefix,current_pid,
thd->thread_id, thd->tmp_table++);
if (lower_case_table_names)
my_casedn_str(files_charset_info, path);
+ sprintf(path, "%s%s", mysql_tmpdir, filename);
if (group)
{
@@ -7812,6 +7861,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
table->temp_pool_slot = temp_pool_slot;
table->copy_blobs= 1;
table->in_use= thd;
+ table->table_charset= param->table_charset;
table->keys_for_keyread.init();
table->keys_in_use.init();
table->read_only_keys.init();
@@ -7821,7 +7871,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
/* Calculate which type of fields we will store in the temporary table */
- reclength=blob_count=null_count=hidden_null_count=group_null_items=0;
+ reclength= string_total_length= 0;
+ blob_count= string_count= null_count= hidden_null_count= group_null_items= 0;
param->using_indirect_summary_function=0;
List_iterator_fast<Item> li(fields);
@@ -7868,6 +7919,12 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
*blob_field++= new_field;
blob_count++;
}
+ if (new_field->real_type() == MYSQL_TYPE_STRING ||
+ new_field->real_type() == MYSQL_TYPE_VARCHAR)
+ {
+ string_count++;
+ string_total_length+= new_field->pack_length();
+ }
thd->change_item_tree(argp, new Item_field(new_field));
if (!(new_field->flags & NOT_NULL_FLAG))
{
@@ -7961,6 +8018,12 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
reclength+=null_pack_length;
if (!reclength)
reclength=1; // Dummy select
+ /* Use packed rows if there is blobs or a lot of space to gain */
+ if (blob_count ||
+ string_total_length >= STRING_TOTAL_LENGTH_TO_PACK_ROWS &&
+ (reclength / string_total_length <= RATIO_TO_PACK_ROWS ||
+ string_total_length / string_count >= AVG_STRING_LENGTH_TO_PACK_ROWS))
+ use_packed_rows= 1;
table->fields=field_count;
table->reclength=reclength;
@@ -8035,10 +8098,9 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
recinfo->length=length;
if (field->flags & BLOB_FLAG)
recinfo->type= (int) FIELD_BLOB;
- else if (!field->zero_pack() &&
- (field->type() == FIELD_TYPE_STRING ||
- field->type() == FIELD_TYPE_VAR_STRING) &&
- length >= 10 && blob_count)
+ else if (use_packed_rows &&
+ field->real_type() == MYSQL_TYPE_STRING &&
+ length >= MIN_STRING_LENGTH_TO_PACK_ROWS)
recinfo->type=FIELD_SKIP_ENDSPACE;
else
recinfo->type=FIELD_NORMAL;
@@ -8077,6 +8139,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->key_length=0;
keyinfo->rec_per_key=0;
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
+ keyinfo->name= (char*) "group_key";
for (; group ; group=group->next,key_part_info++)
{
Field *field=(*group->item)->get_tmp_table_field();
@@ -8093,7 +8156,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
if (!using_unique_constraint)
{
group->buff=(char*) group_buff;
- if (!(group->field=field->new_field(&thd->mem_root,table)))
+ if (!(group->field=field->new_field(thd->mem_root,table)))
goto err; /* purecov: inspected */
if (maybe_null)
{
@@ -8112,6 +8175,8 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
}
else
group->field->move_field((char*) group_buff);
+ /* In GROUP BY 'a' and 'a ' are equal for VARCHAR fields */
+ key_part_info->key_part_flag|= HA_END_SPACE_ARE_EQUAL;
group_buff+= key_part_info->length;
}
keyinfo->key_length+= key_part_info->length;
@@ -8147,7 +8212,7 @@ create_tmp_table(THD *thd,TMP_TABLE_PARAM *param,List<Item> &fields,
keyinfo->key_part=key_part_info;
keyinfo->flags=HA_NOSAME | HA_NULL_ARE_EQUAL;
keyinfo->key_length=(uint16) reclength;
- keyinfo->name=(char*) "tmp";
+ keyinfo->name= (char*) "distinct_key";
keyinfo->algorithm= HA_KEY_ALG_UNDEF;
if (null_pack_length)
{
@@ -8282,12 +8347,10 @@ static bool create_myisam_tmp_table(TABLE *table,TMP_TABLE_PARAM *param,
}
else
{
- seg->type=
- ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
- HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT);
- if (!(field->flags & ZEROFILL_FLAG) &&
- (field->type() == FIELD_TYPE_STRING ||
- field->type() == FIELD_TYPE_VAR_STRING) &&
+ seg->type= ((keyinfo->key_part[i].key_type & FIELDFLAG_BINARY) ?
+ HA_KEYTYPE_BINARY : HA_KEYTYPE_TEXT);
+ /* Tell handler if it can do suffic space compression */
+ if (field->real_type() == MYSQL_TYPE_STRING &&
keyinfo->key_part[i].length > 4)
seg->flag|=HA_SPACE_PACK;
}
@@ -8793,6 +8856,7 @@ sub_select(JOIN *join,JOIN_TAB *join_tab,bool end_of_records)
join->thd->send_kill_message();
return -2; /* purecov: inspected */
}
+ DBUG_PRINT("info", ("select cond 0x%lx", (ulong)select_cond));
if (!select_cond || select_cond->val_int())
{
/*
@@ -9748,9 +9812,6 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
{
Item *item= *group->item;
item->save_org_in_field(group->field);
-#ifdef EMBEDDED_LIBRARY
- join->thd->net.last_errno= 0;
-#endif
/* Store in the used key if the field was 0 */
if (item->maybe_null)
group->buff[-1]=item->null_value ? 1 : 0;
@@ -9792,6 +9853,7 @@ end_update(JOIN *join, JOIN_TAB *join_tab __attribute__((unused)),
DBUG_RETURN(0);
}
+
/* Like end_update, but this is done with unique constraints instead of keys */
static int
@@ -9939,11 +10001,11 @@ static bool test_if_ref(Item_field *left_item,Item *right_item)
/*
We can remove binary fields and numerical fields except float,
as float comparison isn't 100 % secure
- We have to keep binary strings to be able to check for end spaces
+ We have to keep normal strings to be able to check for end spaces
*/
if (field->binary() &&
- field->real_type() != FIELD_TYPE_STRING &&
- field->real_type() != FIELD_TYPE_VAR_STRING &&
+ field->real_type() != MYSQL_TYPE_STRING &&
+ field->real_type() != MYSQL_TYPE_VARCHAR &&
(field->type() != FIELD_TYPE_FLOAT || field->decimals() == 0))
{
return !store_val_in_field(field,right_item);
@@ -10711,7 +10773,7 @@ static int remove_dup_with_compare(THD *thd, TABLE *table, Field **first_field,
}
if (copy_blobs(first_field))
{
- my_error(ER_OUTOFMEMORY,MYF(0));
+ my_message(ER_OUTOFMEMORY, ER(ER_OUTOFMEMORY), MYF(0));
error=0;
goto err;
}
@@ -11162,24 +11224,53 @@ cp_buffer_from_ref(TABLE_REF *ref)
*****************************************************************************/
/*
- Find order/group item in requested columns and change the item to point at
- it. If item doesn't exists, add it first in the field list
- Return 0 if ok.
+ Resolve an ORDER BY or GROUP BY column reference.
+
+ SYNOPSIS
+ find_order_in_list()
+ thd [in] Pointer to current thread structure
+ ref_pointer_array [in/out] All select, group and order by fields
+ tables [in] List of tables to search in (usually FROM clause)
+ order [in] Column reference to be resolved
+ fields [in] List of fields to search in (usually SELECT list)
+ all_fields [in/out] All select, group and order by fields
+ is_group_field [in] True if order is a GROUP field, false if
+ ORDER by field
+
+ DESCRIPTION
+ Given a column reference (represented by 'order') from a GROUP BY or ORDER
+ BY clause, find the actual column it represents. If the column being
+ resolved is from the GROUP BY clause, the procedure searches the SELECT
+ list 'fields' and the columns in the FROM list 'tables'. If 'order' is from
+ the ORDER BY clause, only the SELECT list is being searched.
+
+ If 'order' is resolved to an Item, then order->item is set to the found
+ Item. If there is no item for the found column (that is, it was resolved
+ into a table field), order->item is 'fixed' and is added to all_fields and
+ ref_pointer_array.
+
+ RETURN
+ 0 if OK
+ 1 if error occurred
*/
static int
-find_order_in_list(THD *thd, Item **ref_pointer_array,
- TABLE_LIST *tables,ORDER *order, List<Item> &fields,
- List<Item> &all_fields)
+find_order_in_list(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
+ ORDER *order, List<Item> &fields, List<Item> &all_fields,
+ bool is_group_field)
{
- Item *it= *order->item;
- if (it->type() == Item::INT_ITEM)
+ Item *order_item= *order->item; /* The item from the GROUP/ORDER caluse. */
+ Item::Type order_item_type;
+ Item **select_item; /* The corresponding item from the SELECT clause. */
+ Field *from_field; /* The corresponding field from the FROM clause. */
+
+ if (order_item->type() == Item::INT_ITEM)
{ /* Order by position */
- uint count= (uint) it->val_int();
+ uint count= (uint) order_item->val_int();
if (!count || count > fields.elements)
{
- my_printf_error(ER_BAD_FIELD_ERROR,ER(ER_BAD_FIELD_ERROR),
- MYF(0), it->full_name(), thd->where);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
+ order_item->full_name(), thd->where);
return 1;
}
order->item= ref_pointer_array + count - 1;
@@ -11188,47 +11279,78 @@ find_order_in_list(THD *thd, Item **ref_pointer_array,
order->counter_used= 1;
return 0;
}
+ /* Lookup the current GROUP/ORDER field in the SELECT clause. */
uint counter;
bool unaliased;
- Item **item= find_item_in_list(it, fields, &counter,
+ select_item= find_item_in_list(order_item, fields, &counter,
REPORT_EXCEPT_NOT_FOUND, &unaliased);
- if (!item)
- return 1;
+ if (!select_item)
+ return 1; /* Some error occured. */
+
- if (item != (Item **)not_found_item)
+ /* Check whether the resolved field is not ambiguos. */
+ if (select_item != not_found_item)
{
/*
If we have found field not by its alias in select list but by its
original field name, we should additionaly check if we have conflict
for this name (in case if we would perform lookup in all tables).
*/
- if (unaliased && !it->fixed && it->fix_fields(thd, tables, order->item))
+ if (unaliased && !order_item->fixed && order_item->fix_fields(thd, tables, order->item))
return 1;
- order->item= ref_pointer_array + counter;
- order->in_field_list=1;
- return 0;
+ /* Lookup the current GROUP field in the FROM clause. */
+ order_item_type= order_item->type();
+ if (is_group_field &&
+ order_item_type == Item::FIELD_ITEM || order_item_type == Item::REF_ITEM)
+ {
+ Item **view_ref= NULL;
+ from_field= find_field_in_tables(thd, (Item_ident*) order_item, tables,
+ view_ref, IGNORE_ERRORS, TRUE);
+ if(!from_field)
+ from_field= (Field*) not_found_field;
+ }
+ else
+ from_field= (Field*) not_found_field;
+
+ if (from_field == not_found_field ||
+ from_field && from_field != view_ref_found &&
+ (*select_item)->type() == Item::FIELD_ITEM &&
+ ((Item_field*) (*select_item))->field->eq(from_field))
+ /*
+ If there is no such field in the FROM clause, or it is the same field as
+ the one found in the SELECT clause, then use the Item created for the
+ SELECT field. As a result if there was a derived field that 'shadowed'
+ a table field with the same name, the table field will be chosen over
+ the derived field.
+ */
+ {
+ order->item= ref_pointer_array + counter;
+ order->in_field_list=1;
+ return 0;
+ }
}
order->in_field_list=0;
/*
- We check it->fixed because Item_func_group_concat can put
+ We check order_item->fixed because Item_func_group_concat can put
arguments for which fix_fields already was called.
'it' reassigned in if condition because fix_field can change it.
*/
- if (!it->fixed &&
- (it->fix_fields(thd, tables, order->item) ||
- (it= *order->item)->check_cols(1) ||
+ if (!order_item->fixed &&
+ (order_item->fix_fields(thd, tables, order->item) ||
+ (order_item= *order->item)->check_cols(1) ||
thd->is_fatal_error))
return 1; // Wrong field
uint el= all_fields.elements;
- all_fields.push_front(it); // Add new field to field list
- ref_pointer_array[el]= it;
+ all_fields.push_front(order_item); // Add new field to field list
+ ref_pointer_array[el]= order_item;
order->item= ref_pointer_array + el;
return 0;
}
+
/*
Change order to point at item in select list. If item isn't a number
and doesn't exits in the select list, add it the the field list.
@@ -11241,7 +11363,7 @@ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
for (; order; order=order->next)
{
if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
- all_fields))
+ all_fields, FALSE))
return 1;
}
return 0;
@@ -11255,7 +11377,7 @@ int setup_order(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
setup_group()
thd Thread handler
ref_pointer_array We store references to all fields that was not in
- 'fields' here.
+ 'fields' here.
fields All fields in the select part. Any item in 'order'
that is part of these list is replaced by a pointer
to this fields.
@@ -11293,13 +11415,12 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
for (; order; order=order->next)
{
if (find_order_in_list(thd, ref_pointer_array, tables, order, fields,
- all_fields))
+ all_fields, TRUE))
return 1;
(*order->item)->marker=1; /* Mark found */
if ((*order->item)->with_sum_func)
{
- my_printf_error(ER_WRONG_GROUP_FIELD, ER(ER_WRONG_GROUP_FIELD),MYF(0),
- (*order->item)->full_name());
+ my_error(ER_WRONG_GROUP_FIELD, MYF(0), (*order->item)->full_name());
return 1;
}
}
@@ -11314,9 +11435,7 @@ setup_group(THD *thd, Item **ref_pointer_array, TABLE_LIST *tables,
if (item->type() != Item::SUM_FUNC_ITEM && !item->marker &&
!item->const_item())
{
- my_printf_error(ER_WRONG_FIELD_WITH_GROUP,
- ER(ER_WRONG_FIELD_WITH_GROUP),
- MYF(0),item->full_name());
+ my_error(ER_WRONG_FIELD_WITH_GROUP, MYF(0), item->full_name());
return 1;
}
}
@@ -11504,7 +11623,7 @@ get_sort_by_table(ORDER *a,ORDER *b,TABLE_LIST *tables)
if (!map || (map & (RAND_TABLE_BIT | OUTER_REF_TABLE_BIT)))
DBUG_RETURN(0);
- for (; !(map & tables->table->map); tables= tables->next_local);
+ for (; !(map & tables->table->map); tables= tables->next_leaf);
if (map != tables->table->map)
DBUG_RETURN(0); // More than one table
DBUG_PRINT("exit",("sort by table: %d",tables->table->tablenr));
@@ -11691,7 +11810,7 @@ setup_copy_fields(THD *thd, TMP_TABLE_PARAM *param,
saved value
*/
Field *field= item->field;
- item->result_field=field->new_field(&thd->mem_root,field->table);
+ item->result_field=field->new_field(thd->mem_root,field->table);
char *tmp=(char*) sql_alloc(field->pack_length()+1);
if (!tmp)
goto err;
@@ -11810,9 +11929,6 @@ bool JOIN::alloc_func_list()
before_group_by Set to 1 if this is called before GROUP BY handling
recompute Set to TRUE if sum_funcs must be recomputed
- NOTES
- Calls ::setup() for all item_sum objects in field_list
-
RETURN
0 ok
1 error
@@ -11833,12 +11949,7 @@ bool JOIN::make_sum_func_list(List<Item> &field_list, List<Item> &send_fields,
while ((item=it++))
{
if (item->type() == Item::SUM_FUNC_ITEM && !item->const_item())
- {
*func++= (Item_sum*) item;
- /* let COUNT(DISTINCT) create the temporary table */
- if (((Item_sum*) item)->setup(thd))
- DBUG_RETURN(TRUE);
- }
}
if (before_group_by && rollup.state == ROLLUP::STATE_INITED)
{
@@ -11881,6 +11992,8 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
{
List_iterator_fast<Item> it(all_fields);
Item *item_field,*item;
+ DBUG_ENTER("change_to_use_tmp_fields");
+
res_selected_fields.empty();
res_all_fields.empty();
@@ -11904,8 +12017,8 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
else
item_field= (Item*) new Item_field(field);
if (!item_field)
- return TRUE; // Fatal error
- item_field->name= item->name; /*lint -e613 */
+ DBUG_RETURN(TRUE); // Fatal error
+ item_field->name= item->name;
#ifndef DBUG_OFF
if (_db_on_ && !item_field->name)
{
@@ -11929,7 +12042,7 @@ change_to_use_tmp_fields(THD *thd, Item **ref_pointer_array,
for (i= 0; i < border; i++)
itr++;
itr.sublist(res_selected_fields, elements);
- return FALSE;
+ DBUG_RETURN(FALSE);
}
@@ -11983,6 +12096,31 @@ change_refs_to_tmp_fields(THD *thd, Item **ref_pointer_array,
Code for calculating functions
******************************************************************************/
+
+/*
+ Call ::setup for all sum functions
+
+ SYNOPSIS
+ setup_sum_funcs()
+ thd thread handler
+ func_ptr sum function list
+
+ RETURN
+ FALSE ok
+ TRUE error
+*/
+
+static bool setup_sum_funcs(THD *thd, Item_sum **func_ptr)
+{
+ Item_sum *func;
+ DBUG_ENTER("setup_sum_funcs");
+ while ((func= *(func_ptr++)))
+ if (func->setup(thd))
+ DBUG_RETURN(TRUE);
+ DBUG_RETURN(FALSE);
+}
+
+
static void
init_tmptable_sum_functions(Item_sum **func_ptr)
{
@@ -12138,7 +12276,7 @@ bool JOIN::rollup_init()
return 1;
rollup.ref_pointer_arrays= (Item***) (rollup.fields + send_group_parts);
ref_array= (Item**) (rollup.ref_pointer_arrays+send_group_parts);
- rollup.item_null= new (&thd->mem_root) Item_null();
+ rollup.item_null= new (thd->mem_root) Item_null();
/*
Prepare space for field list for the different levels
@@ -12501,10 +12639,10 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
item_list.push_back(new Item_string(join_type_str[tab->type],
strlen(join_type_str[tab->type]),
cs));
- uint j;
/* Build "possible_keys" value and add it to item_list */
if (!tab->keys.is_clear_all())
{
+ uint j;
for (j=0 ; j < table->keys ; j++)
{
if (tab->keys.is_set(j))
@@ -12654,10 +12792,10 @@ static void select_describe(JOIN *join, bool need_tmp_table, bool need_order,
}
-int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
+bool mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
{
DBUG_ENTER("mysql_explain_union");
- int res= 0;
+ bool res= 0;
SELECT_LEX *first= unit->first_select();
for (SELECT_LEX *sl= first;
@@ -12708,9 +12846,7 @@ int mysql_explain_union(THD *thd, SELECT_LEX_UNIT *unit, select_result *result)
first->options | thd->options | SELECT_DESCRIBE,
result, unit, first);
}
- if (res > 0 || thd->net.report_error)
- res= -1; // mysql_explain_select do not report error
- DBUG_RETURN(res);
+ DBUG_RETURN(res || thd->net.report_error);
}
@@ -12797,8 +12933,17 @@ void st_table_list::print(THD *thd, String *str)
{
append_identifier(thd, str, db, db_length);
str->append('.');
- append_identifier(thd, str, real_name, real_name_length);
- cmp_name= real_name;
+ if (schema_table)
+ {
+ append_identifier(thd, str, schema_table_name,
+ strlen(schema_table_name));
+ cmp_name= schema_table_name;
+ }
+ else
+ {
+ append_identifier(thd, str, real_name, real_name_length);
+ cmp_name= real_name;
+ }
}
if (my_strcasecmp(table_alias_charset, cmp_name, alias))
{
@@ -12921,17 +13066,17 @@ void st_select_lex::print(THD *thd, String *str)
res new select_result object
RETURN
- 0 - OK
- -1 - error
+ FALSE - OK
+ TRUE - error
*/
-int JOIN::change_result(select_result *res)
+bool JOIN::change_result(select_result *res)
{
DBUG_ENTER("JOIN::change_result");
result= res;
if (!procedure && result->prepare(fields_list, select_lex->master_unit()))
{
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
diff --git a/sql/sql_select.h b/sql/sql_select.h
index d489e911363..5e42fc0ee30 100644
--- a/sql/sql_select.h
+++ b/sql/sql_select.h
@@ -277,8 +277,6 @@ class JOIN :public Sql_alloc
hidden_group_fields= 0; /*safety*/
buffer_result= test(select_options & OPTION_BUFFER_RESULT) &&
!test(select_options & OPTION_FOUND_ROWS);
- all_fields= fields_arg;
- fields_list= fields_arg;
error= 0;
select= 0;
return_tab= 0;
@@ -288,6 +286,7 @@ class JOIN :public Sql_alloc
optimized= 0;
cond_equal= 0;
+ all_fields= fields_arg;
fields_list= fields_arg;
bzero((char*) &keyuse,sizeof(keyuse));
tmp_table_param.copy_field=0;
@@ -333,7 +332,7 @@ class JOIN :public Sql_alloc
return (do_send_rows && tmp_table_param.sum_func_count != 0 &&
!group_list);
}
- int change_result(select_result *result);
+ bool change_result(select_result *result);
};
@@ -426,7 +425,7 @@ class store_key :public Sql_alloc
field_arg->table, field_arg->charset());
else
{
- to_field=field_arg->new_field(&thd->mem_root,field_arg->table);
+ to_field=field_arg->new_field(thd->mem_root,field_arg->table);
if (to_field)
to_field->move_field(ptr, (uchar*) null, 1);
}
diff --git a/sql/sql_show.cc b/sql/sql_show.cc
index 28e9baa1c36..7acbe564f58 100644
--- a/sql/sql_show.cc
+++ b/sql/sql_show.cc
@@ -21,6 +21,7 @@
#include "sql_select.h" // For select_describe
#include "sql_acl.h"
#include "repl_failsafe.h"
+#include "sp_head.h"
#include <my_dir.h>
#ifdef HAVE_BERKELEY_DB
@@ -38,65 +39,16 @@ static TYPELIB grant_types = { sizeof(grant_names)/sizeof(char **),
#endif
static int
-store_create_info(THD *thd, TABLE *table, String *packet);
+store_create_info(THD *thd, TABLE_LIST *table_list, String *packet);
static int
view_store_create_info(THD *thd, TABLE_LIST *table, String *packet);
-/*
- Report list of databases
- A database is a directory in the mysql_data_home directory
-*/
-
-int
-mysqld_show_dbs(THD *thd,const char *wild)
-{
- Item_string *field=new Item_string("",0,thd->charset());
- List<Item> field_list;
- char *end;
- List<char> files;
- char *file_name;
- Protocol *protocol= thd->protocol;
- DBUG_ENTER("mysqld_show_dbs");
-
- field->name=(char*) thd->alloc(20+ (wild ? (uint) strlen(wild)+4: 0));
- field->max_length=NAME_LEN;
- end=strmov(field->name,"Database");
- if (wild && wild[0])
- strxmov(end," (",wild,")",NullS);
- field_list.push_back(field);
-
- if (protocol->send_fields(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
- if (mysql_find_files(thd,&files,NullS,mysql_data_home,wild,1))
- DBUG_RETURN(1);
- List_iterator_fast<char> it(files);
-
- while ((file_name=it++))
- {
-#ifndef NO_EMBEDDED_ACCESS_CHECKS
- if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
- acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) ||
- (grant_option && !check_grant_db(thd, file_name)))
-#endif
- {
- protocol->prepare_for_resend();
- protocol->store(file_name, system_charset_info);
- if (protocol->write())
- DBUG_RETURN(-1);
- }
- }
- send_eof(thd);
- DBUG_RETURN(0);
-}
-
-
/***************************************************************************
List all open tables in a database
***************************************************************************/
-int mysqld_show_open_tables(THD *thd,const char *wild)
+bool mysqld_show_open_tables(THD *thd,const char *wild)
{
List<Item> field_list;
OPEN_TABLE_LIST *open_list;
@@ -110,10 +62,10 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
if (!(open_list=list_open_tables(thd,wild)) && thd->is_fatal_error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
for (; open_list ; open_list=open_list->next)
{
@@ -124,83 +76,19 @@ int mysqld_show_open_tables(THD *thd,const char *wild)
protocol->store_tiny((longlong) open_list->locked);
if (protocol->write())
{
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
/***************************************************************************
-** List all tables in a database (fast version)
-** A table is a .frm file in the current databasedir
-***************************************************************************/
-
-int mysqld_show_tables(THD *thd, const char *db, const char *wild,
- bool show_type)
-{
- Item_string *field=new Item_string("",0,thd->charset());
- List<Item> field_list;
- char path[FN_LEN],*end;
- List<char> files;
- char *file_name;
- Protocol *protocol= thd->protocol;
- uint len;
- DBUG_ENTER("mysqld_show_tables");
-
- field->name=(char*) thd->alloc(20+(uint) strlen(db)+
- (wild ? (uint) strlen(wild)+4:0));
- end=strxmov(field->name,"Tables_in_",db,NullS);
- if (wild && wild[0])
- strxmov(end," (",wild,")",NullS);
- field->max_length=NAME_LEN;
- (void) my_snprintf(path, FN_LEN, "%s/%s", mysql_data_home, db);
- end= path + (len= unpack_dirname(path,path));
- len= FN_LEN - len;
- field_list.push_back(field);
- if (show_type)
- field_list.push_back(new Item_empty_string("Table_type", 10));
- if (protocol->send_fields(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
- if (mysql_find_files(thd,&files,db,path,wild,0))
- DBUG_RETURN(-1);
- List_iterator_fast<char> it(files);
- while ((file_name=it++))
- {
- protocol->prepare_for_resend();
- protocol->store(file_name, system_charset_info);
- if (show_type)
- {
- my_snprintf(end, len, "/%s%s", file_name, reg_ext);
- switch (mysql_frm_type(path))
- {
- case FRMTYPE_ERROR:
- protocol->store("ERROR", system_charset_info);
- break;
- case FRMTYPE_TABLE:
- protocol->store("BASE TABLE", system_charset_info);
- break;
- case FRMTYPE_VIEW:
- protocol->store("VIEW", system_charset_info);
- break;
- default:
- DBUG_ASSERT(0); // this should be impossible
- }
- }
- if (protocol->write())
- DBUG_RETURN(-1);
- }
- send_eof(thd);
- DBUG_RETURN(0);
-}
-
-/***************************************************************************
** List all table types supported
***************************************************************************/
-int mysqld_show_storage_engines(THD *thd)
+bool mysqld_show_storage_engines(THD *thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
@@ -212,7 +100,7 @@ int mysqld_show_storage_engines(THD *thd)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
const char *default_type_name=
ha_get_storage_engine((enum db_type)thd->variables.table_type);
@@ -230,10 +118,10 @@ int mysqld_show_storage_engines(THD *thd)
protocol->store(option_name, system_charset_info);
protocol->store(types->comment, system_charset_info);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -275,7 +163,7 @@ static struct show_privileges_st sys_privileges[]=
{NullS, NullS, NullS}
};
-int mysqld_show_privileges(THD *thd)
+bool mysqld_show_privileges(THD *thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
@@ -287,7 +175,7 @@ int mysqld_show_privileges(THD *thd)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
show_privileges_st *privilege= sys_privileges;
for (privilege= sys_privileges; privilege->privilege ; privilege++)
@@ -297,10 +185,10 @@ int mysqld_show_privileges(THD *thd)
protocol->store(privilege->context, system_charset_info);
protocol->store(privilege->comment, system_charset_info);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -340,7 +228,7 @@ static struct show_column_type_st sys_column_types[]=
"A very small integer"},
};
-int mysqld_show_column_types(THD *thd)
+bool mysqld_show_column_types(THD *thd)
{
List<Item> field_list;
Protocol *protocol= thd->protocol;
@@ -363,7 +251,7 @@ int mysqld_show_column_types(THD *thd)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
/* TODO: Change the loop to not use 'i' */
for (uint i=0; i < sizeof(sys_column_types)/sizeof(sys_column_types[0]); i++)
@@ -384,10 +272,10 @@ int mysqld_show_column_types(THD *thd)
protocol->store(sys_column_types[i].default_value, system_charset_info);
protocol->store(sys_column_types[i].comment, system_charset_info);
if (protocol->write())
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -483,215 +371,10 @@ mysql_find_files(THD *thd,List<char> *files, const char *db,const char *path,
/***************************************************************************
- Extended version of mysqld_show_tables
-***************************************************************************/
-
-int mysqld_extend_show_tables(THD *thd,const char *db,const char *wild)
-{
- Item *item;
- List<char> files;
- List<Item> field_list;
- char path[FN_LEN];
- char *file_name;
- TABLE *table;
- Protocol *protocol= thd->protocol;
- TIME time;
- int res;
- DBUG_ENTER("mysqld_extend_show_tables");
-
- (void) sprintf(path,"%s/%s",mysql_data_home,db);
- (void) unpack_dirname(path,path);
- field_list.push_back(item=new Item_empty_string("Name",NAME_LEN));
- field_list.push_back(item=new Item_empty_string("Engine",10));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Version", (longlong) 0, 21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("Row_format",10));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Rows",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Avg_row_length",(int32) 0,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Data_length",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Max_data_length",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Index_length",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Data_free",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Auto_increment",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_datetime("Create_time"));
- item->maybe_null=1;
- field_list.push_back(item=new Item_datetime("Update_time"));
- item->maybe_null=1;
- field_list.push_back(item=new Item_datetime("Check_time"));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("Collation",32));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Checksum",(longlong) 1,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("Create_options",255));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("Comment",80));
- item->maybe_null=1;
- if (protocol->send_fields(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
-
- if (mysql_find_files(thd,&files,db,path,wild,0))
- DBUG_RETURN(-1);
- List_iterator_fast<char> it(files);
- while ((file_name=it++))
- {
- TABLE_LIST table_list;
- bzero((char*) &table_list,sizeof(table_list));
- protocol->prepare_for_resend();
- protocol->store(file_name, system_charset_info);
- table_list.db=(char*) db;
- table_list.real_name= table_list.alias= file_name;
- table_list.select_lex= &thd->lex->select_lex;
- if (lower_case_table_names)
- my_casedn_str(files_charset_info, file_name);
- if ((res= open_and_lock_tables(thd, &table_list)))
- {
- for (uint i=2 ; i < field_list.elements ; i++)
- protocol->store_null();
- // Send error to Comment field if possible
- if (res < 0)
- {
- protocol->store(thd->net.last_error, system_charset_info);
- thd->clear_error();
- }
- else
- DBUG_RETURN(1);
- }
- else if (table_list.view)
- {
- for (uint i= 2; i < field_list.elements; i++)
- protocol->store_null();
- protocol->store("view", system_charset_info);
- }
- else
- {
- const char *str;
- handler *file= (table= table_list.table)->file;
- file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
- protocol->store(file->table_type(), system_charset_info);
- protocol->store((ulonglong) table->frm_version);
- str= ((table->db_options_in_use & HA_OPTION_COMPRESS_RECORD) ?
- "Compressed" :
- (table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
- "Dynamic" : "Fixed");
- protocol->store(str, system_charset_info);
- protocol->store((ulonglong) file->records);
- protocol->store((ulonglong) file->mean_rec_length);
- protocol->store((ulonglong) file->data_file_length);
- if (file->max_data_file_length)
- protocol->store((ulonglong) file->max_data_file_length);
- else
- protocol->store_null();
- protocol->store((ulonglong) file->index_file_length);
- protocol->store((ulonglong) file->delete_length);
- if (table->found_next_number_field)
- {
- table->next_number_field=table->found_next_number_field;
- table->next_number_field->reset();
- file->update_auto_increment();
- protocol->store(table->next_number_field->val_int());
- table->next_number_field=0;
- }
- else
- protocol->store_null();
- if (!file->create_time)
- protocol->store_null();
- else
- {
- thd->variables.time_zone->gmt_sec_to_TIME(&time, file->create_time);
- protocol->store(&time);
- }
- if (!file->update_time)
- protocol->store_null();
- else
- {
- thd->variables.time_zone->gmt_sec_to_TIME(&time, file->update_time);
- protocol->store(&time);
- }
- if (!file->check_time)
- protocol->store_null();
- else
- {
- thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
- protocol->store(&time);
- }
- str= (table->table_charset ? table->table_charset->name : "default");
- protocol->store(str, system_charset_info);
- if (file->table_flags() & HA_HAS_CHECKSUM)
- protocol->store((ulonglong)file->checksum());
- else
- protocol->store_null(); // Checksum
- {
- char option_buff[350],*ptr;
- ptr=option_buff;
- if (table->min_rows)
- {
- ptr=strmov(ptr," min_rows=");
- ptr=longlong10_to_str(table->min_rows,ptr,10);
- }
- if (table->max_rows)
- {
- ptr=strmov(ptr," max_rows=");
- ptr=longlong10_to_str(table->max_rows,ptr,10);
- }
- if (table->avg_row_length)
- {
- ptr=strmov(ptr," avg_row_length=");
- ptr=longlong10_to_str(table->avg_row_length,ptr,10);
- }
- if (table->db_create_options & HA_OPTION_PACK_KEYS)
- ptr=strmov(ptr," pack_keys=1");
- if (table->db_create_options & HA_OPTION_NO_PACK_KEYS)
- ptr=strmov(ptr," pack_keys=0");
- if (table->db_create_options & HA_OPTION_CHECKSUM)
- ptr=strmov(ptr," checksum=1");
- if (table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
- ptr=strmov(ptr," delay_key_write=1");
- if (table->row_type != ROW_TYPE_DEFAULT)
- ptr=strxmov(ptr, " row_format=", ha_row_type[(uint) table->row_type],
- NullS);
- if (file->raid_type)
- {
- char buff[100];
- sprintf(buff," raid_type=%s raid_chunks=%d raid_chunksize=%ld",
- my_raid_type(file->raid_type), file->raid_chunks, file->raid_chunksize/RAID_BLOCK_SIZE);
- ptr=strmov(ptr,buff);
- }
- protocol->store(option_buff+1,
- (ptr == option_buff ? 0 : (uint) (ptr-option_buff)-1)
- , system_charset_info);
- }
- {
- char *comment=table->file->update_table_comment(table->comment);
- protocol->store(comment, system_charset_info);
- if (comment != table->comment)
- my_free(comment,MYF(0));
- }
- }
- close_thread_tables(thd, 0);
- if (protocol->write())
- DBUG_RETURN(-1);
- }
- send_eof(thd);
- DBUG_RETURN(0);
-}
-
-
-/***************************************************************************
** List all columns in a table_list->real_name
***************************************************************************/
-int
+bool
mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
bool verbose)
{
@@ -707,11 +390,9 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
table_list->real_name));
table_list->lock_type= TL_UNLOCK;
- if ((res= open_and_lock_tables(thd, table_list)))
+ if (open_and_lock_tables(thd, table_list))
{
- if (res < 0)
- send_error(thd);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
table= table_list->table;
file=table->file;
@@ -737,7 +418,7 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
// Send first number of fields and records
if (protocol->send_records_num(&field_list, (ulonglong)file->records) ||
protocol->send_fields(&field_list, Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
restore_record(table,default_values); // Get empty record
Field **ptr,*field;
@@ -804,8 +485,9 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
String def(tmp1,sizeof(tmp1), system_charset_info);
type.set(tmp, sizeof(tmp), field->charset());
field->val_str(&type);
+ uint dummy_errors;
def.copy(type.ptr(), type.length(), type.charset(),
- system_charset_info);
+ system_charset_info, &dummy_errors);
protocol->store(def.ptr(), def.length(), def.charset());
}
else if (field->unireg_check == Field::NEXT_NUMBER ||
@@ -845,16 +527,16 @@ mysqld_show_fields(THD *thd, TABLE_LIST *table_list,const char *wild,
system_charset_info);
}
if (protocol->write())
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
-int
+bool
mysqld_show_create(THD *thd, TABLE_LIST *table_list)
{
TABLE *table;
@@ -867,26 +549,24 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
table_list->real_name));
/* Only one table for now, but VIEW can involve several tables */
- if ((res= open_and_lock_tables(thd, table_list)))
+ if (open_and_lock_tables(thd, table_list))
{
- if (res < 0)
- send_error(thd);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
/* TODO: add environment variables show when it become possible */
if (thd->lex->only_view && !table_list->view)
{
- my_error(ER_WRONG_OBJECT, MYF(0), table_list->db,
- table_list->real_name, "VIEW");
- DBUG_RETURN(-1);
+ my_error(ER_WRONG_OBJECT, MYF(0),
+ table_list->db, table_list->real_name, "VIEW");
+ DBUG_RETURN(TRUE);
}
table= table_list->table;
if ((table_list->view ?
view_store_create_info(thd, table_list, &buffer) :
- store_create_info(thd, table, &buffer)))
- DBUG_RETURN(-1);
+ store_create_info(thd, table_list, &buffer)))
+ DBUG_RETURN(TRUE);
List<Item> field_list;
if (table_list->view)
@@ -905,31 +585,34 @@ mysqld_show_create(THD *thd, TABLE_LIST *table_list)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
buffer.length(0);
if (table_list->view)
{
protocol->store(table_list->view_name.str, system_charset_info);
if (view_store_create_info(thd, table_list, &buffer))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
else
{
- protocol->store(table->table_name, system_charset_info);
- if (store_create_info(thd, table, &buffer))
- DBUG_RETURN(-1);
+ if (table_list->schema_table)
+ protocol->store(table_list->schema_table_name, system_charset_info);
+ else
+ protocol->store(table->table_name, system_charset_info);
+ if (store_create_info(thd, table_list, &buffer))
+ DBUG_RETURN(TRUE);
}
protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
if (protocol->write())
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
-int mysqld_show_create_db(THD *thd, char *dbname,
- HA_CREATE_INFO *create_info)
+bool mysqld_show_create_db(THD *thd, char *dbname,
+ HA_CREATE_INFO *create_info)
{
int length;
char path[FN_REFLEN];
@@ -946,8 +629,8 @@ int mysqld_show_create_db(THD *thd, char *dbname,
if (check_db_name(dbname))
{
- net_printf(thd,ER_WRONG_DB_NAME, dbname);
- DBUG_RETURN(1);
+ my_error(ER_WRONG_DB_NAME, MYF(0), dbname);
+ DBUG_RETURN(TRUE);
}
#ifndef NO_EMBEDDED_ACCESS_CHECKS
@@ -958,11 +641,11 @@ int mysqld_show_create_db(THD *thd, char *dbname,
thd->master_access);
if (!(db_access & DB_ACLS) && (!grant_option || check_grant_db(thd,dbname)))
{
- net_printf(thd,ER_DBACCESS_DENIED_ERROR,
- thd->priv_user, thd->host_or_ip, dbname);
+ my_error(ER_DBACCESS_DENIED_ERROR, MYF(0),
+ thd->priv_user, thd->host_or_ip, dbname);
mysql_log.write(thd,COM_INIT_DB,ER(ER_DBACCESS_DENIED_ERROR),
thd->priv_user, thd->host_or_ip, dbname);
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
#endif
@@ -976,8 +659,8 @@ int mysqld_show_create_db(THD *thd, char *dbname,
}
if (access(path,F_OK))
{
- net_printf(thd,ER_BAD_DB_ERROR,dbname);
- DBUG_RETURN(1);
+ my_error(ER_BAD_DB_ERROR, MYF(0), dbname);
+ DBUG_RETURN(TRUE);
}
if (found_libchar)
path[length-1]= FN_LIBCHAR;
@@ -990,7 +673,7 @@ int mysqld_show_create_db(THD *thd, char *dbname,
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
protocol->prepare_for_resend();
protocol->store(dbname, strlen(dbname), system_charset_info);
@@ -1015,12 +698,12 @@ int mysqld_show_create_db(THD *thd, char *dbname,
protocol->store(buffer.ptr(), buffer.length(), buffer.charset());
if (protocol->write())
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
-int
+bool
mysqld_show_logs(THD *thd)
{
List<Item> field_list;
@@ -1033,112 +716,15 @@ mysqld_show_logs(THD *thd)
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
#ifdef HAVE_BERKELEY_DB
if ((have_berkeley_db == SHOW_OPTION_YES) && berkeley_show_logs(protocol))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
#endif
send_eof(thd);
- DBUG_RETURN(0);
-}
-
-
-int
-mysqld_show_keys(THD *thd, TABLE_LIST *table_list)
-{
- TABLE *table;
- Protocol *protocol= thd->protocol;
- DBUG_ENTER("mysqld_show_keys");
- DBUG_PRINT("enter",("db: %s table: %s",table_list->db,
- table_list->real_name));
-
- if (!(table = open_ltable(thd, table_list, TL_UNLOCK)))
- {
- send_error(thd);
- DBUG_RETURN(1);
- }
-
- List<Item> field_list;
- Item *item;
- field_list.push_back(new Item_empty_string("Table",NAME_LEN));
- field_list.push_back(new Item_return_int("Non_unique",1, MYSQL_TYPE_TINY));
- field_list.push_back(new Item_empty_string("Key_name",NAME_LEN));
- field_list.push_back(new Item_return_int("Seq_in_index",2, MYSQL_TYPE_TINY));
- field_list.push_back(new Item_empty_string("Column_name",NAME_LEN));
- field_list.push_back(item=new Item_empty_string("Collation",1));
- item->maybe_null=1;
- field_list.push_back(item=new Item_int("Cardinality",0,21));
- item->maybe_null=1;
- field_list.push_back(item=new Item_return_int("Sub_part",3,
- MYSQL_TYPE_TINY));
- item->maybe_null=1;
- field_list.push_back(item=new Item_empty_string("Packed",10));
- item->maybe_null=1;
- field_list.push_back(new Item_empty_string("Null",3));
- field_list.push_back(new Item_empty_string("Index_type",16));
- field_list.push_back(new Item_empty_string("Comment",255));
- item->maybe_null=1;
-
- if (protocol->send_fields(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1);
-
- KEY *key_info=table->key_info;
- table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK | HA_STATUS_TIME);
- for (uint i=0 ; i < table->keys ; i++,key_info++)
- {
- KEY_PART_INFO *key_part= key_info->key_part;
- const char *str;
- for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
- {
- protocol->prepare_for_resend();
- protocol->store(table->table_name, system_charset_info);
- protocol->store_tiny((longlong) ((key_info->flags & HA_NOSAME) ? 0 :1));
- protocol->store(key_info->name, system_charset_info);
- protocol->store_tiny((longlong) (j+1));
- str=(key_part->field ? key_part->field->field_name :
- "?unknown field?");
- protocol->store(str, system_charset_info);
- if (table->file->index_flags(i, j, 0) & HA_READ_ORDER)
- protocol->store(((key_part->key_part_flag & HA_REVERSE_SORT) ?
- "D" : "A"), 1, system_charset_info);
- else
- protocol->store_null(); /* purecov: inspected */
- KEY *key=table->key_info+i;
- if (key->rec_per_key[j])
- {
- ha_rows records=(table->file->records / key->rec_per_key[j]);
- protocol->store((ulonglong) records);
- }
- else
- protocol->store_null();
-
- /* Check if we have a key part that only uses part of the field */
- if (!(key_info->flags & HA_FULLTEXT) && (!key_part->field ||
- key_part->length != table->field[key_part->fieldnr-1]->key_length()))
- protocol->store_tiny((longlong) key_part->length);
- else
- protocol->store_null();
- protocol->store_null(); // No pack_information yet
-
- /* Null flag */
- uint flags= key_part->field ? key_part->field->flags : 0;
- char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
- protocol->store((const char*) pos, system_charset_info);
- protocol->store(table->file->index_type(i), system_charset_info);
- /* Comment */
- if (!table->keys_in_use.is_set(i))
- protocol->store("disabled",8, system_charset_info);
- else
- protocol->store("", 0, system_charset_info);
- if (protocol->write())
- DBUG_RETURN(1); /* purecov: inspected */
- }
- }
- send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -1156,12 +742,8 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
DBUG_PRINT("enter",("table: %s",table_list->real_name));
table_list->lock_type= TL_UNLOCK;
- if ((res= open_and_lock_tables(thd, table_list)))
- {
- if (res < 0)
- send_error(thd);
+ if (open_and_lock_tables(thd, table_list))
DBUG_VOID_RETURN;
- }
table= table_list->table;
List<Item> field_list;
@@ -1177,30 +759,28 @@ mysqld_list_fields(THD *thd, TABLE_LIST *table_list, const char *wild)
if (thd->protocol->send_fields(&field_list, Protocol::SEND_DEFAULTS |
Protocol::SEND_EOF))
DBUG_VOID_RETURN;
- net_flush(&thd->net);
+ thd->protocol->flush();
DBUG_VOID_RETURN;
}
int
-mysqld_dump_create_info(THD *thd, TABLE *table, int fd)
+mysqld_dump_create_info(THD *thd, TABLE_LIST *table_list, int fd)
{
Protocol *protocol= thd->protocol;
String *packet= protocol->storage_packet();
DBUG_ENTER("mysqld_dump_create_info");
- DBUG_PRINT("enter",("table: %s",table->real_name));
+ DBUG_PRINT("enter",("table: %s",table_list->table->real_name));
protocol->prepare_for_resend();
- if (store_create_info(thd, table, packet))
+ if (store_create_info(thd, table_list, packet))
DBUG_RETURN(-1);
- //if (protocol->convert)
- // protocol->convert->convert((char*) packet->ptr(), packet->length());
if (fd < 0)
{
if (protocol->write())
DBUG_RETURN(-1);
- net_flush(&thd->net);
+ protocol->flush();
}
else
{
@@ -1267,6 +847,15 @@ append_identifier(THD *thd, String *packet, const char *name, uint length)
{
uchar chr= (uchar) *name;
length= my_mbcharlen(system_charset_info, chr);
+ /*
+ my_mbcharlen can retur 0 on a wrong multibyte
+ sequence. It is possible when upgrading from 4.0,
+ and identifier contains some accented characters.
+ The manual says it does not work. So we'll just
+ change length to 1 not to hang in the endless loop.
+ */
+ if (!length)
+ length= 1;
if (length == 1 && chr == (uchar) quote_char)
packet->append(&quote_char, 1, system_charset_info);
packet->append(name, length, packet->charset());
@@ -1327,7 +916,7 @@ static void append_directory(THD *thd, String *packet, const char *dir_type,
#define LIST_PROCESS_HOST_LEN 64
static int
-store_create_info(THD *thd, TABLE *table, String *packet)
+store_create_info(THD *thd, TABLE_LIST *table_list, String *packet)
{
List<Item> field_list;
char tmp[MAX_FIELD_WIDTH], *for_str, buff[128], *end, *alias;
@@ -1335,6 +924,7 @@ store_create_info(THD *thd, TABLE *table, String *packet)
Field **ptr,*field;
uint primary_key;
KEY *key_info;
+ TABLE *table= table_list->table;
handler *file= table->file;
HA_CREATE_INFO create_info;
my_bool foreign_db_mode= (thd->variables.sql_mode & (MODE_POSTGRESQL |
@@ -1356,8 +946,11 @@ store_create_info(THD *thd, TABLE *table, String *packet)
packet->append("CREATE TEMPORARY TABLE ", 23);
else
packet->append("CREATE TABLE ", 13);
- alias= (lower_case_table_names == 2 ? table->table_name :
- table->real_name);
+ if (table_list->schema_table)
+ alias= table_list->schema_table_name;
+ else
+ alias= (lower_case_table_names == 2 ? table->table_name :
+ table->real_name);
append_identifier(thd, packet, alias, strlen(alias));
packet->append(" (\n", 3);
@@ -1436,9 +1029,10 @@ store_create_info(THD *thd, TABLE *table, String *packet)
if (type.length())
{
String def_val;
+ uint dummy_errors;
/* convert to system_charset_info == utf8 */
def_val.copy(type.ptr(), type.length(), field->charset(),
- system_charset_info);
+ system_charset_info, &dummy_errors);
append_unescaped(packet, def_val.ptr(), def_val.length());
}
else
@@ -1633,7 +1227,7 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
if (!foreign_db_mode)
{
buff->append("ALGORITHM=", 10);
- switch(table->algorithm)
+ switch((int8)table->algorithm)
{
case VIEW_ALGORITHM_UNDEFINED:
buff->append("UNDEFINED ", 10);
@@ -1672,9 +1266,13 @@ view_store_create_info(THD *thd, TABLE_LIST *table, String *buff)
class thread_info :public ilink {
public:
- static void *operator new(size_t size) {return (void*) sql_alloc((uint) size); }
+ static void *operator new(size_t size)
+ {
+ return (void*) sql_alloc((uint) size);
+ }
static void operator delete(void *ptr __attribute__((unused)),
- size_t size __attribute__((unused))) {} /*lint -e715 */
+ size_t size __attribute__((unused)))
+ { TRASH(ptr, size); }
ulong thread_id;
time_t start_time;
@@ -1816,451 +1414,2132 @@ void mysqld_list_processes(THD *thd,const char *user, bool verbose)
Status functions
*****************************************************************************/
-static bool write_collation(Protocol *protocol, CHARSET_INFO *cs)
+
+static bool show_status_array(THD *thd, const char *wild,
+ show_var_st *variables,
+ enum enum_var_type value_type,
+ struct system_status_var *status_var,
+ const char *prefix)
{
- protocol->prepare_for_resend();
- protocol->store(cs->name, system_charset_info);
- protocol->store(cs->csname, system_charset_info);
- protocol->store_short((longlong) cs->number);
- protocol->store((cs->state & MY_CS_PRIMARY) ? "Yes" : "",system_charset_info);
- protocol->store((cs->state & MY_CS_COMPILED)? "Yes" : "",system_charset_info);
- protocol->store_short((longlong) cs->strxfrm_multiply);
- return protocol->write();
+ char buff[1024], *prefix_end;
+ /* the variable name should not be longer then 80 characters */
+ char name_buffer[80];
+ int len;
+ Protocol *protocol= thd->protocol;
+ LEX_STRING null_lex_str;
+ DBUG_ENTER("show_status_array");
+
+ null_lex_str.str= 0; // For sys_var->value_ptr()
+ null_lex_str.length= 0;
+
+ prefix_end=strnmov(name_buffer, prefix, sizeof(name_buffer)-1);
+ len=name_buffer + sizeof(name_buffer) - prefix_end;
+
+ for (; variables->name; variables++)
+ {
+ strnmov(prefix_end, variables->name, len);
+ name_buffer[sizeof(name_buffer)-1]=0; /* Safety */
+ SHOW_TYPE show_type=variables->type;
+ if (show_type == SHOW_VARS)
+ {
+ show_status_array(thd, wild, (show_var_st *) variables->value,
+ value_type, status_var, variables->name);
+ }
+ else
+ {
+ if (!(wild && wild[0] && wild_case_compare(system_charset_info,
+ name_buffer, wild)))
+ {
+ char *value=variables->value;
+ const char *pos, *end;
+ long nr;
+
+ protocol->prepare_for_resend();
+ protocol->store(name_buffer, system_charset_info);
+
+ if (show_type == SHOW_SYS)
+ {
+ show_type= ((sys_var*) value)->type();
+ value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
+ &null_lex_str);
+ }
+
+ pos= end= buff;
+ switch (show_type) {
+ case SHOW_LONG_STATUS:
+ case SHOW_LONG_CONST_STATUS:
+ value= ((char *) status_var + (ulong) value);
+ /* fall through */
+ case SHOW_LONG:
+ case SHOW_LONG_CONST:
+ end= int10_to_str(*(long*) value, buff, 10);
+ break;
+ case SHOW_LONGLONG:
+ end= longlong10_to_str(*(longlong*) value, buff, 10);
+ break;
+ case SHOW_HA_ROWS:
+ end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
+ break;
+ case SHOW_BOOL:
+ end= strmov(buff, *(bool*) value ? "ON" : "OFF");
+ break;
+ case SHOW_MY_BOOL:
+ end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
+ break;
+ case SHOW_INT_CONST:
+ case SHOW_INT:
+ end= int10_to_str((long) *(uint32*) value, buff, 10);
+ break;
+ case SHOW_HAVE:
+ {
+ SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
+ pos= show_comp_option_name[(int) tmp];
+ end= strend(pos);
+ break;
+ }
+ case SHOW_CHAR:
+ {
+ if (!(pos= value))
+ pos= "";
+ end= strend(pos);
+ break;
+ }
+ case SHOW_STARTTIME:
+ nr= (long) (thd->query_start() - start_time);
+ end= int10_to_str(nr, buff, 10);
+ break;
+ case SHOW_QUESTION:
+ end= int10_to_str((long) thd->query_id, buff, 10);
+ break;
+#ifdef HAVE_REPLICATION
+ case SHOW_RPL_STATUS:
+ end= strmov(buff, rpl_status_type[(int)rpl_status]);
+ break;
+ case SHOW_SLAVE_RUNNING:
+ {
+ pthread_mutex_lock(&LOCK_active_mi);
+ end= strmov(buff, (active_mi->slave_running &&
+ active_mi->rli.slave_running) ? "ON" : "OFF");
+ pthread_mutex_unlock(&LOCK_active_mi);
+ break;
+ }
+#endif /* HAVE_REPLICATION */
+ case SHOW_OPENTABLES:
+ end= int10_to_str((long) cached_tables(), buff, 10);
+ break;
+ case SHOW_CHAR_PTR:
+ {
+ if (!(pos= *(char**) value))
+ pos= "";
+ end= strend(pos);
+ break;
+ }
+ case SHOW_DOUBLE:
+ {
+ end= buff + sprintf(buff, "%f", *(double*) value);
+ break;
+ }
+#ifdef HAVE_OPENSSL
+ /* First group - functions relying on CTX */
+ case SHOW_SSL_CTX_SESS_ACCEPT:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_good(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_good(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_CB_HITS:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_HITS:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_hits(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_CACHE_FULL:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_cache_full(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_MISSES:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_misses(ssl_acceptor_fd->
+ ssl_context)),
+ buff, 10);
+ break;
+ case SHOW_SSL_CTX_SESS_TIMEOUTS:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_SESS_NUMBER:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_SESS_CONNECT:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_GET_VERIFY_MODE:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
+ end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
+ SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)),
+ buff,10);
+ break;
+ case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
+ if (!ssl_acceptor_fd)
+ {
+ pos= "NONE";
+ end= pos+4;
+ break;
+ }
+ switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
+ {
+ case SSL_SESS_CACHE_OFF:
+ pos= "OFF";
+ break;
+ case SSL_SESS_CACHE_CLIENT:
+ pos= "CLIENT";
+ break;
+ case SSL_SESS_CACHE_SERVER:
+ pos= "SERVER";
+ break;
+ case SSL_SESS_CACHE_BOTH:
+ pos= "BOTH";
+ break;
+ case SSL_SESS_CACHE_NO_AUTO_CLEAR:
+ pos= "NO_AUTO_CLEAR";
+ break;
+ case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
+ pos= "NO_INTERNAL_LOOKUP";
+ break;
+ default:
+ pos= "Unknown";
+ break;
+ }
+ end= strend(pos);
+ break;
+ /* First group - functions relying on SSL */
+ case SHOW_SSL_GET_VERSION:
+ pos= (thd->net.vio->ssl_arg ?
+ SSL_get_version((SSL*) thd->net.vio->ssl_arg) : "");
+ end= strend(pos);
+ break;
+ case SHOW_SSL_SESSION_REUSED:
+ end= int10_to_str((long) (thd->net.vio->ssl_arg ?
+ SSL_session_reused((SSL*) thd->net.vio->
+ ssl_arg) :
+ 0),
+ buff, 10);
+ break;
+ case SHOW_SSL_GET_DEFAULT_TIMEOUT:
+ end= int10_to_str((long) (thd->net.vio->ssl_arg ?
+ SSL_get_default_timeout((SSL*) thd->net.vio->
+ ssl_arg) :
+ 0),
+ buff, 10);
+ break;
+ case SHOW_SSL_GET_VERIFY_MODE:
+ end= int10_to_str((long) (thd->net.vio->ssl_arg ?
+ SSL_get_verify_mode((SSL*) thd->net.vio->
+ ssl_arg):
+ 0),
+ buff, 10);
+ break;
+ case SHOW_SSL_GET_VERIFY_DEPTH:
+ end= int10_to_str((long) (thd->net.vio->ssl_arg ?
+ SSL_get_verify_depth((SSL*) thd->net.vio->
+ ssl_arg):
+ 0),
+ buff, 10);
+ break;
+ case SHOW_SSL_GET_CIPHER:
+ pos= (thd->net.vio->ssl_arg ?
+ SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" );
+ end= strend(pos);
+ break;
+ case SHOW_SSL_GET_CIPHER_LIST:
+ if (thd->net.vio->ssl_arg)
+ {
+ char *to= buff;
+ for (int i=0 ; i++ ;)
+ {
+ const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i);
+ if (p == NULL)
+ break;
+ to= strmov(to, p);
+ *to++= ':';
+ }
+ if (to != buff)
+ to--; // Remove last ':'
+ end= to;
+ }
+ break;
+
+#endif /* HAVE_OPENSSL */
+ case SHOW_KEY_CACHE_LONG:
+ case SHOW_KEY_CACHE_CONST_LONG:
+ value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache;
+ end= int10_to_str(*(long*) value, buff, 10);
+ break;
+ case SHOW_UNDEF: // Show never happen
+ case SHOW_SYS:
+ break; // Return empty string
+ default:
+ break;
+ }
+ if (protocol->store(pos, (uint32) (end - pos), system_charset_info) ||
+ protocol->write())
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+ }
+ }
+ }
+
+ DBUG_RETURN(FALSE);
}
-int mysqld_show_collations(THD *thd, const char *wild)
+
+bool mysqld_show(THD *thd, const char *wild, show_var_st *variables,
+ enum enum_var_type value_type,
+ pthread_mutex_t *mutex,
+ struct system_status_var *status_var)
{
- char buff[8192];
- String packet2(buff,sizeof(buff),thd->charset());
List<Item> field_list;
- CHARSET_INFO **cs;
Protocol *protocol= thd->protocol;
+ DBUG_ENTER("mysqld_show");
- DBUG_ENTER("mysqld_show_charsets");
-
- field_list.push_back(new Item_empty_string("Collation",30));
- field_list.push_back(new Item_empty_string("Charset",30));
- field_list.push_back(new Item_return_int("Id",11, FIELD_TYPE_SHORT));
- field_list.push_back(new Item_empty_string("Default",30));
- field_list.push_back(new Item_empty_string("Compiled",30));
- field_list.push_back(new Item_return_int("Sortlen",3, FIELD_TYPE_SHORT));
+ ha_update_statistics(); /* Export engines statistics */
+ field_list.push_back(new Item_empty_string("Variable_name",30));
+ field_list.push_back(new Item_empty_string("Value",256));
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+ DBUG_RETURN(TRUE); /* purecov: inspected */
+
+ pthread_mutex_lock(mutex);
+ if (show_status_array(thd, wild, variables, value_type, status_var, ""))
+ goto err;
+ pthread_mutex_unlock(mutex);
+ send_eof(thd);
+ DBUG_RETURN(FALSE);
+
+ err:
+ pthread_mutex_unlock(mutex);
+ DBUG_RETURN(TRUE);
+}
+
+
+/* collect status for all running threads */
+
+void calc_sum_of_all_status(STATUS_VAR *to)
+{
+ DBUG_ENTER("calc_sum_of_all_status");
+
+ /* Ensure that thread id not killed during loop */
+ VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
+
+ I_List_iterator<THD> it(threads);
+ THD *tmp;
+
+ /* Get global values as base */
+ *to= global_status_var;
+
+ /* Add to this status from existing threads */
+ while ((tmp= it++))
+ add_to_status(to, &tmp->status_var);
+
+ VOID(pthread_mutex_unlock(&LOCK_thread_count));
+ DBUG_VOID_RETURN;
+}
+
+
+LEX_STRING *make_lex_string(THD *thd, LEX_STRING *lex_str,
+ const char* str, uint length,
+ bool allocate_lex_string)
+{
+ MEM_ROOT *mem= thd->mem_root;
+ if (allocate_lex_string)
+ lex_str= (LEX_STRING *)thd->alloc(sizeof(LEX_STRING));
+ lex_str->str= strmake_root(mem, str, length);
+ lex_str->length= length;
+ return lex_str;
+}
+
+
+/* INFORMATION_SCHEMA name */
+LEX_STRING information_schema_name= {(char*)"information_schema", 18};
+extern ST_SCHEMA_TABLE schema_tables[];
+
+typedef struct st_index_field_values
+{
+ const char *db_value, *table_value;
+} INDEX_FIELD_VALUES;
+
+
+void get_index_field_values(LEX *lex, INDEX_FIELD_VALUES *index_field_values)
+{
+ const char *wild= lex->wild ? lex->wild->ptr() : NullS;
+ switch (lex->orig_sql_command) {
+ case SQLCOM_SHOW_DATABASES:
+ index_field_values->db_value= wild;
+ break;
+ case SQLCOM_SHOW_TABLES:
+ case SQLCOM_SHOW_TABLE_STATUS:
+ index_field_values->db_value= lex->current_select->db;
+ index_field_values->table_value= wild;
+ break;
+ default:
+ index_field_values->db_value= NullS;
+ index_field_values->table_value= NullS;
+ break;
+ }
+}
+
+
+int make_table_list(THD *thd, SELECT_LEX *sel,
+ char *db, char *table)
+{
+ Table_ident *table_ident;
+ LEX_STRING ident_db, ident_table;
+ ident_db.str= db;
+ ident_db.length= strlen(db);
+ ident_table.str= table;
+ ident_table.length= strlen(table);
+ table_ident= new Table_ident(thd, ident_db, ident_table, 1);
+ sel->init_query();
+ if(!sel->add_table_to_list(thd, table_ident, 0, 0, TL_READ,
+ (List<String> *) 0, (List<String> *) 0))
+ return 1;
+ return 0;
+}
+
+
+bool uses_only_table_name_fields(Item *item, TABLE_LIST *table)
+{
+ if (item->type() == Item::FUNC_ITEM)
+ {
+ Item_func *item_func= (Item_func*)item;
+ Item **child;
+ Item **item_end= (item_func->arguments()) + item_func->argument_count();
+ for (child= item_func->arguments(); child != item_end; child++)
+ {
+ if (!uses_only_table_name_fields(*child, table))
+ return 0;
+ }
+ }
+ else if (item->type() == Item::FIELD_ITEM)
+ {
+ Item_field *item_field= (Item_field*)item;
+ CHARSET_INFO *cs= system_charset_info;
+ ST_SCHEMA_TABLE *schema_table= table->schema_table;
+ ST_FIELD_INFO *field_info= schema_table->fields_info;
+ const char *field_name1= field_info[schema_table->idx_field1].field_name;
+ const char *field_name2= 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), 0) &&
+ cs->coll->strnncollsp(cs, (uchar *) field_name2, strlen(field_name2),
+ (uchar *) item_field->field_name,
+ strlen(item_field->field_name), 0)))
+ return 0;
+ }
+ return 1;
+}
+
+
+static COND * make_cond_for_info_schema(COND *cond, TABLE_LIST *table)
+{
+ if (!cond)
+ return (COND*) 0;
+ if (cond->type() == Item::COND_ITEM)
+ {
+ if (((Item_cond*) cond)->functype() == Item_func::COND_AND_FUNC)
+ {
+ /* Create new top level AND item */
+ Item_cond_and *new_cond=new Item_cond_and;
+ if (!new_cond)
+ return (COND*) 0;
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ Item *fix= make_cond_for_info_schema(item, table);
+ if (fix)
+ new_cond->argument_list()->push_back(fix);
+ }
+ switch (new_cond->argument_list()->elements) {
+ case 0:
+ return (COND*) 0;
+ case 1:
+ return new_cond->argument_list()->head();
+ default:
+ new_cond->quick_fix_field();
+ return new_cond;
+ }
+ }
+ else
+ { // Or list
+ Item_cond_or *new_cond=new Item_cond_or;
+ if (!new_cond)
+ return (COND*) 0;
+ List_iterator<Item> li(*((Item_cond*) cond)->argument_list());
+ Item *item;
+ while ((item=li++))
+ {
+ Item *fix=make_cond_for_info_schema(item, table);
+ if (!fix)
+ return (COND*) 0;
+ new_cond->argument_list()->push_back(fix);
+ }
+ new_cond->quick_fix_field();
+ new_cond->top_level_item();
+ return new_cond;
+ }
+ }
+
+ if (!uses_only_table_name_fields(cond, table))
+ return (COND*) 0;
+ return cond;
+}
+
+
+int get_all_tables(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ LEX *lex= thd->lex;
+ TABLE *table= tables->table;
+ SELECT_LEX *select_lex= &lex->select_lex;
+ SELECT_LEX *lsel= tables->schema_select_lex;
+ ST_SCHEMA_TABLE *schema_table= tables->schema_table;
+ DBUG_ENTER("fill_schema_tables");
+
+ if (lsel)
+ {
+ TABLE *old_open_tables= thd->open_tables;
+ TABLE_LIST *show_table_list= (TABLE_LIST*) lsel->table_list.first;
+ lex->all_selects_list= lsel;
+ bool res= open_and_lock_tables(thd, show_table_list);
+ if (schema_table->process_table(thd, show_table_list,
+ table, res, show_table_list->db,
+ show_table_list->real_name))
+ {
+ DBUG_RETURN(1);
+ }
+ close_thread_tables(thd, 0, 0, old_open_tables);
+ show_table_list->table= 0;
+ lex->all_selects_list= select_lex;
+ DBUG_RETURN(0);
+ }
+
+ SELECT_LEX sel;
+ INDEX_FIELD_VALUES idx_field_vals;
+ char path[FN_REFLEN], *end, *base_name, *file_name;
+ uint len;
+ List<char> bases;
+ lex->all_selects_list= &sel;
+ enum enum_schema_tables schema_table_idx=
+ (enum enum_schema_tables) (schema_table - &schema_tables[0]);
+ thr_lock_type lock_type= TL_UNLOCK;
+ if (schema_table_idx == SCH_TABLES)
+ lock_type= TL_READ;
+ get_index_field_values(lex, &idx_field_vals);
+ if (mysql_find_files(thd, &bases, NullS, mysql_data_home,
+ idx_field_vals.db_value, 1))
+ return 1;
+ List_iterator_fast<char> it(bases);
+ COND *partial_cond= make_cond_for_info_schema(cond, tables);
+ while ((base_name=it++) ||
+ /*
+ generate error for non existing database.
+ (to save old behaviour for SHOW TABLES FROM db)
+ */
+ ((lex->orig_sql_command == SQLCOM_SHOW_TABLES ||
+ lex->orig_sql_command == SQLCOM_SHOW_TABLE_STATUS) &&
+ (base_name= select_lex->db) && !bases.elements))
+ {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (!check_access(thd,SELECT_ACL, base_name, &thd->col_access,0,1) ||
+ thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
+ acl_get(thd->host, thd->ip, thd->priv_user, base_name,0) ||
+ (grant_option && !check_grant_db(thd, base_name)))
+#endif
+ {
+ List<char> files;
+ strxmov(path, mysql_data_home, "/", base_name, NullS);
+ end= path + (len= unpack_dirname(path,path));
+ len= FN_LEN - len;
+ if (mysql_find_files(thd, &files, base_name,
+ path, idx_field_vals.table_value, 0))
+ DBUG_RETURN(1);
+
+ List_iterator_fast<char> it(files);
+ while ((file_name=it++))
+ {
+ restore_record(table, default_values);
+ table->field[schema_table->idx_field1]->
+ store(base_name, strlen(base_name), system_charset_info);
+ table->field[schema_table->idx_field2]->
+ store(file_name, strlen(file_name),system_charset_info);
+ if (!partial_cond || partial_cond->val_int())
+ {
+ if (schema_table_idx == SCH_TABLE_NAMES)
+ {
+ if (lex->verbose || lex->orig_sql_command == SQLCOM_END)
+ {
+ my_snprintf(end, len, "/%s%s", file_name, reg_ext);
+ switch (mysql_frm_type(path))
+ {
+ case FRMTYPE_ERROR:
+ table->field[3]->store("ERROR", 5, system_charset_info);
+ break;
+ case FRMTYPE_TABLE:
+ table->field[3]->store("BASE TABLE", 10, system_charset_info);
+ break;
+ case FRMTYPE_VIEW:
+ table->field[3]->store("VIEW", 4, system_charset_info);
+ break;
+ default:
+ DBUG_ASSERT(0);
+ }
+ }
+ table->file->write_row(table->record[0]);
+ }
+ else
+ {
+ int res;
+ TABLE *old_open_tables= thd->open_tables;
+ if (make_table_list(thd, &sel, base_name, file_name))
+ DBUG_RETURN(1);
+ TABLE_LIST *show_table_list= (TABLE_LIST*) sel.table_list.first;
+ show_table_list->lock_type= lock_type;
+ res= open_and_lock_tables(thd, show_table_list);
+ if (schema_table->process_table(thd, show_table_list, table,
+ res, base_name, file_name))
+ {
+ DBUG_RETURN(1);
+ }
+ close_thread_tables(thd, 0, 0, old_open_tables);
+ }
+ }
+ }
+ }
+ }
+ lex->all_selects_list= select_lex;
+ DBUG_RETURN(0);
+}
+
+
+int fill_schema_shemata(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ char path[FN_REFLEN],*end;
+ bool found_libchar;
+ INDEX_FIELD_VALUES idx_field_vals;
+ List<char> files;
+ char *file_name;
+ uint length;
+ HA_CREATE_INFO create;
+ TABLE *table= tables->table;
+
+ get_index_field_values(thd->lex, &idx_field_vals);
+ if (mysql_find_files(thd, &files, NullS, mysql_data_home,
+ idx_field_vals.db_value, 1))
+ return 1;
+ List_iterator_fast<char> it(files);
+ while ((file_name=it++))
+ {
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ if (thd->master_access & (DB_ACLS | SHOW_DB_ACL) ||
+ acl_get(thd->host, thd->ip, thd->priv_user, file_name,0) ||
+ (grant_option && !check_grant_db(thd, file_name)))
+#endif
+ {
+ strxmov(path, mysql_data_home, "/", file_name, NullS);
+ length=unpack_dirname(path,path); // Convert if not unix
+ found_libchar= 0;
+ if (length && path[length-1] == FN_LIBCHAR)
+ {
+ found_libchar= 1;
+ path[length-1]=0; // remove ending '\'
+ }
+
+ if (found_libchar)
+ path[length-1]= FN_LIBCHAR;
+ strmov(path+length, MY_DB_OPT_FILE);
+ load_db_opt(thd, path, &create);
+ restore_record(table, default_values);
+ table->field[1]->store(file_name, strlen(file_name), system_charset_info);
+ table->field[2]->store(create.default_table_charset->csname,
+ strlen(create.default_table_charset->csname),
+ system_charset_info);
+ table->file->write_row(table->record[0]);
+ }
+ }
+ return 0;
+}
+
+
+static int get_schema_tables_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ const char *tmp_buff;
+ TIME time;
+ CHARSET_INFO *cs= system_charset_info;
+
+ DBUG_ENTER("get_schema_tables_record");
+ restore_record(table, default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[2]->store(file_name, strlen(file_name), cs);
+ if (res)
+ {
+ /*
+ there was errors during opening tables
+ */
+ const char *error= thd->net.last_error;
+ table->field[20]->store(error, strlen(error), cs);
+ thd->clear_error();
+ }
+ else if (tables->view)
+ {
+ table->field[3]->store("VIEW", 4, cs);
+ table->field[20]->store("view", 4, cs);
+ }
+ else
+ {
+ TABLE *show_table= tables->table;
+ handler *file= show_table->file;
+ file->info(HA_STATUS_VARIABLE | HA_STATUS_TIME | HA_STATUS_NO_LOCK);
+ table->field[3]->store("BASE TABLE", 10, cs);
+ for (int i= 4; i < 20; i++)
+ {
+ if ((i > 12 && i < 17) || i == 18)
+ continue;
+ table->field[i]->set_notnull();
+ }
+ tmp_buff= file->table_type();
+ table->field[4]->store(tmp_buff, strlen(tmp_buff), cs);
+ table->field[5]->store((longlong) show_table->frm_version);
+ tmp_buff= ((show_table->db_options_in_use &
+ HA_OPTION_COMPRESS_RECORD) ? "Compressed" :
+ (show_table->db_options_in_use & HA_OPTION_PACK_RECORD) ?
+ "Dynamic" : "Fixed");
+ table->field[6]->store(tmp_buff, strlen(tmp_buff), cs);
+ table->field[7]->store((longlong) file->records);
+ table->field[8]->store((longlong) file->mean_rec_length);
+ table->field[9]->store((longlong) file->data_file_length);
+ if (file->max_data_file_length)
+ {
+ table->field[10]->store((longlong) file->max_data_file_length);
+ }
+ table->field[11]->store((longlong) file->index_file_length);
+ table->field[12]->store((longlong) file->delete_length);
+ if (show_table->found_next_number_field)
+ {
+ show_table->next_number_field=show_table->found_next_number_field;
+ show_table->next_number_field->reset();
+ file->update_auto_increment();
+ table->field[13]->store((longlong) show_table->
+ next_number_field->val_int());
+ table->field[13]->set_notnull();
+ show_table->next_number_field=0;
+ }
+ if (file->create_time)
+ {
+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
+ file->create_time);
+ table->field[14]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ table->field[14]->set_notnull();
+ }
+ if (file->update_time)
+ {
+ thd->variables.time_zone->gmt_sec_to_TIME(&time,
+ file->update_time);
+ table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ table->field[15]->set_notnull();
+ }
+ if (file->check_time)
+ {
+ thd->variables.time_zone->gmt_sec_to_TIME(&time, file->check_time);
+ table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ table->field[16]->set_notnull();
+ }
+ tmp_buff= (show_table->table_charset ? show_table->
+ table_charset->name : "default");
+ table->field[17]->store(tmp_buff, strlen(tmp_buff), cs);
+ if (file->table_flags() & (ulong) HA_HAS_CHECKSUM)
+ {
+ table->field[18]->store((longlong) file->checksum());
+ table->field[18]->set_notnull();
+ }
+
+ char option_buff[350],*ptr;
+ ptr=option_buff;
+ if (show_table->min_rows)
+ {
+ ptr=strmov(ptr," min_rows=");
+ ptr=longlong10_to_str(show_table->min_rows,ptr,10);
+ }
+ if (show_table->max_rows)
+ {
+ ptr=strmov(ptr," max_rows=");
+ ptr=longlong10_to_str(show_table->max_rows,ptr,10);
+ }
+ if (show_table->avg_row_length)
+ {
+ ptr=strmov(ptr," avg_row_length=");
+ ptr=longlong10_to_str(show_table->avg_row_length,ptr,10);
+ }
+ if (show_table->db_create_options & HA_OPTION_PACK_KEYS)
+ ptr=strmov(ptr," pack_keys=1");
+ if (show_table->db_create_options & HA_OPTION_NO_PACK_KEYS)
+ ptr=strmov(ptr," pack_keys=0");
+ if (show_table->db_create_options & HA_OPTION_CHECKSUM)
+ ptr=strmov(ptr," checksum=1");
+ if (show_table->db_create_options & HA_OPTION_DELAY_KEY_WRITE)
+ ptr=strmov(ptr," delay_key_write=1");
+ if (show_table->row_type != ROW_TYPE_DEFAULT)
+ ptr=strxmov(ptr, " row_format=",
+ ha_row_type[(uint) show_table->row_type],
+ NullS);
+ if (file->raid_type)
+ {
+ char buff[100];
+ my_snprintf(buff,sizeof(buff),
+ " raid_type=%s raid_chunks=%d raid_chunksize=%ld",
+ my_raid_type(file->raid_type), file->raid_chunks,
+ file->raid_chunksize/RAID_BLOCK_SIZE);
+ ptr=strmov(ptr,buff);
+ }
+ table->field[19]->store(option_buff+1,
+ (ptr == option_buff ? 0 :
+ (uint) (ptr-option_buff)-1), cs);
+ {
+ char *comment= show_table->file->
+ update_table_comment(show_table->comment);
+ if (comment)
+ {
+ table->field[20]->store(comment, strlen(comment), cs);
+ if (comment != show_table->comment)
+ my_free(comment,MYF(0));
+ }
+ }
+ }
+ table->file->write_row(table->record[0]);
+ DBUG_RETURN(0);
+}
+
+
+static int get_schema_column_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ TIME time;
+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("get_schema_column_record");
+ if (res)
+ {
DBUG_RETURN(1);
+ }
+
+ TABLE *show_table= tables->table;
+ handler *file= show_table->file;
+ file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
+ restore_record(show_table, default_values);
+ Field **ptr,*field;
+ int count= 0;
+ for (ptr=show_table->field; (field= *ptr) ; ptr++)
+ {
+ if (!wild || !wild[0] ||
+ !wild_case_compare(system_charset_info, field->field_name,wild))
+ {
+ uint tmp_length;
+ const char *tmp_buff;
+ byte *pos;
+ uint flags=field->flags;
+ char tmp[MAX_FIELD_WIDTH];
+ char tmp1[MAX_FIELD_WIDTH];
+ String type(tmp,sizeof(tmp), system_charset_info);
+ char tmp_buffer[128];
+ count++;
+ restore_record(table, default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[2]->store(file_name, strlen(file_name), cs);
+ table->field[3]->store(field->field_name, strlen(field->field_name),
+ cs);
+ table->field[4]->store((longlong) count);
+ field->sql_type(type);
+ table->field[14]->store(type.ptr(), type.length(), cs);
+ tmp_buff= strchr(type.ptr(), '(');
+ table->field[7]->store(type.ptr(),
+ (tmp_buff ? tmp_buff - type.ptr() :
+ type.length()), cs);
+ if (show_table->timestamp_field == field &&
+ field->unireg_check != Field::TIMESTAMP_UN_FIELD)
+ {
+ table->field[5]->store("CURRENT_TIMESTAMP", 17, cs);
+ table->field[5]->set_notnull();
+ }
+ else if (field->unireg_check != Field::NEXT_NUMBER &&
+ !field->is_null() &&
+ !(field->flags & NO_DEFAULT_VALUE_FLAG))
+ {
+ String def(tmp1,sizeof(tmp1), cs);
+ type.set(tmp, sizeof(tmp), field->charset());
+ field->val_str(&type);
+ uint dummy_errors;
+ def.copy(type.ptr(), type.length(), type.charset(), cs, &dummy_errors);
+ table->field[5]->store(def.ptr(), def.length(), def.charset());
+ table->field[5]->set_notnull();
+ }
+ else if (field->unireg_check == Field::NEXT_NUMBER ||
+ field->maybe_null())
+ table->field[5]->set_null(); // Null as default
+ else
+ {
+ table->field[5]->store("",0, cs);
+ table->field[5]->set_notnull();
+ }
+ pos=(byte*) ((flags & NOT_NULL_FLAG) &&
+ field->type() != FIELD_TYPE_TIMESTAMP ?
+ "" : "YES");
+ table->field[6]->store((const char*) pos,
+ strlen((const char*) pos), cs);
+ if (field->has_charset())
+ table->field[8]->store((longlong) field->field_length/
+ field->charset()->mbmaxlen);
+ else
+ table->field[8]->store((longlong) field->field_length);
+ table->field[9]->store((longlong) field->field_length);
+ {
+ uint dec =field->decimals();
+ switch (field->type()) {
+ case FIELD_TYPE_DECIMAL:
+ {
+ uint int_part=field->field_length - (dec ? dec + 1 : 0);
+ table->field[10]->store((longlong) (int_part + dec - 1));
+ table->field[10]->set_notnull();
+ table->field[11]->store((longlong) field->decimals());
+ table->field[11]->set_notnull();
+ }
+ break;
+ case FIELD_TYPE_TINY:
+ case FIELD_TYPE_SHORT:
+ case FIELD_TYPE_LONG:
+ case FIELD_TYPE_LONGLONG:
+ case FIELD_TYPE_INT24:
+ case FIELD_TYPE_FLOAT:
+ case FIELD_TYPE_DOUBLE:
+ {
+ table->field[10]->store((longlong) field->field_length);
+ table->field[10]->set_notnull();
+ if (dec != NOT_FIXED_DEC)
+ {
+ table->field[11]->store((longlong) dec);
+ table->field[11]->set_notnull();
+ }
+ }
+ break;
+ default:
+ break;
+ }
+ }
+ if (field->has_charset())
+ {
+ pos=(byte*) field->charset()->csname;
+ table->field[12]->store((const char*) pos,
+ strlen((const char*) pos), cs);
+ table->field[12]->set_notnull();
+ pos=(byte*) field->charset()->name;
+ table->field[13]->store((const char*) pos,
+ strlen((const char*) pos), cs);
+ table->field[13]->set_notnull();
+ }
+ pos=(byte*) ((field->flags & PRI_KEY_FLAG) ? "PRI" :
+ (field->flags & UNIQUE_KEY_FLAG) ? "UNI" :
+ (field->flags & MULTIPLE_KEY_FLAG) ? "MUL":"");
+ table->field[15]->store((const char*) pos,
+ strlen((const char*) pos), cs);
+ char *end=tmp;
+ if (field->unireg_check == Field::NEXT_NUMBER)
+ end=strmov(tmp,"auto_increment");
+ table->field[16]->store(tmp, (uint) (end-tmp), cs);
+
+ end=tmp;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ uint col_access;
+ check_access(thd,SELECT_ACL | EXTRA_ACL, base_name,
+ &tables->grant.privilege, 0, 0);
+ col_access= get_column_grant(thd, &tables->grant, tables->db,
+ tables->real_name,
+ field->field_name) & COL_ACLS;
+ for (uint bitnr=0; col_access ; col_access>>=1,bitnr++)
+ {
+ if (col_access & 1)
+ {
+ *end++=',';
+ end=strmov(end,grant_types.type_names[bitnr]);
+ }
+ }
+#else
+ end=strmov(end,"");
+#endif
+ table->field[17]->store(tmp+1,end == tmp ? 0 : (uint) (end-tmp-1), cs);
+ table->field[18]->store(field->comment.str, field->comment.length, cs);
+ table->file->write_row(table->record[0]);
+ }
+ }
+ DBUG_RETURN(0);
+}
+
+
+
+int fill_schema_charsets(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ CHARSET_INFO **cs;
+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
+ TABLE *table= tables->table;
+ CHARSET_INFO *scs= system_charset_info;
+ for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
+ {
+ CHARSET_INFO *tmp_cs= cs[0];
+ if (tmp_cs && (tmp_cs->state & MY_CS_PRIMARY) &&
+ (tmp_cs->state & MY_CS_AVAILABLE) &&
+ !(wild && wild[0] &&
+ wild_case_compare(scs, tmp_cs->csname,wild)))
+ {
+ restore_record(table, default_values);
+ table->field[0]->store(tmp_cs->csname, strlen(tmp_cs->csname), scs);
+ table->field[1]->store(tmp_cs->comment ? tmp_cs->comment : "",
+ strlen(tmp_cs->comment ? tmp_cs->comment : ""),
+ scs);
+ table->field[2]->store(tmp_cs->name, strlen(tmp_cs->name), scs);
+ table->field[3]->store((longlong) tmp_cs->mbmaxlen);
+ table->file->write_row(table->record[0]);
+ }
+ }
+ return 0;
+}
+
+
+int fill_schema_collation(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ CHARSET_INFO **cs;
+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
+ TABLE *table= tables->table;
+ CHARSET_INFO *scs= system_charset_info;
for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
{
CHARSET_INFO **cl;
- if (!cs[0] || !(cs[0]->state & MY_CS_AVAILABLE) ||
- !(cs[0]->state & MY_CS_PRIMARY))
+ CHARSET_INFO *tmp_cs= cs[0];
+ if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
+ !(tmp_cs->state & MY_CS_PRIMARY))
continue;
for ( cl= all_charsets; cl < all_charsets+255 ;cl ++)
{
- if (!cl[0] || !(cl[0]->state & MY_CS_AVAILABLE) ||
- !my_charset_same(cs[0],cl[0]))
+ CHARSET_INFO *tmp_cl= cl[0];
+ if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
+ !my_charset_same(tmp_cs, tmp_cl))
continue;
if (!(wild && wild[0] &&
- wild_case_compare(system_charset_info,cl[0]->name,wild)))
+ wild_case_compare(scs, tmp_cl->name,wild)))
{
- if (write_collation(protocol, cl[0]))
- goto err;
+ const char *tmp_buff;
+ restore_record(table, default_values);
+ table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
+ table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
+ table->field[2]->store((longlong) tmp_cl->number);
+ tmp_buff= (tmp_cl->state & MY_CS_PRIMARY) ? "Yes" : "";
+ table->field[3]->store(tmp_buff, strlen(tmp_buff), scs);
+ tmp_buff= (tmp_cl->state & MY_CS_COMPILED)? "Yes" : "";
+ table->field[4]->store(tmp_buff, strlen(tmp_buff), scs);
+ table->field[5]->store((longlong) tmp_cl->strxfrm_multiply);
+ table->file->write_row(table->record[0]);
}
}
}
- send_eof(thd);
- DBUG_RETURN(0);
-err:
- DBUG_RETURN(1);
+ return 0;
}
-static bool write_charset(Protocol *protocol, CHARSET_INFO *cs)
-{
- protocol->prepare_for_resend();
- protocol->store(cs->csname, system_charset_info);
- protocol->store(cs->comment ? cs->comment : "", system_charset_info);
- protocol->store(cs->name, system_charset_info);
- protocol->store_short((longlong) cs->mbmaxlen);
- return protocol->write();
-}
-int mysqld_show_charsets(THD *thd, const char *wild)
+int fill_schema_coll_charset_app(THD *thd, TABLE_LIST *tables, COND *cond)
{
- char buff[8192];
- String packet2(buff,sizeof(buff),thd->charset());
- List<Item> field_list;
CHARSET_INFO **cs;
- Protocol *protocol= thd->protocol;
+ const char *wild= NullS;
+ TABLE *table= tables->table;
+ CHARSET_INFO *scs= system_charset_info;
+ for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
+ {
+ CHARSET_INFO **cl;
+ CHARSET_INFO *tmp_cs= cs[0];
+ if (!tmp_cs || !(tmp_cs->state & MY_CS_AVAILABLE) ||
+ !(tmp_cs->state & MY_CS_PRIMARY))
+ continue;
+ for ( cl= all_charsets; cl < all_charsets+255 ;cl ++)
+ {
+ CHARSET_INFO *tmp_cl= cl[0];
+ if (!tmp_cl || !(tmp_cl->state & MY_CS_AVAILABLE) ||
+ !my_charset_same(tmp_cs,tmp_cl))
+ continue;
+ restore_record(table, default_values);
+ table->field[0]->store(tmp_cl->name, strlen(tmp_cl->name), scs);
+ table->field[1]->store(tmp_cl->csname , strlen(tmp_cl->csname), scs);
+ table->file->write_row(table->record[0]);
+ }
+ }
+ return 0;
+}
- DBUG_ENTER("mysqld_show_charsets");
- field_list.push_back(new Item_empty_string("Charset",30));
- field_list.push_back(new Item_empty_string("Description",60));
- field_list.push_back(new Item_empty_string("Default collation",60));
- field_list.push_back(new Item_return_int("Maxlen",3, FIELD_TYPE_SHORT));
+void store_schema_proc(THD *thd, TABLE *table,
+ TABLE *proc_table,
+ const char *wild)
+{
+ String tmp_string;
+ TIME time;
+ LEX *lex= thd->lex;
+ CHARSET_INFO *cs= system_charset_info;
+ restore_record(table, default_values);
+ if (lex->orig_sql_command == SQLCOM_SHOW_STATUS_PROC &&
+ proc_table->field[2]->val_int() == TYPE_ENUM_PROCEDURE ||
+ lex->orig_sql_command == SQLCOM_SHOW_STATUS_FUNC &&
+ proc_table->field[2]->val_int() == TYPE_ENUM_FUNCTION ||
+ lex->orig_sql_command == SQLCOM_END)
+ {
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[1], &tmp_string);
+ if (!wild || !wild[0] || !wild_compare(tmp_string.ptr(), wild, 0))
+ {
+ table->field[3]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[3], &tmp_string);
+ table->field[0]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[0], &tmp_string);
+ table->field[2]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[2], &tmp_string);
+ table->field[4]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[9], &tmp_string);
+ table->field[5]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->field[6]->store("SQL", 3, cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[10], &tmp_string);
+ table->field[7]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->field[8]->store("SQL", 3, cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[6], &tmp_string);
+ table->field[11]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[5], &tmp_string);
+ table->field[12]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[7], &tmp_string);
+ table->field[14]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ bzero((char *)&time, sizeof(time));
+ ((Field_timestamp *) proc_table->field[12])->get_time(&time);
+ table->field[15]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ bzero((char *)&time, sizeof(time));
+ ((Field_timestamp *) proc_table->field[13])->get_time(&time);
+ table->field[16]->store_time(&time, MYSQL_TIMESTAMP_DATETIME);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[14], &tmp_string);
+ table->field[17]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[15], &tmp_string);
+ table->field[18]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ tmp_string.length(0);
+ get_field(thd->mem_root, proc_table->field[11], &tmp_string);
+ table->field[19]->store(tmp_string.ptr(), tmp_string.length(), cs);
+ table->file->write_row(table->record[0]);
+ }
+ }
+}
- if (protocol->send_fields(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
+
+int fill_schema_proc(THD *thd, TABLE_LIST *tables, COND *cond)
+{
+ TABLE *proc_table;
+ TABLE_LIST proc_tables;
+ const char *wild= thd->lex->wild ? thd->lex->wild->ptr() : NullS;
+ int res= 0;
+ TABLE *table= tables->table, *old_open_tables= thd->open_tables;
+ DBUG_ENTER("fill_schema_proc");
+
+ bzero((char*) &proc_tables,sizeof(proc_tables));
+ proc_tables.db= (char*) "mysql";
+ proc_tables.real_name= proc_tables.alias= (char*) "proc";
+ proc_tables.lock_type= TL_READ;
+ if (!(proc_table= open_ltable(thd, &proc_tables, TL_READ)))
+ {
DBUG_RETURN(1);
+ }
+ proc_table->file->ha_index_init(0);
+ if ((res= proc_table->file->index_first(proc_table->record[0])))
+ {
+ res= (res == HA_ERR_END_OF_FILE) ? 0 : 1;
+ goto err;
+ }
+ store_schema_proc(thd, table, proc_table, wild);
+ while (!proc_table->file->index_next(proc_table->record[0]))
+ store_schema_proc(thd, table, proc_table, wild);
- for ( cs= all_charsets ; cs < all_charsets+255 ; cs++ )
+err:
+ proc_table->file->ha_index_end();
+ close_thread_tables(thd, 0, 0, old_open_tables);
+ DBUG_RETURN(res);
+}
+
+
+static int get_schema_stat_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("get_schema_stat_record");
+ if (!res && !tables->view)
{
- if (cs[0] && (cs[0]->state & MY_CS_PRIMARY) &&
- (cs[0]->state & MY_CS_AVAILABLE) &&
- !(wild && wild[0] &&
- wild_case_compare(system_charset_info,cs[0]->csname,wild)))
+ TABLE *show_table= tables->table;
+ KEY *key_info=show_table->key_info;
+ show_table->file->info(HA_STATUS_VARIABLE |
+ HA_STATUS_NO_LOCK |
+ HA_STATUS_TIME);
+ for (uint i=0 ; i < show_table->keys ; i++,key_info++)
{
- if (write_charset(protocol, cs[0]))
- goto err;
+ KEY_PART_INFO *key_part= key_info->key_part;
+ const char *str;
+ for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
+ {
+ restore_record(table, default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[2]->store(file_name, strlen(file_name), cs);
+ table->field[3]->store((longlong) ((key_info->flags &
+ HA_NOSAME) ? 0 :1));
+ table->field[4]->store(base_name, strlen(base_name), cs);
+ table->field[5]->store(key_info->name, strlen(key_info->name), cs);
+ table->field[6]->store((longlong) (j+1));
+ str=(key_part->field ? key_part->field->field_name :
+ "?unknown field?");
+ table->field[7]->store(str, strlen(str), cs);
+ if (show_table->file->index_flags(i, j, 0) & HA_READ_ORDER)
+ {
+ table->field[8]->store(((key_part->key_part_flag &
+ HA_REVERSE_SORT) ?
+ "D" : "A"), 1, cs);
+ table->field[8]->set_notnull();
+ }
+ KEY *key=show_table->key_info+i;
+ if (key->rec_per_key[j])
+ {
+ ha_rows records=(show_table->file->records /
+ key->rec_per_key[j]);
+ table->field[9]->store((longlong) records);
+ table->field[9]->set_notnull();
+ }
+ if (!(key_info->flags & HA_FULLTEXT) &&
+ (!key_part->field ||
+ key_part->length !=
+ show_table->field[key_part->fieldnr-1]->key_length()))
+ {
+ table->field[10]->store((longlong) key_part->length);
+ table->field[10]->set_notnull();
+ }
+ uint flags= key_part->field ? key_part->field->flags : 0;
+ const char *pos=(char*) ((flags & NOT_NULL_FLAG) ? "" : "YES");
+ table->field[12]->store(pos, strlen(pos), cs);
+ pos= show_table->file->index_type(i);
+ table->field[13]->store(pos, strlen(pos), cs);
+ if (!show_table->keys_in_use.is_set(i))
+ table->field[14]->store("disabled", 8, cs);
+ else
+ table->field[14]->store("", 0, cs);
+ table->field[14]->set_notnull();
+ table->file->write_row(table->record[0]);
+ }
}
}
- send_eof(thd);
- DBUG_RETURN(0);
-err:
- DBUG_RETURN(1);
+ DBUG_RETURN(res);
}
-
-int mysqld_show(THD *thd, const char *wild, show_var_st *variables,
- enum enum_var_type value_type,
- pthread_mutex_t *mutex,
- struct system_status_var *status_var)
+static int get_schema_views_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
{
- char buff[1024];
- List<Item> field_list;
- Protocol *protocol= thd->protocol;
- LEX_STRING null_lex_str;
- DBUG_ENTER("mysqld_show");
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("get_schema_views_record");
+ if (!res)
+ {
+ if (tables->view)
+ {
+ restore_record(table, default_values);
+ table->field[1]->store(tables->view_db.str, tables->view_db.length, cs);
+ table->field[2]->store(tables->view_name.str,tables->view_name.length,cs);
+ table->field[3]->store(tables->query.str, tables->query.length, cs);
- field_list.push_back(new Item_empty_string("Variable_name",30));
- field_list.push_back(new Item_empty_string("Value",256));
- if (protocol->send_fields(&field_list,
- Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(1); /* purecov: inspected */
- null_lex_str.str= 0; // For sys_var->value_ptr()
- null_lex_str.length= 0;
+ if (tables->with_check != VIEW_CHECK_NONE)
+ {
+ if (tables->with_check == VIEW_CHECK_LOCAL)
+ table->field[4]->store("WITH LOCAL CHECK OPTION", 23, cs);
+ else
+ table->field[4]->store("WITH CASCADED CHECK OPTION", 26, cs);
+ }
+ else
+ table->field[4]->store("NONE", 4, cs);
- pthread_mutex_lock(mutex);
- for (; variables->name; variables++)
+ if (tables->updatable_view)
+ table->field[5]->store("YES", 3, cs);
+ else
+ table->field[5]->store("NO", 2, cs);
+ table->file->write_row(table->record[0]);
+ }
+ }
+ DBUG_RETURN(res);
+}
+
+
+static int get_schema_constarints_record(THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("get_schema_constarints_record");
+ if (!res && !tables->view)
+ {
+ List<FOREIGN_KEY_INFO> f_key_list;
+ TABLE *show_table= tables->table;
+ KEY *key_info=show_table->key_info;
+ uint primary_key= show_table->primary_key;
+ show_table->file->info(HA_STATUS_VARIABLE |
+ HA_STATUS_NO_LOCK |
+ HA_STATUS_TIME);
+ for (uint i=0 ; i < show_table->keys ; i++, key_info++)
+ {
+ if (i != primary_key && !(key_info->flags & HA_NOSAME))
+ continue;
+ restore_record(table, default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[2]->store(key_info->name, strlen(key_info->name), cs);
+ table->field[3]->store(base_name, strlen(base_name), cs);
+ table->field[4]->store(file_name, strlen(file_name), cs);
+ if (i == primary_key && !strcmp(key_info->name, primary_key_name))
+ table->field[5]->store("PRIMARY KEY", 11, cs);
+ else if (key_info->flags & HA_NOSAME)
+ table->field[5]->store("UNIQUE", 6, cs);
+ table->file->write_row(table->record[0]);
+ }
+
+ show_table->file->get_foreign_key_list(thd, &f_key_list);
+ FOREIGN_KEY_INFO *f_key_info;
+ List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
+ while ((f_key_info=it++))
+ {
+ restore_record(table, default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[2]->store(f_key_info->forein_id->str,
+ f_key_info->forein_id->length, cs);
+ table->field[3]->store(base_name, strlen(base_name), cs);
+ table->field[4]->store(file_name, strlen(file_name), cs);
+ table->field[5]->store("FOREIGN KEY", 11, system_charset_info);
+ table->field[6]->store(f_key_info->constraint_method->str,
+ f_key_info->constraint_method->length, cs);
+ table->field[6]->set_notnull();
+ table->file->write_row(table->record[0]);
+ }
+ }
+ DBUG_RETURN(res);
+}
+
+
+static int get_schema_key_column_usage_record(THD *thd,
+ struct st_table_list *tables,
+ TABLE *table, bool res,
+ const char *base_name,
+ const char *file_name)
+{
+ DBUG_ENTER("get_schema_key_column_usage_record");
+ CHARSET_INFO *cs= system_charset_info;
+ if (!res && !tables->view)
{
- if (!(wild && wild[0] && wild_case_compare(system_charset_info,
- variables->name,wild)))
+ List<FOREIGN_KEY_INFO> f_key_list;
+ TABLE *show_table= tables->table;
+ KEY *key_info=show_table->key_info;
+ uint primary_key= show_table->primary_key;
+ show_table->file->info(HA_STATUS_VARIABLE |
+ HA_STATUS_NO_LOCK |
+ HA_STATUS_TIME);
+ for (uint i=0 ; i < show_table->keys ; i++, key_info++)
{
- protocol->prepare_for_resend();
- protocol->store(variables->name, system_charset_info);
- SHOW_TYPE show_type=variables->type;
- char *value=variables->value;
- const char *pos, *end;
- long nr;
-
- if (show_type == SHOW_SYS)
+ if (i != primary_key && !(key_info->flags & HA_NOSAME))
+ continue;
+ uint f_idx= 0;
+ KEY_PART_INFO *key_part= key_info->key_part;
+ for (uint j=0 ; j < key_info->key_parts ; j++,key_part++)
{
- show_type= ((sys_var*) value)->type();
- value= (char*) ((sys_var*) value)->value_ptr(thd, value_type,
- &null_lex_str);
+ uint f_idx= 0;
+ if (key_part->field)
+ {
+ f_idx++;
+ restore_record(table, default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[2]->store(key_info->name, strlen(key_info->name), cs);
+ table->field[4]->store(base_name, strlen(base_name), cs);
+ table->field[5]->store(file_name, strlen(file_name), cs);
+ table->field[6]->store(key_part->field->field_name,
+ strlen(key_part->field->field_name), cs);
+ table->field[7]->store((longlong) f_idx);
+ table->file->write_row(table->record[0]);
+ }
}
+ }
- pos= end= buff;
- switch (show_type) {
- case SHOW_LONG_STATUS:
- case SHOW_LONG_CONST_STATUS:
- value= ((char *) status_var + (uint) value);
- /* fall through */
- case SHOW_LONG:
- case SHOW_LONG_CONST:
- end= int10_to_str(*(long*) value, buff, 10);
- break;
- case SHOW_LONGLONG:
- end= longlong10_to_str(*(longlong*) value, buff, 10);
- break;
- case SHOW_HA_ROWS:
- end= longlong10_to_str((longlong) *(ha_rows*) value, buff, 10);
- break;
- case SHOW_BOOL:
- end= strmov(buff, *(bool*) value ? "ON" : "OFF");
- break;
- case SHOW_MY_BOOL:
- end= strmov(buff, *(my_bool*) value ? "ON" : "OFF");
- break;
- case SHOW_INT_CONST:
- case SHOW_INT:
- end= int10_to_str((long) *(uint32*) value, buff, 10);
- break;
- case SHOW_HAVE:
+ show_table->file->get_foreign_key_list(thd, &f_key_list);
+ FOREIGN_KEY_INFO *f_key_info;
+ List_iterator_fast<FOREIGN_KEY_INFO> it(f_key_list);
+ while ((f_key_info= it++))
+ {
+ LEX_STRING *f_info, *r_info;
+ List_iterator_fast<LEX_STRING> it(f_key_info->foreign_fields),
+ it1(f_key_info->referenced_fields);
+ uint f_idx= 0;
+ while ((f_info= it++))
{
- SHOW_COMP_OPTION tmp= *(SHOW_COMP_OPTION*) value;
- pos= show_comp_option_name[(int) tmp];
- end= strend(pos);
- break;
+ r_info= it1++;
+ f_idx++;
+ restore_record(table, default_values);
+ table->field[1]->store(base_name, strlen(base_name), cs);
+ table->field[2]->store(f_key_info->forein_id->str,
+ f_key_info->forein_id->length, cs);
+ table->field[4]->store(base_name, strlen(base_name), cs);
+ table->field[5]->store(file_name, strlen(file_name), cs);
+ table->field[6]->store(f_info->str, f_info->length, cs);
+ table->field[7]->store((longlong) f_idx);
+ table->field[8]->store(f_key_info->referenced_db->str,
+ f_key_info->referenced_db->length, cs);
+ table->field[9]->set_notnull();
+ table->field[10]->store(f_key_info->referenced_table->str,
+ f_key_info->referenced_table->length, cs);
+ table->field[9]->set_notnull();
+ table->field[10]->store(r_info->str, r_info->length, cs);
+ table->field[10]->set_notnull();
+ table->file->write_row(table->record[0]);
}
- case SHOW_CHAR:
- {
- if (!(pos= value))
- pos= "";
- end= strend(pos);
- break;
- }
- case SHOW_STARTTIME:
- nr= (long) (thd->query_start() - start_time);
- end= int10_to_str(nr, buff, 10);
- break;
- case SHOW_QUESTION:
- end= int10_to_str((long) thd->query_id, buff, 10);
- break;
-#ifdef HAVE_REPLICATION
- case SHOW_RPL_STATUS:
- end= strmov(buff, rpl_status_type[(int)rpl_status]);
- break;
- case SHOW_SLAVE_RUNNING:
+ }
+ }
+ DBUG_RETURN(res);
+}
+
+
+/*
+ Find schema_tables elment by name
+
+ SYNOPSIS
+ find_schema_table()
+ thd thread handler
+ table_name table name
+
+ RETURN
+ 0 table not found
+ # pointer to 'shema_tables' element
+*/
+
+ST_SCHEMA_TABLE *find_schema_table(THD *thd, const char* table_name)
+{
+ ST_SCHEMA_TABLE *schema_table= schema_tables;
+ for ( ; schema_table->table_name; schema_table++)
+ {
+ if (!my_strcasecmp(system_charset_info,
+ schema_table->table_name,
+ table_name))
+ return schema_table;
+ }
+ return 0;
+}
+
+
+ST_SCHEMA_TABLE *get_schema_table(enum enum_schema_tables schema_table_idx)
+{
+ return &schema_tables[schema_table_idx];
+}
+
+
+/*
+ Create information_schema table using schema_table data
+
+ SYNOPSIS
+ create_schema_table()
+ thd thread handler
+ schema_table pointer to 'shema_tables' element
+
+ RETURN
+ # Pointer to created table
+ 0 Can't create table
+*/
+
+TABLE *create_schema_table(THD *thd, TABLE_LIST *table_list)
+{
+ int field_count= 0;
+ Item *item;
+ TABLE *table;
+ List<Item> field_list;
+ ST_SCHEMA_TABLE *schema_table= table_list->schema_table;
+ ST_FIELD_INFO *fields_info= schema_table->fields_info;
+ CHARSET_INFO *cs= system_charset_info;
+ DBUG_ENTER("create_schema_table");
+
+ for ( ; fields_info->field_name; fields_info++)
+ {
+ switch (fields_info->field_type) {
+ case MYSQL_TYPE_LONG:
+ if (!(item= new Item_int(fields_info->field_name,
+ fields_info->value,
+ fields_info->field_length)))
{
- pthread_mutex_lock(&LOCK_active_mi);
- end= strmov(buff, (active_mi->slave_running &&
- active_mi->rli.slave_running) ? "ON" : "OFF");
- pthread_mutex_unlock(&LOCK_active_mi);
- break;
+ DBUG_RETURN(0);
}
-#endif /* HAVE_REPLICATION */
- case SHOW_OPENTABLES:
- end= int10_to_str((long) cached_tables(), buff, 10);
- break;
- case SHOW_CHAR_PTR:
+ break;
+ case MYSQL_TYPE_TIMESTAMP:
+ if (!(item=new Item_datetime(fields_info->field_name)))
{
- if (!(pos= *(char**) value))
- pos= "";
- end= strend(pos);
- break;
+ DBUG_RETURN(0);
}
- case SHOW_DOUBLE:
+ break;
+ default:
+ /* this should be changed when Item_empty_string is fixed(in 4.1) */
+ if (!(item= new Item_empty_string("", 0, cs)))
{
- end= buff + sprintf(buff, "%f", *(double*) value);
- break;
+ DBUG_RETURN(0);
}
-#ifdef HAVE_OPENSSL
- /* First group - functions relying on CTX */
- case SHOW_SSL_CTX_SESS_ACCEPT:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_ACCEPT_GOOD:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_good(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_CONNECT_GOOD:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_good(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_ACCEPT_RENEGOTIATE:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_accept_renegotiate(ssl_acceptor_fd->ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_CONNECT_RENEGOTIATE:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect_renegotiate(ssl_acceptor_fd-> ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_CB_HITS:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cb_hits(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_HITS:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_hits(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_CACHE_FULL:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_cache_full(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_MISSES:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_misses(ssl_acceptor_fd->
- ssl_context)),
- buff, 10);
- break;
- case SHOW_SSL_CTX_SESS_TIMEOUTS:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_timeouts(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_SESS_NUMBER:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_number(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_SESS_CONNECT:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_connect(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_SESS_GET_CACHE_SIZE:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_sess_get_cache_size(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_GET_VERIFY_MODE:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_mode(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_GET_VERIFY_DEPTH:
- end= int10_to_str((long) (!ssl_acceptor_fd ? 0 :
- SSL_CTX_get_verify_depth(ssl_acceptor_fd->ssl_context)),
- buff,10);
- break;
- case SHOW_SSL_CTX_GET_SESSION_CACHE_MODE:
- if (!ssl_acceptor_fd)
- {
- pos= "NONE";
- end= pos+4;
- break;
- }
- switch (SSL_CTX_get_session_cache_mode(ssl_acceptor_fd->ssl_context))
- {
- case SSL_SESS_CACHE_OFF:
- pos= "OFF";
- break;
- case SSL_SESS_CACHE_CLIENT:
- pos= "CLIENT";
- break;
- case SSL_SESS_CACHE_SERVER:
- pos= "SERVER";
- break;
- case SSL_SESS_CACHE_BOTH:
- pos= "BOTH";
- break;
- case SSL_SESS_CACHE_NO_AUTO_CLEAR:
- pos= "NO_AUTO_CLEAR";
- break;
- case SSL_SESS_CACHE_NO_INTERNAL_LOOKUP:
- pos= "NO_INTERNAL_LOOKUP";
- break;
- default:
- pos= "Unknown";
- break;
- }
- end= strend(pos);
- break;
- /* First group - functions relying on SSL */
- case SHOW_SSL_GET_VERSION:
- pos= (thd->net.vio->ssl_arg ?
- SSL_get_version((SSL*) thd->net.vio->ssl_arg) : "");
- end= strend(pos);
- break;
- case SHOW_SSL_SESSION_REUSED:
- end= int10_to_str((long) (thd->net.vio->ssl_arg ?
- SSL_session_reused((SSL*) thd->net.vio->
- ssl_arg) :
- 0),
- buff, 10);
- break;
- case SHOW_SSL_GET_DEFAULT_TIMEOUT:
- end= int10_to_str((long) (thd->net.vio->ssl_arg ?
- SSL_get_default_timeout((SSL*) thd->net.vio->
- ssl_arg) :
- 0),
- buff, 10);
- break;
- case SHOW_SSL_GET_VERIFY_MODE:
- end= int10_to_str((long) (thd->net.vio->ssl_arg ?
- SSL_get_verify_mode((SSL*) thd->net.vio->
- ssl_arg):
- 0),
- buff, 10);
- break;
- case SHOW_SSL_GET_VERIFY_DEPTH:
- end= int10_to_str((long) (thd->net.vio->ssl_arg ?
- SSL_get_verify_depth((SSL*) thd->net.vio->
- ssl_arg):
- 0),
- buff, 10);
- break;
- case SHOW_SSL_GET_CIPHER:
- pos= (thd->net.vio->ssl_arg ?
- SSL_get_cipher((SSL*) thd->net.vio->ssl_arg) : "" );
- end= strend(pos);
- break;
- case SHOW_SSL_GET_CIPHER_LIST:
- if (thd->net.vio->ssl_arg)
- {
- char *to= buff;
- for (int i=0 ; i++ ;)
- {
- const char *p= SSL_get_cipher_list((SSL*) thd->net.vio->ssl_arg,i);
- if (p == NULL)
- break;
- to= strmov(to, p);
- *to++= ':';
- }
- if (to != buff)
- to--; // Remove last ':'
- end= to;
- }
- break;
+ item->max_length= fields_info->field_length * cs->mbmaxlen;
+ item->set_name(fields_info->field_name,
+ strlen(fields_info->field_name), cs);
+ break;
+ }
+ field_list.push_back(item);
+ item->maybe_null= fields_info->maybe_null;
+ field_count++;
+ }
+ TMP_TABLE_PARAM *tmp_table_param =
+ (TMP_TABLE_PARAM*) (thd->calloc(sizeof(TMP_TABLE_PARAM)));
+ tmp_table_param->init();
+ tmp_table_param->table_charset= cs;
+ tmp_table_param->field_count= field_count;
+ SELECT_LEX *select_lex= thd->lex->current_select;
+ if (!(table= create_tmp_table(thd, tmp_table_param,
+ field_list, (ORDER*) 0, 0, 0,
+ (select_lex->options | thd->options |
+ TMP_TABLE_ALL_COLUMNS),
+ HA_POS_ERROR, table_list->alias)))
+ DBUG_RETURN(0);
+ DBUG_RETURN(table);
+}
-#endif /* HAVE_OPENSSL */
- case SHOW_KEY_CACHE_LONG:
- case SHOW_KEY_CACHE_CONST_LONG:
- value= (value-(char*) &dflt_key_cache_var)+ (char*) sql_key_cache;
- end= int10_to_str(*(long*) value, buff, 10);
- break;
- case SHOW_UNDEF: // Show never happen
- case SHOW_SYS:
- break; // Return empty string
- default:
- break;
+
+/*
+ For old SHOW compatibility. It is used when
+ old SHOW doesn't have generated column names
+ Make list of fields for SHOW
+
+ SYNOPSIS
+ make_old_format()
+ thd thread handler
+ schema_table pointer to 'schema_tables' element
+
+ RETURN
+ -1 errror
+ 0 success
+*/
+
+int make_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ ST_FIELD_INFO *field_info= schema_table->fields_info;
+ for ( ; field_info->field_name; field_info++)
+ {
+ if (field_info->old_name)
+ {
+ Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+ if (field)
+ {
+ field->set_name(field_info->old_name,
+ strlen(field_info->old_name),
+ system_charset_info);
+ if (add_item_to_list(thd, field))
+ return 1;
}
- if (protocol->store(pos, (uint32) (end - pos), system_charset_info) ||
- protocol->write())
- goto err; /* purecov: inspected */
}
}
- pthread_mutex_unlock(mutex);
- send_eof(thd);
+ return 0;
+}
+
+
+int make_schemata_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ char tmp[128];
+ LEX *lex= thd->lex;
+ SELECT_LEX *sel= lex->current_select;
+
+ if (!sel->item_list.elements)
+ {
+ ST_FIELD_INFO *field_info= &schema_table->fields_info[1];
+ String buffer(tmp,sizeof(tmp), system_charset_info);
+ Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+ if (!field || add_item_to_list(thd, field))
+ return 1;
+ buffer.length(0);
+ buffer.append(field_info->old_name);
+ if (lex->wild && lex->wild->ptr())
+ {
+ buffer.append(" (");
+ buffer.append(lex->wild->ptr());
+ buffer.append(")");
+ }
+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
+ }
+ return 0;
+}
+
+
+int make_table_names_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ char tmp[128];
+ String buffer(tmp,sizeof(tmp), thd->charset());
+ LEX *lex= thd->lex;
+
+ ST_FIELD_INFO *field_info= &schema_table->fields_info[2];
+ buffer.length(0);
+ buffer.append(field_info->old_name);
+ buffer.append(lex->select_lex.db);
+ if (lex->wild && lex->wild->ptr())
+ {
+ buffer.append(" (");
+ buffer.append(lex->wild->ptr());
+ buffer.append(")");
+ }
+ Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+ if (add_item_to_list(thd, field))
+ return 1;
+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
+ if (thd->lex->verbose)
+ {
+ field->set_name(buffer.ptr(), buffer.length(), system_charset_info);
+ field_info= &schema_table->fields_info[3];
+ field= new Item_field(NullS, NullS, field_info->field_name);
+ if (add_item_to_list(thd, field))
+ return 1;
+ field->set_name(field_info->old_name, strlen(field_info->old_name),
+ system_charset_info);
+ }
+ return 0;
+}
+
+
+int make_columns_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ int fields_arr[]= {3, 14, 13, 6, 15, 5, 16, 17, 18, -1};
+ int *field_num= fields_arr;
+ ST_FIELD_INFO *field_info;
+ for (; *field_num >= 0; field_num++)
+ {
+ field_info= &schema_table->fields_info[*field_num];
+ if (!thd->lex->verbose && (*field_num == 13 ||
+ *field_num == 17 ||
+ *field_num == 18))
+ continue;
+ Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+ if (field)
+ {
+ field->set_name(field_info->old_name,
+ strlen(field_info->old_name),
+ system_charset_info);
+ if (add_item_to_list(thd, field))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+int make_proc_old_format(THD *thd, ST_SCHEMA_TABLE *schema_table)
+{
+ int fields_arr[]= {2, 3, 4, 19, 16, 15, 14, 18, -1};
+ int *field_num= fields_arr;
+ ST_FIELD_INFO *field_info;
+ for (; *field_num >= 0; field_num++)
+ {
+ field_info= &schema_table->fields_info[*field_num];
+ Item_field *field= new Item_field(NullS, NullS, field_info->field_name);
+ if (field)
+ {
+ field->set_name(field_info->old_name,
+ strlen(field_info->old_name),
+ system_charset_info);
+ if (add_item_to_list(thd, field))
+ return 1;
+ }
+ }
+ return 0;
+}
+
+
+/*
+ Create information_schema table
+
+ SYNOPSIS
+ mysql_schema_table()
+ thd thread handler
+ lex pointer to LEX
+ table_list pointer to table_list
+
+ RETURN
+ 0 success
+ 1 error
+*/
+
+int mysql_schema_table(THD *thd, LEX *lex, TABLE_LIST *table_list)
+{
+ TABLE *table;
+ DBUG_ENTER("mysql_schema_table");
+ if (!(table= table_list->schema_table->create_table(thd, table_list)))
+ {
+ DBUG_RETURN(1);
+ }
+ table->tmp_table= TMP_TABLE;
+ table->grant.privilege= SELECT_ACL;
+ table->alias_name_used= my_strcasecmp(table_alias_charset,
+ table_list->real_name,
+ table_list->alias);
+ table_list->schema_table_name= table_list->real_name;
+ table_list->real_name= table->real_name;
+ table_list->table= table;
+ table->next= thd->derived_tables;
+ thd->derived_tables= table;
+ table_list->select_lex->options |= OPTION_SCHEMA_TABLE;
DBUG_RETURN(0);
+}
- err:
- pthread_mutex_unlock(mutex);
- DBUG_RETURN(1);
+
+/*
+ Generate select from information_schema table
+
+ SYNOPSIS
+ make_schema_select()
+ thd thread handler
+ sel pointer to SELECT_LEX
+ schema_table_idx index of 'schema_tables' element
+
+ RETURN
+ 0 success
+ 1 error
+*/
+
+int make_schema_select(THD *thd, SELECT_LEX *sel,
+ enum enum_schema_tables schema_table_idx)
+{
+ ST_SCHEMA_TABLE *schema_table= get_schema_table(schema_table_idx);
+ LEX_STRING db, table;
+ DBUG_ENTER("mysql_schema_select");
+ /*
+ We have to make non const db_name & table_name
+ because of lower_case_table_names
+ */
+ make_lex_string(thd, &db, information_schema_name.str,
+ information_schema_name.length, 0);
+ make_lex_string(thd, &table, schema_table->table_name,
+ strlen(schema_table->table_name), 0);
+ if (!sel->item_list.elements && /* Handle old syntax */
+ schema_table->old_format(thd, schema_table) ||
+ !sel->add_table_to_list(thd, new Table_ident(thd, db, table, 0),
+ 0, 0, TL_READ, (List<String> *) 0,
+ (List<String> *) 0))
+ {
+ DBUG_RETURN(1);
+ }
+ DBUG_RETURN(0);
}
-/* collect status for all running threads */
+/*
+ Fill temporaty schema tables before SELECT
-void calc_sum_of_all_status(STATUS_VAR *to)
+ SYNOPSIS
+ get_schema_tables_result()
+ join join which use schema tables
+
+ RETURN
+ FALSE success
+ TRUE error
+*/
+
+bool get_schema_tables_result(JOIN *join)
{
- DBUG_ENTER("calc_sum_of_all_status");
+ DBUG_ENTER("get_schema_tables_result");
+ JOIN_TAB *tmp_join_tab= join->join_tab+join->tables;
+ THD *thd= join->thd;
+ LEX *lex= thd->lex;
+ bool result= 0;
+ for (JOIN_TAB *tab= join->join_tab; tab < tmp_join_tab; tab++)
+ {
+ if (!tab->table || !tab->table->pos_in_table_list)
+ break;
- /* Ensure that thread id not killed during loop */
- VOID(pthread_mutex_lock(&LOCK_thread_count)); // For unlink from list
+ TABLE_LIST *table_list= tab->table->pos_in_table_list;
+ if (table_list->schema_table && thd->fill_derived_tables())
+ {
+ TABLE_LIST *save_next_global= table_list->next_global;
+ TABLE_LIST **query_tables_last= lex->query_tables_last;
+ TABLE *old_derived_tables= thd->derived_tables;
+ MYSQL_LOCK *sql_lock= thd->lock;
+ lex->sql_command= SQLCOM_SHOW_FIELDS;
- I_List_iterator<THD> it(threads);
- THD *tmp;
-
- /* Get global values as base */
- *to= global_status_var;
-
- /* Add to this status from existing threads */
- while ((tmp= it++))
- add_to_status(to, &tmp->status_var);
-
- VOID(pthread_mutex_unlock(&LOCK_thread_count));
- DBUG_VOID_RETURN;
+ if (&lex->unit != lex->current_select->master_unit()) // is subselect
+ {
+ table_list->table->file->extra(HA_EXTRA_RESET_STATE);
+ table_list->table->file->delete_all_rows();
+ free_io_cache(table_list->table);
+ filesort_free_buffers(table_list->table);
+ }
+ else
+ table_list->table->file->records= 0;
+
+ thd->derived_tables= 0;
+ thd->lock=0;
+ if (table_list->schema_table->fill_table(thd, table_list,
+ tab->select_cond))
+ result= 1;
+ thd->lock= sql_lock;
+ lex->sql_command= SQLCOM_SELECT;
+ thd->derived_tables= old_derived_tables;
+ table_list->next_global= save_next_global;
+ lex->query_tables_last= query_tables_last;
+ }
+ }
+ DBUG_RETURN(result);
}
+ST_FIELD_INFO schema_fields_info[]=
+{
+ {"CATALOG_NAME", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"SCHEMA_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Database"},
+ {"DEFAULT_CHARACTER_SET_NAME", 60, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"SQL_PATH", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO tables_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
+ {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ENGINE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Engine"},
+ {"VERSION", 21 , MYSQL_TYPE_LONG, 0, 1, "Version"},
+ {"ROW_FORMAT", 10, MYSQL_TYPE_STRING, 0, 1, "Row_format"},
+ {"TABLE_ROWS", 21 , MYSQL_TYPE_LONG, 0, 1, "Rows"},
+ {"AVG_ROW_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Avg_row_length"},
+ {"DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_length"},
+ {"MAX_DATA_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Max_data_length"},
+ {"INDEX_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 1, "Index_length"},
+ {"DATA_FREE", 21 , MYSQL_TYPE_LONG, 0, 1, "Data_free"},
+ {"AUTO_INCREMENT", 21 , MYSQL_TYPE_LONG, 0, 1, "Auto_increment"},
+ {"CREATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Create_time"},
+ {"UPDATE_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Update_time"},
+ {"CHECK_TIME", 0, MYSQL_TYPE_TIMESTAMP, 0, 1, "Check_time"},
+ {"COLLATION", 60, MYSQL_TYPE_STRING, 0, 1, "Collation"},
+ {"CHECKSUM", 21 , MYSQL_TYPE_LONG, 0, 1, "Checksum"},
+ {"CREATE_OPTIONS", 255, MYSQL_TYPE_STRING, 0, 1, "Create_options"},
+ {"TABLE_COMMENT", 80, MYSQL_TYPE_STRING, 0, 0, "Comment"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO columns_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Field"},
+ {"ORDINAL_POSITION", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
+ {"COLUMN_DEFAULT", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, "Default"},
+ {"IS_NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
+ {"DATA_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CHARACTER_MAXIMUM_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
+ {"CHARACTER_OCTET_LENGTH", 21 , MYSQL_TYPE_LONG, 0, 0, 0},
+ {"NUMERIC_PRECISION", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
+ {"NUMERIC_SCALE", 21 , MYSQL_TYPE_LONG, 0, 1, 0},
+ {"CHARACTER_SET_NAME", 40, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"COLLATION_NAME", 40, MYSQL_TYPE_STRING, 0, 1, "Collation"},
+ {"COLUMN_TYPE", 65535, MYSQL_TYPE_STRING, 0, 0, "Type"},
+ {"COLUMN_KEY", 3, MYSQL_TYPE_STRING, 0, 0, "Key"},
+ {"EXTRA", 20, MYSQL_TYPE_STRING, 0, 0, "Extra"},
+ {"PRIVILEGES", 80, MYSQL_TYPE_STRING, 0, 0, "Privileges"},
+ {"COLUMN_COMMENT", 255, MYSQL_TYPE_STRING, 0, 0, "Comment"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO charsets_fields_info[]=
+{
+ {"CHARACTER_SET_NAME", 30, MYSQL_TYPE_STRING, 0, 0, "Charset"},
+ {"DESCRIPTION", 60, MYSQL_TYPE_STRING, 0, 0, "Description"},
+ {"DEFAULT_COLLATE_NAME", 60, MYSQL_TYPE_STRING, 0, 0, "Default collation"},
+ {"MAXLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Maxlen"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO collation_fields_info[]=
+{
+ {"COLLATION_NAME", 30, MYSQL_TYPE_STRING, 0, 0, "Collation"},
+ {"CHARSET", 30, MYSQL_TYPE_STRING, 0, 0, "Charset"},
+ {"ID", 11, MYSQL_TYPE_LONG, 0, 0, "Id"},
+ {"DEFAULT", 30 ,MYSQL_TYPE_STRING, 0, 0, "Default"},
+ {"COMPILED", 30 ,MYSQL_TYPE_STRING, 0, 0, "Compiled"},
+ {"SORTLEN", 3 ,MYSQL_TYPE_LONG, 0, 0, "Sortlen"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO coll_charset_app_fields_info[]=
+{
+ {"COLLATION_NAME", 30, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CHARACTER_SET_NAME", 30, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO proc_fields_info[]=
+{
+ {"SPECIFIC_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ROUTINE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"ROUTINE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Db"},
+ {"ROUTINE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Name"},
+ {"ROUTINE_TYPE", 9, MYSQL_TYPE_STRING, 0, 0, "Type"},
+ {"DTD_IDENTIFIER", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ROUTINE_BODY", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ROUTINE_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"EXTERNAL_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"EXTERNAL_LANGUAGE", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"PARAMETER_STYLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_DETERMINISTIC", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"SQL_DATA_ACCESS", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"SQL_PATH", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"SECURITY_TYPE", 7, MYSQL_TYPE_STRING, 0, 0, "Security_type"},
+ {"CREATED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Created"},
+ {"LAST_ALTERED", 0, MYSQL_TYPE_TIMESTAMP, 0, 0, "Modified"},
+ {"SQL_MODE", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ROUTINE_COMMENT", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Comment"},
+ {"DEFINER", 77, MYSQL_TYPE_STRING, 0, 0, "Definer"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO stat_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table"},
+ {"NON_UNIQUE", 1, MYSQL_TYPE_LONG, 0, 0, "Non_unique"},
+ {"INDEX_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"INDEX_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Key_name"},
+ {"SEQ_IN_INDEX", 2, MYSQL_TYPE_LONG, 0, 0, "Seq_in_index"},
+ {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Column_name"},
+ {"COLLATION", 1, MYSQL_TYPE_STRING, 0, 1, "Collation"},
+ {"CARDINALITY", 21, MYSQL_TYPE_LONG, 0, 1, "Cardinality"},
+ {"SUB_PART", 3, MYSQL_TYPE_LONG, 0, 1, "Sub_part"},
+ {"PACKED", 10, MYSQL_TYPE_STRING, 0, 1, "Packed"},
+ {"NULLABLE", 3, MYSQL_TYPE_STRING, 0, 0, "Null"},
+ {"INDEX_TYPE", 16, MYSQL_TYPE_STRING, 0, 0, "Index_type"},
+ {"COMMENT", 16, MYSQL_TYPE_STRING, 0, 1, "Comment"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO view_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"VIEW_DEFINITION", 65535, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CHECK_OPTION", 30, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_UPDATABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO user_privileges_fields_info[]=
+{
+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO schema_privileges_fields_info[]=
+{
+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO table_privileges_fields_info[]=
+{
+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO column_privileges_fields_info[]=
+{
+ {"GRANTEE", 81, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"PRIVILEGE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"IS_GRANTABLE", 3, MYSQL_TYPE_STRING, 0, 0, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO table_constraints_fields_info[]=
+{
+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CONSTRAINT_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CONSTRAINT_METHOD", 20, MYSQL_TYPE_STRING, 0, 1, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO key_column_usage_fields_info[]=
+{
+ {"CONSTRAINT_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"CONSTRAINT_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"CONSTRAINT_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"ORDINAL_POSITION", 10 ,MYSQL_TYPE_LONG, 0, 0, 0},
+ {"REFERENCED_TABLE_SCHEMA", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"REFERENCED_TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"REFERENCED_COLUMN_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+ST_FIELD_INFO table_names_fields_info[]=
+{
+ {"TABLE_CATALOG", FN_REFLEN, MYSQL_TYPE_STRING, 0, 1, 0},
+ {"TABLE_SCHEMA",NAME_LEN, MYSQL_TYPE_STRING, 0, 0, 0},
+ {"TABLE_NAME", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Tables_in_"},
+ {"TABLE_TYPE", NAME_LEN, MYSQL_TYPE_STRING, 0, 0, "Table_type"},
+ {0, 0, MYSQL_TYPE_STRING, 0, 0, 0}
+};
+
+
+/*
+ Description of ST_FIELD_INFO in table.h
+*/
+
+ST_SCHEMA_TABLE schema_tables[]=
+{
+ {"SCHEMATA", schema_fields_info, create_schema_table,
+ fill_schema_shemata, make_schemata_old_format, 0, 1, -1},
+ {"TABLES", tables_fields_info, create_schema_table,
+ get_all_tables, make_old_format, get_schema_tables_record, 1, 2},
+ {"COLUMNS", columns_fields_info, create_schema_table,
+ get_all_tables, make_columns_old_format, get_schema_column_record, 1, 2},
+ {"CHARACTER_SETS", charsets_fields_info, create_schema_table,
+ fill_schema_charsets, make_old_format, 0, -1, -1},
+ {"COLLATIONS", collation_fields_info, create_schema_table,
+ fill_schema_collation, make_old_format, 0, -1, -1},
+ {"COLLATION_CHARACTER_SET_APPLICABILITY", coll_charset_app_fields_info,
+ create_schema_table, fill_schema_coll_charset_app, 0, 0, -1, -1},
+ {"ROUTINES", proc_fields_info, create_schema_table,
+ fill_schema_proc, make_proc_old_format, 0, -1, -1},
+ {"STATISTICS", stat_fields_info, create_schema_table,
+ get_all_tables, make_old_format, get_schema_stat_record, 1, 2},
+ {"VIEWS", view_fields_info, create_schema_table,
+ get_all_tables, 0, get_schema_views_record, 1, 2},
+ {"USER_PRIVILEGES", user_privileges_fields_info, create_schema_table,
+ fill_schema_user_privileges, 0, 0, -1, -1},
+ {"SCHEMA_PRIVILEGES", schema_privileges_fields_info, create_schema_table,
+ fill_schema_schema_privileges, 0, 0, -1, -1},
+ {"TABLE_PRIVILEGES", table_privileges_fields_info, create_schema_table,
+ fill_schema_table_privileges, 0, 0, -1, -1},
+ {"COLUMN_PRIVILEGES", column_privileges_fields_info, create_schema_table,
+ fill_schema_column_privileges, 0, 0, -1, -1},
+ {"TABLE_CONSTRAINTS", table_constraints_fields_info, create_schema_table,
+ get_all_tables, 0, get_schema_constarints_record, 3, 4},
+ {"KEY_COLUMN_USAGE", key_column_usage_fields_info, create_schema_table,
+ get_all_tables, 0, get_schema_key_column_usage_record, 4, 5},
+ {"TABLE_NAMES", table_names_fields_info, create_schema_table,
+ get_all_tables, make_table_names_old_format, 0, 1, 2},
+ {0, 0, 0, 0, 0, 0, 0, 0}
+};
+
+
#ifdef __GNUC__
template class List_iterator_fast<char>;
template class List<char>;
diff --git a/sql/sql_string.cc b/sql/sql_string.cc
index 7d0dd3ca566..226a80201a1 100644
--- a/sql/sql_string.cc
+++ b/sql/sql_string.cc
@@ -121,12 +121,13 @@ bool String::set(ulonglong num, CHARSET_INFO *cs)
bool String::set(double num,uint decimals, CHARSET_INFO *cs)
{
char buff[331];
+ uint dummy_errors;
str_charset=cs;
if (decimals >= NOT_FIXED_DEC)
{
uint32 len= my_sprintf(buff,(buff, "%.14g",num));// Enough for a DATETIME
- return copy(buff, len, &my_charset_latin1, cs);
+ return copy(buff, len, &my_charset_latin1, cs, &dummy_errors);
}
#ifdef HAVE_FCONVERT
int decpt,sign;
@@ -141,7 +142,8 @@ bool String::set(double num,uint decimals, CHARSET_INFO *cs)
buff[0]='-';
pos=buff;
}
- return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs);
+ uint dummy_errors;
+ return copy(pos,(uint32) strlen(pos), &my_charset_latin1, cs, &dummy_errors);
}
if (alloc((uint32) ((uint32) decpt+3+decimals)))
return TRUE;
@@ -191,7 +193,8 @@ end:
#else
sprintf(buff,"%.*f",(int) decimals,num);
#endif
- return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs);
+ return copy(buff,(uint32) strlen(buff), &my_charset_latin1, cs,
+ &dummy_errors);
#endif
}
@@ -336,14 +339,12 @@ bool String::copy(const char *str, uint32 arg_length,
uint32 offset;
if (!needs_conversion(arg_length, from_cs, to_cs, &offset))
{
- if (errors)
- *errors= 0;
+ *errors= 0;
return copy(str, arg_length, to_cs);
}
if ((from_cs == &my_charset_bin) && offset)
{
- if (errors)
- *errors= 0;
+ *errors= 0;
return copy_aligned(str, arg_length, offset, to_cs);
}
uint32 new_length= to_cs->mbmaxlen*arg_length;
@@ -382,7 +383,8 @@ bool String::set_ascii(const char *str, uint32 arg_length)
set(str, arg_length, str_charset);
return 0;
}
- return copy(str, arg_length, &my_charset_latin1, str_charset);
+ uint dummy_errors;
+ return copy(str, arg_length, &my_charset_latin1, str_charset, &dummy_errors);
}
@@ -436,10 +438,12 @@ bool String::append(const char *s,uint32 arg_length)
if (str_charset->mbminlen > 1)
{
uint32 add_length=arg_length * str_charset->mbmaxlen;
+ uint dummy_errors;
if (realloc(str_length+ add_length))
return TRUE;
str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
- s, arg_length, &my_charset_latin1);
+ s, arg_length, &my_charset_latin1,
+ &dummy_errors);
return FALSE;
}
@@ -476,10 +480,11 @@ bool String::append(const char *s,uint32 arg_length, CHARSET_INFO *cs)
if (needs_conversion(arg_length, cs, str_charset, &dummy_offset))
{
uint32 add_length= arg_length / cs->mbminlen * str_charset->mbmaxlen;
+ uint dummy_errors;
if (realloc(str_length + add_length))
return TRUE;
str_length+= copy_and_convert(Ptr+str_length, add_length, str_charset,
- s, arg_length, cs);
+ s, arg_length, cs, &dummy_errors);
}
else
{
@@ -715,8 +720,8 @@ void String::qs_append(uint i)
int sortcmp(const String *s,const String *t, CHARSET_INFO *cs)
{
return cs->coll->strnncollsp(cs,
- (unsigned char *) s->ptr(),s->length(),
- (unsigned char *) t->ptr(),t->length());
+ (unsigned char *) s->ptr(),s->length(),
+ (unsigned char *) t->ptr(),t->length(), 0);
}
@@ -829,8 +834,7 @@ outp:
else
break;
}
- if (errors)
- *errors= error_count;
+ *errors= error_count;
return (uint32) (to - to_start);
}
diff --git a/sql/sql_string.h b/sql/sql_string.h
index d6807fa83ad..cb9db52c830 100644
--- a/sql/sql_string.h
+++ b/sql/sql_string.h
@@ -29,7 +29,7 @@ int sortcmp(const String *a,const String *b, CHARSET_INFO *cs);
String *copy_if_not_alloced(String *a,String *b,uint32 arg_length);
uint32 copy_and_convert(char *to, uint32 to_length, CHARSET_INFO *to_cs,
const char *from, uint32 from_length,
- CHARSET_INFO *from_cs, uint *errors= 0);
+ CHARSET_INFO *from_cs, uint *errors);
class String
{
@@ -72,9 +72,9 @@ public:
static void *operator new(size_t size, MEM_ROOT *mem_root)
{ return (void*) alloc_root(mem_root, (uint) size); }
static void operator delete(void *ptr_arg,size_t size)
- {}
+ { TRASH(ptr_arg, size); }
static void operator delete(void *ptr_arg,size_t size, MEM_ROOT *mem_root)
- {}
+ { TRASH(ptr_arg, size); }
~String() { free(); }
inline void set_charset(CHARSET_INFO *charset) { str_charset= charset; }
@@ -141,6 +141,34 @@ public:
bool set(longlong num, CHARSET_INFO *cs);
bool set(ulonglong num, CHARSET_INFO *cs);
bool set(double num,uint decimals, CHARSET_INFO *cs);
+
+ /*
+ PMG 2004.11.12
+ This is a method that works the same as perl's "chop". It simply
+ drops the last character of a string. This is useful in the case
+ of the federated storage handler where I'm building a unknown
+ number, list of values and fields to be used in a sql insert
+ statement to be run on the remote server, and have a comma after each.
+ When the list is complete, I "chop" off the trailing comma
+
+ ex.
+ String stringobj;
+ stringobj.append("VALUES ('foo', 'fi', 'fo',");
+ stringobj.chop();
+ stringobj.append(")");
+
+ In this case, the value of string was:
+
+ VALUES ('foo', 'fi', 'fo',
+ VALUES ('foo', 'fi', 'fo'
+ VALUES ('foo', 'fi', 'fo')
+
+ */
+ inline void chop()
+ {
+ Ptr[str_length--]= '\0';
+ }
+
inline void free()
{
if (alloced)
@@ -199,7 +227,7 @@ public:
CHARSET_INFO *cs);
bool set_or_copy_aligned(const char *s, uint32 arg_length, CHARSET_INFO *cs);
bool copy(const char*s,uint32 arg_length, CHARSET_INFO *csfrom,
- CHARSET_INFO *csto, uint *errors= 0);
+ CHARSET_INFO *csto, uint *errors);
bool append(const String &s);
bool append(const char *s);
bool append(const char *s,uint32 arg_length);
diff --git a/sql/sql_table.cc b/sql/sql_table.cc
index 26c483a61a8..56605d1c6e0 100644
--- a/sql/sql_table.cc
+++ b/sql/sql_table.cc
@@ -29,12 +29,6 @@
#include <io.h>
#endif
-#define tmp_disable_binlog(A) \
- ulong save_options= (A)->options; \
- (A)->options&= ~OPTION_BIN_LOG;
-
-#define reenable_binlog(A) (A)->options= save_options;
-
const char *primary_key_name="PRIMARY";
static bool check_if_keyname_exists(const char *name,KEY *start, KEY *end);
@@ -63,15 +57,15 @@ static int copy_data_between_tables(TABLE *from,TABLE *to,
Wait if global_read_lock (FLUSH TABLES WITH READ LOCK) is set.
RETURN
- 0 ok. In this case ok packet is sent to user
- -1 Error (Error message given but not sent to user)
+ FALSE OK. In this case ok packet is sent to user
+ TRUE Error
*/
-int 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, my_bool if_exists,
+ my_bool drop_temporary)
{
- int error= 0;
+ bool error= FALSE;
DBUG_ENTER("mysql_rm_table");
/* mark for close and remove all cached entries */
@@ -84,9 +78,8 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
{
if (thd->global_read_lock)
{
- my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE,MYF(0),
- tables->real_name);
- error= 1;
+ my_error(ER_TABLE_NOT_LOCKED_FOR_WRITE, MYF(0), tables->real_name);
+ error= TRUE;
goto err;
}
while (global_read_lock && ! thd->killed)
@@ -106,9 +99,9 @@ int mysql_rm_table(THD *thd,TABLE_LIST *tables, my_bool if_exists,
pthread_mutex_unlock(&thd->mysys_var->mutex);
if (error)
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
send_ok(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -268,9 +261,9 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
if (wrong_tables.length())
{
if (!foreign_key_error)
- my_error(ER_BAD_TABLE_ERROR,MYF(0), wrong_tables.c_ptr());
+ my_error(ER_BAD_TABLE_ERROR, MYF(0), wrong_tables.c_ptr());
else
- my_error(ER_ROW_IS_REFERENCED, MYF(0));
+ my_message(ER_ROW_IS_REFERENCED, ER(ER_ROW_IS_REFERENCED), MYF(0));
error= 1;
}
@@ -282,7 +275,8 @@ int mysql_rm_table_part2(THD *thd, TABLE_LIST *tables, bool if_exists,
if (!error)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- tmp_table_deleted && !some_tables_deleted);
+ tmp_table_deleted && !some_tables_deleted,
+ FALSE);
mysql_bin_log.write(&qinfo);
}
}
@@ -391,6 +385,41 @@ void check_duplicates_in_interval(const char *set_or_name,
}
}
+
+/*
+ Check TYPELIB (set or enum) max and total lengths
+
+ 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.
+
+ RETURN VALUES
+ void
+*/
+void calculate_interval_lengths(CHARSET_INFO *cs, TYPELIB *interval,
+ 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++)
+ {
+ uint length= cs->cset->numchars(cs, *pos, *pos + *len);
+ *tot_length+= length;
+ set_if_bigger(*max_length, (uint32)length);
+ }
+}
+
+
/*
Preparation for table creation
@@ -404,6 +433,9 @@ void check_duplicates_in_interval(const char *set_or_name,
DESCRIPTION
Prepares the table and key structures for table creation.
+ NOTES
+ sets create_info->varchar if the table has a varchar or blob.
+
RETURN VALUES
0 ok
-1 error
@@ -418,20 +450,24 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
const char *key_name;
create_field *sql_field,*dup_field;
uint field,null_fields,blob_columns;
+ uint max_key_length= file->max_key_length();
ulong pos;
KEY *key_info;
KEY_PART_INFO *key_part_info;
int timestamps= 0, timestamps_with_niladic= 0;
int field_no,dup_no;
int select_field_pos,auto_increment=0;
+ List_iterator<create_field> it(fields),it2(fields);
DBUG_ENTER("mysql_prepare_table");
- List_iterator<create_field> it(fields),it2(fields);
select_field_pos=fields.elements - select_field_count;
null_fields=blob_columns=0;
+ create_info->varchar= 0;
for (field_no=0; (sql_field=it++) ; field_no++)
{
+ CHARSET_INFO *save_cs;
+
if (!sql_field->charset)
sql_field->charset= create_info->default_table_charset;
/*
@@ -443,26 +479,138 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (create_info->table_charset && sql_field->charset != &my_charset_bin)
sql_field->charset= create_info->table_charset;
- CHARSET_INFO *savecs= sql_field->charset;
+ save_cs= sql_field->charset;
if ((sql_field->flags & BINCMP_FLAG) &&
!(sql_field->charset= get_charset_by_csname(sql_field->charset->csname,
MY_CS_BINSORT,MYF(0))))
{
char tmp[64];
- strmake(strmake(tmp, savecs->csname, sizeof(tmp)-4), "_bin", 4);
+ strmake(strmake(tmp, save_cs->csname, sizeof(tmp)-4), "_bin", 4);
my_error(ER_UNKNOWN_COLLATION, MYF(0), tmp);
DBUG_RETURN(-1);
}
- sql_field->create_length_to_internal_length();
+ if ((sql_field->sql_type == FIELD_TYPE_SET ||
+ sql_field->sql_type == FIELD_TYPE_ENUM) && !sql_field->interval)
+ {
+ uint32 dummy;
+ CHARSET_INFO *cs= sql_field->charset;
+ TYPELIB *interval;
- /* Don't pack keys in old tables if the user has requested this */
- if ((sql_field->flags & BLOB_FLAG) ||
- sql_field->sql_type == FIELD_TYPE_VAR_STRING &&
- create_info->row_type != ROW_TYPE_FIXED)
+ /*
+ Create typelib from interval_list, and if necessary
+ convert strings from client character set to the
+ column character set.
+ */
+
+ interval= sql_field->interval= typelib(sql_field->interval_list);
+ List_iterator<String> it(sql_field->interval_list);
+ String conv, *tmp;
+ for (uint i= 0; (tmp= it++); i++)
+ {
+ if (String::needs_conversion(tmp->length(), tmp->charset(), cs, &dummy))
+ {
+ uint cnv_errs;
+ conv.copy(tmp->ptr(), tmp->length(), tmp->charset(), cs, &cnv_errs);
+ char *buf= (char*) sql_alloc(conv.length()+1);
+ memcpy(buf, conv.ptr(), conv.length());
+ buf[conv.length()]= '\0';
+ interval->type_names[i]= buf;
+ interval->type_lengths[i]= conv.length();
+ }
+
+ // Strip trailing spaces.
+ uint 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';
+ }
+ sql_field->interval_list.empty(); // Don't need interval_list anymore
+
+
+ /*
+ Convert the default value from client character
+ set into the column character set if necessary.
+ */
+ if (sql_field->def)
+ {
+ sql_field->def=
+ sql_field->def->safe_charset_converter(cs);
+ }
+
+ if (sql_field->sql_type == FIELD_TYPE_SET)
+ {
+ uint32 field_length;
+ if (sql_field->def)
+ {
+ char *not_used;
+ uint not_used2;
+ bool not_found= 0;
+ String str, *def= sql_field->def->val_str(&str);
+ def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
+ (void) find_set(interval, def->ptr(), def->length(),
+ cs, &not_used, &not_used2, &not_found);
+ if (not_found)
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
+ }
+ calculate_interval_lengths(cs, interval, &dummy, &field_length);
+ sql_field->length= field_length + (interval->count - 1);
+ }
+ else /* FIELD_TYPE_ENUM */
+ {
+ uint32 field_length;
+ if (sql_field->def)
+ {
+ String str, *def= sql_field->def->val_str(&str);
+ def->length(cs->cset->lengthsp(cs, def->ptr(), def->length()));
+ if (!find_type2(interval, def->ptr(), def->length(), cs))
+ {
+ my_error(ER_INVALID_DEFAULT, MYF(0), sql_field->field_name);
+ DBUG_RETURN(-1);
+ }
+ }
+ calculate_interval_lengths(cs, interval, &field_length, &dummy);
+ sql_field->length= field_length;
+ }
+ set_if_smaller(sql_field->length, MAX_FIELD_WIDTH-1);
+ }
+
+ sql_field->create_length_to_internal_length();
+ if (sql_field->length > MAX_FIELD_VARCHARLENGTH &&
+ !(sql_field->flags & BLOB_FLAG))
{
- db_options|=HA_OPTION_PACK_RECORD;
+ /* Convert long VARCHAR columns to TEXT or BLOB */
+ char warn_buff[MYSQL_ERRMSG_SIZE];
+
+ if (sql_field->def)
+ {
+ my_error(ER_TOO_BIG_FIELDLENGTH, MYF(0), sql_field->field_name,
+ MAX_FIELD_VARCHARLENGTH / sql_field->charset->mbmaxlen);
+ DBUG_RETURN(-1);
+ }
+ sql_field->sql_type= FIELD_TYPE_BLOB;
+ sql_field->flags|= BLOB_FLAG;
+ sprintf(warn_buff, ER(ER_AUTO_CONVERT), sql_field->field_name,
+ "VARCHAR",
+ (sql_field->charset == &my_charset_bin) ? "BLOB" : "TEXT");
+ push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE, ER_AUTO_CONVERT,
+ warn_buff);
+ }
+
+ if ((sql_field->flags & BLOB_FLAG) && sql_field->length)
+ {
+ if (sql_field->sql_type == FIELD_TYPE_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);
+ }
+ sql_field->length= 0; // Probably from an item
}
+
if (!(sql_field->flags & NOT_NULL_FLAG))
null_fields++;
@@ -485,7 +633,7 @@ int mysql_prepare_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);
DBUG_RETURN(-1);
}
else
@@ -497,6 +645,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
create_info->default_table_charset);
sql_field->length= dup_field->length;
sql_field->pack_length= dup_field->pack_length;
+ sql_field->key_length= dup_field->key_length;
sql_field->create_length_to_internal_length();
sql_field->decimals= dup_field->decimals;
sql_field->flags= dup_field->flags;
@@ -507,6 +656,11 @@ int mysql_prepare_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 &&
+ create_info->row_type != ROW_TYPE_FIXED)
+ db_options|= HA_OPTION_PACK_RECORD;
it2.rewind();
}
/* If fixed row records, we need one bit to check for deleted rows */
@@ -532,13 +686,13 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD;
blob_columns++;
+ create_info->varchar= 1;
break;
case FIELD_TYPE_GEOMETRY:
#ifdef HAVE_SPATIAL
if (!(file->table_flags() & HA_CAN_GEOMETRY))
{
- my_printf_error(ER_CHECK_NOT_IMPLEMENTED, ER(ER_CHECK_NOT_IMPLEMENTED),
- MYF(0), "GEOMETRY");
+ my_error(ER_CHECK_NOT_IMPLEMENTED, MYF(0), "GEOMETRY");
DBUG_RETURN(-1);
}
sql_field->pack_flag=FIELDFLAG_GEOM |
@@ -549,17 +703,37 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
sql_field->length=8; // Unireg field length
sql_field->unireg_check=Field::BLOB_FIELD;
blob_columns++;
+ create_info->varchar= 1;
break;
#else
- my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED), MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
DBUG_RETURN(-1);
#endif /*HAVE_SPATIAL*/
- case FIELD_TYPE_VAR_STRING:
- case FIELD_TYPE_STRING:
+ case MYSQL_TYPE_VARCHAR:
+#ifndef QQ_ALL_HANDLERS_SUPPORT_VARCHAR
+ if (file->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_printf_error(ER_TOO_BIG_FIELDLENGTH, ER(ER_TOO_BIG_FIELDLENGTH),
+ MYF(0), sql_field->field_name, MAX_FIELD_CHARLENGTH);
+ DBUG_RETURN(-1);
+ }
+ }
+ else
+#endif
+ create_info->varchar= 1;
+ /* 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;
+ sql_field->pack_flag|= FIELDFLAG_BINARY;
break;
case FIELD_TYPE_ENUM:
sql_field->pack_flag=pack_length_to_packflag(sql_field->pack_length) |
@@ -626,24 +800,27 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
if (timestamps_with_niladic > 1)
{
- my_error(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,MYF(0));
+ my_message(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS,
+ ER(ER_TOO_MUCH_AUTO_TIMESTAMP_COLS), MYF(0));
DBUG_RETURN(-1);
}
if (auto_increment > 1)
{
- my_error(ER_WRONG_AUTO_KEY,MYF(0));
+ my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
DBUG_RETURN(-1);
}
if (auto_increment &&
(file->table_flags() & HA_NO_AUTO_INCREMENT))
{
- my_error(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,MYF(0));
+ my_message(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT,
+ ER(ER_TABLE_CANT_HANDLE_AUTO_INCREMENT), MYF(0));
DBUG_RETURN(-1);
}
if (blob_columns && (file->table_flags() & HA_NO_BLOBS))
{
- my_error(ER_TABLE_CANT_HANDLE_BLOB,MYF(0));
+ my_message(ER_TABLE_CANT_HANDLE_BLOB, ER(ER_TABLE_CANT_HANDLE_BLOB),
+ MYF(0));
DBUG_RETURN(-1);
}
@@ -669,9 +846,9 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (fk_key->ref_columns.elements &&
fk_key->ref_columns.elements != fk_key->columns.elements)
{
- my_error(ER_WRONG_FK_DEF, MYF(0), fk_key->name ? fk_key->name :
- "foreign key without name",
- ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
+ my_error(ER_WRONG_FK_DEF, MYF(0),
+ (fk_key->name ? fk_key->name : "foreign key without name"),
+ ER(ER_KEY_REF_DO_NOT_MATCH_TABLE_REF));
DBUG_RETURN(-1);
}
continue;
@@ -770,8 +947,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->flags= HA_SPATIAL;
break;
#else
- my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
DBUG_RETURN(-1);
#endif
case Key::FOREIGN_KEY:
@@ -793,7 +970,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (!(file->table_flags() & HA_CAN_FULLTEXT))
{
- my_error(ER_TABLE_CANT_HANDLE_FT, MYF(0));
+ my_message(ER_TABLE_CANT_HANDLE_FT, ER(ER_TABLE_CANT_HANDLE_FT),
+ MYF(0));
DBUG_RETURN(-1);
}
}
@@ -810,36 +988,35 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (key_info->key_parts != 1)
{
- my_printf_error(ER_WRONG_ARGUMENTS,
- ER(ER_WRONG_ARGUMENTS),MYF(0),"SPATIAL INDEX");
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "SPATIAL INDEX");
DBUG_RETURN(-1);
}
}
- else
- if (key_info->algorithm == HA_KEY_ALG_RTREE)
+ else if (key_info->algorithm == HA_KEY_ALG_RTREE)
{
#ifdef HAVE_RTREE_KEYS
if ((key_info->key_parts & 1) == 1)
{
- my_printf_error(ER_WRONG_ARGUMENTS,
- ER(ER_WRONG_ARGUMENTS),MYF(0),"RTREE INDEX");
+ my_error(ER_WRONG_ARGUMENTS, MYF(0), "RTREE INDEX");
DBUG_RETURN(-1);
}
/* TODO: To be deleted */
- my_printf_error(ER_NOT_SUPPORTED_YET, ER(ER_NOT_SUPPORTED_YET),
- MYF(0), "RTREE INDEX");
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "RTREE INDEX");
DBUG_RETURN(-1);
#else
- my_printf_error(ER_FEATURE_DISABLED,ER(ER_FEATURE_DISABLED),MYF(0),
- sym_group_rtree.name, sym_group_rtree.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_rtree.name, sym_group_rtree.needed_define);
DBUG_RETURN(-1);
#endif
}
- List_iterator<key_part_spec> cols(key->columns);
+ List_iterator<key_part_spec> cols(key->columns), cols2(key->columns);
CHARSET_INFO *ft_key_charset=0; // for FULLTEXT
for (uint column_nr=0 ; (column=cols++) ; column_nr++)
{
+ uint length;
+ key_part_spec *dup_column;
+
it.rewind();
field=0;
while ((sql_field=it++) &&
@@ -849,28 +1026,31 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
field++;
if (!sql_field)
{
- my_printf_error(ER_KEY_COLUMN_DOES_NOT_EXITS,
- ER(ER_KEY_COLUMN_DOES_NOT_EXITS),MYF(0),
- column->field_name);
+ my_error(ER_KEY_COLUMN_DOES_NOT_EXITS, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
- /* for fulltext keys keyseg length is 1 for blobs (it's ignored in
- ft code anyway, and 0 (set to column width later) for char's.
- it has to be correct col width for char's, as char data are not
- prefixed with length (unlike blobs, where ft code takes data length
- from a data prefix, ignoring column->length).
- */
+ while ((dup_column= cols2++) != column)
+ {
+ if (!my_strcasecmp(system_charset_info,
+ column->field_name, dup_column->field_name))
+ {
+ my_printf_error(ER_DUP_FIELDNAME,
+ ER(ER_DUP_FIELDNAME),MYF(0),
+ column->field_name);
+ DBUG_RETURN(-1);
+ }
+ }
+ cols2.rewind();
if (key->type == Key::FULLTEXT)
{
- if ((sql_field->sql_type != FIELD_TYPE_STRING &&
- sql_field->sql_type != FIELD_TYPE_VAR_STRING &&
+ if ((sql_field->sql_type != MYSQL_TYPE_STRING &&
+ sql_field->sql_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
(ft_key_charset && sql_field->charset != ft_key_charset))
{
- my_printf_error(ER_BAD_FT_COLUMN,ER(ER_BAD_FT_COLUMN),MYF(0),
- column->field_name);
+ my_error(ER_BAD_FT_COLUMN, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
ft_key_charset=sql_field->charset;
@@ -891,28 +1071,25 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (!(file->table_flags() & HA_CAN_INDEX_BLOBS))
{
- my_printf_error(ER_BLOB_USED_AS_KEY,ER(ER_BLOB_USED_AS_KEY),MYF(0),
- column->field_name);
+ my_error(ER_BLOB_USED_AS_KEY, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
if (!column->length)
{
- my_printf_error(ER_BLOB_KEY_WITHOUT_LENGTH,
- ER(ER_BLOB_KEY_WITHOUT_LENGTH),MYF(0),
- column->field_name);
+ my_error(ER_BLOB_KEY_WITHOUT_LENGTH, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
}
#ifdef HAVE_SPATIAL
- if (key->type == Key::SPATIAL)
+ if (key->type == Key::SPATIAL)
{
- if (!column->length )
+ if (!column->length)
{
/*
- BAR: 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
- Lately we'll extend this code to support more dimensions
+ 4 is: (Xmin,Xmax,Ymin,Ymax), this is for 2D case
+ Lately we'll extend this code to support more dimensions
*/
- column->length=4*sizeof(double);
+ column->length= 4*sizeof(double);
}
}
#endif
@@ -928,13 +1105,13 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_info->flags|= HA_NULL_PART_KEY;
if (!(file->table_flags() & HA_NULL_IN_KEY))
{
- my_printf_error(ER_NULL_COLUMN_IN_INDEX,ER(ER_NULL_COLUMN_IN_INDEX),
- MYF(0),column->field_name);
+ my_error(ER_NULL_COLUMN_IN_INDEX, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
if (key->type == Key::SPATIAL)
{
- my_error(ER_SPATIAL_CANT_HAVE_NULL, MYF(0));
+ my_message(ER_SPATIAL_CANT_HAVE_NULL,
+ ER(ER_SPATIAL_CANT_HAVE_NULL), MYF(0));
DBUG_RETURN(-1);
}
}
@@ -948,7 +1125,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_part_info->fieldnr= field;
key_part_info->offset= (uint16) sql_field->offset;
key_part_info->key_type=sql_field->pack_flag;
- uint length=sql_field->pack_length;
+ length= sql_field->key_length;
+
if (column->length)
{
if (f_is_blob(sql_field->pack_flag))
@@ -980,7 +1158,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
(key_info->flags & HA_NOSAME))) &&
column->length != length)))
{
- my_error(ER_WRONG_SUB_KEY,MYF(0));
+ my_message(ER_WRONG_SUB_KEY, ER(ER_WRONG_SUB_KEY), MYF(0));
DBUG_RETURN(-1);
}
else if (!(file->table_flags() & HA_NO_PREFIX_CHAR_KEYS))
@@ -988,8 +1166,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
}
else if (length == 0)
{
- my_printf_error(ER_WRONG_KEY_COLUMN, ER(ER_WRONG_KEY_COLUMN), MYF(0),
- column->field_name);
+ my_error(ER_WRONG_KEY_COLUMN, MYF(0), column->field_name);
DBUG_RETURN(-1);
}
if (length > file->max_key_part_length())
@@ -1014,12 +1191,13 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
/* Use packed keys for long strings on the first column */
if (!(db_options & HA_OPTION_NO_PACK_KEYS) &&
(length >= KEY_DEFAULT_PACK_LENGTH &&
- (sql_field->sql_type == FIELD_TYPE_STRING ||
- sql_field->sql_type == FIELD_TYPE_VAR_STRING ||
+ (sql_field->sql_type == MYSQL_TYPE_STRING ||
+ sql_field->sql_type == MYSQL_TYPE_VARCHAR ||
sql_field->pack_flag & FIELDFLAG_BLOB)))
{
- if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB))
- key_info->flags|= HA_BINARY_PACK_KEY;
+ if (column_nr == 0 && (sql_field->pack_flag & FIELDFLAG_BLOB) ||
+ sql_field->sql_type == MYSQL_TYPE_VARCHAR)
+ key_info->flags|= HA_BINARY_PACK_KEY | HA_VAR_LENGTH_KEY;
else
key_info->flags|= HA_PACK_KEY;
}
@@ -1033,7 +1211,8 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
{
if (primary_key)
{
- my_error(ER_MULTIPLE_PRI_KEY,MYF(0));
+ my_message(ER_MULTIPLE_PRI_KEY, ER(ER_MULTIPLE_PRI_KEY),
+ MYF(0));
DBUG_RETURN(-1);
}
key_name=primary_key_name;
@@ -1044,7 +1223,7 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
key_info_buffer,key_info);
if (check_if_keyname_exists(key_name,key_info_buffer,key_info))
{
- my_error(ER_DUP_KEYNAME,MYF(0),key_name);
+ my_error(ER_DUP_KEYNAME, MYF(0), key_name);
DBUG_RETURN(-1);
}
key_info->name=(char*) key_name;
@@ -1058,7 +1237,6 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (!(key_info->flags & HA_NULL_PART_KEY))
unique_key=1;
key_info->key_length=(uint16) key_length;
- uint max_key_length= file->max_key_length();
if (key_length > max_key_length && key->type != Key::FULLTEXT)
{
my_error(ER_TOO_LONG_KEY,MYF(0),max_key_length);
@@ -1069,12 +1247,12 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
if (!unique_key && !primary_key &&
(file->table_flags() & HA_REQUIRE_PRIMARY_KEY))
{
- my_error(ER_REQUIRES_PRIMARY_KEY,MYF(0));
+ my_message(ER_REQUIRES_PRIMARY_KEY, ER(ER_REQUIRES_PRIMARY_KEY), MYF(0));
DBUG_RETURN(-1);
}
if (auto_increment > 0)
{
- my_error(ER_WRONG_AUTO_KEY,MYF(0));
+ my_message(ER_WRONG_AUTO_KEY, ER(ER_WRONG_AUTO_KEY), MYF(0));
DBUG_RETURN(-1);
}
/* Sort keys in optimized order */
@@ -1108,30 +1286,31 @@ int mysql_prepare_table(THD *thd, HA_CREATE_INFO *create_info,
and must be zero for standard create of table.
RETURN VALUES
- 0 ok
- -1 error
+ FALSE OK
+ TRUE error
*/
-int mysql_create_table(THD *thd,const char *db, const char *table_name,
- HA_CREATE_INFO *create_info,
- List<create_field> &fields,
- List<Key> &keys,bool tmp_table,
- uint select_field_count)
+bool mysql_create_table(THD *thd,const char *db, const char *table_name,
+ HA_CREATE_INFO *create_info,
+ List<create_field> &fields,
+ List<Key> &keys,bool tmp_table,
+ uint select_field_count)
{
char path[FN_REFLEN];
const char *alias;
- int error= -1;
uint db_options, key_count;
KEY *key_info_buffer;
handler *file;
+ bool error= TRUE;
enum db_type new_db_type;
DBUG_ENTER("mysql_create_table");
/* Check for duplicate fields and check type of table to create */
if (!fields.elements)
{
- my_error(ER_TABLE_MUST_HAVE_COLUMNS,MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_TABLE_MUST_HAVE_COLUMNS, ER(ER_TABLE_MUST_HAVE_COLUMNS),
+ MYF(0));
+ DBUG_RETURN(TRUE);
}
if ((new_db_type= ha_checktype(create_info->db_type)) !=
create_info->db_type)
@@ -1160,8 +1339,8 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if ((create_info->options & HA_LEX_CREATE_TMP_TABLE) &&
(file->table_flags() & HA_NO_TEMP_TABLES))
{
- my_error(ER_ILLEGAL_HA,MYF(0),table_name);
- DBUG_RETURN(-1);
+ my_error(ER_ILLEGAL_HA, MYF(0), table_name);
+ DBUG_RETURN(TRUE);
}
#endif
@@ -1186,7 +1365,7 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
keys, tmp_table, db_options, file,
key_info_buffer, &key_count,
select_field_count))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
/* Check if table exists */
if (create_info->options & HA_LEX_CREATE_TMP_TABLE)
@@ -1209,10 +1388,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{
create_info->table_existed= 1; // Mark that table existed
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), alias);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
if (wait_if_global_read_lock(thd, 0, 1))
DBUG_RETURN(error);
@@ -1224,10 +1403,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (create_info->options & HA_LEX_CREATE_IF_NOT_EXISTS)
{
create_info->table_existed= 1; // Mark that table existed
- error= 0;
+ error= FALSE;
}
else
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
goto end;
}
}
@@ -1253,10 +1432,10 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
if (create_if_not_exists)
{
create_info->table_existed= 1; // Mark that table existed
- error= 0;
+ error= FALSE;
}
else
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),table_name);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
goto end;
}
}
@@ -1289,10 +1468,12 @@ int mysql_create_table(THD *thd,const char *db, const char *table_name,
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
test(create_info->options &
- HA_LEX_CREATE_TMP_TABLE));
+ HA_LEX_CREATE_TMP_TABLE),
+ FALSE);
mysql_bin_log.write(&qinfo);
}
- error=0;
+ error= FALSE;
+
end:
VOID(pthread_mutex_unlock(&LOCK_open));
start_waiting_global_read_lock(thd);
@@ -1401,7 +1582,7 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
create_info, *extra_fields, *keys, 0,
select_field_count))
{
- if (!(table= open_table(thd, create_table, &thd->mem_root, (bool*) 0)))
+ if (!(table= open_table(thd, create_table, thd->mem_root, (bool*) 0)))
quick_rm_table(create_info->db_type, create_table->db,
table_case_name(create_info, create_table->real_name));
}
@@ -1422,7 +1603,6 @@ TABLE *create_table_from_items(THD *thd, HA_CREATE_INFO *create_info,
}
table->file->extra(HA_EXTRA_WRITE_CACHE);
DBUG_RETURN(table);
- /* Note that leaving the function resets binlogging properties */
}
@@ -1553,6 +1733,7 @@ void close_cached_table(THD *thd, TABLE *table)
/* When lock on LOCK_open is freed other threads can continue */
pthread_cond_broadcast(&COND_refresh);
+ DBUG_VOID_RETURN;
}
static int send_check_errmsg(THD *thd, TABLE_LIST* table,
@@ -1565,7 +1746,7 @@ static int send_check_errmsg(THD *thd, TABLE_LIST* table,
protocol->store((char*) operator_name, system_charset_info);
protocol->store("error", 5, system_charset_info);
protocol->store(errmsg, system_charset_info);
- thd->net.last_error[0]=0;
+ thd->clear_error();
if (protocol->write())
return -1;
return 1;
@@ -1740,21 +1921,29 @@ end:
}
-static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
- HA_CHECK_OPT* check_opt,
- const char *operator_name,
- thr_lock_type lock_type,
- bool open_for_modify,
- uint extra_open_options,
- int (*prepare_func)(THD *, TABLE_LIST *,
- HA_CHECK_OPT *),
- int (handler::*operator_func)
- (THD *, HA_CHECK_OPT *))
+/*
+ RETURN VALUES
+ FALSE Message sent to net (admin operation went ok)
+ TRUE Message should be sent by caller
+ (admin operation or network communication failed)
+*/
+static bool mysql_admin_table(THD* thd, TABLE_LIST* tables,
+ HA_CHECK_OPT* check_opt,
+ const char *operator_name,
+ thr_lock_type lock_type,
+ bool open_for_modify,
+ uint extra_open_options,
+ int (*prepare_func)(THD *, TABLE_LIST *,
+ HA_CHECK_OPT *),
+ int (handler::*operator_func)(THD *,
+ HA_CHECK_OPT *),
+ int (view_operator_func)(THD *, TABLE_LIST*))
{
- TABLE_LIST *table;
+ TABLE_LIST *table, *next_global_table;
List<Item> field_list;
Item *item;
Protocol *protocol= thd->protocol;
+ int result_code;
DBUG_ENTER("mysql_admin_table");
field_list.push_back(item = new Item_empty_string("Table", NAME_LEN*2));
@@ -1767,7 +1956,7 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
item->maybe_null = 1;
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
mysql_ha_flush(thd, tables, MYSQL_HA_CLOSE_FINAL);
for (table= tables; table; table= table->next_local)
@@ -1778,23 +1967,44 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
strxmov(table_name,db ? db : "",".",table->real_name,NullS);
thd->open_options|= extra_open_options;
- table->table = open_ltable(thd, table, lock_type);
-#ifdef EMBEDDED_LIBRARY
- thd->net.last_errno= 0; // these errors shouldn't get client
-#endif
+ table->lock_type= lock_type;
+ /* open only one table from local list of command */
+ next_global_table= table->next_global;
+ table->next_global= 0;
+ open_and_lock_tables(thd, table);
+ table->next_global= next_global_table;
+ /* if view are unsupported */
+ if (table->view && !view_operator_func)
+ {
+ result_code= HA_ADMIN_NOT_IMPLEMENTED;
+ goto send_result;
+ }
thd->open_options&= ~extra_open_options;
if (prepare_func)
{
switch ((*prepare_func)(thd, table, check_opt)) {
- case 1: continue; // error, message written to net
- case -1: goto err; // error, message could be written to net
- default: ; // should be 0 otherwise
+ case 1: // error, message written to net
+ close_thread_tables(thd);
+ continue;
+ case -1: // error, message could be written to net
+ goto err;
+ default: // should be 0 otherwise
+ ;
}
}
+ /*
+ CHECK TABLE command is only command where VIEW allowed here and this
+ command use only temporary teble method for VIEWs resolving => there
+ can't be VIEW tree substitition of join view => if opening table
+ succeed then table->table will have real TABLE pointer as value (in
+ case of join view substitution table->table can be 0, but here it is
+ impossible)
+ */
if (!table->table)
{
+ char buf[ERRMSGSIZE+ERRMSGSIZE+2];
const char *err_msg;
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
@@ -1802,12 +2012,26 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
protocol->store("error",5, system_charset_info);
if (!(err_msg=thd->net.last_error))
err_msg=ER(ER_CHECK_NO_SUCH_TABLE);
+ /* if it was a view will check md5 sum */
+ if (table->view &&
+ view_checksum(thd, table) == HA_ADMIN_WRONG_CHECKSUM)
+ {
+ strxmov(buf, err_msg, "; ", ER(ER_VIEW_CHECKSUM), NullS);
+ err_msg= (const char *)buf;
+ }
protocol->store(err_msg, system_charset_info);
- thd->net.last_error[0]=0;
+ thd->clear_error();
if (protocol->write())
goto err;
continue;
}
+
+ if (table->view)
+ {
+ result_code= (*view_operator_func)(thd, table);
+ goto send_result;
+ }
+
table->table->pos_in_table_list= table;
if ((table->table->db_stat & HA_READ_ONLY) && open_for_modify)
{
@@ -1846,10 +2070,11 @@ static int mysql_admin_table(THD* thd, TABLE_LIST* tables,
open_for_modify=0;
}
- int result_code = (table->table->file->*operator_func)(thd, check_opt);
-#ifdef EMBEDDED_LIBRARY
- thd->net.last_errno= 0; // these errors shouldn't get client
-#endif
+ result_code = (table->table->file->*operator_func)(thd, check_opt);
+
+send_result:
+
+ thd->clear_error(); // these errors shouldn't get client
protocol->prepare_for_resend();
protocol->store(table_name, system_charset_info);
protocol->store(operator_name, system_charset_info);
@@ -1924,6 +2149,13 @@ send_result_message:
table->next_global= save_next_global;
goto send_result_message;
}
+ case HA_ADMIN_WRONG_CHECKSUM:
+ {
+ protocol->store("note", 4, system_charset_info);
+ protocol->store(ER(ER_VIEW_CHECKSUM), strlen(ER(ER_VIEW_CHECKSUM)),
+ system_charset_info);
+ break;
+ }
default: // Probably HA_ADMIN_INTERNAL_ERROR
protocol->store("error", 5, system_charset_info);
@@ -1950,50 +2182,50 @@ send_result_message:
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
-int mysql_backup_table(THD* thd, TABLE_LIST* table_list)
+bool mysql_backup_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_backup_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
"backup", TL_READ, 0, 0, 0,
- &handler::backup));
+ &handler::backup, 0));
}
-int mysql_restore_table(THD* thd, TABLE_LIST* table_list)
+bool mysql_restore_table(THD* thd, TABLE_LIST* table_list)
{
DBUG_ENTER("mysql_restore_table");
DBUG_RETURN(mysql_admin_table(thd, table_list, 0,
"restore", TL_WRITE, 1, 0,
&prepare_for_restore,
- &handler::restore));
+ &handler::restore, 0));
}
-int mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+bool mysql_repair_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_repair_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"repair", TL_WRITE, 1, HA_OPEN_FOR_REPAIR,
&prepare_for_repair,
- &handler::repair));
+ &handler::repair, 0));
}
-int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+bool mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
DBUG_ENTER("mysql_optimize_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"optimize", TL_WRITE, 1,0,0,
- &handler::optimize));
+ &handler::optimize, 0));
}
@@ -2006,11 +2238,11 @@ int mysql_optimize_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
tables Table list (one table only)
RETURN VALUES
- 0 ok
- -1 error
+ FALSE ok
+ TRUE error
*/
-int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
+bool mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
LEX_STRING *key_cache_name)
{
HA_CHECK_OPT check_opt;
@@ -2023,13 +2255,13 @@ int mysql_assign_to_keycache(THD* thd, TABLE_LIST* tables,
{
pthread_mutex_unlock(&LOCK_global_system_variables);
my_error(ER_UNKNOWN_KEY_CACHE, MYF(0), key_cache_name->str);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
pthread_mutex_unlock(&LOCK_global_system_variables);
check_opt.key_cache= key_cache;
DBUG_RETURN(mysql_admin_table(thd, tables, &check_opt,
"assign_to_keycache", TL_READ_NO_INSERT, 0,
- 0, 0, &handler::assign_to_keycache));
+ 0, 0, &handler::assign_to_keycache, 0));
}
@@ -2081,16 +2313,16 @@ int reassign_keycache_tables(THD *thd, KEY_CACHE *src_cache,
tables Table list (one table only)
RETURN VALUES
- 0 ok
- -1 error
+ FALSE ok
+ TRUE error
*/
-int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
+bool mysql_preload_keys(THD* thd, TABLE_LIST* tables)
{
DBUG_ENTER("mysql_preload_keys");
DBUG_RETURN(mysql_admin_table(thd, tables, 0,
"preload_keys", TL_READ, 0, 0, 0,
- &handler::preload_keys));
+ &handler::preload_keys, 0));
}
@@ -2105,13 +2337,13 @@ int mysql_preload_keys(THD* thd, TABLE_LIST* tables)
table_ident Src table_ident
RETURN VALUES
- 0 ok
- -1 error
+ FALSE OK
+ TRUE error
*/
-int mysql_create_like_table(THD* thd, TABLE_LIST* table,
- HA_CREATE_INFO *create_info,
- Table_ident *table_ident)
+bool mysql_create_like_table(THD* thd, TABLE_LIST* table,
+ HA_CREATE_INFO *create_info,
+ Table_ident *table_ident)
{
TABLE **tmp_table;
char src_path[FN_REFLEN], dst_path[FN_REFLEN];
@@ -2119,7 +2351,8 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
char *table_name= table->real_name;
char *src_db= thd->db;
char *src_table= table_ident->table.str;
- int err, res= -1;
+ int err;
+ bool res= TRUE;
TABLE_LIST src_tables_list;
DBUG_ENTER("mysql_create_like_table");
@@ -2132,7 +2365,7 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
table_ident->db.str && check_db_name((src_db= table_ident->db.str)))
{
my_error(ER_WRONG_TABLE_NAME, MYF(0), src_table);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
bzero((gptr)&src_tables_list, sizeof(src_tables_list));
@@ -2216,10 +2449,11 @@ int mysql_create_like_table(THD* thd, TABLE_LIST* table,
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
test(create_info->options &
- HA_LEX_CREATE_TMP_TABLE));
+ HA_LEX_CREATE_TMP_TABLE),
+ FALSE);
mysql_bin_log.write(&qinfo);
}
- res= 0;
+ res= FALSE;
goto err;
table_exists:
@@ -2230,7 +2464,7 @@ table_exists:
ER(ER_TABLE_EXISTS_ERROR), table_name);
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_NOTE,
ER_TABLE_EXISTS_ERROR,warn_buff);
- res= 0;
+ res= FALSE;
}
else
my_error(ER_TABLE_EXISTS_ERROR, MYF(0), table_name);
@@ -2243,7 +2477,7 @@ err:
}
-int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
+bool mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
{
#ifdef OS2
thr_lock_type lock_type = TL_WRITE;
@@ -2254,11 +2488,11 @@ int mysql_analyze_table(THD* thd, TABLE_LIST* tables, HA_CHECK_OPT* check_opt)
DBUG_ENTER("mysql_analyze_table");
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"analyze", lock_type, 1,0,0,
- &handler::analyze));
+ &handler::analyze, 0));
}
-int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
+bool mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
{
#ifdef OS2
thr_lock_type lock_type = TL_WRITE;
@@ -2270,7 +2504,7 @@ int mysql_check_table(THD* thd, TABLE_LIST* tables,HA_CHECK_OPT* check_opt)
DBUG_RETURN(mysql_admin_table(thd, tables, check_opt,
"check", lock_type,
0, HA_OPEN_FOR_REPAIR, 0,
- &handler::check));
+ &handler::check, &view_checksum));
}
@@ -2326,7 +2560,7 @@ mysql_discard_or_import_tablespace(THD *thd,
goto err;
if (mysql_bin_log.is_open())
{
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
err:
@@ -2549,13 +2783,13 @@ int mysql_drop_indexes(THD *thd, TABLE_LIST *table_list,
Alter table
*/
-int mysql_alter_table(THD *thd,char *new_db, char *new_name,
- HA_CREATE_INFO *create_info,
- TABLE_LIST *table_list,
- List<create_field> &fields, List<Key> &keys,
- uint order_num, ORDER *order,
- enum enum_duplicates handle_duplicates,
- ALTER_INFO *alter_info, bool do_send_ok)
+bool mysql_alter_table(THD *thd,char *new_db, char *new_name,
+ HA_CREATE_INFO *create_info,
+ TABLE_LIST *table_list,
+ List<create_field> &fields, List<Key> &keys,
+ uint order_num, ORDER *order,
+ enum enum_duplicates handle_duplicates,
+ ALTER_INFO *alter_info, bool do_send_ok)
{
TABLE *table,*new_table=0;
int error;
@@ -2584,7 +2818,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
DBUG_RETURN(mysql_discard_or_import_tablespace(thd,table_list,
alter_info->tablespace_op));
if (!(table=open_ltable(thd,table_list,TL_WRITE_ALLOW_READ)))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
/* Check that we are not trying to rename to an existing table */
if (new_name)
@@ -2615,8 +2849,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (find_temporary_table(thd,new_db,new_name_buff))
{
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
- DBUG_RETURN(-1);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
+ DBUG_RETURN(TRUE);
}
}
else
@@ -2627,8 +2861,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
F_OK))
{
/* Table will be closed in do_command() */
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0), new_alias);
- DBUG_RETURN(-1);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_alias);
+ DBUG_RETURN(TRUE);
}
}
}
@@ -2668,7 +2902,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
error=0;
if (!access(new_name_buff,F_OK))
{
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name);
error= -1;
}
else
@@ -2715,7 +2949,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
if (do_send_ok)
@@ -2812,8 +3046,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (def->sql_type == FIELD_TYPE_BLOB)
{
- my_error(ER_BLOB_CANT_HAVE_DEFAULT,MYF(0),def->change);
- DBUG_RETURN(-1);
+ my_error(ER_BLOB_CANT_HAVE_DEFAULT, MYF(0), def->change);
+ DBUG_RETURN(TRUE);
}
def->def=alter->def; // Use new default
alter_it.remove();
@@ -2826,8 +3060,8 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
{
if (def->change && ! def->field)
{
- my_error(ER_BAD_FIELD_ERROR,MYF(0),def->change,table_name);
- DBUG_RETURN(-1);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), def->change, table_name);
+ DBUG_RETURN(TRUE);
}
if (!def->after)
create_list.push_back(def);
@@ -2844,22 +3078,23 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
}
if (!find)
{
- my_error(ER_BAD_FIELD_ERROR,MYF(0),def->after,table_name);
- DBUG_RETURN(-1);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0), def->after, table_name);
+ DBUG_RETURN(TRUE);
}
find_it.after(def); // Put element after this
}
}
if (alter_info->alter_list.elements)
{
- my_error(ER_BAD_FIELD_ERROR,MYF(0),alter_info->alter_list.head()->name,
- table_name);
- DBUG_RETURN(-1);
+ my_error(ER_BAD_FIELD_ERROR, MYF(0),
+ alter_info->alter_list.head()->name, table_name);
+ DBUG_RETURN(TRUE);
}
if (!create_list.elements)
{
- my_error(ER_CANT_REMOVE_ALL_FIELDS,MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_CANT_REMOVE_ALL_FIELDS, ER(ER_CANT_REMOVE_ALL_FIELDS),
+ MYF(0));
+ DBUG_RETURN(TRUE);
}
/*
@@ -2948,21 +3183,21 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
!my_strcasecmp(system_charset_info,key->name,primary_key_name))
{
my_error(ER_WRONG_NAME_FOR_INDEX, MYF(0), key->name);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
}
if (alter_info->drop_list.elements)
{
- my_error(ER_CANT_DROP_FIELD_OR_KEY,MYF(0),
- alter_info->drop_list.head()->name);
+ my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
+ alter_info->drop_list.head()->name);
goto err;
}
if (alter_info->alter_list.elements)
{
- my_error(ER_CANT_DROP_FIELD_OR_KEY,MYF(0),
- alter_info->alter_list.head()->name);
+ my_error(ER_CANT_DROP_FIELD_OR_KEY, MYF(0),
+ alter_info->alter_list.head()->name);
goto err;
}
@@ -3067,7 +3302,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
bzero((void*) &tbl, sizeof(tbl));
tbl.db= new_db;
tbl.real_name= tbl.alias= tmp_name;
- new_table= open_table(thd, &tbl, &thd->mem_root, 0);
+ new_table= open_table(thd, &tbl, thd->mem_root, 0);
}
else
{
@@ -3130,7 +3365,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
goto end_temporary;
@@ -3165,7 +3400,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (!access(new_name_buff,F_OK))
{
error=1;
- my_error(ER_TABLE_EXISTS_ERROR,MYF(0),new_name_buff);
+ my_error(ER_TABLE_EXISTS_ERROR, MYF(0), new_name_buff);
VOID(quick_rm_table(new_db_type,new_db,tmp_name));
VOID(pthread_mutex_unlock(&LOCK_open));
goto err;
@@ -3264,7 +3499,7 @@ int mysql_alter_table(THD *thd,char *new_db, char *new_name,
if (mysql_bin_log.is_open())
{
thd->clear_error();
- Query_log_event qinfo(thd, thd->query, thd->query_length, 0);
+ Query_log_event qinfo(thd, thd->query, thd->query_length, 0, FALSE);
mysql_bin_log.write(&qinfo);
}
VOID(pthread_cond_broadcast(&COND_refresh));
@@ -3303,10 +3538,10 @@ end_temporary:
if (do_send_ok)
send_ok(thd,copied+deleted,0L,tmp_name);
thd->some_tables_deleted=0;
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
@@ -3492,8 +3727,8 @@ copy_data_between_tables(TABLE *from,TABLE *to,
RETURN
Like mysql_alter_table().
*/
-int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
- bool do_send_ok)
+bool mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
+ bool do_send_ok)
{
DBUG_ENTER("mysql_recreate_table");
LEX *lex= thd->lex;
@@ -3506,6 +3741,8 @@ int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
create_info.db_type=DB_TYPE_DEFAULT;
create_info.row_type=ROW_TYPE_DEFAULT;
create_info.default_table_charset=default_charset_info;
+ /* Force alter table to recreate table */
+ lex->alter_info.flags= ALTER_CHANGE_COLUMN;
DBUG_RETURN(mysql_alter_table(thd, NullS, NullS, &create_info,
table_list, lex->create_list,
lex->key_list, 0, (ORDER *) 0,
@@ -3513,7 +3750,7 @@ int mysql_recreate_table(THD *thd, TABLE_LIST *table_list,
}
-int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
+bool mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
{
TABLE_LIST *table;
List<Item> field_list;
@@ -3527,7 +3764,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
item->maybe_null= 1;
if (protocol->send_fields(&field_list,
Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
for (table= tables; table; table= table->next_local)
{
@@ -3546,7 +3783,7 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
{
/* Table didn't exist */
protocol->store_null();
- thd->net.last_error[0]=0;
+ thd->clear_error();
}
else
{
@@ -3608,11 +3845,11 @@ int mysql_checksum_table(THD *thd, TABLE_LIST *tables, HA_CHECK_OPT *check_opt)
}
send_eof(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
close_thread_tables(thd); // Shouldn't be needed
if (table)
table->table=0;
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
diff --git a/sql/sql_trigger.cc b/sql/sql_trigger.cc
index 17f3bc48678..a88dc0b20bf 100644
--- a/sql/sql_trigger.cc
+++ b/sql/sql_trigger.cc
@@ -38,12 +38,13 @@ static File_option triggers_file_parameters[]=
methods.
RETURN VALUE
- 0 - Success, non-0 in case of error.
+ FALSE Success
+ TRUE error
*/
-int mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
+bool mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
{
TABLE *table;
- int result= 0;
+ bool result= 0;
DBUG_ENTER("mysql_create_or_drop_trigger");
@@ -53,7 +54,7 @@ int mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
*/
if (open_and_lock_tables(thd, tables))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
/*
TODO: We should check if user has TRIGGER privilege for table here.
@@ -61,7 +62,7 @@ int mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
we don't have proper privilege checking for triggers in place yet.
*/
if (check_global_access(thd, SUPER_ACL))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
table= tables->table;
@@ -74,19 +75,19 @@ int mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
if (tables->view || table->tmp_table != NO_TMP_TABLE)
{
my_error(ER_TRG_ON_VIEW_OR_TEMP_TABLE, MYF(0), tables->alias);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
if (!table->triggers)
{
if (!create)
{
- my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
- DBUG_RETURN(-1);
+ my_message(ER_TRG_DOES_NOT_EXIST, ER(ER_TRG_DOES_NOT_EXIST), MYF(0));
+ DBUG_RETURN(TRUE);
}
if (!(table->triggers= new (&table->mem_root) Table_triggers_list()))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
/*
@@ -96,12 +97,12 @@ int mysql_create_or_drop_trigger(THD *thd, TABLE_LIST *tables, bool create)
global read lock is held without helding LOCK_open).
*/
if (wait_if_global_read_lock(thd, 0, 0))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
VOID(pthread_mutex_lock(&LOCK_open));
- if ((create ? table->triggers->create_trigger(thd, tables):
- table->triggers->drop_trigger(thd, tables)))
- result= -1;
+ result= (create ?
+ table->triggers->create_trigger(thd, tables):
+ table->triggers->drop_trigger(thd, tables));
/* It is sensible to invalidate table in any case */
close_cached_table(thd, table);
@@ -134,14 +135,14 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
TABLE *table= tables->table;
char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
LEX_STRING dir, file;
- MEM_ROOT *old_global_root;
LEX_STRING *trg_def, *name;
+ Item_trigger_field *trg_field;
List_iterator_fast<LEX_STRING> it(names_list);
/* We don't allow creation of several triggers of the same type yet */
if (bodies[lex->trg_chistics.event][lex->trg_chistics.action_time])
{
- my_error(ER_TRG_ALREADY_EXISTS, MYF(0));
+ my_message(ER_TRG_ALREADY_EXISTS, ER(ER_TRG_ALREADY_EXISTS), MYF(0));
return 1;
}
@@ -151,12 +152,37 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
if (my_strcasecmp(system_charset_info, lex->name_and_length.str,
name->str) == 0)
{
- my_error(ER_TRG_ALREADY_EXISTS, MYF(0));
+ my_message(ER_TRG_ALREADY_EXISTS, ER(ER_TRG_ALREADY_EXISTS), MYF(0));
return 1;
}
}
/*
+ Let us check if all references to fields in old/new versions of row in
+ this trigger are ok.
+
+ NOTE: We do it here more from ease of use standpoint. We still have to
+ do some checks on each execution. E.g. we can catch privilege changes
+ only during execution. Also in near future, when we will allow access
+ to other tables from trigger we won't be able to catch changes in other
+ tables...
+
+ To simplify code a bit we have to create Fields for accessing to old row
+ values if we have ON UPDATE trigger.
+ */
+ if (!old_field && lex->trg_chistics.event == TRG_EVENT_UPDATE &&
+ prepare_old_row_accessors(table))
+ return 1;
+
+ for (trg_field= (Item_trigger_field *)(lex->trg_table_fields.first);
+ trg_field; trg_field= trg_field->next_trg_field)
+ {
+ trg_field->setup_field(thd, table, lex->trg_chistics.event);
+ if (trg_field->fix_fields(thd, (TABLE_LIST *)0, (Item **)0))
+ return 1;
+ }
+
+ /*
Here we are creating file with triggers and save all triggers in it.
sql_create_definition_file() files handles renaming and backup of older
versions
@@ -168,9 +194,6 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
triggers_file_ext, NullS) - file_buff;
file.str= file_buff;
- old_global_root= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
- my_pthread_setspecific_ptr(THR_MALLOC, &table->mem_root);
-
/*
Soon we will invalidate table object and thus Table_triggers_list object
so don't care about place to which trg_def->ptr points and other
@@ -181,17 +204,12 @@ bool Table_triggers_list::create_trigger(THD *thd, TABLE_LIST *tables)
*/
if (!(trg_def= (LEX_STRING *)alloc_root(&table->mem_root,
sizeof(LEX_STRING))) ||
- definitions_list.push_back(trg_def))
- {
- my_pthread_setspecific_ptr(THR_MALLOC, old_global_root);
+ definitions_list.push_back(trg_def, &table->mem_root))
return 1;
- }
trg_def->str= thd->query;
trg_def->length= thd->query_length;
- my_pthread_setspecific_ptr(THR_MALLOC, old_global_root);
-
return sql_create_definition_file(&dir, &file, &triggers_file_type,
(gptr)this, triggers_file_parameters, 3);
}
@@ -265,7 +283,7 @@ bool Table_triggers_list::drop_trigger(THD *thd, TABLE_LIST *tables)
}
}
- my_error(ER_TRG_DOES_NOT_EXIST, MYF(0));
+ my_message(ER_TRG_DOES_NOT_EXIST, ER(ER_TRG_DOES_NOT_EXIST), MYF(0));
return 1;
}
@@ -283,6 +301,44 @@ Table_triggers_list::~Table_triggers_list()
/*
+ Prepare array of Field objects which will represent OLD.* row values in
+ ON UPDATE trigger (by referencing to record[1] instead of record[0]).
+
+ SYNOPSIS
+ prepare_old_row_accessors()
+ table - pointer to TABLE object for which we are creating fields.
+
+ RETURN VALUE
+ False - success
+ True - error
+*/
+bool Table_triggers_list::prepare_old_row_accessors(TABLE *table)
+{
+ Field **fld, **old_fld;
+
+ if (!(old_field= (Field **)alloc_root(&table->mem_root,
+ (table->fields + 1) *
+ sizeof(Field*))))
+ return 1;
+
+ for (fld= table->field, old_fld= old_field; *fld; fld++, old_fld++)
+ {
+ /*
+ QQ: it is supposed that it is ok to use this function for field
+ cloning...
+ */
+ if (!(*old_fld= (*fld)->new_field(&table->mem_root, table)))
+ return 1;
+ (*old_fld)->move_field((my_ptrdiff_t)(table->record[1] -
+ table->record[0]));
+ }
+ *old_fld= 0;
+
+ return 0;
+}
+
+
+/*
Check whenever .TRG file for table exist and load all triggers it contains.
SYNOPSIS
@@ -302,7 +358,6 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
char path_buff[FN_REFLEN];
LEX_STRING path;
File_parser *parser;
- MEM_ROOT *old_global_mem_root;
DBUG_ENTER("Table_triggers_list::check_n_load");
@@ -326,7 +381,6 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
if (!strncmp(triggers_file_type.str, parser->type()->str,
parser->type()->length))
{
- Field **fld, **old_fld;
Table_triggers_list *triggers=
new (&table->mem_root) Table_triggers_list();
@@ -339,31 +393,10 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
table->triggers= triggers;
- /*
- We have to prepare array of Field objects which will represent OLD.*
- row values by referencing to record[1] instead of record[0]
-
- TODO: This could be avoided if there is no ON UPDATE trigger.
- */
- if (!(triggers->old_field=
- (Field **)alloc_root(&table->mem_root, (table->fields + 1) *
- sizeof(Field*))))
+ /* TODO: This could be avoided if there is no ON UPDATE trigger. */
+ if (triggers->prepare_old_row_accessors(table))
DBUG_RETURN(1);
- for (fld= table->field, old_fld= triggers->old_field; *fld;
- fld++, old_fld++)
- {
- /*
- QQ: it is supposed that it is ok to use this function for field
- cloning...
- */
- if (!(*old_fld= (*fld)->new_field(&table->mem_root, table)))
- DBUG_RETURN(1);
- (*old_fld)->move_field((my_ptrdiff_t)(table->record[1] -
- table->record[0]));
- }
- *old_fld= 0;
-
List_iterator_fast<LEX_STRING> it(triggers->definitions_list);
LEX_STRING *trg_create_str, *trg_name_str;
char *trg_name_buff;
@@ -374,7 +407,7 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
while ((trg_create_str= it++))
{
lex_start(thd, (uchar*)trg_create_str->str, trg_create_str->length);
- lex.trg_table= table;
+
if (yyparse((void *)thd) || thd->is_fatal_error)
{
/*
@@ -406,13 +439,23 @@ bool Table_triggers_list::check_n_load(THD *thd, const char *db,
trg_name_str->str= trg_name_buff;
trg_name_str->length= lex.name_and_length.length;
- old_global_mem_root= my_pthread_getspecific_ptr(MEM_ROOT*, THR_MALLOC);
- my_pthread_setspecific_ptr(THR_MALLOC, &table->mem_root);
-
- if (triggers->names_list.push_back(trg_name_str))
+ if (triggers->names_list.push_back(trg_name_str, &table->mem_root))
goto err_with_lex_cleanup;
- my_pthread_setspecific_ptr(THR_MALLOC, old_global_mem_root);
+ /*
+ Let us bind Item_trigger_field objects representing access to fields
+ in old/new versions of row in trigger to Field objects in table being
+ opened.
+
+ We ignore errors here, because if even something is wrong we still will
+ be willing to open table to perform some operations (e.g. SELECT)...
+ Anyway some things can be checked only during trigger execution.
+ */
+ for (Item_trigger_field *trg_field=
+ (Item_trigger_field *)(lex.trg_table_fields.first);
+ trg_field;
+ trg_field= trg_field->next_trg_field)
+ trg_field->setup_field(thd, table, lex.trg_chistics.event);
lex_end(&lex);
}
@@ -431,7 +474,8 @@ err_with_lex_cleanup:
We don't care about this error message much because .TRG files will
be merged into .FRM anyway.
*/
- my_error(ER_WRONG_OBJECT, MYF(0), table_name, triggers_file_ext, "TRIGGER");
+ my_error(ER_WRONG_OBJECT, MYF(0),
+ table_name, triggers_file_ext, "TRIGGER");
DBUG_RETURN(1);
}
diff --git a/sql/sql_trigger.h b/sql/sql_trigger.h
index 8ab2ab003f8..82e7c1ce023 100644
--- a/sql/sql_trigger.h
+++ b/sql/sql_trigger.h
@@ -58,5 +58,14 @@ public:
static bool check_n_load(THD *thd, const char *db, const char *table_name,
TABLE *table);
+ bool has_delete_triggers()
+ {
+ return (bodies[TRG_EVENT_DELETE][TRG_ACTION_BEFORE] ||
+ bodies[TRG_EVENT_DELETE][TRG_ACTION_AFTER]);
+ }
+
friend class Item_trigger_field;
+
+private:
+ bool prepare_old_row_accessors(TABLE *table);
};
diff --git a/sql/sql_udf.cc b/sql/sql_udf.cc
index 0bb8ac8a28b..7fd81f22e66 100644
--- a/sql/sql_udf.cc
+++ b/sql/sql_udf.cc
@@ -368,7 +368,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
if (!initialized)
{
- send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
DBUG_RETURN(1);
}
@@ -379,19 +379,19 @@ int mysql_create_function(THD *thd,udf_func *udf)
*/
if (strchr(udf->dl, '/'))
{
- send_error(thd, ER_UDF_NO_PATHS,ER(ER_UDF_NO_PATHS));
+ my_message(ER_UDF_NO_PATHS, ER(ER_UDF_NO_PATHS), MYF(0));
DBUG_RETURN(1);
}
if (udf->name.length > NAME_LEN)
{
- net_printf(thd, ER_TOO_LONG_IDENT,udf->name);
+ my_error(ER_TOO_LONG_IDENT, MYF(0), udf->name);
DBUG_RETURN(1);
}
rw_wrlock(&THR_LOCK_udf);
if ((hash_search(&udf_hash,(byte*) udf->name.str, udf->name.length)))
{
- net_printf(thd, ER_UDF_EXISTS, udf->name);
+ my_error(ER_UDF_EXISTS, MYF(0), udf->name);
goto err;
}
if (!(dl = find_udf_dl(udf->dl)))
@@ -400,7 +400,8 @@ int mysql_create_function(THD *thd,udf_func *udf)
{
DBUG_PRINT("error",("dlopen of %s failed, error: %d (%s)",
udf->dl,errno,dlerror()));
- net_printf(thd, ER_CANT_OPEN_LIBRARY, udf->dl, errno, dlerror());
+ my_error(ER_CANT_OPEN_LIBRARY, MYF(0),
+ udf->dl, errno, dlerror());
goto err;
}
new_dl=1;
@@ -410,16 +411,13 @@ int mysql_create_function(THD *thd,udf_func *udf)
if (udf->func == NULL)
{
- net_printf(thd, ER_CANT_FIND_DL_ENTRY, udf->name);
+ my_error(ER_CANT_FIND_DL_ENTRY, MYF(0), udf->name);
goto err;
}
udf->name.str=strdup_root(&mem,udf->name.str);
udf->dl=strdup_root(&mem,udf->dl);
if (!(u_d=add_udf(&udf->name,udf->returns,udf->dl,udf->type)))
- {
- send_error(thd,0); // End of memory
goto err;
- }
u_d->dlhandle = dl;
u_d->func=udf->func;
u_d->func_init=udf->func_init;
@@ -447,7 +445,7 @@ int mysql_create_function(THD *thd,udf_func *udf)
close_thread_tables(thd);
if (error)
{
- net_printf(thd, ER_ERROR_ON_WRITE, "func@mysql",error);
+ my_error(ER_ERROR_ON_WRITE, MYF(0), "func@mysql", error);
del_udf(u_d);
goto err;
}
@@ -470,14 +468,14 @@ int mysql_drop_function(THD *thd,const LEX_STRING *udf_name)
DBUG_ENTER("mysql_drop_function");
if (!initialized)
{
- send_error(thd, ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES));
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
DBUG_RETURN(1);
}
rw_wrlock(&THR_LOCK_udf);
if (!(udf=(udf_func*) hash_search(&udf_hash,(byte*) udf_name->str,
(uint) udf_name->length)))
{
- net_printf(thd, ER_FUNCTION_NOT_DEFINED, udf_name->str);
+ my_error(ER_FUNCTION_NOT_DEFINED, MYF(0), udf_name->str);
goto err;
}
del_udf(udf);
diff --git a/sql/sql_udf.h b/sql/sql_udf.h
index 7b10b80f148..d1f99a6d232 100644
--- a/sql/sql_udf.h
+++ b/sql/sql_udf.h
@@ -56,8 +56,9 @@ class udf_handler :public Sql_alloc
public:
table_map used_tables_cache;
bool const_item_cache;
+ bool not_original;
udf_handler(udf_func *udf_arg) :u_d(udf_arg), buffers(0), error(0),
- is_null(0), initialized(0)
+ is_null(0), initialized(0), not_original(0)
{}
~udf_handler();
const char *name() const { return u_d ? u_d->name.str : "?"; }
diff --git a/sql/sql_union.cc b/sql/sql_union.cc
index 46f11683e4e..815e04c0111 100644
--- a/sql/sql_union.cc
+++ b/sql/sql_union.cc
@@ -24,21 +24,20 @@
#include "mysql_priv.h"
#include "sql_select.h"
-int mysql_union(THD *thd, LEX *lex, select_result *result,
- SELECT_LEX_UNIT *unit)
+bool mysql_union(THD *thd, LEX *lex, select_result *result,
+ SELECT_LEX_UNIT *unit)
{
DBUG_ENTER("mysql_union");
- int res, res_cln;
+ bool res;
if (!(res= unit->prepare(thd, result, SELECT_NO_UNLOCK)))
res= unit->exec();
- if (res == 0 && thd->cursor && thd->cursor->is_open())
+ if (!res && thd->cursor && thd->cursor->is_open())
{
thd->cursor->set_unit(unit);
- res_cln= 0;
}
else
- res_cln= unit->cleanup();
- DBUG_RETURN(res?res:res_cln);
+ res|= unit->cleanup();
+ DBUG_RETURN(res);
}
@@ -76,7 +75,7 @@ bool select_union::send_data(List<Item> &values)
unit->offset_limit_cnt--;
return 0;
}
- fill_record(table->field, values, 1);
+ fill_record(thd, table->field, values, 1);
if (thd->net.report_error || write_record(thd, table,&info))
{
if (thd->net.last_errno == ER_RECORD_FILE_FULL)
@@ -104,8 +103,7 @@ bool select_union::flush()
int error;
if ((error=table->file->extra(HA_EXTRA_NO_CACHE)))
{
- table->file->print_error(error,MYF(0));
- ::send_error(thd);
+ table->file->print_error(error, MYF(0));
return 1;
}
return 0;
@@ -147,8 +145,8 @@ st_select_lex_unit::init_prepare_fake_select_lex(THD *thd)
}
-int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
- ulong additional_options)
+bool st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
+ ulong additional_options)
{
SELECT_LEX *lex_select_save= thd_arg->lex->current_select;
SELECT_LEX *sl, *first_select;
@@ -177,16 +175,16 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (!sl->join->procedure &&
result->prepare(sl->join->fields_list, this))
{
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
sl->join->select_options|= SELECT_DESCRIBE;
sl->join->reinit();
}
}
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
prepared= 1;
- res= 0;
+ res= FALSE;
thd_arg->lex->current_select= sl= first_select= first_select_in_union();
found_rows_for_union= first_select->options & OPTION_FOUND_ROWS;
@@ -239,7 +237,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
sl->with_wild= 0;
last_procedure= join->procedure;
- if (res || thd_arg->is_fatal_error)
+ if ((res= (res || thd_arg->is_fatal_error)))
goto err;
if (sl == first_select)
{
@@ -269,7 +267,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
while ((type= tp++, item_tmp= it++))
{
if (((Item_type_holder*)type)->join_types(thd_arg, item_tmp))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
}
@@ -315,26 +313,23 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
if (!item_list.elements)
{
Field **field;
- Item_arena backup;
- if (arena->is_conventional())
- arena= 0;
- else
- thd->set_n_backup_item_arena(arena, &backup);
+ Item_arena *tmp_arena,backup;
+ tmp_arena= thd->change_arena_if_needed(&backup);
for (field= table->field; *field; field++)
{
Item_field *item= new Item_field(*field);
if (!item || item_list.push_back(item))
{
- if (arena)
- thd->restore_backup_item_arena(arena, &backup);
- DBUG_RETURN(-1);
+ if (tmp_arena)
+ thd->restore_backup_item_arena(tmp_arena, &backup);
+ DBUG_RETURN(TRUE);
}
}
- if (arena)
+ if (tmp_arena)
+ thd->restore_backup_item_arena(tmp_arena, &backup);
+ if (arena->is_stmt_prepare())
{
- thd->restore_backup_item_arena(arena, &backup);
-
/* prepare fake select to initialize it correctly */
ulong options_tmp= init_prepare_fake_select_lex(thd);
/*
@@ -346,7 +341,7 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
result)))
{
fake_select_lex->table_list.empty();
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
fake_select_lex->item_list= item_list;
@@ -381,15 +376,15 @@ int st_select_lex_unit::prepare(THD *thd_arg, select_result *sel_result,
thd_arg->lex->current_select= lex_select_save;
- DBUG_RETURN(res || thd_arg->is_fatal_error ? 1 : 0);
+ DBUG_RETURN(res || thd_arg->is_fatal_error);
err:
thd_arg->lex->current_select= lex_select_save;
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
-int st_select_lex_unit::exec()
+bool st_select_lex_unit::exec()
{
SELECT_LEX *lex_select_save= thd->lex->current_select;
SELECT_LEX *select_cursor=first_select_in_union();
@@ -398,7 +393,7 @@ int st_select_lex_unit::exec()
DBUG_ENTER("st_select_lex_unit::exec");
if (executed && !uncacheable && !describe)
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
executed= 1;
if (uncacheable || !item || !item->assigned() || describe)
@@ -413,7 +408,7 @@ int st_select_lex_unit::exec()
}
/* re-enabling indexes for next subselect iteration */
if (union_distinct && table->file->enable_indexes(HA_KEY_SWITCH_ALL))
- DBUG_ASSERT(1);
+ DBUG_ASSERT(TRUE);
}
for (SELECT_LEX *sl= select_cursor; sl; sl= sl->next_select())
{
@@ -468,7 +463,7 @@ int st_select_lex_unit::exec()
if (sl == union_distinct)
{
if (table->file->disable_indexes(HA_KEY_SWITCH_ALL))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
table->no_keyread=1;
}
res= sl->join->error;
@@ -477,7 +472,7 @@ int st_select_lex_unit::exec()
{
examined_rows+= thd->examined_row_count;
thd->lex->current_select= lex_select_save;
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
}
}
if (res)
@@ -503,7 +498,7 @@ int st_select_lex_unit::exec()
optimized= 1;
/* Send result to 'result' */
- res= -1;
+ res= TRUE;
{
List<Item_func_match> empty_list;
empty_list.empty();
@@ -522,7 +517,7 @@ int st_select_lex_unit::exec()
fake_select_lex->options, result)))
{
fake_select_lex->table_list.empty();
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
/*
@@ -569,7 +564,7 @@ int st_select_lex_unit::exec()
}
-int st_select_lex_unit::cleanup()
+bool st_select_lex_unit::cleanup()
{
int error= 0;
JOIN *join;
@@ -577,7 +572,7 @@ int st_select_lex_unit::cleanup()
if (cleaned)
{
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
cleaned= 1;
@@ -651,19 +646,19 @@ void st_select_lex_unit::reinit_exec_mechanism()
old_result old select_result object
RETURN
- 0 - OK
- -1 - error
+ FALSE - OK
+ TRUE - error
*/
-int st_select_lex_unit::change_result(select_subselect *result,
- select_subselect *old_result)
+bool st_select_lex_unit::change_result(select_subselect *result,
+ select_subselect *old_result)
{
- int res= 0;
+ bool res= FALSE;
for (SELECT_LEX *sl= first_select_in_union(); sl; sl= sl->next_select())
{
if (sl->join && sl->join->result == old_result)
- if ((res= sl->join->change_result(result)))
- return (res);
+ if (sl->join->change_result(result))
+ return TRUE;
}
if (fake_select_lex && fake_select_lex->join)
res= fake_select_lex->join->change_result(result);
diff --git a/sql/sql_update.cc b/sql/sql_update.cc
index 5e91e730079..9613e39d403 100644
--- a/sql/sql_update.cc
+++ b/sql/sql_update.cc
@@ -38,15 +38,15 @@ static bool compare_record(TABLE *table, ulong query_id)
if (memcmp(table->null_flags,
table->null_flags+table->rec_buff_length,
table->null_bytes))
- return 1; // Diff in NULL value
+ return TRUE; // Diff in NULL value
/* Compare updated fields */
for (Field **ptr=table->field ; *ptr ; ptr++)
{
if ((*ptr)->query_id == query_id &&
(*ptr)->cmp_binary_offset(table->rec_buff_length))
- return 1;
+ return TRUE;
}
- return 0;
+ return FALSE;
}
@@ -86,6 +86,27 @@ static bool check_fields(THD *thd, List<Item> &items)
}
+/*
+ Process usual UPDATE
+
+ SYNOPSIS
+ mysql_update()
+ thd thread handler
+ fields fields for update
+ values values of fields for update
+ conds WHERE clause expression
+ order_num number of elemen in ORDER BY clause
+ order ORDER BY clause list
+ limit limit clause
+ handle_duplicates how to handle duplicates
+
+ RETURN
+ 0 - OK
+ 2 - privilege check and openning table passed, but we need to convert to
+ multi-update because of view substitution
+ 1 - error
+*/
+
int mysql_update(THD *thd,
TABLE_LIST *table_list,
List<Item> &fields,
@@ -99,25 +120,49 @@ int mysql_update(THD *thd,
bool safe_update= thd->options & OPTION_SAFE_UPDATES;
bool used_key_is_modified, transactional_table, log_delayed;
bool ignore_err= (thd->lex->duplicates == DUP_IGNORE);
- int error=0;
int res;
+ int error=0;
uint used_index;
#ifndef NO_EMBEDDED_ACCESS_CHECKS
uint want_privilege;
#endif
+ uint table_count= 0;
ulong query_id=thd->query_id, timestamp_query_id;
ha_rows updated, found;
key_map old_used_keys;
TABLE *table;
SQL_SELECT *select;
READ_RECORD info;
+ SELECT_LEX *select_lex= &thd->lex->select_lex;
DBUG_ENTER("mysql_update");
LINT_INIT(used_index);
LINT_INIT(timestamp_query_id);
- if ((error= open_and_lock_tables(thd, table_list)))
- DBUG_RETURN(error);
+ if (open_tables(thd, table_list, &table_count))
+ DBUG_RETURN(1);
+
+ if (table_list->ancestor && table_list->ancestor->next_local)
+ {
+ DBUG_ASSERT(table_list->view);
+ DBUG_PRINT("info", ("Switch to multi-update"));
+ /* pass counter value */
+ thd->lex->table_count= table_count;
+ /*
+ give correct value to multi_lock_option, because it will be used
+ in multiupdate
+ */
+ thd->lex->multi_lock_option= table_list->lock_type;
+ /* convert to multiupdate */
+ return 2;
+ }
+
+ if (lock_tables(thd, table_list, table_count) ||
+ mysql_handle_derived(thd->lex, &mysql_derived_prepare) ||
+ (thd->fill_derived_tables() &&
+ mysql_handle_derived(thd->lex, &mysql_derived_filling)))
+ DBUG_RETURN(1);
+
thd->proc_info="init";
table= table_list->table;
table->file->info(HA_STATUS_VARIABLE | HA_STATUS_NO_LOCK);
@@ -132,8 +177,8 @@ int mysql_update(THD *thd,
table_list->grant.want_privilege :
table->grant.want_privilege);
#endif
- if ((error= mysql_prepare_update(thd, table_list, &conds, order_num, order)))
- DBUG_RETURN(error);
+ if (mysql_prepare_update(thd, table_list, &conds, order_num, order))
+ DBUG_RETURN(1);
old_used_keys= table->used_keys; // Keys used in WHERE
/*
@@ -151,20 +196,20 @@ int mysql_update(THD *thd,
table_list->grant.want_privilege= table->grant.want_privilege= want_privilege;
#endif
{
- thd->lex->select_lex.no_wrap_view_item= 1;
+ select_lex->no_wrap_view_item= 1;
res= setup_fields(thd, 0, table_list, fields, 1, 0, 0);
- thd->lex->select_lex.no_wrap_view_item= 0;
+ select_lex->no_wrap_view_item= 0;
if (res)
- DBUG_RETURN(-1); /* purecov: inspected */
+ DBUG_RETURN(1); /* purecov: inspected */
}
if (table_list->view && check_fields(thd, fields))
{
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
if (!table_list->updatable || check_key_in_view(thd, table_list))
{
my_error(ER_NON_UPDATABLE_TABLE, MYF(0), table_list->alias, "UPDATE");
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
if (table->timestamp_field)
{
@@ -182,8 +227,8 @@ int mysql_update(THD *thd,
#endif
if (setup_fields(thd, 0, table_list, values, 0, 0, 0))
{
- free_underlaid_joins(thd, &thd->lex->select_lex);
- DBUG_RETURN(-1); /* purecov: inspected */
+ free_underlaid_joins(thd, select_lex);
+ DBUG_RETURN(1); /* purecov: inspected */
}
// Don't count on usage of 'only index' when calculating which key to use
@@ -193,10 +238,10 @@ int mysql_update(THD *thd,
(select && select->check_quick(thd, safe_update, limit)) || !limit)
{
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, select_lex);
if (error)
{
- DBUG_RETURN(-1); // Error in where
+ DBUG_RETURN(1); // Error in where
}
send_ok(thd); // No matching records
DBUG_RETURN(0);
@@ -212,7 +257,7 @@ int mysql_update(THD *thd,
goto err;
}
}
- init_ftfuncs(thd, &thd->lex->select_lex, 1);
+ init_ftfuncs(thd, select_lex, 1);
/* Check if we are modifying a key that we are used to search with */
if (select && select->quick)
@@ -361,8 +406,9 @@ int mysql_update(THD *thd,
if (!(select && select->skip_record()))
{
store_record(table,record[1]);
- if (fill_record(fields,values, 0) || thd->net.report_error)
+ if (fill_record(thd, fields, values, 0))
break; /* purecov: inspected */
+
found++;
if (table->triggers)
@@ -436,7 +482,7 @@ int mysql_update(THD *thd,
if (error <= 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed);
+ log_delayed, FALSE);
if (mysql_bin_log.write(&qinfo) && transactional_table)
error=1; // Rollback update
}
@@ -455,10 +501,8 @@ int mysql_update(THD *thd,
thd->lock=0;
}
- free_underlaid_joins(thd, &thd->lex->select_lex);
- if (error >= 0)
- send_error(thd,thd->killed_errno()); /* purecov: inspected */
- else
+ free_underlaid_joins(thd, select_lex);
+ if (error < 0)
{
char buff[80];
sprintf(buff, ER(ER_UPDATE_INFO), (ulong) found, (ulong) updated,
@@ -472,18 +516,18 @@ int mysql_update(THD *thd,
thd->count_cuted_fields= CHECK_FIELD_IGNORE; /* calc cuted fields */
thd->abort_on_warning= 0;
free_io_cache(table);
- DBUG_RETURN(0);
+ DBUG_RETURN((error >= 0 || thd->net.report_error) ? 1 : 0);
err:
delete select;
- free_underlaid_joins(thd, &thd->lex->select_lex);
+ free_underlaid_joins(thd, select_lex);
if (table->key_read)
{
table->key_read=0;
table->file->extra(HA_EXTRA_NO_KEYREAD);
}
thd->abort_on_warning= 0;
- DBUG_RETURN(-1);
+ DBUG_RETURN(1);
}
/*
@@ -498,11 +542,10 @@ err:
order - ORDER BY clause list
RETURN VALUE
- 0 - OK
- 1 - error (message is sent to user)
- -1 - error (message is not sent to user)
+ FALSE OK
+ TRUE error
*/
-int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
+bool mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
Item **conds, uint order_num, ORDER *order)
{
TABLE *table= table_list->table;
@@ -520,22 +563,23 @@ int mysql_prepare_update(THD *thd, TABLE_LIST *table_list,
tables.table= table;
tables.alias= table_list->alias;
- if (setup_tables(thd, table_list, conds) ||
- setup_conds(thd, table_list, conds) ||
+ if (setup_tables(thd, table_list, conds, &select_lex->leaf_tables,
+ FALSE, FALSE) ||
+ setup_conds(thd, table_list, select_lex->leaf_tables, conds) ||
select_lex->setup_ref_array(thd, order_num) ||
setup_order(thd, select_lex->ref_pointer_array,
table_list, all_fields, all_fields, order) ||
setup_ftfuncs(select_lex))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
/* Check that we are not using table that we are updating in a sub select */
- if (unique_table(table_list, table_list->next_independent()))
+ if (unique_table(table_list, table_list->next_global))
{
my_error(ER_UPDATE_TABLE_USED, MYF(0), table_list->real_name);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
select_lex->fix_prepare_information(thd, conds);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
}
@@ -568,49 +612,70 @@ static table_map get_table_map(List<Item> *items)
thd thread handler
RETURN
- 0 OK
- -1 Error
+ FALSE OK
+ TRUE Error
*/
-int mysql_multi_update_prepare(THD *thd)
+bool mysql_multi_update_prepare(THD *thd)
{
LEX *lex= thd->lex;
+ ulong opened_tables;
TABLE_LIST *table_list= lex->query_tables;
List<Item> *fields= &lex->select_lex.item_list;
TABLE_LIST *tl;
- table_map tables_for_update= 0, readonly_tables= 0;
+ TABLE_LIST *leaves;
+ table_map tables_for_update;
int res;
bool update_view= 0;
+ /*
+ if this multi-update was converted from usual update, here is table
+ counter else junk will be assigned here, but then replaced with real
+ count in open_tables()
+ */
+ uint table_count= lex->table_count;
+ const bool using_lock_tables= thd->locked_tables != 0;
+ bool original_multiupdate= (thd->lex->sql_command == SQLCOM_UPDATE_MULTI);
+ /* following need for prepared statements, to run next time multi-update */
+ thd->lex->sql_command= SQLCOM_UPDATE_MULTI;
DBUG_ENTER("mysql_multi_update_prepare");
+
+ /* open tables and create derived ones, but do not lock and fill them */
+ if ((original_multiupdate && open_tables(thd, table_list, & table_count)) ||
+ mysql_handle_derived(lex, &mysql_derived_prepare))
+ DBUG_RETURN(TRUE);
+ /*
+ setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
+ second time, but this call will do nothing (there are check for second
+ call in setup_tables()).
+ */
+
+ if (setup_tables(thd, table_list, &lex->select_lex.where,
+ &lex->select_lex.leaf_tables, FALSE, FALSE))
+ DBUG_RETURN(TRUE);
/*
Ensure that we have update privilege for all tables and columns in the
SET part
*/
- for (tl= table_list; tl; tl= tl->next_local)
+ for (tl= (leaves= lex->select_lex.leaf_tables); tl; tl= tl->next_leaf)
{
- TABLE *table= tl->table;
/*
Update of derived tables is checked later
We don't check privileges here, becasue then we would get error
"UPDATE command denided .. for column N" instead of
"Target table ... is not updatable"
*/
- if (!tl->derived)
- tl->grant.want_privilege= table->grant.want_privilege=
+ TABLE *table= tl->table;
+ TABLE_LIST *tlist;
+ if (!(tlist= tl->belong_to_view?tl->belong_to_view:tl)->derived)
+ tlist->grant.want_privilege= table->grant.want_privilege=
(UPDATE_ACL & ~table->grant.privilege);
}
- /*
- setup_tables() need for VIEWs. JOIN::prepare() will call setup_tables()
- second time, but this call will do nothing (there are check for second
- call in setup_tables()).
- */
- if (setup_tables(thd, table_list, &lex->select_lex.where) ||
- (thd->lex->select_lex.no_wrap_view_item= 1,
+ if ((lex->select_lex.no_wrap_view_item= 1,
res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
- thd->lex->select_lex.no_wrap_view_item= 0,
+ lex->select_lex.no_wrap_view_item= 0,
res))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
for (tl= table_list; tl ; tl= tl->next_local)
{
@@ -623,51 +688,116 @@ int mysql_multi_update_prepare(THD *thd)
if (update_view && check_fields(thd, *fields))
{
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
- {
- // Find tables used in items
- List_iterator_fast<Item> it(*fields);
- Item *item;
- while ((item= it++))
- {
- tables_for_update|= item->used_tables();
- }
- }
+ tables_for_update= get_table_map(fields);
/*
- Count tables and setup timestamp handling
+ Setup timestamp handling and locking mode
*/
- for (tl= table_list; tl ; tl= tl->next_local)
+ for (tl= leaves; tl; tl= tl->next_leaf)
{
TABLE *table= tl->table;
+ TABLE_LIST *tlist= tl->belong_to_view?tl->belong_to_view:tl;
/* We only need SELECT privilege for columns in the values list */
- tl->grant.want_privilege= table->grant.want_privilege=
+ tlist->grant.want_privilege= table->grant.want_privilege=
(SELECT_ACL & ~table->grant.privilege);
- // Only set timestamp column if this is not modified
+ /* Only set timestamp column if this is not modified */
if (table->timestamp_field &&
table->timestamp_field->query_id == thd->query_id)
table->timestamp_field_type= TIMESTAMP_NO_AUTO_SET;
- if (!tl->updatable || check_key_in_view(thd, tl))
- readonly_tables|= table->map;
+ /* if table will be updated then check that it is unique */
+ if (table->map & tables_for_update)
+ {
+ if (!tl->updatable || check_key_in_view(thd, tl))
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), tl->alias, "UPDATE");
+ DBUG_RETURN(TRUE);
+ }
+
+ /*
+ Multi-update can't be constructed over-union => we always have
+ single SELECT on top and have to check underlying SELECTs of it
+ */
+ if (lex->select_lex.check_updateable_in_subqueries(tl->db,
+ tl->real_name))
+ {
+ my_error(ER_UPDATE_TABLE_USED, MYF(0), tl->real_name);
+ DBUG_RETURN(TRUE);
+ }
+ DBUG_PRINT("info",("setting table `%s` for update", tl->alias));
+ tl->lock_type= lex->multi_lock_option;
+ tl->updating= 1;
+ }
+ else
+ {
+ DBUG_PRINT("info",("setting table `%s` for read-only", tl->alias));
+ tl->lock_type= TL_READ;
+ tl->updating= 0;
+ }
+ if (!using_lock_tables)
+ tl->table->reginfo.lock_type= tl->lock_type;
}
- if (tables_for_update & readonly_tables)
+
+ /* check single table update for view compound from several tables */
+ for (tl= table_list; tl; tl= tl->next_local)
{
- // find readonly table/view which cause error
- for (tl= table_list; tl ; tl= tl->next_local)
+ if (tl->table == 0)
{
- if ((readonly_tables & tl->table->map) &&
- (tables_for_update & tl->table->map))
+ DBUG_ASSERT(tl->view &&
+ tl->ancestor && tl->ancestor->next_local);
+ TABLE_LIST *for_update= 0;
+ if (tl->check_single_table(&for_update, tables_for_update))
{
- my_error(ER_NON_UPDATABLE_TABLE, MYF(0), tl->alias, "UPDATE");
+ my_error(ER_VIEW_MULTIUPDATE, MYF(0),
+ tl->view_db.str, tl->view_name.str);
DBUG_RETURN(-1);
}
}
}
- DBUG_RETURN (0);
+
+ opened_tables= thd->status_var.opened_tables;
+ /* now lock and fill tables */
+ if (lock_tables(thd, table_list, table_count))
+ DBUG_RETURN(TRUE);
+
+ /*
+ we have to re-call fixfields for fixed items, because lock maybe
+ reopened tables
+ */
+ if (opened_tables != thd->status_var.opened_tables)
+ {
+ /*
+ Fields items cleanup(). There are only Item_fields in the list, so we
+ do not do Item tree walking
+ */
+ List_iterator_fast<Item> it(*fields);
+ Item *item;
+ while ((item= it++))
+ item->cleanup();
+
+ /* We have to cleanup translation tables of views. */
+ for (TABLE_LIST *tbl= table_list; tbl; tbl= tbl->next_global)
+ tbl->cleanup_items();
+
+ /* undone setup_tables() */
+ table_list->setup_is_done= 0;
+
+ if (setup_tables(thd, table_list, &lex->select_lex.where,
+ &lex->select_lex.leaf_tables, FALSE, FALSE) ||
+ (lex->select_lex.no_wrap_view_item= 1,
+ res= setup_fields(thd, 0, table_list, *fields, 1, 0, 0),
+ lex->select_lex.no_wrap_view_item= 0,
+ res))
+ DBUG_RETURN(TRUE);
+ }
+ if (thd->fill_derived_tables() &&
+ mysql_handle_derived(lex, &mysql_derived_filling))
+ DBUG_RETURN(TRUE);
+ DBUG_RETURN (FALSE);
}
@@ -675,30 +805,27 @@ int mysql_multi_update_prepare(THD *thd)
Setup multi-update handling and call SELECT to do the join
*/
-int mysql_multi_update(THD *thd,
- TABLE_LIST *table_list,
- List<Item> *fields,
- List<Item> *values,
- COND *conds,
- ulong options,
- enum enum_duplicates handle_duplicates,
- SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
+bool mysql_multi_update(THD *thd,
+ TABLE_LIST *table_list,
+ List<Item> *fields,
+ List<Item> *values,
+ COND *conds,
+ ulong options,
+ enum enum_duplicates handle_duplicates,
+ SELECT_LEX_UNIT *unit, SELECT_LEX *select_lex)
{
- int res;
+ bool res= FALSE;
multi_update *result;
DBUG_ENTER("mysql_multi_update");
- /* QQ: This should be fixed soon to get lower granularity locks */
- select_lex->set_lock_for_tables(thd->lex->multi_lock_option);
- if ((res= open_and_lock_tables(thd, table_list)))
- DBUG_RETURN(res);
-
- if ((res= mysql_multi_update_prepare(thd)))
- DBUG_RETURN(res);
+ if (mysql_multi_update_prepare(thd))
+ DBUG_RETURN(TRUE);
- if (!(result= new multi_update(thd, table_list, fields, values,
+ if (!(result= new multi_update(thd, table_list,
+ thd->lex->select_lex.leaf_tables,
+ fields, values,
handle_duplicates)))
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
thd->no_trans_update= 0;
thd->abort_on_warning= test(thd->variables.sql_mode &
@@ -715,17 +842,19 @@ int mysql_multi_update(THD *thd,
result, unit, select_lex);
delete result;
thd->abort_on_warning= 0;
- DBUG_RETURN(res);
+ DBUG_RETURN(TRUE);
}
multi_update::multi_update(THD *thd_arg, TABLE_LIST *table_list,
+ TABLE_LIST *leaves_list,
List<Item> *field_list, List<Item> *value_list,
enum enum_duplicates handle_duplicates_arg)
- :all_tables(table_list), update_tables(0), thd(thd_arg), tmp_tables(0),
- updated(0), found(0), fields(field_list), values(value_list),
- table_count(0), copy_field(0), handle_duplicates(handle_duplicates_arg),
- do_update(1), trans_safe(0), transactional_tables(1)
+ :all_tables(table_list), leaves(leaves_list), update_tables(0),
+ thd(thd_arg), tmp_tables(0), updated(0), found(0), fields(field_list),
+ values(value_list), table_count(0), copy_field(0),
+ handle_duplicates(handle_duplicates_arg), do_update(1), trans_safe(0),
+ transactional_tables(1)
{}
@@ -753,7 +882,7 @@ int multi_update::prepare(List<Item> &not_used_values,
if (!tables_to_update)
{
- my_error(ER_NO_TABLES_USED, MYF(0));
+ my_message(ER_NO_TABLES_USED, ER(ER_NO_TABLES_USED), MYF(0));
DBUG_RETURN(1);
}
@@ -772,8 +901,9 @@ int multi_update::prepare(List<Item> &not_used_values,
*/
update.empty();
- for (table_ref= all_tables; table_ref; table_ref= table_ref->next_local)
+ for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
{
+ /* TODO: add support of view of join support */
TABLE *table=table_ref->table;
if (tables_to_update & table->map)
{
@@ -840,10 +970,10 @@ int multi_update::prepare(List<Item> &not_used_values,
which will cause an error when reading a row.
(This issue is mostly relevent for MyISAM tables)
*/
- for (table_ref= all_tables; table_ref; table_ref= table_ref->next_local)
+ for (table_ref= leaves; table_ref; table_ref= table_ref->next_leaf)
{
TABLE *table=table_ref->table;
- if (!(tables_to_update & table->map) &&
+ if (!(tables_to_update & table->map) &&
find_table_in_local_list(update_tables, table_ref->db,
table_ref->real_name))
table->no_cache= 1; // Disable row cache
@@ -965,7 +1095,7 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
case JT_SYSTEM:
case JT_CONST:
case JT_EQ_REF:
- return 1; // At most one matching row
+ return TRUE; // At most one matching row
case JT_REF:
return !check_if_key_used(table, join_tab->ref.key, *fields);
case JT_ALL:
@@ -976,11 +1106,11 @@ static bool safe_update_on_fly(JOIN_TAB *join_tab, List<Item> *fields)
if ((table->file->table_flags() & HA_PRIMARY_KEY_IN_READ_INDEX) &&
table->primary_key < MAX_KEY)
return !check_if_key_used(table, table->primary_key, *fields);
- return 1;
+ return TRUE;
default:
break; // Avoid compler warning
}
- return 0;
+ return FALSE;
}
@@ -1039,8 +1169,10 @@ bool multi_update::send_data(List<Item> &not_used_values)
{
table->status|= STATUS_UPDATED;
store_record(table,record[1]);
- if (fill_record(*fields_for_table[offset], *values_for_table[offset], 0))
+ if (fill_record(thd, *fields_for_table[offset],
+ *values_for_table[offset], 0))
DBUG_RETURN(1);
+
found++;
if (compare_record(table, thd->query_id))
{
@@ -1083,7 +1215,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
{
int error;
TABLE *tmp_table= tmp_tables[offset];
- fill_record(tmp_table->field+1, *values_for_table[offset], 1);
+ fill_record(thd, tmp_table->field+1, *values_for_table[offset], 1);
found++;
/* Store pointer to row */
memcpy((char*) tmp_table->field[0]->ptr,
@@ -1109,7 +1241,7 @@ bool multi_update::send_data(List<Item> &not_used_values)
void multi_update::send_error(uint errcode,const char *err)
{
/* First send error what ever it is ... */
- ::send_error(thd,errcode,err);
+ my_error(errcode, MYF(0), err);
/* If nothing updated return */
if (!updated)
@@ -1283,7 +1415,7 @@ bool multi_update::send_eof()
if (local_error <= 0)
thd->clear_error();
Query_log_event qinfo(thd, thd->query, thd->query_length,
- log_delayed);
+ log_delayed, FALSE);
if (mysql_bin_log.write(&qinfo) && trans_safe)
local_error= 1; // Rollback update
}
@@ -1302,8 +1434,7 @@ bool multi_update::send_eof()
/* Safety: If we haven't got an error before (should not happen) */
my_message(ER_UNKNOWN_ERROR, "An error occured in multi-table update",
MYF(0));
- ::send_error(thd);
- return 1;
+ return TRUE;
}
@@ -1313,5 +1444,5 @@ bool multi_update::send_eof()
(thd->client_capabilities & CLIENT_FOUND_ROWS) ? found : updated;
::send_ok(thd, (ulong) thd->row_count_func,
thd->insert_id_used ? thd->insert_id() : 0L,buff);
- return 0;
+ return FALSE;
}
diff --git a/sql/sql_view.cc b/sql/sql_view.cc
index f8994148ffc..993a4d1987b 100644
--- a/sql/sql_view.cc
+++ b/sql/sql_view.cc
@@ -21,6 +21,8 @@
#include "parse_file.h"
#include "sp.h"
+#define MD5_BUFF_LENGTH 33
+
static int mysql_register_view(THD *thd, TABLE_LIST *view,
enum_view_create_mode mode);
@@ -42,13 +44,12 @@ TYPELIB updatable_views_with_limit_typelib=
mode - VIEW_CREATE_NEW, VIEW_ALTER, VIEW_CREATE_OR_REPLACE
RETURN VALUE
- 0 OK
- -1 Error
- 1 Error and error message given
+ FALSE OK
+ TRUE Error
*/
-int mysql_create_view(THD *thd,
- enum_view_create_mode mode)
+bool mysql_create_view(THD *thd,
+ enum_view_create_mode mode)
{
LEX *lex= thd->lex;
bool link_to_local;
@@ -56,9 +57,12 @@ int mysql_create_view(THD *thd,
TABLE_LIST *view= lex->unlink_first_table(&link_to_local);
TABLE_LIST *tables= lex->query_tables;
TABLE_LIST *tbl;
- SELECT_LEX *select_lex= &lex->select_lex, *sl;
+ SELECT_LEX *select_lex= &lex->select_lex;
+#ifndef NO_EMBEDDED_ACCESS_CHECKS
+ SELECT_LEX *sl;
+#endif
SELECT_LEX_UNIT *unit= &lex->unit;
- int res= 0;
+ bool res= FALSE;
DBUG_ENTER("mysql_create_view");
if (lex->proc_list.first ||
@@ -67,16 +71,17 @@ int mysql_create_view(THD *thd,
my_error(ER_VIEW_SELECT_CLAUSE, MYF(0), (lex->result ?
"INTO" :
"PROCEDURE"));
- res= -1;
+ res= TRUE;
goto err;
}
if (lex->derived_tables ||
lex->variables_used || lex->param_list.elements)
{
- my_error((lex->derived_tables ?
+ int err= (lex->derived_tables ?
ER_VIEW_SELECT_DERIVED :
- ER_VIEW_SELECT_VARIABLE), MYF(0));
- res= -1;
+ ER_VIEW_SELECT_VARIABLE);
+ my_message(err, ER(err), MYF(0));
+ res= TRUE;
goto err;
}
@@ -102,7 +107,7 @@ int mysql_create_view(THD *thd,
(check_access(thd, DELETE_ACL, view->db, &view->grant.privilege,
0, 0) ||
grant_option && check_grant(thd, DELETE_ACL, view, 0, 1, 0))))
- DBUG_RETURN(1);
+ DBUG_RETURN(TRUE);
for (sl= select_lex; sl; sl= sl->next_select())
{
for (tbl= sl->get_table_list(); tbl; tbl= tbl->next_local)
@@ -113,14 +118,9 @@ int mysql_create_view(THD *thd,
*/
if (check_some_access(thd, VIEW_ANY_ACL, tbl))
{
- my_printf_error(ER_TABLEACCESS_DENIED_ERROR,
- ER(ER_TABLEACCESS_DENIED_ERROR),
- MYF(0),
- "ANY",
- thd->priv_user,
- thd->host_or_ip,
- tbl->real_name);
- DBUG_RETURN(-1);
+ my_error(ER_TABLEACCESS_DENIED_ERROR, MYF(0),
+ "ANY", thd->priv_user, thd->host_or_ip, tbl->real_name);
+ DBUG_RETURN(TRUE);
}
/*
Mark this table as a table which will be checked after the prepare
@@ -156,7 +156,7 @@ int mysql_create_view(THD *thd,
&tbl->grant.privilege, 0, 0) ||
grant_option && check_grant(thd, SELECT_ACL, tbl, 0, 1, 0))
{
- res= 1;
+ res= TRUE;
goto err;
}
}
@@ -178,8 +178,8 @@ int mysql_create_view(THD *thd,
}
#endif
- if ((res= open_and_lock_tables(thd, tables)))
- DBUG_RETURN(res);
+ if (open_and_lock_tables(thd, tables))
+ DBUG_RETURN(TRUE);
/*
check that tables are not temporary and this VIEW do not used in query
@@ -188,10 +188,11 @@ int mysql_create_view(THD *thd,
for (tbl= tables; tbl; tbl= tbl->next_global)
{
/* is this table temporary and is not view? */
- if (tbl->table->tmp_table != NO_TMP_TABLE && !tbl->view)
+ if (tbl->table->tmp_table != NO_TMP_TABLE && !tbl->view &&
+ !tbl->schema_table)
{
my_error(ER_VIEW_SELECT_TMPTABLE, MYF(0), tbl->alias);
- res= -1;
+ res= TRUE;
goto err;
}
@@ -201,7 +202,7 @@ int mysql_create_view(THD *thd,
strcmp(tbl->view_name.str, view->real_name) == 0)
{
my_error(ER_NO_SUCH_TABLE, MYF(0), tbl->view_db.str, tbl->view_name.str);
- res= -1;
+ res= TRUE;
goto err;
}
@@ -221,7 +222,7 @@ int mysql_create_view(THD *thd,
some errors from prepare are reported to user, if is not then
it will be checked after err: label
*/
- res= 1;
+ res= TRUE;
goto err;
}
@@ -256,7 +257,7 @@ int mysql_create_view(THD *thd,
if (strcmp(item->name, check->name) == 0)
{
my_error(ER_DUP_FIELDNAME, MYF(0), item->name);
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
}
}
@@ -284,18 +285,13 @@ int mysql_create_view(THD *thd,
/*
Do we have more privileges on view field then underlying table field?
*/
- if ((~fld->have_privileges & priv))
+ if (!fld->field->table->tmp_table && (~fld->have_privileges & priv))
{
/* VIEW column has more privileges */
- my_printf_error(ER_COLUMNACCESS_DENIED_ERROR,
- ER(ER_COLUMNACCESS_DENIED_ERROR),
- MYF(0),
- "create view",
- thd->priv_user,
- thd->host_or_ip,
- item->name,
- view->real_name);
- DBUG_RETURN(-1);
+ my_error(ER_COLUMNACCESS_DENIED_ERROR, MYF(0),
+ "create view", thd->priv_user, thd->host_or_ip, item->name,
+ view->real_name);
+ DBUG_RETURN(TRUE);
}
}
}
@@ -304,7 +300,7 @@ int mysql_create_view(THD *thd,
if (wait_if_global_read_lock(thd, 0, 0))
{
- res= -1;
+ res= TRUE;
goto err;
}
VOID(pthread_mutex_lock(&LOCK_open));
@@ -316,15 +312,13 @@ int mysql_create_view(THD *thd,
send_ok(thd);
lex->link_first_table_back(view, link_to_local);
- return 0;
+ DBUG_RETURN(0);
err:
thd->proc_info= "end";
lex->link_first_table_back(view, link_to_local);
unit->cleanup();
- if (thd->net.report_error)
- res= -1;
- DBUG_RETURN(res);
+ DBUG_RETURN(res || thd->net.report_error);
}
@@ -383,9 +377,10 @@ static LEX_STRING view_file_type[]= {{(char*)"VIEW", 4}};
static int mysql_register_view(THD *thd, TABLE_LIST *view,
enum_view_create_mode mode)
{
+ LEX *lex= thd->lex;
char buff[4096];
String str(buff,(uint32) sizeof(buff), system_charset_info);
- char md5[33];
+ char md5[MD5_BUFF_LENGTH];
bool can_be_merged;
char dir_buff[FN_REFLEN], file_buff[FN_REFLEN];
LEX_STRING dir, file;
@@ -396,7 +391,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
{
ulong sql_mode= thd->variables.sql_mode & MODE_ANSI_QUOTES;
thd->variables.sql_mode&= ~MODE_ANSI_QUOTES;
- thd->lex->unit.print(&str);
+ lex->unit.print(&str);
thd->variables.sql_mode|= sql_mode;
}
str.append('\0');
@@ -434,14 +429,14 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
DBUG_RETURN(-1);
}
- if (!(parser= sql_parse_prepare(&path, &thd->mem_root, 0)))
+ if (!(parser= sql_parse_prepare(&path, thd->mem_root, 0)))
DBUG_RETURN(1);
if (!parser->ok() ||
strncmp("VIEW", parser->type()->str, parser->type()->length))
{
- my_error(ER_WRONG_OBJECT, MYF(0), (view->db ? view->db : thd->db),
- view->real_name, "VIEW");
+ my_error(ER_WRONG_OBJECT, MYF(0),
+ (view->db ? view->db : thd->db), view->real_name, "VIEW");
DBUG_RETURN(-1);
}
@@ -451,7 +446,7 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
TODO: read dependence list, too, to process cascade/restrict
TODO: special cascade/restrict procedure for alter?
*/
- if (parser->parse((gptr)view, &thd->mem_root,
+ if (parser->parse((gptr)view, thd->mem_root,
view_parameters + revision_number_position, 1))
{
DBUG_RETURN(thd->net.report_error? -1 : 0);
@@ -475,31 +470,59 @@ static int mysql_register_view(THD *thd, TABLE_LIST *view,
view->calc_md5(md5);
view->md5.str= md5;
view->md5.length= 32;
- can_be_merged= thd->lex->can_be_merged();
- if (thd->lex->create_view_algorithm == VIEW_ALGORITHM_MERGE &&
- !thd->lex->can_be_merged())
+ can_be_merged= lex->can_be_merged();
+ if (lex->create_view_algorithm == VIEW_ALGORITHM_MERGE &&
+ !lex->can_be_merged())
{
push_warning(thd, MYSQL_ERROR::WARN_LEVEL_WARN, ER_WARN_VIEW_MERGE,
ER(ER_WARN_VIEW_MERGE));
- thd->lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
+ lex->create_view_algorithm= VIEW_ALGORITHM_UNDEFINED;
}
- view->algorithm= thd->lex->create_view_algorithm;
- view->with_check= thd->lex->create_view_check;
+ view->algorithm= lex->create_view_algorithm;
+ view->with_check= lex->create_view_check;
if ((view->updatable_view= (can_be_merged &&
view->algorithm != VIEW_ALGORITHM_TMPTABLE)))
{
/* TODO: change here when we will support UNIONs */
- for (TABLE_LIST *tbl= (TABLE_LIST *)thd->lex->select_lex.table_list.first;
- tbl;
- tbl= tbl->next_local)
+ for (TABLE_LIST *tbl= (TABLE_LIST *)lex->select_lex.table_list.first;
+ tbl;
+ tbl= tbl->next_local)
{
- if (tbl->view && !tbl->updatable_view)
+ if ((tbl->view && !tbl->updatable_view) || tbl->schema_table)
+ {
+ view->updatable_view= 0;
+ break;
+ }
+ for (TABLE_LIST *up= tbl; up; up= up->embedding)
{
- view->updatable_view= 0;
- break;
+ if (up->outer_join)
+ {
+ view->updatable_view= 0;
+ goto loop_out;
+ }
}
}
}
+loop_out:
+ /*
+ Check that table of main select do not used in subqueries.
+
+ This test can catch only very simple cases of such non-updateable views,
+ all other will be detected before updating commands execution.
+ (it is more optimisation then real check)
+
+ NOTE: this skip cases of using table via VIEWs, joined VIEWs, VIEWs with
+ UNION
+ */
+ if (view->updatable_view &&
+ !lex->select_lex.next_select() &&
+ !((TABLE_LIST*)lex->select_lex.table_list.first)->next_local &&
+ find_table_in_global_list(lex->query_tables->next_global,
+ lex->query_tables->db,
+ lex->query_tables->real_name))
+ {
+ view->updatable_view= 0;
+ }
if (view->with_check != VIEW_CHECK_NONE &&
!view->updatable_view)
@@ -546,6 +569,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
SELECT_LEX *end;
THD *thd= current_thd;
LEX *old_lex= thd->lex, *lex;
+ SELECT_LEX *view_select;
int res= 0;
/*
@@ -565,7 +589,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
TODO: when VIEWs will be stored in cache, table mem_root should
be used here
*/
- if (parser->parse((gptr)table, &thd->mem_root, view_parameters,
+ if (parser->parse((gptr)table, thd->mem_root, view_parameters,
required_view_parameters))
goto err;
@@ -586,9 +610,10 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
now Lex placed in statement memory
*/
- table->view= lex= thd->lex= (LEX*) new(&thd->mem_root) st_lex_local;
+ table->view= lex= thd->lex= (LEX*) new(thd->mem_root) st_lex_local;
lex_start(thd, (uchar*)table->query.str, table->query.length);
- lex->select_lex.select_number= ++thd->select_number;
+ view_select= &lex->select_lex;
+ view_select->select_number= ++thd->select_number;
old_lex->derived_tables|= DERIVED_VIEW;
{
ulong options= thd->options;
@@ -631,6 +656,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
table);
TABLE_LIST *view_tables= lex->query_tables;
TABLE_LIST *view_tables_tail= 0;
+ TABLE_LIST *tbl;
if (lex->spfuns.records)
{
@@ -658,7 +684,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
mark to avoid temporary table using and put view reference and find
last view table
*/
- for (TABLE_LIST *tbl= view_tables;
+ for (tbl= view_tables;
tbl;
tbl= (view_tables_tail= tbl)->next_global)
{
@@ -675,7 +701,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
if (check_table_access(thd, SELECT_ACL, view_tables, 1) &&
check_table_access(thd, SHOW_VIEW_ACL, table, 1))
{
- my_error(ER_VIEW_NO_EXPLAIN, MYF(0));
+ my_message(ER_VIEW_NO_EXPLAIN, ER(ER_VIEW_NO_EXPLAIN), MYF(0));
goto err;
}
}
@@ -689,7 +715,7 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
old_lex->safe_to_cache_query= (old_lex->safe_to_cache_query &&
lex->safe_to_cache_query);
/* move SQL_CACHE to whole query */
- if (lex->select_lex.options & OPTION_TO_QUERY_CACHE)
+ if (view_select->options & OPTION_TO_QUERY_CACHE)
old_lex->select_lex.options|= OPTION_TO_QUERY_CACHE;
/*
@@ -699,13 +725,12 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
tables just after VIEW instead of tail of list, to be able check that
table is unique. Also we store old next table for the same purpose.
*/
- table->old_next= table->next_global;
if (view_tables)
{
if (table->next_global)
{
+ view_tables_tail->next_global= table->next_global;
table->next_global->prev_global= &view_tables_tail->next_global;
- view_tables_tail->next_global= table->old_next;
}
else
{
@@ -727,32 +752,57 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
old_lex->can_use_merged()) &&
!old_lex->can_not_use_merged())
{
- /*
- TODO: support multi tables substitutions
- */
/* lex should contain at least one table */
DBUG_ASSERT(view_tables != 0);
table->effective_algorithm= VIEW_ALGORITHM_MERGE;
DBUG_PRINT("info", ("algorithm: MERGE"));
table->updatable= (table->updatable_view != 0);
- table->effective_with_check= table->with_check;
+ table->effective_with_check= (uint8)table->with_check;
table->ancestor= view_tables;
- /*
- next table should include SELECT_LEX under this table SELECT_LEX
- TODO: here should be loop for multi tables substitution
- */
+ /* next table should include SELECT_LEX under this table SELECT_LEX */
table->ancestor->select_lex= table->select_lex;
+
/*
- move lock type (TODO: should we issue error in case of TMPTABLE
- algorithm and non-read locking)?
+ Process upper level tables of view. As far as we do noy suport union
+ here we can go through local tables of view most upper SELECT
*/
- view_tables->lock_type= table->lock_type;
+ for(tbl= (TABLE_LIST*)view_select->table_list.first;
+ tbl;
+ tbl= tbl->next_local)
+ {
+ /*
+ move lock type (TODO: should we issue error in case of TMPTABLE
+ algorithm and non-read locking)?
+ */
+ tbl->lock_type= table->lock_type;
+ }
+
+ /* multi table view */
+ if (view_tables->next_local)
+ {
+ /* make nested join structure for view tables */
+ NESTED_JOIN *nested_join;
+ if (!(nested_join= table->nested_join=
+ (NESTED_JOIN *) thd->calloc(sizeof(NESTED_JOIN))))
+ goto err;
+ nested_join->join_list= view_select->top_join_list;
+
+ /* re-nest tables of VIEW */
+ {
+ List_iterator_fast<TABLE_LIST> ti(nested_join->join_list);
+ while ((tbl= ti++))
+ {
+ tbl->join_list= &nested_join->join_list;
+ tbl->embedding= table;
+ }
+ }
+ }
/* Store WHERE clause for post-processing in setup_ancestor */
- table->where= lex->select_lex.where;
+ table->where= view_select->where;
/*
Add subqueries units to SELECT in which we merging current view.
@@ -779,13 +829,14 @@ mysql_make_view(File_parser *parser, TABLE_LIST *table)
table->effective_algorithm= VIEW_ALGORITHM_TMPTABLE;
DBUG_PRINT("info", ("algorithm: TEMPORARY TABLE"));
- lex->select_lex.linkage= DERIVED_TABLE_TYPE;
+ view_select->linkage= DERIVED_TABLE_TYPE;
table->updatable= 0;
table->effective_with_check= VIEW_CHECK_NONE;
+ old_lex->subqueries= TRUE;
/* SELECT tree link */
lex->unit.include_down(table->select_lex);
- lex->unit.slave= &lex->select_lex; // fix include_down initialisation
+ lex->unit.slave= view_select; // fix include_down initialisation
table->derived= &lex->unit;
}
@@ -796,7 +847,7 @@ ok:
if (arena)
thd->restore_backup_item_arena(arena, &backup);
/* global SELECT list linking */
- end= &lex->select_lex; // primary SELECT_LEX is always last
+ end= view_select; // primary SELECT_LEX is always last
end->link_next= old_lex->all_selects_list;
old_lex->all_selects_list->link_prev= &end->link_next;
old_lex->all_selects_list= lex->all_selects_list;
@@ -825,12 +876,11 @@ err:
drop_mode - cascade/check
RETURN VALUE
- 0 OK
- -1 Error
- 1 Error and error message given
+ FALSE OK
+ TRUE Error
*/
-int mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
+bool mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
{
DBUG_ENTER("mysql_drop_view");
char path[FN_REFLEN];
@@ -866,11 +916,11 @@ int mysql_drop_view(THD *thd, TABLE_LIST *views, enum_drop_mode drop_mode)
VOID(pthread_mutex_unlock(&LOCK_open));
}
send_ok(thd);
- DBUG_RETURN(0);
+ DBUG_RETURN(FALSE);
err:
VOID(pthread_mutex_unlock(&LOCK_open));
- DBUG_RETURN(-1);
+ DBUG_RETURN(TRUE);
}
@@ -933,24 +983,26 @@ frm_type_enum mysql_frm_type(char *path)
bool check_key_in_view(THD *thd, TABLE_LIST *view)
{
TABLE *table;
- Item **trans;
+ Field_translator *trans;
KEY *key_info, *key_info_end;
uint i, elements_in_view;
DBUG_ENTER("check_key_in_view");
/*
- we do not support updatable UNIONs in VIW, so we can check just limit of
+ we do not support updatable UNIONs in VIEW, so we can check just limit of
LEX::select_lex
*/
- if (!view->view || thd->lex->sql_command == SQLCOM_INSERT ||
+ if ((!view->view && !view->belong_to_view) || thd->lex->sql_command == SQLCOM_INSERT ||
thd->lex->select_lex.select_limit == HA_POS_ERROR)
DBUG_RETURN(FALSE); /* it is normal table or query without LIMIT */
table= view->table;
+ if (view->belong_to_view)
+ view= view->belong_to_view;
trans= view->field_translation;
key_info_end= (key_info= table->key_info)+ table->keys;
elements_in_view= view->view->select_lex.item_list.elements;
- DBUG_ASSERT(view->table != 0 && view->field_translation != 0);
+ DBUG_ASSERT(table != 0 && view->field_translation != 0);
/* Loop over all keys to see if a unique-not-null key is used */
for (;key_info != key_info_end ; key_info++)
@@ -967,7 +1019,7 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
for (k= 0; k < elements_in_view; k++)
{
Item_field *field;
- if ((field= trans[k]->filed_for_view_update()) &&
+ if ((field= trans[k].item->filed_for_view_update()) &&
field->field == key_part->field)
break;
}
@@ -988,14 +1040,14 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
for (i= 0; i < elements_in_view; i++)
{
Item_field *field;
- if ((field= trans[i]->filed_for_view_update()) &&
+ if ((field= trans[i].item->filed_for_view_update()) &&
field->field == *field_ptr)
break;
}
if (i == elements_in_view) // If field didn't exists
{
/*
- Keys or all fields of underlaying tables are not foud => we have
+ Keys or all fields of underlying tables are not foud => we have
to check variable updatable_views_with_limit to decide should we
issue an error or just a warning
*/
@@ -1022,22 +1074,56 @@ bool check_key_in_view(THD *thd, TABLE_LIST *view)
insert_view_fields()
list list for insertion
view view for processing
+
+ RETURN
+ FALSE OK
+ TRUE error (is not sent to cliet)
*/
-void insert_view_fields(List<Item> *list, TABLE_LIST *view)
+bool insert_view_fields(List<Item> *list, TABLE_LIST *view)
{
uint elements_in_view= view->view->select_lex.item_list.elements;
- Item **trans;
+ Field_translator *trans;
DBUG_ENTER("insert_view_fields");
if (!(trans= view->field_translation))
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
for (uint i= 0; i < elements_in_view; i++)
{
Item_field *fld;
- if ((fld= trans[i]->filed_for_view_update()))
+ if ((fld= trans[i].item->filed_for_view_update()))
list->push_back(fld);
+ else
+ {
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0), view->alias, "INSERT");
+ DBUG_RETURN(TRUE);
+ }
}
- DBUG_VOID_RETURN;
+ DBUG_RETURN(FALSE);
+}
+
+/*
+ checking view md5 check suum
+
+ SINOPSYS
+ view_checksum()
+ thd threar handler
+ view view for check
+
+ RETUIRN
+ HA_ADMIN_OK OK
+ HA_ADMIN_NOT_IMPLEMENTED it is not VIEW
+ HA_ADMIN_WRONG_CHECKSUM check sum is wrong
+*/
+
+int view_checksum(THD *thd, TABLE_LIST *view)
+{
+ char md5[MD5_BUFF_LENGTH];
+ if (!view->view || view->md5.length != 32)
+ return HA_ADMIN_NOT_IMPLEMENTED;
+ view->calc_md5(md5);
+ return (strncmp(md5, view->md5.str, 32) ?
+ HA_ADMIN_WRONG_CHECKSUM :
+ HA_ADMIN_OK);
}
diff --git a/sql/sql_view.h b/sql/sql_view.h
index 538f548d97b..4e6aaf7f477 100644
--- a/sql/sql_view.h
+++ b/sql/sql_view.h
@@ -16,19 +16,21 @@
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/
-int mysql_create_view(THD *thd,
- enum_view_create_mode mode);
+bool mysql_create_view(THD *thd,
+ enum_view_create_mode mode);
my_bool mysql_make_view(File_parser *parser, TABLE_LIST *table);
-int mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
+bool mysql_drop_view(THD *thd, TABLE_LIST *view, enum_drop_mode drop_mode);
bool check_key_in_view(THD *thd, TABLE_LIST * view);
-void insert_view_fields(List<Item> *list, TABLE_LIST *view);
+bool insert_view_fields(List<Item> *list, TABLE_LIST *view);
frm_type_enum mysql_frm_type(char *path);
+int view_checksum(THD *thd, TABLE_LIST *view);
+
extern TYPELIB updatable_views_with_limit_typelib;
#define VIEW_ANY_ACL (SELECT_ACL | UPDATE_ACL | INSERT_ACL | DELETE_ACL)
diff --git a/sql/sql_yacc.yy b/sql/sql_yacc.yy
index c658d2ae016..8b3cdda5d9e 100644
--- a/sql/sql_yacc.yy
+++ b/sql/sql_yacc.yy
@@ -51,10 +51,13 @@ int yylex(void *yylval, void *yythd);
ER_WARN_DEPRECATED_SYNTAX, \
ER(ER_WARN_DEPRECATED_SYNTAX), (A), (B));
-inline Item *or_or_concat(THD *thd, Item* A, Item* B)
+/* Helper for parsing "IS [NOT] truth_value" */
+inline Item *is_truth_value(Item *A, bool v1, bool v2)
{
- return (thd->variables.sql_mode & MODE_PIPES_AS_CONCAT ?
- (Item*) new Item_func_concat(A,B) : (Item*) new Item_cond_or(A,B));
+ return new Item_func_if(create_func_ifnull(A,
+ new Item_int((char *) (v2 ? "TRUE" : "FALSE"), v2, 1)),
+ new Item_int((char *) (v1 ? "TRUE" : "FALSE"), v1, 1),
+ new Item_int((char *) (v1 ? "FALSE" : "TRUE"),!v1, 1));
}
%}
@@ -140,6 +143,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token CLIENT_SYM
%token COMMENT_SYM
%token COMMIT_SYM
+%token CONSISTENT_SYM
%token COUNT_SYM
%token CREATE
%token CROSS
@@ -176,6 +180,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token SELECT_SYM
%token SHOW
%token SLAVE
+%token SNAPSHOT_SYM
%token SQL_SYM
%token SQL_THREAD
%token START_SYM
@@ -195,6 +200,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token ALGORITHM_SYM
%token ALL
%token AND_SYM
+%token AND_AND_SYM
%token AS
%token ASC
%token AUTO_INC
@@ -339,7 +345,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token NCHAR_SYM
%token NCHAR_STRING
%token NVARCHAR_SYM
-%token NOT
+%token NOT_SYM
+%token NOT2_SYM
%token NO_SYM
%token NULL_SYM
%token NUM
@@ -350,7 +357,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token OPTION
%token OPTIONALLY
%token OR_SYM
-%token OR_OR_CONCAT
+%token OR2_SYM
+%token OR_OR_SYM
%token ORDER_SYM
%token OUT_SYM
%token OUTER
@@ -434,6 +442,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token UNICODE_SYM
%token UNION_SYM
%token UNIQUE_SYM
+%token UNKNOWN_SYM
%token USAGE
%token USE_FRM
%token USE_SYM
@@ -636,8 +645,8 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%token BEFORE_SYM
%left SET_VAR
-%left OR_OR_CONCAT OR_SYM XOR
-%left AND_SYM
+%left OR_OR_SYM OR_SYM OR2_SYM XOR
+%left AND_SYM AND_AND_SYM
%left BETWEEN_SYM CASE_SYM WHEN_SYM THEN_SYM ELSE
%left EQ EQUAL_SYM GE GT_SYM LE LT NE IS LIKE REGEXP IN_SYM
%left '|'
@@ -647,7 +656,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%left '*' '/' '%' DIV_SYM MOD_SYM
%left '^'
%left NEG '~'
-%right NOT
+%right NOT_SYM NOT2_SYM
%right BINARY COLLATE_SYM
%type <lex_str>
@@ -661,7 +670,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_table_alias
%type <table>
- table_ident table_ident_nodb references
+ table_ident table_ident_nodb references from_table_ident
%type <simple_string>
remember_name remember_end opt_ident opt_db text_or_password
@@ -676,6 +685,7 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
table_option opt_if_not_exists opt_no_write_to_binlog opt_var_type
opt_var_ident_type delete_option opt_temporary all_or_any opt_distinct
opt_ignore_leaves fulltext_options spatial_type union_option
+ start_transaction_opts
%type <ulong_num>
ULONG_NUM raid_types merge_insert_types
@@ -689,7 +699,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
%type <item>
literal text_literal insert_ident order_ident
simple_ident select_item2 expr opt_expr opt_else sum_expr in_sum_expr
- table_wild no_in_expr expr_expr simple_expr no_and_expr udf_expr
+ bool_term bool_factor bool_test bool_pri
+ predicate bit_expr bit_term bit_factor value_expr term factor
+ table_wild simple_expr udf_expr
using_list expr_or_default set_expr_or_default interval_expr
param_marker singlerow_subselect singlerow_subselect_init
exists_subselect exists_subselect_init geometry_function
@@ -776,9 +788,9 @@ bool my_yyoverflow(short **a, YYSTYPE **b, ulong *yystacksize);
opt_delete_options opt_delete_option varchar nchar nvarchar
opt_outer table_list table_name opt_option opt_place
opt_attribute opt_attribute_list attribute column_list column_list_id
- opt_column_list grant_privileges opt_table user_list grant_option
- grant_privilege grant_privilege_list
- flush_options flush_option
+ opt_column_list grant_privileges opt_table grant_list grant_option
+ grant_privilege grant_privilege_list user_list rename_list
+ clear_privileges flush_options flush_option
equal optional_braces opt_key_definition key_usage_list2
opt_mi_check_type opt_to mi_check_types normal_join
table_to_table_list table_to_table opt_table_list opt_as
@@ -802,7 +814,7 @@ END_OF_INPUT
%type <NONE>
'-' '+' '*' '/' '%' '(' ')'
- ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_CONCAT BETWEEN_SYM CASE_SYM
+ ',' '!' '{' '}' '&' '|' AND_SYM OR_SYM OR_OR_SYM BETWEEN_SYM CASE_SYM
THEN_SYM WHEN_SYM DIV_SYM MOD_SYM
%%
@@ -814,7 +826,7 @@ query:
if (!thd->bootstrap &&
(!(thd->lex->select_lex.options & OPTION_FOUND_COMMENT)))
{
- send_error(thd,ER_EMPTY_QUERY);
+ my_message(ER_EMPTY_QUERY, ER(ER_EMPTY_QUERY), MYF(0));
YYABORT;
}
else
@@ -1150,7 +1162,7 @@ create:
if (lex->sphead)
{
- net_printf(YYTHD, ER_SP_NO_RECURSIVE_CREATE, "PROCEDURE");
+ my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "PROCEDURE");
YYABORT;
}
/* Order is important here: new - reset - init */
@@ -1223,11 +1235,12 @@ create:
if (lex->sphead)
{
- net_printf(YYTHD, ER_SP_NO_RECURSIVE_CREATE, "TRIGGER");
+ my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "TRIGGER");
YYABORT;
}
-
- sp= new sp_head();
+
+ if (!(sp= new sp_head()))
+ YYABORT;
sp->reset_thd_mem_root(YYTHD);
sp->init(lex);
@@ -1274,8 +1287,26 @@ create:
TL_WRITE))
YYABORT;
}
+ | CREATE USER clear_privileges grant_list
+ {
+ Lex->sql_command = SQLCOM_CREATE_USER;
+ }
;
+clear_privileges:
+ /* Nothing */
+ {
+ LEX *lex=Lex;
+ lex->users_list.empty();
+ lex->columns.empty();
+ lex->grant= lex->grant_tot_col= 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_sys '.' IDENT_sys
{
@@ -1304,7 +1335,7 @@ create_function_tail:
if (lex->sphead)
{
- net_printf(YYTHD, ER_SP_NO_RECURSIVE_CREATE, "FUNCTION");
+ my_error(ER_SP_NO_RECURSIVE_CREATE, MYF(0), "FUNCTION");
YYABORT;
}
/* Order is important here: new - reset - init */
@@ -1402,7 +1433,7 @@ sp_chistic:
sp_c_chistic:
sp_chistic { }
| DETERMINISTIC_SYM { Lex->sp_chistics.detistic= TRUE; }
- | NOT DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; }
+ | not DETERMINISTIC_SYM { Lex->sp_chistics.detistic= FALSE; }
;
sp_suid:
@@ -1464,7 +1495,7 @@ sp_fdparam:
if (spc->find_pvar(&$1, TRUE))
{
- net_printf(YYTHD, ER_SP_DUP_PARAM, $1.str);
+ my_error(ER_SP_DUP_PARAM, MYF(0), $1.str);
YYABORT;
}
spc->push_pvar(&$1, (enum enum_field_types)$2, sp_param_in);
@@ -1490,7 +1521,7 @@ sp_pdparam:
if (spc->find_pvar(&$2, TRUE))
{
- net_printf(YYTHD, ER_SP_DUP_PARAM, $2.str);
+ my_error(ER_SP_DUP_PARAM, MYF(0), $2.str);
YYABORT;
}
spc->push_pvar(&$2, (enum enum_field_types)$3,
@@ -1528,12 +1559,14 @@ sp_decls:
better error handling this way.) */
if (($2.vars || $2.conds) && ($1.curs || $1.hndlrs))
{ /* Variable or condition following cursor or handler */
- send_error(YYTHD, ER_SP_VARCOND_AFTER_CURSHNDLR);
+ my_message(ER_SP_VARCOND_AFTER_CURSHNDLR,
+ ER(ER_SP_VARCOND_AFTER_CURSHNDLR), MYF(0));
YYABORT;
}
if ($2.curs && $1.hndlrs)
{ /* Cursor following handler */
- send_error(YYTHD, ER_SP_CURSOR_AFTER_HANDLER);
+ my_message(ER_SP_CURSOR_AFTER_HANDLER,
+ ER(ER_SP_CURSOR_AFTER_HANDLER), MYF(0));
YYABORT;
}
$$.vars= $1.vars + $2.vars;
@@ -1581,7 +1614,7 @@ sp_decl:
if (spc->find_cond(&$2, TRUE))
{
- net_printf(YYTHD, ER_SP_DUP_COND, $2.str);
+ my_error(ER_SP_DUP_COND, MYF(0), $2.str);
YYABORT;
}
YYTHD->lex->spcont->push_cond(&$2, $5);
@@ -1638,7 +1671,7 @@ sp_decl:
if (ctx->find_cursor(&$2, &offp, TRUE))
{
- net_printf(YYTHD, ER_SP_DUP_CURS, $2.str);
+ my_error(ER_SP_DUP_CURS, MYF(0), $2.str);
delete $5;
YYABORT;
}
@@ -1665,12 +1698,14 @@ sp_cursor_stmt:
if (lex->sql_command != SQLCOM_SELECT)
{
- send_error(YYTHD, ER_SP_BAD_CURSOR_QUERY);
+ my_message(ER_SP_BAD_CURSOR_QUERY, ER(ER_SP_BAD_CURSOR_QUERY),
+ MYF(0));
YYABORT;
}
if (lex->result)
{
- send_error(YYTHD, ER_SP_BAD_CURSOR_SELECT);
+ my_message(ER_SP_BAD_CURSOR_SELECT, ER(ER_SP_BAD_CURSOR_SELECT),
+ MYF(0));
YYABORT;
}
lex->sp_lex_in_use= TRUE;
@@ -1740,7 +1775,7 @@ sp_hcond:
$$= Lex->spcont->find_cond(&$1);
if ($$ == NULL)
{
- net_printf(YYTHD, ER_SP_COND_MISMATCH, $1.str);
+ my_error(ER_SP_COND_MISMATCH, MYF(0), $1.str);
YYABORT;
}
}
@@ -1749,7 +1784,7 @@ sp_hcond:
$$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
$$->type= sp_cond_type_t::warning;
}
- | NOT FOUND_SYM /* SQLSTATEs 02??? */
+ | not FOUND_SYM /* SQLSTATEs 02??? */
{
$$= (sp_cond_type_t *)YYTHD->alloc(sizeof(sp_cond_type_t));
$$->type= sp_cond_type_t::notfound;
@@ -1769,7 +1804,7 @@ sp_decl_idents:
if (spc->find_pvar(&$1, TRUE))
{
- net_printf(YYTHD, ER_SP_DUP_VAR, $1.str);
+ my_error(ER_SP_DUP_VAR, MYF(0), $1.str);
YYABORT;
}
spc->push_pvar(&$1, (enum_field_types)0, sp_param_in);
@@ -1782,7 +1817,7 @@ sp_decl_idents:
if (spc->find_pvar(&$3, TRUE))
{
- net_printf(YYTHD, ER_SP_DUP_VAR, $3.str);
+ my_error(ER_SP_DUP_VAR, MYF(0), $3.str);
YYABORT;
}
spc->push_pvar(&$3, (enum_field_types)0, sp_param_in);
@@ -1815,7 +1850,7 @@ sp_proc_stmt:
}
if (lex->sql_command == SQLCOM_CHANGE_DB)
{ /* "USE db" doesn't work in a procedure */
- send_error(YYTHD, ER_SP_NO_USE);
+ my_message(ER_SP_NO_USE, ER(ER_SP_NO_USE), MYF(0));
YYABORT;
}
/* Don't add an instruction for empty SET statements.
@@ -1834,7 +1869,7 @@ sp_proc_stmt:
*/
if (sp->m_type != TYPE_ENUM_PROCEDURE)
{
- send_error(YYTHD, ER_SP_BADSTATEMENT);
+ my_message(ER_SP_BADSTATEMENT, ER(ER_SP_BADSTATEMENT), MYF(0));
YYABORT;
}
else
@@ -1848,7 +1883,7 @@ sp_proc_stmt:
i->m_query.length= lex->ptr - sp->m_tmp_query;
else
i->m_query.length= lex->tok_end - sp->m_tmp_query;
- i->m_query.str= strmake_root(&YYTHD->mem_root,
+ i->m_query.str= strmake_root(YYTHD->mem_root,
(char *)sp->m_tmp_query,
i->m_query.length);
i->set_lex(lex);
@@ -1864,7 +1899,7 @@ sp_proc_stmt:
if (lex->sphead->m_type == TYPE_ENUM_PROCEDURE)
{
- send_error(YYTHD, ER_SP_BADRETURN);
+ my_message(ER_SP_BADRETURN, ER(ER_SP_BADRETURN), MYF(0));
YYABORT;
}
else
@@ -1873,7 +1908,7 @@ sp_proc_stmt:
if ($2->type() == Item::SUBSELECT_ITEM)
{ /* QQ For now, just disallow subselects as values */
- send_error(lex->thd, ER_SP_BADSTATEMENT);
+ my_message(ER_SP_BADSTATEMENT, ER(ER_SP_BADSTATEMENT), MYF(0));
YYABORT;
}
i= new sp_instr_freturn(lex->sphead->instructions(),
@@ -1936,7 +1971,7 @@ sp_proc_stmt:
if (! lab)
{
- net_printf(YYTHD, ER_SP_LILABEL_MISMATCH, "LEAVE", $2.str);
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "LEAVE", $2.str);
YYABORT;
}
else
@@ -1966,7 +2001,7 @@ sp_proc_stmt:
if (! lab || lab->type != SP_LAB_ITER)
{
- net_printf(YYTHD, ER_SP_LILABEL_MISMATCH, "ITERATE", $2.str);
+ my_error(ER_SP_LILABEL_MISMATCH, MYF(0), "ITERATE", $2.str);
YYABORT;
}
else
@@ -1994,7 +2029,7 @@ sp_proc_stmt:
if (lab)
{
- net_printf(YYTHD, ER_SP_LABEL_REDEFINE, $2.str);
+ my_error(ER_SP_LABEL_REDEFINE, MYF(0), $2.str);
YYABORT;
}
else
@@ -2018,7 +2053,7 @@ sp_proc_stmt:
if (sp->m_in_handler)
{
- send_error(lex->thd, ER_SP_GOTO_IN_HNDLR);
+ my_message(ER_SP_GOTO_IN_HNDLR, ER(ER_SP_GOTO_IN_HNDLR), MYF(0));
YYABORT;
}
lab= ctx->find_label($2.str);
@@ -2069,7 +2104,7 @@ sp_proc_stmt:
if (! lex->spcont->find_cursor(&$2, &offset))
{
- net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str);
+ my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
YYABORT;
}
i= new sp_instr_copen(sp->instructions(), lex->spcont, offset);
@@ -2084,7 +2119,7 @@ sp_proc_stmt:
if (! lex->spcont->find_cursor(&$3, &offset))
{
- net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $3.str);
+ my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $3.str);
YYABORT;
}
i= new sp_instr_cfetch(sp->instructions(), lex->spcont, offset);
@@ -2101,7 +2136,7 @@ sp_proc_stmt:
if (! lex->spcont->find_cursor(&$2, &offset))
{
- net_printf(YYTHD, ER_SP_CURSOR_MISMATCH, $2.str);
+ my_error(ER_SP_CURSOR_MISMATCH, MYF(0), $2.str);
YYABORT;
}
i= new sp_instr_cclose(sp->instructions(), lex->spcont, offset);
@@ -2125,7 +2160,7 @@ sp_fetch_list:
if (!spc || !(spv = spc->find_pvar(&$1)))
{
- net_printf(YYTHD, ER_SP_UNDECLARED_VAR, $1.str);
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
YYABORT;
}
else
@@ -2147,7 +2182,7 @@ sp_fetch_list:
if (!spc || !(spv = spc->find_pvar(&$3)))
{
- net_printf(YYTHD, ER_SP_UNDECLARED_VAR, $3.str);
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), $3.str);
YYABORT;
}
else
@@ -2271,7 +2306,7 @@ sp_labeled_control:
if (lab)
{
- net_printf(YYTHD, ER_SP_LABEL_REDEFINE, $1.str);
+ my_error(ER_SP_LABEL_REDEFINE, MYF(0), $1.str);
YYABORT;
}
else
@@ -2292,7 +2327,7 @@ sp_labeled_control:
if (!lab ||
my_strcasecmp(system_charset_info, $5.str, lab->name) != 0)
{
- net_printf(YYTHD, ER_SP_LABEL_MISMATCH, $5.str);
+ my_error(ER_SP_LABEL_MISMATCH, MYF(0), $5.str);
YYABORT;
}
}
@@ -2488,7 +2523,7 @@ table_option:
opt_if_not_exists:
/* empty */ { $$= 0; }
- | IF NOT EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
+ | IF not EXISTS { $$=HA_LEX_CREATE_IF_NOT_EXISTS; };
opt_create_table_options:
/* empty */
@@ -2550,9 +2585,9 @@ default_charset:
cinfo->default_table_charset && $4 &&
!my_charset_same(cinfo->default_table_charset,$4))
{
- net_printf(YYTHD, ER_CONFLICTING_DECLARATIONS,
- "CHARACTER SET ", cinfo->default_table_charset->csname,
- "CHARACTER SET ", $4->csname);
+ my_error(ER_CONFLICTING_DECLARATIONS, MYF(0),
+ "CHARACTER SET ", cinfo->default_table_charset->csname,
+ "CHARACTER SET ", $4->csname);
YYABORT;
}
Lex->create_info.default_table_charset= $4;
@@ -2567,8 +2602,8 @@ default_collation:
cinfo->default_table_charset && $4 &&
!my_charset_same(cinfo->default_table_charset,$4))
{
- net_printf(YYTHD,ER_COLLATION_CHARSET_MISMATCH,
- $4->name, cinfo->default_table_charset->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $4->name, cinfo->default_table_charset->csname);
YYABORT;
}
Lex->create_info.default_table_charset= $4;
@@ -2580,7 +2615,7 @@ storage_engines:
{
$$ = ha_resolve_by_name($1.str,$1.length);
if ($$ == DB_TYPE_UNKNOWN) {
- net_printf(YYTHD, ER_UNKNOWN_STORAGE_ENGINE, $1.str);
+ my_error(ER_UNKNOWN_STORAGE_ENGINE, MYF(0), $1.str);
YYABORT;
}
};
@@ -2693,7 +2728,7 @@ field_spec:
field_ident
{
LEX *lex=Lex;
- lex->length=lex->dec=0; lex->type=0; lex->interval=0;
+ lex->length=lex->dec=0; lex->type=0;
lex->default_value= lex->on_update_value= 0;
lex->comment=0;
lex->charset=NULL;
@@ -2706,7 +2741,7 @@ field_spec:
lex->length,lex->dec,lex->type,
lex->default_value, lex->on_update_value,
lex->comment,
- lex->change,lex->interval,lex->charset,
+ lex->change,&lex->interval_list,lex->charset,
lex->uint_geom_type))
YYABORT;
};
@@ -2734,14 +2769,17 @@ type:
| BINARY '(' NUM ')' { Lex->length=$3.str;
Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_STRING; }
+ | BINARY { Lex->length= (char*) "1";
+ Lex->charset=&my_charset_bin;
+ $$=FIELD_TYPE_STRING; }
| varchar '(' NUM ')' opt_binary { Lex->length=$3.str;
- $$=FIELD_TYPE_VAR_STRING; }
+ $$= MYSQL_TYPE_VARCHAR; }
| nvarchar '(' NUM ')' { Lex->length=$3.str;
- $$=FIELD_TYPE_VAR_STRING;
+ $$= MYSQL_TYPE_VARCHAR;
Lex->charset=national_charset_info; }
| VARBINARY '(' NUM ')' { Lex->length=$3.str;
Lex->charset=&my_charset_bin;
- $$=FIELD_TYPE_VAR_STRING; }
+ $$= MYSQL_TYPE_VARCHAR; }
| YEAR_SYM opt_len field_options { $$=FIELD_TYPE_YEAR; }
| DATE_SYM { $$=FIELD_TYPE_DATE; }
| TIME_SYM { $$=FIELD_TYPE_TIME; }
@@ -2770,18 +2808,18 @@ type:
$$=FIELD_TYPE_TINY_BLOB; }
| BLOB_SYM opt_len { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_BLOB; }
- | spatial_type {
+ | spatial_type
+ {
#ifdef HAVE_SPATIAL
- Lex->charset=&my_charset_bin;
- Lex->uint_geom_type= (uint)$1;
- $$=FIELD_TYPE_GEOMETRY;
+ Lex->charset=&my_charset_bin;
+ Lex->uint_geom_type= (uint)$1;
+ $$=FIELD_TYPE_GEOMETRY;
#else
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- sym_group_geom.name,
- sym_group_geom.needed_define);
- YYABORT;
+ my_error(ER_FEATURE_DISABLED, MYF(0)
+ sym_group_geom.name, sym_group_geom.needed_define);
+ YYABORT;
#endif
- }
+ }
| MEDIUMBLOB { Lex->charset=&my_charset_bin;
$$=FIELD_TYPE_MEDIUM_BLOB; }
| LONGBLOB { Lex->charset=&my_charset_bin;
@@ -2800,17 +2838,9 @@ type:
| FIXED_SYM float_options field_options
{ $$=FIELD_TYPE_DECIMAL;}
| ENUM {Lex->interval_list.empty();} '(' string_list ')' opt_binary
- {
- LEX *lex=Lex;
- lex->interval=typelib(lex->interval_list);
- $$=FIELD_TYPE_ENUM;
- }
+ { $$=FIELD_TYPE_ENUM; }
| SET { Lex->interval_list.empty();} '(' string_list ')' opt_binary
- {
- LEX *lex=Lex;
- lex->interval=typelib(lex->interval_list);
- $$=FIELD_TYPE_SET;
- }
+ { $$=FIELD_TYPE_SET; }
| LONG_SYM opt_binary { $$=FIELD_TYPE_MEDIUM_BLOB; }
| SERIAL_SYM
{
@@ -2910,7 +2940,7 @@ opt_attribute_list:
attribute:
NULL_SYM { Lex->type&= ~ NOT_NULL_FLAG; }
- | NOT NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
+ | not NULL_SYM { Lex->type|= NOT_NULL_FLAG; }
| DEFAULT now_or_signed_literal { Lex->default_value=$2; }
| ON UPDATE_SYM NOW_SYM optional_braces
{ Lex->on_update_value= new Item_func_now_local(); }
@@ -2945,8 +2975,8 @@ attribute:
{
if (Lex->charset && !my_charset_same(Lex->charset,$2))
{
- net_printf(YYTHD,ER_COLLATION_CHARSET_MISMATCH,
- $2->name,Lex->charset->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $2->name,Lex->charset->csname);
YYABORT;
}
else
@@ -2971,7 +3001,7 @@ charset_name:
{
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))))
{
- net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,$1.str);
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
YYABORT;
}
}
@@ -2989,7 +3019,7 @@ old_or_new_charset_name:
if (!($$=get_charset_by_csname($1.str,MY_CS_PRIMARY,MYF(0))) &&
!($$=get_old_charset_by_name($1.str)))
{
- net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,$1.str);
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), $1.str);
YYABORT;
}
}
@@ -3005,7 +3035,7 @@ collation_name:
{
if (!($$=get_charset_by_name($1.str,MYF(0))))
{
- net_printf(YYTHD,ER_UNKNOWN_COLLATION,$1.str);
+ my_error(ER_UNKNOWN_COLLATION, MYF(0), $1.str);
YYABORT;
}
};
@@ -3029,9 +3059,10 @@ opt_binary:
| BYTE_SYM { Lex->charset=&my_charset_bin; }
| UNICODE_SYM
{
- if (!(Lex->charset=get_charset_by_csname("ucs2",MY_CS_PRIMARY,MYF(0))))
+ if (!(Lex->charset=get_charset_by_csname("ucs2",
+ MY_CS_PRIMARY,MYF(0))))
{
- net_printf(YYTHD,ER_UNKNOWN_CHARACTER_SET,"ucs2");
+ my_error(ER_UNKNOWN_CHARACTER_SET, MYF(0), "ucs2");
YYABORT;
}
}
@@ -3093,8 +3124,8 @@ key_type:
#ifdef HAVE_SPATIAL
$$= Key::SPATIAL;
#else
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
YYABORT;
#endif
};
@@ -3126,8 +3157,8 @@ opt_unique_or_fulltext:
#ifdef HAVE_SPATIAL
$$= Key::SPATIAL;
#else
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_message(ER_FEATURE_DISABLED, ER(ER_FEATURE_DISABLED), MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
YYABORT;
#endif
}
@@ -3157,9 +3188,7 @@ key_part:
int key_part_len= atoi($3.str);
if (!key_part_len)
{
- my_printf_error(ER_UNKNOWN_ERROR,
- "Key part '%s' length cannot be 0",
- MYF(0), $1.str);
+ my_error(ER_KEY_PART_0, MYF(0), $1.str);
}
$$=new key_part_spec($1.str,(uint) key_part_len);
};
@@ -3291,7 +3320,7 @@ alter_list_item:
| MODIFY_SYM opt_column field_ident
{
LEX *lex=Lex;
- lex->length=lex->dec=0; lex->type=0; lex->interval=0;
+ lex->length=lex->dec=0; lex->type=0;
lex->default_value= lex->on_update_value= 0;
lex->comment=0;
lex->charset= NULL;
@@ -3305,7 +3334,7 @@ alter_list_item:
lex->length,lex->dec,lex->type,
lex->default_value, lex->on_update_value,
lex->comment,
- $3.str, lex->interval, lex->charset,
+ $3.str, &lex->interval_list, lex->charset,
lex->uint_geom_type))
YYABORT;
}
@@ -3368,7 +3397,7 @@ alter_list_item:
if (check_table_name($3->table.str,$3->table.length) ||
$3->db.str && check_db_name($3->db.str))
{
- net_printf(lex->thd,ER_WRONG_TABLE_NAME,$3->table.str);
+ my_error(ER_WRONG_TABLE_NAME, MYF(0), $3->table.str);
YYABORT;
}
lex->alter_info.flags|= ALTER_RENAME;
@@ -3383,8 +3412,8 @@ alter_list_item:
$5= $5 ? $5 : $4;
if (!my_charset_same($4,$5))
{
- net_printf(YYTHD,ER_COLLATION_CHARSET_MISMATCH,
- $5->name,$4->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $5->name, $4->csname);
YYABORT;
}
LEX *lex= Lex;
@@ -3473,10 +3502,21 @@ slave:
start:
- START_SYM TRANSACTION_SYM { Lex->sql_command = SQLCOM_BEGIN;}
- {}
+ START_SYM TRANSACTION_SYM start_transaction_opts
+ {
+ Lex->sql_command = SQLCOM_BEGIN;
+ Lex->start_transaction_opt= $3;
+ }
;
+start_transaction_opts:
+ /*empty*/ { $$ = 0; }
+ | WITH CONSISTENT_SYM SNAPSHOT_SYM
+ {
+ $$= MYSQL_START_TRANS_OPT_WITH_CONS_SNAPSHOT;
+ }
+ ;
+
slave_thread_opts:
{ Lex->slave_thd_opt= 0; }
slave_thread_opt_list
@@ -3504,7 +3544,8 @@ slave_until:
!((lex->mi.log_file_name && lex->mi.pos) ||
(lex->mi.relay_log_name && lex->mi.relay_log_pos)))
{
- send_error(lex->thd, ER_BAD_SLAVE_UNTIL_COND);
+ my_message(ER_BAD_SLAVE_UNTIL_COND,
+ ER(ER_BAD_SLAVE_UNTIL_COND), MYF(0));
YYABORT;
}
@@ -3640,8 +3681,25 @@ rename:
}
table_to_table_list
{}
+ | RENAME USER clear_privileges rename_list
+ {
+ Lex->sql_command = SQLCOM_RENAME_USER;
+ }
;
+rename_list:
+ user TO_SYM user
+ {
+ if (Lex->users_list.push_back($1) || Lex->users_list.push_back($3))
+ YYABORT;
+ }
+ | rename_list ',' user TO_SYM user
+ {
+ if (Lex->users_list.push_back($3) || Lex->users_list.push_back($5))
+ YYABORT;
+ }
+ ;
+
table_to_table_list:
table_to_table
| table_to_table_list ',' table_to_table;
@@ -3938,9 +3996,102 @@ optional_braces:
/* all possible expressions */
expr:
- expr_expr { $$= $1; }
- | simple_expr { $$= $1; }
- ;
+ expr or bool_term { $$= new Item_cond_or($1,$3); }
+ | expr XOR bool_term { $$= new Item_cond_xor($1,$3); }
+ | bool_term ;
+
+bool_term:
+ bool_term and bool_factor { $$= new Item_cond_and($1,$3); }
+ | bool_factor ;
+
+bool_factor:
+ NOT_SYM bool_factor { $$= negate_expression(YYTHD, $2); }
+ | bool_test ;
+
+bool_test:
+ bool_pri IS TRUE_SYM { $$= is_truth_value($1,1,0); }
+ | bool_pri IS not TRUE_SYM { $$= is_truth_value($1,0,0); }
+ | bool_pri IS FALSE_SYM { $$= is_truth_value($1,0,1); }
+ | bool_pri IS not FALSE_SYM { $$= is_truth_value($1,1,1); }
+ | bool_pri IS UNKNOWN_SYM { $$= new Item_func_isnull($1); }
+ | bool_pri IS not UNKNOWN_SYM { $$= new Item_func_isnotnull($1); }
+ | bool_pri ;
+
+bool_pri:
+ bool_pri IS NULL_SYM { $$= new Item_func_isnull($1); }
+ | bool_pri IS not NULL_SYM { $$= new Item_func_isnotnull($1); }
+ | predicate BETWEEN_SYM bit_expr AND_SYM bool_pri
+ { $$= new Item_func_between($1,$3,$5); }
+ | predicate not BETWEEN_SYM bit_expr AND_SYM bool_pri
+ { $$= negate_expression(YYTHD, new Item_func_between($1,$4,$6)); }
+ | predicate ;
+
+predicate:
+ bit_expr IN_SYM '(' expr_list ')'
+ { $4->push_front($1); $$= new Item_func_in(*$4); }
+ | bit_expr not IN_SYM '(' expr_list ')'
+ { $5->push_front($1); $$= negate_expression(YYTHD, new Item_func_in(*$5)); }
+ | bit_expr IN_SYM in_subselect
+ { $$= new Item_in_subselect($1, $3); }
+ | bit_expr not IN_SYM in_subselect
+ { $$= negate_expression(YYTHD, new Item_in_subselect($1, $4)); }
+ | bit_expr SOUNDS_SYM LIKE bit_expr
+ { $$= new Item_func_eq(new Item_func_soundex($1),
+ new Item_func_soundex($4)); }
+ | bit_expr LIKE simple_expr opt_escape
+ { $$= new Item_func_like($1,$3,$4); }
+ | bit_expr not LIKE simple_expr opt_escape
+ { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
+ | bit_expr REGEXP bit_expr { $$= new Item_func_regex($1,$3); }
+ | bit_expr not REGEXP bit_expr
+ { $$= negate_expression(YYTHD, new Item_func_regex($1,$4)); }
+ | bit_expr EQUAL_SYM bit_expr { $$= new Item_func_equal($1,$3); }
+ | bit_expr comp_op bit_expr %prec EQ
+ { $$= (*$2)(0)->create($1,$3); }
+ | bit_expr comp_op all_or_any in_subselect %prec EQ
+ { $$= all_any_subquery_creator($1, $2, $3, $4); }
+ | bit_expr ;
+
+bit_expr:
+ bit_expr '|' bit_term { $$= new Item_func_bit_or($1,$3); }
+ | bit_term ;
+
+bit_term:
+ bit_term '&' bit_factor { $$= new Item_func_bit_and($1,$3); }
+ | bit_factor ;
+
+bit_factor:
+ bit_factor SHIFT_LEFT value_expr
+ { $$= new Item_func_shift_left($1,$3); }
+ | bit_factor SHIFT_RIGHT value_expr
+ { $$= new Item_func_shift_right($1,$3); }
+ | value_expr ;
+
+value_expr:
+ value_expr '+' term { $$= new Item_func_plus($1,$3); }
+ | value_expr '-' term { $$= new Item_func_minus($1,$3); }
+ | value_expr '+' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,0); }
+ | value_expr '-' interval_expr interval
+ { $$= new Item_date_add_interval($1,$3,$4,1); }
+ | term ;
+
+term:
+ term '*' factor { $$= new Item_func_mul($1,$3); }
+ | term '/' factor { $$= new Item_func_div($1,$3); }
+ | term '%' factor { $$= new Item_func_mod($1,$3); }
+ | term DIV_SYM factor { $$= new Item_func_int_div($1,$3); }
+ | term MOD_SYM factor { $$= new Item_func_mod($1,$3); }
+ | factor ;
+
+factor:
+ factor '^' simple_expr { $$= new Item_func_bit_xor($1,$3); }
+ | simple_expr ;
+
+or: OR_SYM | OR2_SYM;
+and: AND_SYM | AND_AND_SYM;
+not: NOT_SYM | NOT2_SYM;
+not2: '!' | NOT2_SYM;
comp_op: EQ { $$ = &comp_eq_creator; }
| GE { $$ = &comp_ge_creator; }
@@ -3954,169 +4105,6 @@ all_or_any: ALL { $$ = 1; }
| ANY_SYM { $$ = 0; }
;
-/* expressions that begin with 'expr' */
-expr_expr:
- expr IN_SYM '(' expr_list ')'
- { $4->push_front($1); $$= new Item_func_in(*$4); }
- | expr NOT IN_SYM '(' expr_list ')'
- { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
- | expr IN_SYM in_subselect
- { $$= new Item_in_subselect($1, $3); }
- | expr NOT IN_SYM in_subselect
- {
- $$= new Item_func_not(new Item_in_subselect($1, $4));
- }
- | expr BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_between($1,$3,$5); }
- | expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
- | expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
- | expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
- | expr XOR expr { $$= new Item_cond_xor($1,$3); }
- | expr AND_SYM expr { $$= new Item_cond_and($1,$3); }
- | expr SOUNDS_SYM LIKE expr
- {
- $$= new Item_func_eq(new Item_func_soundex($1),
- new Item_func_soundex($4));
- }
- | expr LIKE simple_expr opt_escape
- { $$= new Item_func_like($1,$3,$4); }
- | expr NOT LIKE simple_expr opt_escape
- { $$= new Item_func_not(new Item_func_like($1,$4,$5));}
- | expr REGEXP expr { $$= new Item_func_regex($1,$3); }
- | expr NOT REGEXP expr
- { $$= new Item_func_not(new Item_func_regex($1,$4)); }
- | expr IS NULL_SYM { $$= new Item_func_isnull($1); }
- | expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
- | expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
- | expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); }
- | expr comp_op all_or_any in_subselect %prec EQ
- {
- $$= all_any_subquery_creator($1, $2, $3, $4);
- }
- | expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
- | expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
- | expr '+' expr { $$= new Item_func_plus($1,$3); }
- | expr '-' expr { $$= new Item_func_minus($1,$3); }
- | expr '*' expr { $$= new Item_func_mul($1,$3); }
- | expr '/' expr { $$= new Item_func_div($1,$3); }
- | expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
- | expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
- | expr '|' expr { $$= new Item_func_bit_or($1,$3); }
- | expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
- | expr '&' expr { $$= new Item_func_bit_and($1,$3); }
- | expr '%' expr { $$= new Item_func_mod($1,$3); }
- | expr '+' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,0); }
- | expr '-' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,1); }
- ;
-
-/* expressions that begin with 'expr' that do NOT follow IN_SYM */
-no_in_expr:
- no_in_expr BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_between($1,$3,$5); }
- | no_in_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
- | no_in_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
- | no_in_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
- | no_in_expr XOR expr { $$= new Item_cond_xor($1,$3); }
- | no_in_expr AND_SYM expr { $$= new Item_cond_and($1,$3); }
- | no_in_expr SOUNDS_SYM LIKE expr
- {
- $$= new Item_func_eq(new Item_func_soundex($1),
- new Item_func_soundex($4));
- }
- | no_in_expr LIKE simple_expr opt_escape
- { $$= new Item_func_like($1,$3,$4); }
- | no_in_expr NOT LIKE simple_expr opt_escape
- { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
- | no_in_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
- | no_in_expr NOT REGEXP expr
- { $$= new Item_func_not(new Item_func_regex($1,$4)); }
- | no_in_expr IS NULL_SYM { $$= new Item_func_isnull($1); }
- | no_in_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
- | no_in_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
- | no_in_expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); }
- | no_in_expr comp_op all_or_any in_subselect %prec EQ
- {
- all_any_subquery_creator($1, $2, $3, $4);
- }
- | no_in_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
- | no_in_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
- | no_in_expr '+' expr { $$= new Item_func_plus($1,$3); }
- | no_in_expr '-' expr { $$= new Item_func_minus($1,$3); }
- | no_in_expr '*' expr { $$= new Item_func_mul($1,$3); }
- | no_in_expr '/' expr { $$= new Item_func_div($1,$3); }
- | no_in_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
- | no_in_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
- | no_in_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
- | no_in_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
- | no_in_expr '%' expr { $$= new Item_func_mod($1,$3); }
- | no_in_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
- | no_in_expr '+' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,0); }
- | no_in_expr '-' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,1); }
- | simple_expr;
-
-/* expressions that begin with 'expr' that does NOT follow AND */
-no_and_expr:
- no_and_expr IN_SYM '(' expr_list ')'
- { $4->push_front($1); $$= new Item_func_in(*$4); }
- | no_and_expr NOT IN_SYM '(' expr_list ')'
- { $5->push_front($1); $$= new Item_func_not(new Item_func_in(*$5)); }
- | no_and_expr IN_SYM in_subselect
- { $$= new Item_in_subselect($1, $3); }
- | no_and_expr NOT IN_SYM in_subselect
- {
- $$= new Item_func_not(new Item_in_subselect($1, $4));
- }
- | no_and_expr BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_between($1,$3,$5); }
- | no_and_expr NOT BETWEEN_SYM no_and_expr AND_SYM expr
- { $$= new Item_func_not(new Item_func_between($1,$4,$6)); }
- | no_and_expr OR_OR_CONCAT expr { $$= or_or_concat(YYTHD, $1,$3); }
- | no_and_expr OR_SYM expr { $$= new Item_cond_or($1,$3); }
- | no_and_expr XOR expr { $$= new Item_cond_xor($1,$3); }
- | no_and_expr SOUNDS_SYM LIKE expr
- {
- $$= new Item_func_eq(new Item_func_soundex($1),
- new Item_func_soundex($4));
- }
- | no_and_expr LIKE simple_expr opt_escape
- { $$= new Item_func_like($1,$3,$4); }
- | no_and_expr NOT LIKE simple_expr opt_escape
- { $$= new Item_func_not(new Item_func_like($1,$4,$5)); }
- | no_and_expr REGEXP expr { $$= new Item_func_regex($1,$3); }
- | no_and_expr NOT REGEXP expr
- { $$= new Item_func_not(new Item_func_regex($1,$4)); }
- | no_and_expr IS NULL_SYM { $$= new Item_func_isnull($1); }
- | no_and_expr IS NOT NULL_SYM { $$= new Item_func_isnotnull($1); }
- | no_and_expr EQUAL_SYM expr { $$= new Item_func_equal($1,$3); }
- | no_and_expr comp_op expr %prec EQ { $$= (*$2)(0)->create($1,$3); }
- | no_and_expr comp_op all_or_any in_subselect %prec EQ
- {
- all_any_subquery_creator($1, $2, $3, $4);
- }
- | no_and_expr SHIFT_LEFT expr { $$= new Item_func_shift_left($1,$3); }
- | no_and_expr SHIFT_RIGHT expr { $$= new Item_func_shift_right($1,$3); }
- | no_and_expr '+' expr { $$= new Item_func_plus($1,$3); }
- | no_and_expr '-' expr { $$= new Item_func_minus($1,$3); }
- | no_and_expr '*' expr { $$= new Item_func_mul($1,$3); }
- | no_and_expr '/' expr { $$= new Item_func_div($1,$3); }
- | no_and_expr DIV_SYM expr { $$= new Item_func_int_div($1,$3); }
- | no_and_expr '|' expr { $$= new Item_func_bit_or($1,$3); }
- | no_and_expr '^' expr { $$= new Item_func_bit_xor($1,$3); }
- | no_and_expr '&' expr { $$= new Item_func_bit_and($1,$3); }
- | no_and_expr '%' expr { $$= new Item_func_mod($1,$3); }
- | no_and_expr MOD_SYM expr { $$= new Item_func_mod($1,$3); }
- | no_and_expr '+' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,0); }
- | no_and_expr '-' interval_expr interval
- { $$= new Item_date_add_interval($1,$3,$4,1); }
- | simple_expr;
-
interval_expr:
INTERVAL_SYM expr { $$=$2; }
;
@@ -4159,17 +4147,12 @@ simple_expr:
Lex->variables_used= 1;
}
| sum_expr
- | '+' expr %prec NEG { $$= $2; }
- | '-' expr %prec NEG { $$= new Item_func_neg($2); }
- | '~' expr %prec NEG { $$= new Item_func_bit_neg($2); }
- | NOT expr %prec NEG
- {
- $$= negate_expression(YYTHD, $2);
- }
- | '!' expr %prec NEG
- {
- $$= negate_expression(YYTHD, $2);
- }
+ | simple_expr OR_OR_SYM simple_expr
+ { $$= new Item_func_concat($1, $3); }
+ | '+' simple_expr %prec NEG { $$= $2; }
+ | '-' simple_expr %prec NEG { $$= new Item_func_neg($2); }
+ | '~' simple_expr %prec NEG { $$= new Item_func_bit_neg($2); }
+ | not2 simple_expr %prec NEG { $$= negate_expression(YYTHD, $2); }
| '(' expr ')' { $$= $2; }
| '(' expr ',' expr_list ')'
{
@@ -4184,12 +4167,12 @@ simple_expr:
| EXISTS exists_subselect { $$= $2; }
| singlerow_subselect { $$= $1; }
| '{' ident expr '}' { $$= $3; }
- | MATCH ident_list_arg AGAINST '(' expr fulltext_options ')'
+ | MATCH ident_list_arg AGAINST '(' bit_expr fulltext_options ')'
{ $2->push_front($5);
Select->add_ftfunc_to_list((Item_func_match*)
($$=new Item_func_match(*$2,$6))); }
| ASCII_SYM '(' expr ')' { $$= new Item_func_ascii($3); }
- | BINARY expr %prec NEG
+ | BINARY simple_expr %prec NEG
{
$$= create_func_cast($2, ITEM_CAST_CHAR, -1, &my_charset_bin);
}
@@ -4217,9 +4200,9 @@ simple_expr:
{
if (!$1.symbol->create_func)
{
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- $1.symbol->group->name,
- $1.symbol->group->needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ $1.symbol->group->name,
+ $1.symbol->group->needed_define);
YYABORT;
}
$$= ((Item*(*)(void))($1.symbol->create_func))();
@@ -4228,9 +4211,9 @@ simple_expr:
{
if (!$1.symbol->create_func)
{
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- $1.symbol->group->name,
- $1.symbol->group->needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ $1.symbol->group->name,
+ $1.symbol->group->needed_define);
YYABORT;
}
$$= ((Item*(*)(Item*))($1.symbol->create_func))($3);
@@ -4239,9 +4222,9 @@ simple_expr:
{
if (!$1.symbol->create_func)
{
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- $1.symbol->group->name,
- $1.symbol->group->needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ $1.symbol->group->name,
+ $1.symbol->group->needed_define);
YYABORT;
}
$$= ((Item*(*)(Item*,Item*))($1.symbol->create_func))($3,$5);
@@ -4250,9 +4233,9 @@ simple_expr:
{
if (!$1.symbol->create_func)
{
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- $1.symbol->group->name,
- $1.symbol->group->needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ $1.symbol->group->name,
+ $1.symbol->group->needed_define);
YYABORT;
}
$$= ((Item*(*)(Item*,Item*,Item*))($1.symbol->create_func))($3,$5,$7);
@@ -4355,8 +4338,8 @@ simple_expr:
#ifdef HAVE_SPATIAL
$$= $1;
#else
- net_printf(Lex->thd, ER_FEATURE_DISABLED,
- sym_group_geom.name, sym_group_geom.needed_define);
+ my_error(ER_FEATURE_DISABLED, MYF(0),
+ sym_group_geom.name, sym_group_geom.needed_define);
YYABORT;
#endif
}
@@ -4434,7 +4417,7 @@ simple_expr:
}
| OLD_PASSWORD '(' expr ')'
{ $$= new Item_func_old_password($3); }
- | POSITION_SYM '(' no_in_expr IN_SYM expr ')'
+ | POSITION_SYM '(' bit_expr IN_SYM expr ')'
{ $$ = new Item_func_locate($5,$3); }
| QUARTER_SYM '(' expr ')'
{ $$ = new Item_func_quarter($3); }
@@ -4781,7 +4764,7 @@ opt_distinct:
|DISTINCT { $$ = 1; };
opt_gconcat_separator:
- /* empty */ { $$ = new (&YYTHD->mem_root) String(",",1,default_charset_info); }
+ /* empty */ { $$ = new (YYTHD->mem_root) String(",",1,default_charset_info); }
|SEPARATOR_SYM text_string { $$ = $2; };
@@ -4881,11 +4864,11 @@ when_list2:
table_ref:
table_factor { $$=$1; }
| join_table { $$=$1; }
- {
+ {
LEX *lex= Lex;
if (!($$= lex->current_select->nest_last_join(lex->thd)))
YYABORT;
- }
+ }
;
join_table_list:
@@ -4975,20 +4958,20 @@ table_factor:
sel->get_use_index(),
sel->get_ignore_index())))
YYABORT;
- sel->add_joined_table($$);
+ sel->add_joined_table($$);
}
| '('
- {
+ {
LEX *lex= Lex;
if (lex->current_select->init_nested_join(lex->thd))
YYABORT;
- }
+ }
join_table_list ')'
{
LEX *lex= Lex;
if (!($$= lex->current_select->end_nested_join(lex->thd)))
YYABORT;
- }
+ }
| '{' ident table_ref LEFT OUTER JOIN_SYM table_ref ON expr '}'
{ add_join_on($7,$9); $7->outer_join|=JOIN_TYPE_LEFT; $$=$7; }
| '(' SELECT_SYM select_derived ')' opt_table_alias
@@ -5070,15 +5053,15 @@ key_list_or_empty:
key_usage_list2:
key_usage_list2 ',' ident
{ Select->
- interval_list.push_back(new (&YYTHD->mem_root) String((const char*) $3.str, $3.length,
+ interval_list.push_back(new (YYTHD->mem_root) String((const char*) $3.str, $3.length,
system_charset_info)); }
| ident
{ Select->
- interval_list.push_back(new (&YYTHD->mem_root) String((const char*) $1.str, $1.length,
+ interval_list.push_back(new (YYTHD->mem_root) String((const char*) $1.str, $1.length,
system_charset_info)); }
| PRIMARY_SYM
{ Select->
- interval_list.push_back(new (&YYTHD->mem_root) String("PRIMARY", 7,
+ interval_list.push_back(new (YYTHD->mem_root) String("PRIMARY", 7,
system_charset_info)); };
using_list:
@@ -5212,12 +5195,12 @@ olap_opt:
LEX *lex=Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
{
- net_printf(lex->thd, ER_WRONG_USAGE, "WITH CUBE",
+ my_error(ER_WRONG_USAGE, MYF(0), "WITH CUBE",
"global union parameters");
YYABORT;
}
lex->current_select->olap= CUBE_TYPE;
- net_printf(lex->thd, ER_NOT_SUPPORTED_YET, "CUBE");
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "CUBE");
YYABORT; /* To be deleted in 5.1 */
}
| WITH ROLLUP_SYM
@@ -5225,7 +5208,7 @@ olap_opt:
LEX *lex= Lex;
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
{
- net_printf(lex->thd, ER_WRONG_USAGE, "WITH ROLLUP",
+ my_error(ER_WRONG_USAGE, MYF(0), "WITH ROLLUP",
"global union parameters");
YYABORT;
}
@@ -5249,9 +5232,8 @@ order_clause:
lex->current_select->olap !=
UNSPECIFIED_OLAP_TYPE)
{
- net_printf(lex->thd, ER_WRONG_USAGE,
- "CUBE/ROLLUP",
- "ORDER BY");
+ my_error(ER_WRONG_USAGE, MYF(0),
+ "CUBE/ROLLUP", "ORDER BY");
YYABORT;
}
} order_list;
@@ -5349,9 +5331,7 @@ procedure_clause:
LEX *lex=Lex;
if (&lex->select_lex != lex->current_select)
{
- net_printf(lex->thd, ER_WRONG_USAGE,
- "PROCEDURE",
- "subquery");
+ my_error(ER_WRONG_USAGE, MYF(0), "PROCEDURE", "subquery");
YYABORT;
}
lex->proc_list.elements=0;
@@ -5415,7 +5395,7 @@ select_var_ident:
if (!lex->spcont || !(t=lex->spcont->find_pvar(&$1)))
{
- net_printf(YYTHD, ER_SP_UNDECLARED_VAR, $1.str);
+ my_error(ER_SP_UNDECLARED_VAR, MYF(0), $1.str);
YYABORT;
}
if (! lex->result)
@@ -5464,11 +5444,12 @@ do: DO_SYM
{
LEX *lex=Lex;
lex->sql_command = SQLCOM_DO;
- if (!(lex->insert_list = new List_item))
- YYABORT;
+ mysql_init_select(lex);
+ }
+ expr_list
+ {
+ Lex->insert_list= $3;
}
- values
- {}
;
/*
@@ -5506,7 +5487,7 @@ drop:
LEX *lex=Lex;
if (lex->sphead)
{
- net_printf(YYTHD, ER_SP_NO_DROP_SP, "FUNCTION");
+ my_error(ER_SP_NO_DROP_SP, MYF(0), "FUNCTION");
YYABORT;
}
lex->sql_command = SQLCOM_DROP_FUNCTION;
@@ -5518,21 +5499,17 @@ drop:
LEX *lex=Lex;
if (lex->sphead)
{
- net_printf(YYTHD, ER_SP_NO_DROP_SP, "PROCEDURE");
+ my_error(ER_SP_NO_DROP_SP, MYF(0), "PROCEDURE");
YYABORT;
}
lex->sql_command = SQLCOM_DROP_PROCEDURE;
lex->drop_if_exists= $3;
lex->spname= $4;
}
- | DROP USER
+ | DROP USER clear_privileges user_list
{
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_DROP_USER;
- lex->users_list.empty();
- }
- user_list
- {}
+ Lex->sql_command = SQLCOM_DROP_USER;
+ }
| DROP VIEW_SYM if_exists table_list opt_restrict
{
THD *thd= YYTHD;
@@ -5771,8 +5748,8 @@ update:
else if (lex->select_lex.get_table_list()->derived)
{
/* it is single table update and it is update of derived table */
- net_printf(lex->thd, ER_NON_UPDATABLE_TABLE,
- lex->select_lex.get_table_list()->alias, "UPDATE");
+ my_error(ER_NON_UPDATABLE_TABLE, MYF(0),
+ lex->select_lex.get_table_list()->alias, "UPDATE");
YYABORT;
}
else
@@ -5890,21 +5867,32 @@ show: SHOW
;
show_param:
- DATABASES wild
- { Lex->sql_command= SQLCOM_SHOW_DATABASES; }
- | opt_full TABLES opt_db wild
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->select_lex.db= $3;
- }
- | TABLE_SYM STATUS_SYM opt_db wild
- {
- LEX *lex= Lex;
- lex->sql_command= SQLCOM_SHOW_TABLES;
- lex->describe= DESCRIBE_EXTENDED;
- lex->select_lex.db= $3;
- }
+ DATABASES ext_select_item_list wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_DATABASES;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_SCHEMATA))
+ YYABORT;
+ }
+ | opt_full TABLES ext_select_item_list opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_TABLES;
+ lex->select_lex.db= $4;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLE_NAMES))
+ YYABORT;
+ }
+ | TABLE_SYM STATUS_SYM ext_select_item_list opt_db wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_TABLE_STATUS;
+ lex->select_lex.db= $4;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_TABLES))
+ YYABORT;
+ }
| OPEN_SYM TABLES opt_db wild
{
LEX *lex= Lex;
@@ -5914,12 +5902,14 @@ show_param:
| ENGINE_SYM storage_engines
{ Lex->create_info.db_type= $2; }
show_engine_param
- | opt_full COLUMNS from_or_in table_ident opt_db wild
+ | opt_full COLUMNS ext_select_item_list from_table_ident opt_db wild_and_where
{
- Lex->sql_command= SQLCOM_SHOW_FIELDS;
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
if ($5)
$4->change_db($5);
- if (!Select->add_table_to_list(YYTHD, $4, NULL, 0))
+ if (prepare_schema_table(YYTHD, lex, $4, SCH_COLUMNS))
YYABORT;
}
| NEW_SYM MASTER_SYM FOR_SYM SLAVE WITH MASTER_LOG_FILE_SYM EQ
@@ -5945,13 +5935,15 @@ show_param:
LEX *lex= Lex;
lex->sql_command= SQLCOM_SHOW_BINLOG_EVENTS;
} opt_limit_clause_init
- | keys_or_index from_or_in table_ident opt_db
- {
- Lex->sql_command= SQLCOM_SHOW_KEYS;
+ | keys_or_index ext_select_item_list from_table_ident opt_db where_clause
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_KEYS;
if ($4)
$3->change_db($4);
- if (!Select->add_table_to_list(YYTHD, $3, NULL, 0))
- YYABORT;
+ if (prepare_schema_table(YYTHD, lex, $3, SCH_STATISTICS))
+ YYABORT;
}
| COLUMN_SYM TYPES_SYM
{
@@ -5998,10 +5990,22 @@ show_param:
thd->lex->sql_command= SQLCOM_SHOW_VARIABLES;
thd->lex->option_type= (enum_var_type) $1;
}
- | charset wild
- { Lex->sql_command= SQLCOM_SHOW_CHARSETS; }
- | COLLATION_SYM wild
- { Lex->sql_command= SQLCOM_SHOW_COLLATIONS; }
+ | charset ext_select_item_list wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_CHARSETS;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_CHARSETS))
+ YYABORT;
+ }
+ | COLLATION_SYM ext_select_item_list wild_and_where
+ {
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_COLLATIONS;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_COLLATIONS))
+ YYABORT;
+ }
| BERKELEY_DB_SYM LOGS_SYM
{ Lex->sql_command= SQLCOM_SHOW_LOGS; WARN_DEPRECATED("SHOW BDB LOGS", "SHOW ENGINE BDB LOGS"); }
| LOGS_SYM
@@ -6080,13 +6084,21 @@ show_param:
lex->sql_command = SQLCOM_SHOW_CREATE_FUNC;
lex->spname= $3;
}
- | PROCEDURE STATUS_SYM wild
+ | PROCEDURE STATUS_SYM ext_select_item_list wild_and_where
{
- Lex->sql_command = SQLCOM_SHOW_STATUS_PROC;
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_STATUS_PROC;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
+ YYABORT;
}
- | FUNCTION_SYM STATUS_SYM wild
+ | FUNCTION_SYM STATUS_SYM ext_select_item_list wild_and_where
{
- Lex->sql_command = SQLCOM_SHOW_STATUS_FUNC;
+ LEX *lex= Lex;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_STATUS_FUNC;
+ if (prepare_schema_table(YYTHD, lex, 0, SCH_PROCEDURES))
+ YYABORT;
};
show_engine_param:
@@ -6097,7 +6109,7 @@ show_engine_param:
Lex->sql_command = SQLCOM_SHOW_INNODB_STATUS;
break;
default:
- net_printf(YYTHD, ER_NOT_SUPPORTED_YET, "STATUS");
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "STATUS");
YYABORT;
}
}
@@ -6108,7 +6120,7 @@ show_engine_param:
Lex->sql_command = SQLCOM_SHOW_LOGS;
break;
default:
- net_printf(YYTHD, ER_NOT_SUPPORTED_YET, "LOGS");
+ my_error(ER_NOT_SUPPORTED_YET, MYF(0), "LOGS");
YYABORT;
}
};
@@ -6128,7 +6140,7 @@ opt_db:
wild:
/* empty */
| LIKE TEXT_STRING_sys
- { Lex->wild= new (&YYTHD->mem_root) String($2.str, $2.length,
+ { Lex->wild= new (YYTHD->mem_root) String($2.str, $2.length,
system_charset_info); };
opt_full:
@@ -6147,16 +6159,49 @@ binlog_from:
/* empty */ { Lex->mi.pos = 4; /* skip magic number */ }
| FROM ulonglong_num { Lex->mi.pos = $2; };
+from_table_ident:
+ /* empty */ { $$= 0; }
+ | from_or_in table_ident { $$= $2; }
+ ;
+
+wild_and_where:
+ /* empty */
+ | LIKE TEXT_STRING_sys
+ { Lex->wild= new (YYTHD->mem_root) String($2.str, $2.length,
+ system_charset_info); }
+ | WHERE expr
+ {
+ Select->where= $2;
+ if ($2)
+ $2->top_level_item();
+ }
+ ;
+
+ext_select_item_list:
+ {
+ LEX *lex=Lex;
+ SELECT_LEX *sel= lex->current_select;
+ lex->lock_option= TL_READ;
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
+ }
+ /* empty */
+ | select_item_list {};
+
/* A Oracle compatible synonym for show */
describe:
describe_command table_ident
{
- LEX *lex=Lex;
- lex->wild=0;
- lex->verbose=0;
- lex->sql_command=SQLCOM_SHOW_FIELDS;
- if (!Select->add_table_to_list(lex->thd, $2, NULL,0))
+ LEX *lex= Lex;
+ lex->lock_option= TL_READ;
+ mysql_init_select(lex);
+ lex->current_select->parsing_place= SELECT_LIST;
+ lex->sql_command= SQLCOM_SELECT;
+ lex->orig_sql_command= SQLCOM_SHOW_FIELDS;
+ lex->select_lex.db= 0;
+ lex->verbose= 0;
+ if (prepare_schema_table(YYTHD, lex, $2, SCH_COLUMNS))
YYABORT;
}
opt_describe_column {}
@@ -6182,7 +6227,7 @@ opt_describe_column:
/* empty */ {}
| text_string { Lex->wild= $1; }
| ident
- { Lex->wild= new (&YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info); };
+ { Lex->wild= new (YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info); };
/* flush things */
@@ -6258,19 +6303,10 @@ purge_option:
}
| BEFORE_SYM expr
{
- if ($2->check_cols(1) || $2->fix_fields(Lex->thd, 0, &$2))
- {
- net_printf(Lex->thd, ER_WRONG_ARGUMENTS, "PURGE LOGS BEFORE");
- YYABORT;
- }
- Item *tmp= new Item_func_unix_timestamp($2);
- /*
- it is OK only emulate fix_fieds, because we need only
- value of constant
- */
- tmp->quick_fix_field();
- Lex->sql_command = SQLCOM_PURGE_BEFORE;
- Lex->purge_time= (ulong) tmp->val_int();
+ LEX *lex= Lex;
+ lex->value_list.empty();
+ lex->value_list.push_front($2);
+ lex->sql_command= SQLCOM_PURGE_BEFORE;
}
;
@@ -6280,13 +6316,9 @@ kill:
KILL_SYM kill_option expr
{
LEX *lex=Lex;
- if ($3->fix_fields(lex->thd, 0, &$3) || $3->check_cols(1))
- {
- send_error(lex->thd, ER_SET_CONSTANTS_ONLY);
- YYABORT;
- }
- lex->sql_command=SQLCOM_KILL;
- lex->thread_id= (ulong) $3->val_int();
+ lex->value_list.empty();
+ lex->value_list.push_front($3);
+ lex->sql_command= SQLCOM_KILL;
};
kill_option:
@@ -6428,7 +6460,7 @@ text_literal:
text_string:
TEXT_STRING_literal
- { $$= new (&YYTHD->mem_root) String($1.str,$1.length,YYTHD->variables.collation_connection); }
+ { $$= new (YYTHD->mem_root) String($1.str,$1.length,YYTHD->variables.collation_connection); }
| HEX_NUM
{
Item *tmp = new Item_varbinary($1.str,$1.length);
@@ -6453,7 +6485,7 @@ param_marker:
(uchar *) thd->query));
if (!($$= item) || lex->param_list.push_back(item))
{
- send_error(thd, ER_OUT_OF_RESOURCES);
+ my_message(ER_OUT_OF_RESOURCES, ER(ER_OUT_OF_RESOURCES), MYF(0));
YYABORT;
}
}
@@ -6509,7 +6541,6 @@ NUM_literal:
$$= new Item_real($1.str, $1.length);
if (YYTHD->net.report_error)
{
- send_error(YYTHD, 0, NullS);
YYABORT;
}
}
@@ -6518,7 +6549,6 @@ NUM_literal:
$$ = new Item_float($1.str, $1.length);
if (YYTHD->net.report_error)
{
- send_error(YYTHD, 0, NullS);
YYABORT;
}
}
@@ -6602,41 +6632,35 @@ simple_ident_q:
(!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)
{
- net_printf(YYTHD, ER_TRG_NO_SUCH_ROW_IN_TRG, "OLD",
- "on INSERT");
+ my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "OLD", "on INSERT");
YYABORT;
}
if (lex->trg_chistics.event == TRG_EVENT_DELETE &&
new_row)
{
- net_printf(YYTHD, ER_TRG_NO_SUCH_ROW_IN_TRG, "NEW",
- "on DELETE");
+ my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0), "NEW", "on DELETE");
YYABORT;
}
- Item_trigger_field *trg_fld=
- new Item_trigger_field(new_row ? Item_trigger_field::NEW_ROW :
- Item_trigger_field::OLD_ROW,
- $3.str);
-
- if (lex->trg_table &&
- trg_fld->setup_field(thd, lex->trg_table,
- lex->trg_chistics.event))
- {
- /*
- FIXME. Far from perfect solution. See comment for
- "SET NEW.field_name:=..." for more info.
- */
- net_printf(YYTHD, ER_BAD_FIELD_ERROR, $3.str,
- new_row ? "NEW": "OLD");
+ if (!(trg_fld= new Item_trigger_field(new_row ?
+ Item_trigger_field::NEW_ROW:
+ Item_trigger_field::OLD_ROW,
+ $3.str)))
YYABORT;
- }
+
+ /*
+ Let us add this item to list of all Item_trigger_field objects
+ in trigger.
+ */
+ lex->trg_table_fields.link_in_list((byte *)trg_fld,
+ (byte**)&trg_fld->next_trg_field);
$$= (Item *)trg_fld;
}
@@ -6645,9 +6669,8 @@ simple_ident_q:
SELECT_LEX *sel= lex->current_select;
if (sel->no_table_names_allowed)
{
- my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- ER(ER_TABLENAME_NOT_ALLOWED_HERE),
- MYF(0), $1.str, thd->where);
+ my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
+ MYF(0), $1.str, thd->where);
}
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
@@ -6662,9 +6685,8 @@ simple_ident_q:
SELECT_LEX *sel= lex->current_select;
if (sel->no_table_names_allowed)
{
- my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- ER(ER_TABLENAME_NOT_ALLOWED_HERE),
- MYF(0), $2.str, thd->where);
+ my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
+ MYF(0), $2.str, thd->where);
}
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
@@ -6678,9 +6700,8 @@ simple_ident_q:
SELECT_LEX *sel= lex->current_select;
if (sel->no_table_names_allowed)
{
- my_printf_error(ER_TABLENAME_NOT_ALLOWED_HERE,
- ER(ER_TABLENAME_NOT_ALLOWED_HERE),
- MYF(0), $3.str, thd->where);
+ my_error(ER_TABLENAME_NOT_ALLOWED_HERE,
+ MYF(0), $3.str, thd->where);
}
$$= (sel->parsing_place != IN_HAVING ||
sel->get_in_sum_expr() > 0) ?
@@ -6721,8 +6742,8 @@ IDENT_sys:
$1.length);
if (wlen < $1.length)
{
- net_printf(YYTHD, ER_INVALID_CHARACTER_STRING, cs->csname,
- $1.str + wlen);
+ my_error(ER_INVALID_CHARACTER_STRING, MYF(0),
+ cs->csname, $1.str + wlen);
YYABORT;
}
$$= $1;
@@ -6846,6 +6867,7 @@ keyword:
| COMMIT_SYM {}
| COMPRESSED_SYM {}
| CONCURRENT {}
+ | CONSISTENT_SYM {}
| CONTAINS_SYM {}
| CUBE_SYM {}
| DATA_SYM {}
@@ -6998,6 +7020,7 @@ keyword:
| SHARE_SYM {}
| SHUTDOWN {}
| SLAVE {}
+ | SNAPSHOT_SYM {}
| SOUNDS_SYM {}
| SQL_CACHE_SYM {}
| SQL_BUFFER_RESULT {}
@@ -7028,6 +7051,7 @@ keyword:
| UNCOMMITTED_SYM {}
| UNDEFINED_SYM {}
| UNICODE_SYM {}
+ | UNKNOWN_SYM {}
| UNTIL_SYM {}
| USER {}
| USE_FRM {}
@@ -7103,7 +7127,8 @@ option_value:
*/
if (lex->query_tables)
{
- send_error(YYTHD, ER_SP_SUBSELECT_NYI);
+ my_message(ER_SP_SUBSELECT_NYI, ER(ER_SP_SUBSELECT_NYI),
+ MYF(0));
YYABORT;
}
sp_instr_set_user_var *i=
@@ -7126,7 +7151,8 @@ option_value:
sp_instr_set_trigger_field *i;
if (lex->query_tables)
{
- send_error(YYTHD, ER_SP_SUBSELECT_NYI);
+ my_message(ER_SP_SUBSELECT_NYI, ER(ER_SP_SUBSELECT_NYI),
+ MYF(0));
YYABORT;
}
if ($3)
@@ -7136,28 +7162,19 @@ option_value:
/* QQ: Shouldn't this be field's default value ? */
it= new Item_null();
}
- i= new sp_instr_set_trigger_field(lex->sphead->instructions(),
- lex->spcont, $1.base_name, it);
- if (lex->trg_table && i->setup_field(YYTHD, lex->trg_table,
- lex->trg_chistics.event))
- {
- /*
- FIXME. Now we are catching this kind of errors only
- during opening tables. But this doesn't save us from most
- common user error - misspelling field name, because we
- will bark too late in this case... Moreover it is easy to
- make table unusable with such kind of error...
-
- So in future we either have to parse trigger definition
- second time during create trigger or gather all trigger
- fields in one list and perform setup_field() for them as
- separate stage.
-
- Error message also should be improved.
- */
- net_printf(YYTHD, ER_BAD_FIELD_ERROR, $1.base_name, "NEW");
+
+ if (!(i= new sp_instr_set_trigger_field(
+ lex->sphead->instructions(), lex->spcont,
+ $1.base_name, it)))
YYABORT;
- }
+
+ /*
+ Let us add this item to list of all Item_trigger_field
+ objects in trigger.
+ */
+ lex->trg_table_fields.link_in_list((byte *)&i->trigger_field,
+ (byte **)&i->trigger_field.next_trg_field);
+
lex->sphead->add_instr(i);
}
else if ($1.var)
@@ -7221,7 +7238,8 @@ option_value:
$3= $3 ? $3 : $2;
if (!my_charset_same($2,$3))
{
- net_printf(thd,ER_COLLATION_CHARSET_MISMATCH,$3->name,$2->csname);
+ my_error(ER_COLLATION_CHARSET_MISMATCH, MYF(0),
+ $3->name, $2->csname);
YYABORT;
}
lex->var_list.push_back(new set_var_collation_client($3,$3,$3));
@@ -7287,18 +7305,18 @@ internal_variable_name:
{
if ($1.str[0]=='O' || $1.str[0]=='o')
{
- net_printf(YYTHD, ER_TRG_CANT_CHANGE_ROW, "OLD", "");
+ my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "OLD", "");
YYABORT;
}
if (lex->trg_chistics.event == TRG_EVENT_DELETE)
{
- net_printf(YYTHD, ER_TRG_NO_SUCH_ROW_IN_TRG, "NEW",
- "on DELETE");
+ my_error(ER_TRG_NO_SUCH_ROW_IN_TRG, MYF(0),
+ "NEW", "on DELETE");
YYABORT;
}
if (lex->trg_chistics.action_time == TRG_ACTION_AFTER)
{
- net_printf(YYTHD, ER_TRG_CANT_CHANGE_ROW, "NEW", "after ");
+ my_error(ER_TRG_CANT_CHANGE_ROW, MYF(0), "NEW", "after ");
YYABORT;
}
/* This special combination will denote field of NEW row */
@@ -7311,7 +7329,7 @@ internal_variable_name:
if (!tmp)
YYABORT;
if (!tmp->is_struct())
- net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
+ my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str);
$$.var= tmp;
$$.base_name= $1;
}
@@ -7322,7 +7340,7 @@ internal_variable_name:
if (!tmp)
YYABORT;
if (!tmp->is_struct())
- net_printf(YYTHD, ER_VARIABLE_IS_NOT_STRUCT, $3.str);
+ my_error(ER_VARIABLE_IS_NOT_STRUCT, MYF(0), $3.str);
$$.var= tmp;
$$.base_name.str= (char*) "default";
$$.base_name.length= 7;
@@ -7469,56 +7487,40 @@ handler_rkey_mode:
/* GRANT / REVOKE */
revoke:
- REVOKE
- {
- LEX *lex=Lex;
- lex->sql_command = SQLCOM_REVOKE;
- lex->users_list.empty();
- lex->columns.empty();
- lex->grant= lex->grant_tot_col=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));
- }
- revoke_command
+ REVOKE clear_privileges revoke_command
{}
;
revoke_command:
- grant_privileges ON opt_table FROM user_list
- {}
+ grant_privileges ON opt_table FROM grant_list
+ {
+ Lex->sql_command = SQLCOM_REVOKE;
+ }
|
- ALL PRIVILEGES ',' GRANT OPTION FROM user_list
+ ALL opt_privileges ',' GRANT OPTION FROM grant_list
{
Lex->sql_command = SQLCOM_REVOKE_ALL;
}
;
grant:
- GRANT
- {
- LEX *lex=Lex;
- lex->users_list.empty();
- lex->columns.empty();
- lex->sql_command = SQLCOM_GRANT;
- lex->grant= lex->grant_tot_col= 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));
- }
- grant_privileges ON opt_table TO_SYM user_list
+ GRANT clear_privileges grant_privileges ON opt_table TO_SYM grant_list
require_clause grant_options
- {}
+ {
+ Lex->sql_command = SQLCOM_GRANT;
+ }
;
grant_privileges:
grant_privilege_list {}
- | ALL PRIVILEGES { Lex->grant = GLOBAL_ACLS;}
- | ALL { Lex->grant = GLOBAL_ACLS;}
+ | ALL opt_privileges { Lex->grant = GLOBAL_ACLS;}
;
+opt_privileges:
+ /* empty */
+ | PRIVILEGES
+ ;
+
grant_privilege_list:
grant_privilege
| grant_privilege_list ',' grant_privilege;
@@ -7567,7 +7569,7 @@ require_list_element:
LEX *lex=Lex;
if (lex->x509_subject)
{
- net_printf(lex->thd,ER_DUP_ARGUMENT, "SUBJECT");
+ my_error(ER_DUP_ARGUMENT, MYF(0), "SUBJECT");
YYABORT;
}
lex->x509_subject=$2.str;
@@ -7577,7 +7579,7 @@ require_list_element:
LEX *lex=Lex;
if (lex->x509_issuer)
{
- net_printf(lex->thd,ER_DUP_ARGUMENT, "ISSUER");
+ my_error(ER_DUP_ARGUMENT, MYF(0), "ISSUER");
YYABORT;
}
lex->x509_issuer=$2.str;
@@ -7587,7 +7589,7 @@ require_list_element:
LEX *lex=Lex;
if (lex->ssl_cipher)
{
- net_printf(lex->thd,ER_DUP_ARGUMENT, "CIPHER");
+ my_error(ER_DUP_ARGUMENT, MYF(0), "CIPHER");
YYABORT;
}
lex->ssl_cipher=$2.str;
@@ -7603,7 +7605,8 @@ opt_table:
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE);
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
+ ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
YYABORT;
}
}
@@ -7615,7 +7618,8 @@ opt_table:
lex->grant = DB_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE);
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
+ ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
YYABORT;
}
}
@@ -7627,7 +7631,8 @@ opt_table:
lex->grant= GLOBAL_ACLS & ~GRANT_ACL;
else if (lex->columns.elements)
{
- send_error(lex->thd,ER_ILLEGAL_GRANT_FOR_TABLE);
+ my_message(ER_ILLEGAL_GRANT_FOR_TABLE,
+ ER(ER_ILLEGAL_GRANT_FOR_TABLE), MYF(0));
YYABORT;
}
}
@@ -7643,8 +7648,18 @@ opt_table:
user_list:
+ user { if (Lex->users_list.push_back($1)) YYABORT;}
+ | user_list ',' user
+ {
+ if (Lex->users_list.push_back($3))
+ YYABORT;
+ }
+ ;
+
+
+grant_list:
grant_user { if (Lex->users_list.push_back($1)) YYABORT;}
- | user_list ',' grant_user
+ | grant_list ',' grant_user
{
if (Lex->users_list.push_back($3))
YYABORT;
@@ -7700,7 +7715,7 @@ column_list:
column_list_id:
ident
{
- String *new_str = new (&YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
+ String *new_str = new (YYTHD->mem_root) String((const char*) $1.str,$1.length,system_charset_info);
List_iterator <LEX_COLUMN> iter(Lex->columns);
class LEX_COLUMN *point;
LEX *lex=Lex;
@@ -7767,7 +7782,7 @@ grant_option:
;
begin:
- BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN;} opt_work {}
+ BEGIN_SYM { Lex->sql_command = SQLCOM_BEGIN; Lex->start_transaction_opt= 0;} opt_work {}
;
opt_work:
@@ -7812,7 +7827,7 @@ union_list:
if (lex->exchange)
{
/* Only the last SELECT can have INTO...... */
- net_printf(lex->thd, ER_WRONG_USAGE, "UNION", "INTO");
+ my_error(ER_WRONG_USAGE, MYF(0), "UNION", "INTO");
YYABORT;
}
if (lex->current_select->linkage == GLOBAL_OPTIONS_TYPE)
diff --git a/sql/strfunc.cc b/sql/strfunc.cc
index b5255e9be06..2253f48e558 100644
--- a/sql/strfunc.cc
+++ b/sql/strfunc.cc
@@ -136,7 +136,7 @@ uint find_type2(TYPELIB *typelib, const char *x, uint length, CHARSET_INFO *cs)
int find,pos,findpos;
const char *j;
DBUG_ENTER("find_type2");
- DBUG_PRINT("enter",("x: '%s' lib: 0x%lx",x,typelib));
+ DBUG_PRINT("enter",("x: '%.*s' lib: 0x%lx", length, x, typelib));
if (!typelib->count)
{
diff --git a/sql/structs.h b/sql/structs.h
index cc053e2e2fd..5d0c7bc4f1f 100644
--- a/sql/structs.h
+++ b/sql/structs.h
@@ -89,10 +89,16 @@ typedef struct st_key {
enum ha_key_alg algorithm;
KEY_PART_INFO *key_part;
char *name; /* Name of key */
- ulong *rec_per_key; /* Key part distribution */
+ /*
+ Array of AVG(#records with the same field value) for 1st ... Nth key part.
+ 0 means 'not known'.
+ For temporary heap tables this member is NULL.
+ */
+ ulong *rec_per_key;
union {
int bdb_return_if_eq;
} handler;
+ struct st_table *table;
} KEY;
@@ -161,6 +167,7 @@ enum SHOW_TYPE
SHOW_LONG, SHOW_LONGLONG, SHOW_INT, SHOW_CHAR, SHOW_CHAR_PTR, SHOW_DOUBLE,
SHOW_BOOL, SHOW_MY_BOOL, SHOW_OPENTABLES, SHOW_STARTTIME, SHOW_QUESTION,
SHOW_LONG_CONST, SHOW_INT_CONST, SHOW_HAVE, SHOW_SYS, SHOW_HA_ROWS,
+ SHOW_VARS,
#ifdef HAVE_OPENSSL
SHOW_SSL_CTX_SESS_ACCEPT, SHOW_SSL_CTX_SESS_ACCEPT_GOOD,
SHOW_SSL_GET_VERSION, SHOW_SSL_CTX_GET_SESSION_CACHE_MODE,
diff --git a/sql/table.cc b/sql/table.cc
index 0116cf180c1..b4a07448b14 100644
--- a/sql/table.cc
+++ b/sql/table.cc
@@ -83,13 +83,14 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
uchar *null_pos;
uint null_bit, new_frm_ver, field_pack_length;
SQL_CRYPT *crypted=0;
- MEM_ROOT *old_root;
+ MEM_ROOT **root_ptr, *old_root;
DBUG_ENTER("openfrm");
DBUG_PRINT("enter",("name: '%s' form: 0x%lx",name,outparam));
error=1;
disk_buff=NULL;
- old_root= my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
+ root_ptr= my_pthread_getspecific_ptr(MEM_ROOT**, THR_MALLOC);
+ old_root= *root_ptr;
if ((file=my_open(fn_format(index_file, name, "", reg_ext,
MY_UNPACK_FILENAME),
@@ -123,7 +124,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
outparam->blob_ptr_size=sizeof(char*);
outparam->db_stat = db_stat;
init_sql_alloc(&outparam->mem_root, TABLE_ALLOC_BLOCK_SIZE, 0);
- my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root);
+ *root_ptr= &outparam->mem_root;
outparam->real_name=strdup_root(&outparam->mem_root,
name+dirname_length(name));
@@ -138,7 +139,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
*fn_ext(outparam->path)='\0'; // Remove extension
if (head[0] != (uchar) 254 || head[1] != 1 ||
- (head[2] != FRM_VER && head[2] != FRM_VER+1 && head[2] != FRM_VER+3))
+ (head[2] != FRM_VER && head[2] != FRM_VER+1 &&
+ ! (head[2] >= FRM_VER+3 && head[2] <= FRM_VER+4)))
goto err_not_open; /* purecov: inspected */
new_field_pack_flag=head[27];
new_frm_ver= (head[2] - FRM_VER);
@@ -214,7 +216,8 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
for (i=0 ; i < keys ; i++, keyinfo++)
{
- if (new_frm_ver == 3)
+ keyinfo->table= outparam;
+ if (new_frm_ver >= 3)
{
keyinfo->flags= (uint) uint2korr(strpos) ^ HA_NOSAME;
keyinfo->key_length= (uint) uint2korr(strpos+2);
@@ -274,9 +277,9 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
#ifdef HAVE_CRYPTED_FRM
else if (*(head+26) == 2)
{
- my_pthread_setspecific_ptr(THR_MALLOC,old_root);
+ *root_ptr= old_root
crypted=get_crypt_for_frm();
- my_pthread_setspecific_ptr(THR_MALLOC,&outparam->mem_root);
+ *root_ptr= &outparam->mem_root;
outparam->crypted=1;
}
#endif
@@ -432,7 +435,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
Field::geometry_type geom_type= Field::GEOM_GEOMETRY;
LEX_STRING comment;
- if (new_frm_ver == 3)
+ if (new_frm_ver >= 3)
{
/* new frm file in 4.1 */
field_length= uint2korr(strpos+3);
@@ -440,11 +443,10 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
pack_flag= uint2korr(strpos+8);
unireg_type= (uint) strpos[10];
interval_nr= (uint) strpos[12];
-
uint comment_length=uint2korr(strpos+15);
field_type=(enum_field_types) (uint) strpos[13];
- // charset and geometry_type share the same byte in frm
+ /* charset and geometry_type share the same byte in frm */
if (field_type == FIELD_TYPE_GEOMETRY)
{
#ifdef HAVE_SPATIAL
@@ -485,7 +487,26 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
/* old frm file */
field_type= (enum_field_types) f_packtype(pack_flag);
- charset=f_is_binary(pack_flag) ? &my_charset_bin : outparam->table_charset;
+ if (f_is_binary(pack_flag))
+ {
+ /*
+ Try to choose the best 4.1 type:
+ - for 4.0 "CHAR(N) BINARY" or "VARCHAR(N) BINARY"
+ try to find a binary collation for character set.
+ - for other types (e.g. BLOB) just use my_charset_bin.
+ */
+ if (!f_is_blob(pack_flag))
+ {
+ // 3.23 or 4.0 string
+ if (!(charset= get_charset_by_csname(outparam->table_charset->csname,
+ MY_CS_BINSORT, MYF(0))))
+ charset= &my_charset_bin;
+ }
+ else
+ charset= &my_charset_bin;
+ }
+ else
+ charset= outparam->table_charset;
bzero((char*) &comment, sizeof(comment));
}
*field_ptr=reg_field=
@@ -589,10 +610,12 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
keyinfo->key_length+= HA_KEY_NULL_LENGTH;
}
if (field->type() == FIELD_TYPE_BLOB ||
- field->real_type() == FIELD_TYPE_VAR_STRING)
+ field->real_type() == MYSQL_TYPE_VARCHAR)
{
if (field->type() == FIELD_TYPE_BLOB)
key_part->key_part_flag|= HA_BLOB_PART;
+ else
+ key_part->key_part_flag|= HA_VAR_LENGTH_PART;
keyinfo->extra_length+=HA_KEY_BLOB_LENGTH;
key_part->store_length+=HA_KEY_BLOB_LENGTH;
keyinfo->key_length+= HA_KEY_BLOB_LENGTH;
@@ -762,7 +785,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
}
outparam->db_low_byte_first=outparam->file->low_byte_first();
- my_pthread_setspecific_ptr(THR_MALLOC,old_root);
+ *root_ptr= old_root;
thd->status_var.opened_tables++;
#ifndef DBUG_OFF
if (use_hash)
@@ -782,7 +805,7 @@ int openfrm(THD *thd, const char *name, const char *alias, uint db_stat,
err_end: /* Here when no file */
delete crypted;
- my_pthread_setspecific_ptr(THR_MALLOC,old_root);
+ *root_ptr= old_root;
frm_error(error,outparam,name,ME_ERROR+ME_WAITTANG);
delete outparam->file;
outparam->file=0; // For easier errorchecking
@@ -983,11 +1006,11 @@ static void frm_error(int error, TABLE *form, const char *name, myf errortype)
uint length=dirname_part(buff,name);
buff[length-1]=0;
db=buff+dirname_length(buff);
- my_error(ER_NO_SUCH_TABLE,MYF(0),db,form->real_name);
+ my_error(ER_NO_SUCH_TABLE, MYF(0), db, form->real_name);
}
else
- my_error(ER_FILE_NOT_FOUND,errortype,
- fn_format(buff,name,form_dev,reg_ext,0),my_errno);
+ my_error(ER_FILE_NOT_FOUND, errortype,
+ fn_format(buff, name, form_dev, reg_ext, 0), my_errno);
break;
case 2:
{
@@ -995,14 +1018,14 @@ static void frm_error(int error, TABLE *form, const char *name, myf errortype)
datext= datext==NullS ? "" : datext;
err_no= (my_errno == ENOENT) ? ER_FILE_NOT_FOUND : (my_errno == EAGAIN) ?
ER_FILE_USED : ER_CANT_OPEN_FILE;
- my_error(err_no,errortype,
- fn_format(buff,form->real_name,form_dev,datext,2),my_errno);
+ my_error(err_no, errortype,
+ fn_format(buff, form->real_name, form_dev, datext, 2), my_errno);
break;
}
default: /* Better wrong error than none */
case 4:
- my_error(ER_NOT_FORM_FILE,errortype,
- fn_format(buff,name,form_dev,reg_ext,0));
+ my_error(ER_NOT_FORM_FILE, errortype,
+ fn_format(buff, name, form_dev, reg_ext, 0));
break;
}
DBUG_VOID_RETURN;
@@ -1212,7 +1235,11 @@ File create_frm(register my_string name, uint reclength, uchar *fileinfo,
if ((file=my_create(name,CREATE_MODE,O_RDWR | O_TRUNC,MYF(MY_WME))) >= 0)
{
bzero((char*) fileinfo,64);
- fileinfo[0]=(uchar) 254; fileinfo[1]= 1; fileinfo[2]= FRM_VER+3; // Header
+ /* header */
+ fileinfo[0]=(uchar) 254;
+ fileinfo[1]= 1;
+ fileinfo[2]= FRM_VER+3+ test(create_info->varchar);
+
fileinfo[3]= (uchar) ha_checktype(create_info->db_type);
fileinfo[4]=1;
int2store(fileinfo+6,IO_SIZE); /* Next block starts here */
@@ -1365,7 +1392,7 @@ bool check_db_name(char *name)
if (use_mb(system_charset_info))
{
int len=my_ismbchar(system_charset_info, name,
- name+system_charset_info->mbmaxlen);
+ name+system_charset_info->mbmaxlen);
if (len)
{
name += len;
@@ -1442,7 +1469,7 @@ bool check_column_name(const char *name)
if (use_mb(system_charset_info))
{
int len=my_ismbchar(system_charset_info, name,
- name+system_charset_info->mbmaxlen);
+ name+system_charset_info->mbmaxlen);
if (len)
{
name += len;
@@ -1477,7 +1504,8 @@ db_type get_table_type(const char *name)
error=my_read(file,(byte*) head,4,MYF(MY_NABP));
my_close(file,MYF(0));
if (error || head[0] != (uchar) 254 || head[1] != 1 ||
- (head[2] != FRM_VER && head[2] != FRM_VER+1 && head[2] != FRM_VER+3))
+ (head[2] != FRM_VER && head[2] != FRM_VER+1 &&
+ (head[2] < FRM_VER+3 || head[2] > FRM_VER+4)))
DBUG_RETURN(DB_TYPE_UNKNOWN);
DBUG_RETURN(ha_checktype((enum db_type) (uint) *(head+3)));
}
@@ -1516,10 +1544,68 @@ void st_table_list::calc_md5(char *buffer)
void st_table_list::set_ancestor()
{
- if (ancestor->ancestor)
- ancestor->set_ancestor();
- table= ancestor->table;
- ancestor->table->grant= grant;
+ /* process all tables of view */
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->ancestor)
+ ancestor->set_ancestor();
+ tbl->table->grant= grant;
+ }
+ /* if view contain only one table, substitute TABLE of it */
+ if (!ancestor->next_local)
+ {
+ table= ancestor->table;
+ schema_table= ancestor->schema_table;
+ }
+}
+
+
+/*
+ Save old want_privilege and clear want_privilege
+
+ SYNOPSIS
+ save_and_clear_want_privilege()
+*/
+
+void st_table_list::save_and_clear_want_privilege()
+{
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->table)
+ {
+ privilege_backup= tbl->table->grant.want_privilege;
+ tbl->table->grant.want_privilege= 0;
+ }
+ else
+ {
+ DBUG_ASSERT(tbl->view && tbl->ancestor &&
+ tbl->ancestor->next_local);
+ tbl->save_and_clear_want_privilege();
+ }
+ }
+}
+
+
+/*
+ restore want_privilege saved by save_and_clear_want_privilege
+
+ SYNOPSIS
+ restore_want_privilege()
+*/
+
+void st_table_list::restore_want_privilege()
+{
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->table)
+ tbl->table->grant.want_privilege= privilege_backup;
+ else
+ {
+ DBUG_ASSERT(tbl->view && tbl->ancestor &&
+ tbl->ancestor->next_local);
+ tbl->restore_want_privilege();
+ }
+ }
}
@@ -1549,10 +1635,11 @@ void st_table_list::set_ancestor()
bool st_table_list::setup_ancestor(THD *thd, Item **conds,
uint8 check_opt_type)
{
- Item **transl;
+ Field_translator *transl;
SELECT_LEX *select= &view->select_lex;
SELECT_LEX *current_select_save= thd->lex->current_select;
Item *item;
+ TABLE_LIST *tbl;
List_iterator_fast<Item> it(select->item_list);
uint i= 0;
bool save_set_query_id= thd->set_query_id;
@@ -1560,38 +1647,57 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
bool save_allow_sum_func= thd->allow_sum_func;
DBUG_ENTER("st_table_list::setup_ancestor");
- if (ancestor->ancestor &&
- ancestor->setup_ancestor(thd, conds,
- (check_opt_type == VIEW_CHECK_CASCADED ?
- VIEW_CHECK_CASCADED :
- VIEW_CHECK_NONE)))
- DBUG_RETURN(1);
+ for (tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->ancestor &&
+ tbl->setup_ancestor(thd, conds,
+ (check_opt_type == VIEW_CHECK_CASCADED ?
+ VIEW_CHECK_CASCADED :
+ VIEW_CHECK_NONE)))
+ DBUG_RETURN(1);
+ }
if (field_translation)
{
/* prevent look up in SELECTs tree */
thd->lex->current_select= &thd->lex->select_lex;
+ thd->lex->select_lex.no_wrap_view_item= 1;
thd->set_query_id= 1;
/* this view was prepared already on previous PS/SP execution */
- Item **end= field_translation + select->item_list.elements;
- for (Item **item= field_translation; item < end; item++)
+ Field_translator *end= field_translation + select->item_list.elements;
+ /* real rights will be checked in VIEW field */
+ save_and_clear_want_privilege();
+ /* aggregate function are allowed */
+ thd->allow_sum_func= 1;
+ for (transl= field_translation; transl < end; transl++)
{
- /* TODO: fix for several tables in VIEW */
- uint want_privilege= ancestor->table->grant.want_privilege;
- /* real rights will be checked in VIEW field */
- ancestor->table->grant.want_privilege= 0;
- /* aggregate function are allowed */
- thd->allow_sum_func= 1;
- if (!(*item)->fixed && (*item)->fix_fields(thd, ancestor, item))
+ if (!transl->item->fixed &&
+ transl->item->fix_fields(thd, ancestor, &transl->item))
goto err;
- ancestor->table->grant.want_privilege= want_privilege;
+ }
+ for (tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->on_expr && !tbl->on_expr->fixed &&
+ tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr))
+ goto err;
+ }
+ if (where && !where->fixed && where->fix_fields(thd, ancestor, &where))
+ goto err;
+ restore_want_privilege();
+
+ /* WHERE/ON resolved => we can rename fields */
+ for (transl= field_translation; transl < end; transl++)
+ {
+ transl->item->rename((char *)transl->name);
}
goto ok;
}
/* view fields translation table */
if (!(transl=
- (Item**)(thd->current_arena->alloc(select->item_list.elements * sizeof(Item*)))))
+ (Field_translator*)(thd->current_arena->
+ alloc(select->item_list.elements *
+ sizeof(Field_translator)))))
{
DBUG_RETURN(1);
}
@@ -1607,22 +1713,29 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
used fields correctly.
*/
thd->set_query_id= 1;
+ /* real rights will be checked in VIEW field */
+ save_and_clear_want_privilege();
+ /* aggregate function are allowed */
+ thd->allow_sum_func= 1;
while ((item= it++))
{
- /* TODO: fix for several tables in VIEW */
- uint want_privilege= ancestor->table->grant.want_privilege;
- /* real rights will be checked in VIEW field */
- ancestor->table->grant.want_privilege= 0;
- /* aggregate function are allowed */
- thd->allow_sum_func= 1;
+ /* save original name of view column */
+ char *name= item->name;
if (!item->fixed && item->fix_fields(thd, ancestor, &item))
goto err;
- ancestor->table->grant.want_privilege= want_privilege;
- transl[i++]= item;
+ /* set new item get in fix fields and original column name */
+ transl[i].name= name;
+ transl[i++].item= item;
}
field_translation= transl;
/* TODO: sort this list? Use hash for big number of fields */
+ for (tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->on_expr && !tbl->on_expr->fixed &&
+ tbl->on_expr->fix_fields(thd, ancestor, &tbl->on_expr))
+ goto err;
+ }
if (where ||
(check_opt_type == VIEW_CHECK_CASCADED &&
ancestor->check_option))
@@ -1695,6 +1808,8 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
if (arena)
thd->restore_backup_item_arena(arena, &backup);
}
+ restore_want_privilege();
+
/*
fix_fields do not need tables, because new are only AND operation and we
just need recollect statistics
@@ -1703,6 +1818,15 @@ bool st_table_list::setup_ancestor(THD *thd, Item **conds,
check_option->fix_fields(thd, 0, &check_option))
goto err;
+ /* WHERE/ON resolved => we can rename fields */
+ {
+ Field_translator *end= field_translation + select->item_list.elements;
+ for (transl= field_translation; transl < end; transl++)
+ {
+ transl->item->rename((char *)transl->name);
+ }
+ }
+
/* full text function moving to current select */
if (view->select_lex.ftfunc_list->elements)
{
@@ -1736,6 +1860,25 @@ err:
/*
+ cleunup items belonged to view fields translation table
+
+ SYNOPSIS
+ st_table_list::cleanup_items()
+*/
+
+void st_table_list::cleanup_items()
+{
+ if (!field_translation)
+ return;
+
+ Field_translator *end= (field_translation +
+ view->select_lex.item_list.elements);
+ for (Field_translator *transl= field_translation; transl < end; transl++)
+ transl->item->walk(&Item::cleanup_processor, 0);
+}
+
+
+/*
check CHECK OPTION condition
SYNOPSIS
@@ -1769,6 +1912,96 @@ int st_table_list::view_check_option(THD *thd, bool ignore_failure)
}
+/*
+ Find table in underlying tables by mask and check that only this
+ table belong to given mask
+
+ SYNOPSIS
+ st_table_list::check_single_table()
+ table reference on variable where to store found table
+ (should be 0 on call, to find table, or point to table for
+ unique test)
+ map bit mask of tables
+
+ RETURN
+ FALSE table not found or found only one
+ TRUE found several tables
+*/
+
+bool st_table_list::check_single_table(st_table_list **table, table_map map)
+{
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ {
+ if (tbl->table)
+ {
+ if (tbl->table->map & map)
+ {
+ if (*table)
+ return TRUE;
+ else
+ *table= tbl;
+ }
+ }
+ else
+ if (tbl->check_single_table(table, map))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
+ Set insert_values buffer
+
+ SYNOPSIS
+ set_insert_values()
+ mem_root memory pool for allocating
+
+ RETURN
+ FALSE - OK
+ TRUE - out of memory
+*/
+
+bool st_table_list::set_insert_values(MEM_ROOT *mem_root)
+{
+ if (table)
+ {
+ if (!table->insert_values &&
+ !(table->insert_values= (byte *)alloc_root(mem_root,
+ table->rec_buff_length)))
+ return TRUE;
+ }
+ else
+ {
+ DBUG_ASSERT(view && ancestor && ancestor->next_local);
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ if (tbl->set_insert_values(mem_root))
+ return TRUE;
+ }
+ return FALSE;
+}
+
+
+/*
+ clear insert_values reference
+
+ SYNOPSIS
+ clear_insert_values()
+*/
+
+void st_table_list::clear_insert_values()
+{
+ if (table)
+ table->insert_values= 0;
+ else
+ {
+ DBUG_ASSERT(view && ancestor && ancestor->next_local);
+ for (TABLE_LIST *tbl= ancestor; tbl; tbl= tbl->next_local)
+ tbl->clear_insert_values();
+ }
+}
+
+
void Field_iterator_view::set(TABLE_LIST *table)
{
ptr= table->field_translation;
@@ -1790,7 +2023,7 @@ Item *Field_iterator_table::item(THD *thd)
const char *Field_iterator_view::name()
{
- return (*ptr)->name;
+ return ptr->name;
}
diff --git a/sql/table.h b/sql/table.h
index d5bbd0ac2e2..f5f2a76c6f1 100644
--- a/sql/table.h
+++ b/sql/table.h
@@ -160,6 +160,8 @@ struct st_table {
my_bool no_keyread, no_cache;
my_bool clear_query_id; /* To reset query_id for tables and cols */
my_bool auto_increment_field_not_null;
+ my_bool insert_or_update; /* Can be used by the handler */
+ my_bool alias_name_used; /* true if table_name is alias */
Field *next_number_field, /* Set if next_number is activated */
*found_next_number_field, /* Set on open */
*rowid_field;
@@ -204,6 +206,57 @@ struct st_table {
};
+typedef struct st_foreign_key_info
+{
+ LEX_STRING *forein_id;
+ LEX_STRING *referenced_db;
+ LEX_STRING *referenced_table;
+ LEX_STRING *constraint_method;
+ List<LEX_STRING> foreign_fields;
+ List<LEX_STRING> referenced_fields;
+} FOREIGN_KEY_INFO;
+
+
+enum enum_schema_tables
+{
+ SCH_SCHEMATA= 0, SCH_TABLES, SCH_COLUMNS, SCH_CHARSETS, SCH_COLLATIONS,
+ SCH_COLLATION_CHARACTER_SET_APPLICABILITY, SCH_PROCEDURES, SCH_STATISTICS,
+ SCH_VIEWS, SCH_USER_PRIVILEGES, SCH_SCHEMA_PRIVILEGES, SCH_TABLE_PRIVILEGES,
+ SCH_COLUMN_PRIVILEGES, SCH_TABLE_CONSTRAINTS, SCH_KEY_COLUMN_USAGE,
+ SCH_TABLE_NAMES
+};
+
+
+typedef struct st_field_info
+{
+ const char* field_name;
+ uint field_length;
+ enum enum_field_types field_type;
+ int value;
+ bool maybe_null;
+ const char* old_name;
+} ST_FIELD_INFO;
+
+struct st_table_list;
+typedef class Item COND;
+
+typedef struct st_schema_table
+{
+ const char* table_name;
+ ST_FIELD_INFO *fields_info;
+ /* Create information_schema table */
+ TABLE *(*create_table) (THD *thd, struct st_table_list *table_list);
+ /* Fill table with data */
+ int (*fill_table) (THD *thd, struct st_table_list *tables, COND *cond);
+ /* Handle fileds for old SHOW */
+ int (*old_format) (THD *thd, struct st_schema_table *schema_table);
+ int (*process_table) (THD *thd, struct st_table_list *tables,
+ TABLE *table, bool res, const char *base_name,
+ const char *file_name);
+ int idx_field1, idx_field2;
+} ST_SCHEMA_TABLE;
+
+
#define JOIN_TYPE_LEFT 1
#define JOIN_TYPE_RIGHT 2
@@ -222,6 +275,12 @@ struct st_table {
#define VIEW_CHECK_SKIP 2
struct st_lex;
+class select_union;
+struct Field_translator
+{
+ Item *item;
+ const char *name;
+};
typedef struct st_table_list
{
@@ -229,7 +288,7 @@ typedef struct st_table_list
struct st_table_list *next_local;
/* link in a global list of all queries tables */
struct st_table_list *next_global, **prev_global;
- char *db, *alias, *real_name;
+ char *db, *alias, *real_name, *schema_table_name;
char *option; /* Used by cache index */
Item *on_expr; /* Used with outer join */
COND_EQUAL *cond_equal; /* Used with outer join */
@@ -238,6 +297,11 @@ typedef struct st_table_list
List<String> *use_index, *ignore_index;
TABLE *table; /* opened table */
/*
+ select_result for derived table to pass it from table creation to table
+ filling procedure
+ */
+ select_union *derived_result;
+ /*
Reference from aux_tables to local list entry of main select of
multi-delete statement:
delete t1 from t2,t1 where t1.a<'B' and t2.b=t1.b;
@@ -246,16 +310,18 @@ typedef struct st_table_list
*/
st_table_list *correspondent_table;
st_select_lex_unit *derived; /* SELECT_LEX_UNIT of derived table */
+ ST_SCHEMA_TABLE *schema_table; /* Information_schema table */
+ st_select_lex *schema_select_lex;
/* link to select_lex where this table was used */
st_select_lex *select_lex;
st_lex *view; /* link on VIEW lex for merging */
- Item **field_translation; /* array of VIEW fields */
+ Field_translator *field_translation; /* array of VIEW fields */
/* ancestor of this table (VIEW merge algorithm) */
st_table_list *ancestor;
/* most upper view this table belongs to */
st_table_list *belong_to_view;
- /* next_global before adding VIEW tables */
- st_table_list *old_next;
+ /* list of join table tree leaves */
+ st_table_list *next_leaf;
Item *where; /* VIEW WHERE clause condition */
Item *check_option; /* WITH CHECK OPTION condition */
LEX_STRING query; /* text of (CRETE/SELECT) statement */
@@ -275,6 +341,7 @@ typedef struct st_table_list
*/
uint8 effective_with_check;
uint effective_algorithm; /* which algorithm was really used */
+ uint privilege_backup; /* place for saving privileges */
GRANT_INFO grant;
thr_lock_type lock_type;
uint outer_join; /* Which join type */
@@ -306,14 +373,14 @@ typedef struct st_table_list
void set_ancestor();
int view_check_option(THD *thd, bool ignore_failure);
bool setup_ancestor(THD *thd, Item **conds, uint8 check_option);
+ void cleanup_items();
bool placeholder() {return derived || view; }
void print(THD *thd, String *str);
- inline st_table_list *next_independent()
- {
- if (view)
- return old_next;
- return next_global;
- }
+ void save_and_clear_want_privilege();
+ void restore_want_privilege();
+ bool check_single_table(st_table_list **table, table_map map);
+ bool set_insert_values(MEM_ROOT *mem_root);
+ void clear_insert_values();
} TABLE_LIST;
class Item;
@@ -348,14 +415,14 @@ public:
class Field_iterator_view: public Field_iterator
{
- Item **ptr, **array_end;
+ Field_translator *ptr, *array_end;
public:
Field_iterator_view() :ptr(0), array_end(0) {}
void set(TABLE_LIST *table);
void next() { ptr++; }
bool end_of_fields() { return ptr == array_end; }
const char *name();
- Item *item(THD *thd) { return *ptr; }
+ Item *item(THD *thd) { return ptr->item; }
Field *field() { return 0; }
};
diff --git a/sql/thr_malloc.cc b/sql/thr_malloc.cc
index fa678ec7de2..3a9ca397bba 100644
--- a/sql/thr_malloc.cc
+++ b/sql/thr_malloc.cc
@@ -38,7 +38,7 @@ void init_sql_alloc(MEM_ROOT *mem_root, uint block_size, uint pre_alloc)
gptr sql_alloc(uint Size)
{
- MEM_ROOT *root=my_pthread_getspecific_ptr(MEM_ROOT*,THR_MALLOC);
+ MEM_ROOT *root= *my_pthread_getspecific_ptr(MEM_ROOT**,THR_MALLOC);
char *ptr= (char*) alloc_root(root,Size);
return ptr;
}
@@ -108,8 +108,11 @@ char *sql_strmake_with_convert(const char *str, uint32 arg_length,
memcpy(pos, str, new_length);
}
else
+ {
+ uint dummy_errors;
new_length= copy_and_convert((char*) pos, new_length, to_cs, str,
- arg_length, from_cs);
+ arg_length, from_cs, &dummy_errors);
+ }
pos[new_length]= 0;
*result_length= new_length;
return pos;
diff --git a/sql/unireg.cc b/sql/unireg.cc
index decac2a0549..636156940a4 100644
--- a/sql/unireg.cc
+++ b/sql/unireg.cc
@@ -383,7 +383,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
if (create_fields.elements > MAX_FIELDS)
{
- my_error(ER_TOO_MANY_FIELDS,MYF(0));
+ my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
DBUG_RETURN(1);
}
@@ -448,7 +448,7 @@ static bool pack_header(uchar *forminfo, enum db_type table_type,
if (info_length+(ulong) create_fields.elements*FCOMP+288+
n_length+int_length+com_length > 65535L || int_count > 255)
{
- my_error(ER_TOO_MANY_FIELDS,MYF(0));
+ my_message(ER_TOO_MANY_FIELDS, ER(ER_TOO_MANY_FIELDS), MYF(0));
DBUG_RETURN(1);
}
diff --git a/sql/unireg.h b/sql/unireg.h
index 2879e30d861..31b28da2423 100644
--- a/sql/unireg.h
+++ b/sql/unireg.h
@@ -60,6 +60,9 @@
#define MAX_MBWIDTH 3 /* Max multibyte sequence */
#define MAX_FIELD_CHARLENGTH 255
+#define MAX_FIELD_VARCHARLENGTH 65535
+#define CONVERT_IF_BIGGER_TO_BLOB 512 /* Used for CREATE ... SELECT */
+
/* Max column width +1 */
#define MAX_FIELD_WIDTH (MAX_FIELD_CHARLENGTH*MAX_MBWIDTH+1)
@@ -145,6 +148,7 @@
#define TE_INFO_LENGTH 3
#define MTYP_NOEMPTY_BIT 128
+#define FRM_VER_TRUE_VARCHAR (FRM_VER+4)
/*
Minimum length pattern before Turbo Boyer-Moore is used
for SELECT "text" LIKE "%pattern%", excluding the two
diff --git a/strings/ctype-big5.c b/strings/ctype-big5.c
index 8345c53202c..d9532cddc4d 100644
--- a/strings/ctype-big5.c
+++ b/strings/ctype-big5.c
@@ -264,24 +264,33 @@ static int my_strnncoll_big5(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_big5(CHARSET_INFO * cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
uint length= min(a_length, b_length);
int res= my_strnncoll_big5_internal(&a, &b, length);
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
+
if (!res && a_length != b_length)
{
const uchar *end;
int swap= 0;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
*/
if (a_length < b_length)
{
- /* put shorter key in a */
+ /* put longer key in a */
a_length= b_length;
a= b;
- swap= -1; /* swap sign of result */
+ swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -407,7 +416,7 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)),
*min_str++= *max_str++ = *ptr;
continue;
}
- if (*ptr == w_one) /* '_' in SQL */
+ if (*ptr == w_one) /* '_' in SQL */
{
*min_str++='\0'; /* This should be min char */
*max_str++=max_sort_char;
@@ -415,7 +424,13 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str-min_org);
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
*max_length= res_length;
do {
*min_str++ = 0;
@@ -425,26 +440,27 @@ static my_bool my_like_range_big5(CHARSET_INFO *cs __attribute__((unused)),
}
*min_str++= *max_str++ = *ptr;
}
- *min_length= *max_length= (uint) (min_str-min_org);
+
+ *min_length= *max_length= (uint) (min_str-min_org);
while (min_str != min_end)
- {
- *min_str++ = ' '; /* Because if key compression */
- *max_str++ = ' ';
- }
+ *min_str++= *max_str++= ' ';
return 0;
}
+
static int ismbchar_big5(CHARSET_INFO *cs __attribute__((unused)),
const char* p, const char *e)
{
return (isbig5head(*(p)) && (e)-(p)>1 && isbig5tail(*((p)+1))? 2: 0);
}
+
static int mbcharlen_big5(CHARSET_INFO *cs __attribute__((unused)), uint c)
{
return (isbig5head(c)? 2 : 1);
}
+
/* page 0 0xA140-0xC7FC */
static uint16 tab_big5_uni0[]={
0x3000,0xFF0C,0x3001,0x3002,0xFF0E,0x2022,0xFF1B,0xFF1A,
diff --git a/strings/ctype-bin.c b/strings/ctype-bin.c
index 7d17f62c8d0..db57c75d9f1 100644
--- a/strings/ctype-bin.c
+++ b/strings/ctype-bin.c
@@ -103,7 +103,9 @@ static int my_strnncoll_binary(CHARSET_INFO * cs __attribute__((unused)),
static int my_strnncollsp_binary(CHARSET_INFO * cs __attribute__((unused)),
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference
+ __attribute__((unused)))
{
return my_strnncoll_binary(cs,s,slen,t,tlen,0);
}
@@ -130,6 +132,9 @@ static int my_strnncoll_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
slen Length of 's'
t String to compare
tlen Length of 't'
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
NOTE
This function is used for character strings with binary collations.
@@ -144,10 +149,16 @@ static int my_strnncoll_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
const uchar *end;
uint length;
+ int res;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
end= a + (length= min(a_length, b_length));
while (a < end)
@@ -155,6 +166,7 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
if (*a++ != *b++)
return ((int) a[-1] - (int) b[-1]);
}
+ res= 0;
if (a_length != b_length)
{
int swap= 0;
@@ -162,12 +174,15 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
*/
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
if (a_length < b_length)
{
/* put shorter key in s */
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -175,7 +190,7 @@ static int my_strnncollsp_8bit_bin(CHARSET_INFO * cs __attribute__((unused)),
return ((int) *a - (int) ' ') ^ swap;
}
}
- return 0;
+ return res;
}
diff --git a/strings/ctype-czech.c b/strings/ctype-czech.c
index 6f9e9f74d35..07c45788d30 100644
--- a/strings/ctype-czech.c
+++ b/strings/ctype-czech.c
@@ -275,8 +275,9 @@ static int my_strnncoll_czech(CHARSET_INFO *cs __attribute__((unused)),
static
int my_strnncollsp_czech(CHARSET_INFO * cs,
- const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference)
{
for ( ; slen && s[slen-1] == ' ' ; slen--);
for ( ; tlen && t[tlen-1] == ' ' ; tlen--);
@@ -352,7 +353,7 @@ static int my_strnxfrm_czech(CHARSET_INFO *cs __attribute__((unused)),
#ifdef REAL_MYSQL
-#define min_sort_char ' '
+#define min_sort_char 0
#define max_sort_char '9'
#define EXAMPLE
@@ -391,8 +392,17 @@ static my_bool my_like_range_czech(CHARSET_INFO *cs __attribute__((unused)),
*min_str++= *max_str++ = *ptr;
}
- *min_length= (uint) (min_str - min_org);
+
+ if (cs->state & MY_CS_BINSORT)
+ *min_length= (uint) (min_str - min_org);
+ else
+ {
+ /* 'a\0\0... is the smallest possible string */
+ *min_length= res_length;
+ }
+ /* a\ff\ff... is the biggest possible string */
*max_length= res_length;
+
while (min_str != min_end)
{
*min_str++ = min_sort_char; /* Because of key compression */
@@ -589,12 +599,12 @@ static MY_COLLATION_HANDLER my_collation_latin2_czech_ci_handler =
CHARSET_INFO my_charset_latin2_czech_ci =
{
- 2,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */
- "latin2", /* cs name */
- "latin2_czech_cs", /* name */
- "", /* comment */
- NULL, /* tailoring */
+ 2,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_CSSORT, /* state */
+ "latin2", /* cs name */
+ "latin2_czech_cs", /* name */
+ "", /* comment */
+ NULL, /* tailoring */
ctype_czech,
to_lower_czech,
to_upper_czech,
diff --git a/strings/ctype-gbk.c b/strings/ctype-gbk.c
index 0be56e8d946..858624c0600 100644
--- a/strings/ctype-gbk.c
+++ b/strings/ctype-gbk.c
@@ -2625,14 +2625,22 @@ int my_strnncoll_gbk(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_gbk(CHARSET_INFO * cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
uint length= min(a_length, b_length);
int res= my_strnncoll_gbk_internal(&a, &b, length);
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
+
if (!res && a_length != b_length)
{
const uchar *end;
int swap= 0;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -2643,6 +2651,7 @@ static int my_strnncollsp_gbk(CHARSET_INFO * cs __attribute__((unused)),
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -2728,22 +2737,26 @@ static my_bool my_like_range_gbk(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str - min_org);
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
*max_length= res_length;
do {
*min_str++= 0;
- *max_str++ = max_sort_char;
+ *max_str++= max_sort_char;
} while (min_str != min_end);
return 0;
}
*min_str++= *max_str++ = *ptr;
}
+
*min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end)
- {
- *min_str++ = ' '; /* Because if key compression */
- *max_str++ = ' ';
- }
+ *min_str++= *max_str++= ' '; /* Because if key compression */
return 0;
}
diff --git a/strings/ctype-latin1.c b/strings/ctype-latin1.c
index 5f1850b7772..69c9ed4b023 100644
--- a/strings/ctype-latin1.c
+++ b/strings/ctype-latin1.c
@@ -572,11 +572,16 @@ static int my_strnncoll_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
- const uchar *a_end= a + a_length;
- const uchar *b_end= b + b_length;
+ const uchar *a_end= a + a_length, *b_end= b + b_length;
uchar a_char, a_extend= 0, b_char, b_extend= 0;
+ int res;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
while ((a < a_end || a_extend) && (b < b_end || b_extend))
{
@@ -609,9 +614,12 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
if (b_extend)
return -1;
+ res= 0;
if (a != a_end || b != b_end)
{
int swap= 0;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -622,6 +630,7 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
a_end= b_end;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for ( ; a < a_end ; a++)
{
@@ -629,7 +638,7 @@ static int my_strnncollsp_latin1_de(CHARSET_INFO *cs __attribute__((unused)),
return ((int) *a - (int) ' ') ^ swap;
}
}
- return 0;
+ return res;
}
diff --git a/strings/ctype-mb.c b/strings/ctype-mb.c
index 7d81766c4cb..ae81cefad5a 100644
--- a/strings/ctype-mb.c
+++ b/strings/ctype-mb.c
@@ -362,6 +362,9 @@ static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
slen Length of 's'
t String to compare
tlen Length of 't'
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
NOTE
This function is used for character strings with binary collations.
@@ -376,10 +379,16 @@ static int my_strnncoll_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
const uchar *end;
uint length;
+ int res;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
end= a + (length= min(a_length, b_length));
while (a < end)
@@ -387,9 +396,12 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
if (*a++ != *b++)
return ((int) a[-1] - (int) b[-1]);
}
+ res= 0;
if (a_length != b_length)
{
int swap= 0;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -400,6 +412,7 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -407,7 +420,7 @@ static int my_strnncollsp_mb_bin(CHARSET_INFO * cs __attribute__((unused)),
return ((int) *a - (int) ' ') ^ swap;
}
}
- return 0;
+ return res;
}
@@ -443,6 +456,37 @@ static void my_hash_sort_mb_bin(CHARSET_INFO *cs __attribute__((unused)),
}
}
+
+/*
+ Write max key: create a buffer with multibyte
+ representation of the max_sort_char character,
+ and copy it into max_str in a loop.
+*/
+static void pad_max_char(CHARSET_INFO *cs, char *str, char *end)
+{
+ char buf[10];
+ char buflen= cs->cset->wc_mb(cs, cs->max_sort_char, (uchar*) buf,
+ (uchar*) buf + sizeof(buf));
+ DBUG_ASSERT(buflen > 0);
+ do
+ {
+ if ((str + buflen) < end)
+ {
+ /* Enough space for the characer */
+ memcpy(str, buf, buflen);
+ str+= buflen;
+ }
+ else
+ {
+ /*
+ There is no space for whole multibyte
+ character, then add trailing spaces.
+ */
+ *str++= ' ';
+ }
+ } while (str < end);
+}
+
/*
** Calculate min_str and max_str that ranges a LIKE string.
** Arguments:
@@ -467,10 +511,15 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
char *min_str,char *max_str,
uint *min_length,uint *max_length)
{
- const char *end=ptr+ptr_length;
- char *min_org=min_str;
- char *min_end=min_str+res_length;
- char *max_end=max_str+res_length;
+ const char *end;
+ char *min_org= min_str;
+ char *min_end= min_str + res_length;
+ char *max_end= max_str + res_length;
+ uint charlen= my_charpos(cs, ptr, ptr+ptr_length, res_length/cs->mbmaxlen);
+
+ if (charlen < ptr_length)
+ ptr_length= charlen;
+ end= ptr + ptr_length;
for (; ptr != end && min_str != min_end ; ptr++)
{
@@ -482,16 +531,20 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
}
if (*ptr == w_one || *ptr == w_many) /* '_' and '%' in SQL */
{
- char buf[10];
- uint buflen;
- uint charlen= my_charpos(cs, min_org, min_str, res_length/cs->mbmaxlen);
+ charlen= my_charpos(cs, min_org, min_str, res_length/cs->mbmaxlen);
if (charlen < (uint) (min_str - min_org))
min_str= min_org + charlen;
- /* Write min key */
- *min_length= (uint) (min_str - min_org);
- *max_length=res_length;
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
+ *max_length= res_length;
+ /* Create min key */
do
{
*min_str++= (char) cs->min_sort_char;
@@ -502,38 +555,19 @@ my_bool my_like_range_mb(CHARSET_INFO *cs,
representation of the max_sort_char character,
and copy it into max_str in a loop.
*/
- buflen= cs->cset->wc_mb(cs, cs->max_sort_char, (uchar*) buf,
- (uchar*) buf + sizeof(buf));
- DBUG_ASSERT(buflen > 0);
- do
- {
- if ((max_str + buflen) <= max_end)
- {
- /* Enough space for max characer */
- memcpy(max_str, buf, buflen);
- max_str+= buflen;
- }
- else
- {
- /*
- There is no space for whole multibyte
- character, then add trailing spaces.
- */
-
- *max_str++= ' ';
- }
- } while (max_str != max_end);
+ pad_max_char(cs, max_str, max_end);
return 0;
}
*min_str++= *max_str++ = *ptr;
}
- *min_length= *max_length = (uint) (min_str - min_org);
+ *min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end)
- *min_str++ = *max_str++ = ' '; /* Because if key compression */
+ *min_str++= *max_str= ' '; /* Because if key compression */
return 0;
}
+
static int my_wildcmp_mb_bin(CHARSET_INFO *cs,
const char *str,const char *str_end,
const char *wildstr,const char *wildend,
diff --git a/strings/ctype-simple.c b/strings/ctype-simple.c
index a019665a235..0659cb5d387 100644
--- a/strings/ctype-simple.c
+++ b/strings/ctype-simple.c
@@ -71,6 +71,9 @@ int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
a_length Length of 'a'
b Second string to compare
b_length Length of 'b'
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
IMPLEMENTATION
If one string is shorter as the other, then we space extend the other
@@ -89,10 +92,16 @@ int my_strnncoll_simple(CHARSET_INFO * cs, const uchar *s, uint slen,
*/
int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
const uchar *map= cs->sort_order, *end;
uint length;
+ int res;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
end= a + (length= min(a_length, b_length));
while (a < end)
@@ -100,9 +109,12 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
if (map[*a++] != map[*b++])
return ((int) map[a[-1]] - (int) map[b[-1]]);
}
+ res= 0;
if (a_length != b_length)
{
int swap= 0;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -113,6 +125,7 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -120,7 +133,7 @@ int my_strnncollsp_simple(CHARSET_INFO * cs, const uchar *a, uint a_length,
return ((int) *a - (int) ' ') ^ swap;
}
}
- return 0;
+ return res;
}
@@ -218,14 +231,19 @@ void my_hash_sort_simple(CHARSET_INFO *cs,
ulong *nr1, ulong *nr2)
{
register uchar *sort_order=cs->sort_order;
- const uchar *pos = key;
+ const uchar *end= key + len;
- key+= len;
+ /*
+ Remove end space. We have to do this to be able to compare
+ 'A ' and 'A' as identical
+ */
+ while (end > key && end[-1] == ' ')
+ end--;
- for (; pos < (uchar*) key ; pos++)
+ for (; key < (uchar*) end ; key++)
{
nr1[0]^=(ulong) ((((uint) nr1[0] & 63)+nr2[0]) *
- ((uint) sort_order[(uint) *pos])) + (nr1[0] << 8);
+ ((uint) sort_order[(uint) *key])) + (nr1[0] << 8);
nr2[0]+=3;
}
}
@@ -996,8 +1014,10 @@ my_bool my_like_range_simple(CHARSET_INFO *cs,
}
if (*ptr == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str - min_org);
- *max_length=res_length;
+ /* Calculate length of keys */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
+ *max_length= res_length;
do
{
*min_str++= 0;
@@ -1007,10 +1027,10 @@ my_bool my_like_range_simple(CHARSET_INFO *cs,
}
*min_str++= *max_str++ = *ptr;
}
- *min_length= *max_length = (uint) (min_str - min_org);
+ *min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end)
- *min_str++ = *max_str++ = ' '; /* Because if key compression */
+ *min_str++= *max_str++ = ' '; /* Because if key compression */
return 0;
}
diff --git a/strings/ctype-sjis.c b/strings/ctype-sjis.c
index 4176ff2e538..12bee9082b6 100644
--- a/strings/ctype-sjis.c
+++ b/strings/ctype-sjis.c
@@ -244,14 +244,21 @@ static int my_strnncoll_sjis(CHARSET_INFO *cs __attribute__((unused)),
static int my_strnncollsp_sjis(CHARSET_INFO *cs __attribute__((unused)),
const uchar *a, uint a_length,
- const uchar *b, uint b_length)
+ const uchar *b, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
- const uchar *a_end= a + a_length;
- const uchar *b_end= b + b_length;
+ const uchar *a_end= a + a_length, *b_end= b + b_length;
int res= my_strnncoll_sjis_internal(cs, &a, a_length, &b, b_length);
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
+
if (!res && (a != a_end || b != b_end))
{
int swap= 0;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -262,6 +269,7 @@ static int my_strnncollsp_sjis(CHARSET_INFO *cs __attribute__((unused)),
a_end= b_end;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (; a < a_end ; a++)
{
@@ -347,8 +355,14 @@ static my_bool my_like_range_sjis(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == w_many)
{ /* '%' in SQL */
- *min_length = (uint)(min_str - min_org);
- *max_length = res_length;
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
+ *max_length= res_length;
do
{
*min_str++= 0;
@@ -358,9 +372,10 @@ static my_bool my_like_range_sjis(CHARSET_INFO *cs __attribute__((unused)),
}
*min_str++ = *max_str++ = *ptr++;
}
- *min_length = *max_length = (uint)(min_str - min_org);
- while (min_str < min_end)
- *min_str++ = *max_str++ = ' '; /* Because if key compression */
+
+ *min_length= *max_length= (uint) (min_str - min_org);
+ while (min_str != min_end)
+ *min_str++= *max_str++= ' '; /* Because if key compression */
return 0;
}
@@ -4581,14 +4596,19 @@ uint my_well_formed_len_sjis(CHARSET_INFO *cs __attribute__((unused)),
*/
if (((int8)b[0]) >= 0)
{
- /* Single byte character */
- b+= 1;
+ /* Single byte ascii character */
+ b++;
}
else if (issjishead((uchar)*b) && (e-b)>1 && issjistail((uchar)b[1]))
{
/* Double byte character */
b+= 2;
}
+ else if (((uchar)*b) >= 0xA1 && ((uchar)*b) <= 0xDF)
+ {
+ /* Half width kana */
+ b++;
+ }
else
{
/* Wrong byte sequence */
diff --git a/strings/ctype-tis620.c b/strings/ctype-tis620.c
index a2ba4783591..80af8e2014b 100644
--- a/strings/ctype-tis620.c
+++ b/strings/ctype-tis620.c
@@ -320,7 +320,7 @@ static int t_ctype[][TOT_LEVELS] = {
/*0xFC*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xFD*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
/*0xFE*/ { IGNORE, IGNORE, IGNORE, IGNORE, X },
-/* Utilize 0xFF for max_sort_chr in my_like_range_tis620 */
+ /* Utilize 0xFF for max_sort_chr in my_like_range_tis620 */
/*0xFF*/ { 255 /*IGNORE*/, IGNORE, IGNORE, IGNORE, X },
};
@@ -541,7 +541,7 @@ int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)),
tc1= buf;
if ((len1 + len2 +2) > (int) sizeof(buf))
- tc1= (uchar*) malloc(len1+len2);
+ tc1= (uchar*) malloc(len1+len2+2);
tc2= tc1 + len1+1;
memcpy((char*) tc1, (char*) s1, len1);
tc1[len1]= 0; /* if length(s1)> len1, need to put 'end of string' */
@@ -559,20 +559,20 @@ int my_strnncoll_tis620(CHARSET_INFO *cs __attribute__((unused)),
static
int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
const uchar *a0, uint a_length,
- const uchar *b0, uint b_length)
+ const uchar *b0, uint b_length,
+ my_bool diff_if_only_endspace_difference)
{
- uchar buf[80] ;
- uchar *end, *a, *b;
+ uchar buf[80], *end, *a, *b, *alloced= NULL;
uint length;
int res= 0;
- int alloced= 0;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
a= buf;
if ((a_length + b_length +2) > (int) sizeof(buf))
- {
- a= (uchar*) malloc(a_length+b_length);
- alloced= 1;
- }
+ alloced= a= (uchar*) malloc(a_length+b_length+2);
b= a + a_length+1;
memcpy((char*) a, (char*) a0, a_length);
@@ -594,6 +594,8 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
if (a_length != b_length)
{
int swap= 0;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
/*
Check the next not space character of the longer key. If it's < ' ',
then it's smaller than the other key.
@@ -604,6 +606,7 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
a_length= b_length;
a= b;
swap= -1; /* swap sign of result */
+ res= -res;
}
for (end= a + a_length-length; a < end ; a++)
{
@@ -618,7 +621,7 @@ int my_strnncollsp_tis620(CHARSET_INFO * cs __attribute__((unused)),
ret:
if (alloced)
- free(a);
+ free(alloced);
return res;
}
@@ -687,8 +690,14 @@ my_bool my_like_range_tis620(CHARSET_INFO *cs __attribute__((unused)),
}
if (*ptr == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str - min_org);
- *max_length=res_length;
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
+ *max_length= res_length;
do
{
*min_str++ = 0;
@@ -698,10 +707,10 @@ my_bool my_like_range_tis620(CHARSET_INFO *cs __attribute__((unused)),
}
*min_str++= *max_str++ = *ptr;
}
- *min_length= *max_length = (uint) (min_str - min_org);
+ *min_length= *max_length = (uint) (min_str - min_org);
while (min_str != min_end)
- *min_str++ = *max_str++ = ' '; /* Because of key compression */
+ *min_str++= *max_str++ = ' '; /* Because of key compression */
return 0;
}
diff --git a/strings/ctype-uca.c b/strings/ctype-uca.c
index 91af7af0c54..fb44a56ef0f 100644
--- a/strings/ctype-uca.c
+++ b/strings/ctype-uca.c
@@ -7048,6 +7048,9 @@ static int my_strnncoll_uca(CHARSET_INFO *cs,
slen First string length
t Second string
tlen Seconf string length
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
NOTES:
Works exactly the same with my_strnncoll_uca(),
@@ -7085,13 +7088,16 @@ static int my_strnncoll_uca(CHARSET_INFO *cs,
static int my_strnncollsp_uca(CHARSET_INFO *cs,
my_uca_scanner_handler *scanner_handler,
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference)
{
- my_uca_scanner sscanner;
- my_uca_scanner tscanner;
- int s_res;
- int t_res;
+ my_uca_scanner sscanner, tscanner;
+ int s_res, t_res;
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
+
scanner_handler->init(&sscanner, cs, s, slen);
scanner_handler->init(&tscanner, cs, t, tlen);
@@ -7113,7 +7119,7 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
return (s_res - t_res);
s_res= scanner_handler->next(&sscanner);
} while (s_res > 0);
- return 0;
+ return diff_if_only_endspace_difference ? 1 : 0;
}
if (s_res < 0 && t_res > 0)
@@ -7128,7 +7134,7 @@ static int my_strnncollsp_uca(CHARSET_INFO *cs,
return (s_res - t_res);
t_res= scanner_handler->next(&tscanner);
} while (t_res > 0);
- return 0;
+ return diff_if_only_endspace_difference ? -1 : 0;
}
return ( s_res - t_res );
@@ -7288,6 +7294,7 @@ int my_wildcmp_uca(CHARSET_INFO *cs,
{
while (1)
{
+ my_bool escaped= 0;
if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
(const uchar*)wildend)) <= 0)
return 1;
@@ -7305,6 +7312,7 @@ int my_wildcmp_uca(CHARSET_INFO *cs,
(const uchar*)wildend)) <= 0)
return 1;
wildstr+= scan;
+ escaped= 1;
}
if ((scan= mb_wc(cs, &s_wc, (const uchar*)str,
@@ -7312,7 +7320,7 @@ int my_wildcmp_uca(CHARSET_INFO *cs,
return 1;
str+= scan;
- if (w_wc == (my_wc_t)w_one)
+ if (!escaped && w_wc == (my_wc_t)w_one)
{
result= 1; /* Found an anchor char */
}
@@ -7939,11 +7947,13 @@ static int my_strnncoll_any_uca(CHARSET_INFO *cs,
}
static int my_strnncollsp_any_uca(CHARSET_INFO *cs,
- const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference)
{
return my_strnncollsp_uca(cs, &my_any_uca_scanner_handler,
- s, slen, t, tlen);
+ s, slen, t, tlen,
+ diff_if_only_endspace_difference);
}
static void my_hash_sort_any_uca(CHARSET_INFO *cs,
@@ -7976,11 +7986,13 @@ static int my_strnncoll_ucs2_uca(CHARSET_INFO *cs,
}
static int my_strnncollsp_ucs2_uca(CHARSET_INFO *cs,
- const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference)
{
return my_strnncollsp_uca(cs, &my_ucs2_uca_scanner_handler,
- s, slen, t, tlen);
+ s, slen, t, tlen,
+ diff_if_only_endspace_difference);
}
static void my_hash_sort_ucs2_uca(CHARSET_INFO *cs,
@@ -8567,7 +8579,7 @@ CHARSET_INFO my_charset_utf8_icelandic_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8594,7 +8606,7 @@ CHARSET_INFO my_charset_utf8_latvian_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8621,7 +8633,7 @@ CHARSET_INFO my_charset_utf8_romanian_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8648,7 +8660,7 @@ CHARSET_INFO my_charset_utf8_slovenian_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8675,7 +8687,7 @@ CHARSET_INFO my_charset_utf8_polish_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8702,7 +8714,7 @@ CHARSET_INFO my_charset_utf8_estonian_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8729,7 +8741,7 @@ CHARSET_INFO my_charset_utf8_spanish_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8756,7 +8768,7 @@ CHARSET_INFO my_charset_utf8_swedish_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8783,7 +8795,7 @@ CHARSET_INFO my_charset_utf8_turkish_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8810,7 +8822,7 @@ CHARSET_INFO my_charset_utf8_czech_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8838,7 +8850,7 @@ CHARSET_INFO my_charset_utf8_danish_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8865,7 +8877,7 @@ CHARSET_INFO my_charset_utf8_lithuanian_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8892,7 +8904,7 @@ CHARSET_INFO my_charset_utf8_slovak_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8919,7 +8931,7 @@ CHARSET_INFO my_charset_utf8_spanish2_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8946,7 +8958,7 @@ CHARSET_INFO my_charset_utf8_roman_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
@@ -8973,7 +8985,7 @@ CHARSET_INFO my_charset_utf8_persian_uca_ci=
NULL, /* ident_map */
8, /* strxfrm_multiply */
1, /* mbminlen */
- 2, /* mbmaxlen */
+ 3, /* mbmaxlen */
9, /* min_sort_char */
0xFFFF, /* max_sort_char */
&my_charset_utf8_handler,
diff --git a/strings/ctype-ucs2.c b/strings/ctype-ucs2.c
index 851c2044f47..d3fb16aa52e 100644
--- a/strings/ctype-ucs2.c
+++ b/strings/ctype-ucs2.c
@@ -137,6 +137,9 @@ static void my_hash_sort_ucs2(CHARSET_INFO *cs, const uchar *s, uint slen,
int res;
const uchar *e=s+slen;
+ while (e > s+1 && e[-1] == ' ' && e[-2] == '\0')
+ e-= 2;
+
while ((s < e) && (res=my_ucs2_uni(cs,&wc, (uchar *)s, (uchar*)e)) >0)
{
int plane = (wc>>8) & 0xFF;
@@ -218,11 +221,80 @@ static int my_strnncoll_ucs2(CHARSET_INFO *cs,
return t_is_prefix ? t-te : ((se-s) - (te-t));
}
-static int my_strnncollsp_ucs2(CHARSET_INFO *cs,
- const uchar *s, uint slen,
- const uchar *t, uint tlen)
+/*
+ Compare strings, discarding end space
+
+ SYNOPSIS
+ my_strnncollsp_ucs2()
+ cs character set handler
+ a First string to compare
+ a_length Length of 'a'
+ b Second string to compare
+ b_length Length of 'b'
+
+ IMPLEMENTATION
+ If one string is shorter as the other, then we space extend the other
+ so that the strings have equal length.
+
+ This will ensure that the following things hold:
+
+ "a" == "a "
+ "a\0" < "a"
+ "a\0" < "a "
+
+ RETURN
+ < 0 a < b
+ = 0 a == b
+ > 0 a > b
+*/
+
+static int my_strnncollsp_ucs2(CHARSET_INFO *cs __attribute__((unused)),
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference
+ __attribute__((unused)))
{
- return my_strnncoll_ucs2(cs,s,slen,t,tlen,0);
+ const uchar *se, *te;
+ uint minlen;
+
+ /* extra safety to make sure the lengths are even numbers */
+ slen&= ~1;
+ tlen&= ~1;
+
+ se= s + slen;
+ te= t + tlen;
+
+ for (minlen= min(slen, tlen); minlen; minlen-= 2)
+ {
+ int s_wc = uni_plane[s[0]] ? (int) uni_plane[s[0]][s[1]].sort :
+ (((int) s[0]) << 8) + (int) s[1];
+
+ int t_wc = uni_plane[t[0]] ? (int) uni_plane[t[0]][t[1]].sort :
+ (((int) t[0]) << 8) + (int) t[1];
+ if ( s_wc != t_wc )
+ return s_wc - t_wc;
+
+ s+= 2;
+ t+= 2;
+ }
+
+ if (slen != tlen)
+ {
+ int swap= 0;
+ if (slen < tlen)
+ {
+ s= t;
+ se= te;
+ swap= -1;
+ }
+
+ for ( ; s < se ; s+= 2)
+ {
+ if (s[0] || s[1] != ' ')
+ return (((int)s[0] << 8) + (int) s[1] - (int) ' ') ^ swap;
+ }
+ }
+ return 0;
}
@@ -1287,8 +1359,10 @@ int my_strnncoll_ucs2_bin(CHARSET_INFO *cs,
static int my_strnncollsp_ucs2_bin(CHARSET_INFO *cs,
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference)
{
+ /* TODO: Needs to be fixed to handle end space! */
return my_strnncoll_ucs2_bin(cs,s,slen,t,tlen,0);
}
@@ -1377,8 +1451,14 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
}
if (ptr[0] == '\0' && ptr[1] == w_many) /* '%' in SQL */
{
- *min_length= (uint) (min_str - min_org);
- *max_length=res_length;
+ /*
+ Calculate length of keys:
+ 'a\0\0... is the smallest possible string when we have space expand
+ a\ff\ff... is the biggest possible string
+ */
+ *min_length= ((cs->state & MY_CS_BINSORT) ? (uint) (min_str - min_org) :
+ res_length);
+ *max_length= res_length;
do {
*min_str++ = 0;
*min_str++ = 0;
@@ -1390,7 +1470,6 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
*min_str++= *max_str++ = ptr[0];
*min_str++= *max_str++ = ptr[1];
}
- *min_length= *max_length = (uint) (min_str - min_org);
/* Temporary fix for handling w_one at end of string (key compression) */
{
@@ -1402,14 +1481,16 @@ my_bool my_like_range_ucs2(CHARSET_INFO *cs,
}
}
+ *min_length= *max_length = (uint) (min_str - min_org);
while (min_str + 1 < min_end)
{
*min_str++ = *max_str++ = '\0';
- *min_str++ = *max_str++ = ' '; /* Because if key compression */
+ *min_str++ = *max_str++ = ' '; /* Because if key compression */
}
return 0;
}
+
static MY_COLLATION_HANDLER my_collation_ucs2_general_ci_handler =
{
NULL, /* init */
diff --git a/strings/ctype-utf8.c b/strings/ctype-utf8.c
index b3097649158..ab646d36e25 100644
--- a/strings/ctype-utf8.c
+++ b/strings/ctype-utf8.c
@@ -1545,31 +1545,33 @@ int my_wildcmp_unicode(CHARSET_INFO *cs,
{
while (1)
{
+ my_bool escaped= 0;
if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
(const uchar*)wildend)) <= 0)
return 1;
-
- if (w_wc == (my_wc_t)escape)
- {
- wildstr+= scan;
- if ((scan= mb_wc(cs,&w_wc, (const uchar*)wildstr,
- (const uchar*)wildend)) <= 0)
- return 1;
- }
-
+
if (w_wc == (my_wc_t)w_many)
{
result= 1; /* Found an anchor char */
break;
}
-
+
wildstr+= scan;
+ if (w_wc == (my_wc_t)escape)
+ {
+ if ((scan= mb_wc(cs, &w_wc, (const uchar*)wildstr,
+ (const uchar*)wildend)) <= 0)
+ return 1;
+ wildstr+= scan;
+ escaped= 1;
+ }
+
if ((scan= mb_wc(cs, &s_wc, (const uchar*)str,
- (const uchar*)str_end)) <=0)
+ (const uchar*)str_end)) <= 0)
return 1;
str+= scan;
- if (w_wc == (my_wc_t)w_one)
+ if (!escaped && w_wc == (my_wc_t)w_one)
{
result= 1; /* Found an anchor char */
}
@@ -1921,12 +1923,20 @@ static void my_caseup_utf8(CHARSET_INFO *cs, char *s, uint slen)
}
}
-static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen, ulong *n1, ulong *n2)
+static void my_hash_sort_utf8(CHARSET_INFO *cs, const uchar *s, uint slen,
+ ulong *n1, ulong *n2)
{
my_wc_t wc;
int res;
const uchar *e=s+slen;
+ /*
+ Remove end space. We have to do this to be able to compare
+ 'A ' and 'A' as identical
+ */
+ while (e > s && e[-1] == ' ')
+ e--;
+
while ((s < e) && (res=my_utf8_uni(cs,&wc, (uchar *)s, (uchar*)e))>0 )
{
int plane = (wc>>8) & 0xFF;
@@ -2019,6 +2029,9 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
a_length Length of 'a'
b Second string to compare
b_length Length of 'b'
+ diff_if_only_endspace_difference
+ Set to 1 if the strings should be regarded as different
+ if they only difference in end space
IMPLEMENTATION
If one string is shorter as the other, then we space extend the other
@@ -2037,13 +2050,17 @@ static int my_strnncoll_utf8(CHARSET_INFO *cs,
*/
static int my_strnncollsp_utf8(CHARSET_INFO *cs,
- const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *s, uint slen,
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference)
{
- int s_res,t_res;
+ int s_res, t_res, res;
my_wc_t s_wc,t_wc;
- const uchar *se= s+slen;
- const uchar *te= t+tlen;
+ const uchar *se= s+slen, *te= t+tlen;
+
+#ifndef VARCHAR_WITH_DIFF_ENDSPACE_ARE_DIFFERENT_FOR_UNIQUE
+ diff_if_only_endspace_difference= 0;
+#endif
while ( s < se && t < te )
{
@@ -2072,16 +2089,20 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
slen= se-s;
tlen= te-t;
+ res= 0;
if (slen != tlen)
{
int swap= 0;
+ if (diff_if_only_endspace_difference)
+ res= 1; /* Assume 'a' is bigger */
if (slen < tlen)
{
slen= tlen;
s= t;
se= te;
swap= -1;
+ res= -res;
}
/*
This following loop uses the fact that in UTF-8
@@ -2099,7 +2120,7 @@ static int my_strnncollsp_utf8(CHARSET_INFO *cs,
return ((int)*s - (int) ' ') ^ swap;
}
}
- return 0;
+ return res;
}
diff --git a/strings/ctype-win1250ch.c b/strings/ctype-win1250ch.c
index b4dbda3e8ed..896aef775cf 100644
--- a/strings/ctype-win1250ch.c
+++ b/strings/ctype-win1250ch.c
@@ -479,7 +479,8 @@ static int my_strnncoll_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
static
int my_strnncollsp_win1250ch(CHARSET_INFO * cs,
const uchar *s, uint slen,
- const uchar *t, uint tlen)
+ const uchar *t, uint tlen,
+ my_bool diff_if_only_endspace_difference)
{
for ( ; slen && s[slen-1] == ' ' ; slen--);
for ( ; tlen && t[tlen-1] == ' ' ; tlen--);
@@ -594,11 +595,19 @@ my_like_range_win1250ch(CHARSET_INFO *cs __attribute__((unused)),
if (*min_str != min_sort_char)
only_min_found= 0;
min_str++;
- *max_str++ = like_range_prefix_max_win1250ch[(uint)(*ptr)];
+ *max_str++= like_range_prefix_max_win1250ch[(uint)(*ptr)];
}
- *min_length = (uint) (min_str - min_org);
- *max_length = res_length;
+ if (cs->state & MY_CS_BINSORT)
+ *min_length= (uint) (min_str - min_org);
+ else
+ {
+ /* 'a\0\0... is the smallest possible string */
+ *min_length= res_length;
+ }
+ /* a\ff\ff... is the biggest possible string */
+ *max_length= res_length;
+
while (min_str != min_end)
{
*min_str++ = min_sort_char;
@@ -624,12 +633,12 @@ static MY_COLLATION_HANDLER my_collation_czech_ci_handler =
CHARSET_INFO my_charset_cp1250_czech_ci =
{
- 34,0,0, /* number */
- MY_CS_COMPILED|MY_CS_STRNXFRM, /* state */
- "cp1250", /* cs name */
- "cp1250_czech_cs", /* name */
- "", /* comment */
- NULL, /* tailoring */
+ 34,0,0, /* number */
+ MY_CS_COMPILED|MY_CS_STRNXFRM|MY_CS_CSSORT, /* state */
+ "cp1250", /* cs name */
+ "cp1250_czech_cs", /* name */
+ "", /* comment */
+ NULL, /* tailoring */
ctype_win1250ch,
to_lower_win1250ch,
to_upper_win1250ch,
diff --git a/strings/decimal.c b/strings/decimal.c
index c34f570eec3..c691bcb62fc 100644
--- a/strings/decimal.c
+++ b/strings/decimal.c
@@ -98,10 +98,12 @@
implementation-defined.
*/
-#include <decimal.h>
+#include <my_global.h>
#include <m_ctype.h>
#include <myisampack.h>
#include <my_sys.h> /* for my_alloca */
+#include <m_string.h>
+#include <decimal.h>
typedef decimal_digit dec1;
typedef longlong dec2;
@@ -206,7 +208,7 @@ int decimal2string(decimal *from, char *to, int *to_len)
char *s=to;
dec1 *buf, *buf0=from->buf, tmp;
- DBUG_ASSERT(*to_len > 2+from->sign);
+ DBUG_ASSERT(*to_len >= 2+from->sign);
/* removing leading zeroes */
i=((intg-1) % DIG_PER_DEC1)+1;
@@ -308,7 +310,7 @@ static int str2dec(char *from, decimal *to, char **end, my_bool fixed)
char *s=from, *s1;
int i, intg, frac, error, intg1, frac1;
dec1 x,*buf;
-
+ LINT_INIT(error);
sanity(to);
while (my_isspace(&my_charset_latin1, *s))
@@ -366,6 +368,7 @@ static int str2dec(char *from, decimal *to, char **end, my_bool fixed)
intg=intg1*DIG_PER_DEC1;
}
}
+ /* Error is guranteed to be set here */
to->intg=intg;
to->frac=frac;
@@ -503,7 +506,7 @@ int decimal2ulonglong(decimal *from, ulonglong *to)
{
dec1 *buf=from->buf;
ulonglong x=0;
- int intg;
+ int intg, frac;
if (from->sign)
{
@@ -515,21 +518,24 @@ int decimal2ulonglong(decimal *from, ulonglong *to)
{
ulonglong y=x;
x=x*DIG_BASE + *buf++;
- if (unlikely(x < y))
+ if (unlikely(y > (ULONGLONG_MAX/DIG_BASE) || x < y))
{
*to=y;
return E_DEC_OVERFLOW;
}
}
*to=x;
- return from->frac ? E_DEC_TRUNCATED : E_DEC_OK;
+ for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
+ if (*buf++)
+ return E_DEC_TRUNCATED;
+ return E_DEC_OK;
}
int decimal2longlong(decimal *from, longlong *to)
{
dec1 *buf=from->buf;
longlong x=0;
- int intg;
+ int intg, frac;
for (intg=from->intg; intg > 0; intg-=DIG_PER_DEC1)
{
@@ -537,11 +543,11 @@ int decimal2longlong(decimal *from, longlong *to)
/*
Attention: trick!
we're calculating -|from| instead of |from| here
- because |MIN_LONGLONG| > MAX_LONGLONG
+ because |LONGLONG_MIN| > LONGLONG_MAX
so we can convert -9223372036854775808 correctly
*/
x=x*DIG_BASE - *buf++;
- if (unlikely(x > y))
+ if (unlikely(y < (LONGLONG_MIN/DIG_BASE) || x > y))
{
*to= from->sign ? y : -y;
return E_DEC_OVERFLOW;
@@ -555,7 +561,10 @@ int decimal2longlong(decimal *from, longlong *to)
}
*to=from->sign ? x : -x;
- return from->frac ? E_DEC_TRUNCATED : E_DEC_OK;
+ for (frac=from->frac; unlikely(frac > 0); frac-=DIG_PER_DEC1)
+ if (*buf++)
+ return E_DEC_TRUNCATED;
+ return E_DEC_OK;
}
/*
@@ -579,7 +588,7 @@ int decimal2bin(decimal *from, char *to, int precision, int frac)
{
dec1 mask=from->sign ? -1 : 0, *buf1=from->buf, *stop1;
int error=E_DEC_OK, intg=precision-frac,
- isize1, intg1, intg1x=from->intg,
+ isize1, intg1, intg1x, from_intg=from->intg,
intg0=intg/DIG_PER_DEC1,
frac0=frac/DIG_PER_DEC1,
intg0x=intg-intg0*DIG_PER_DEC1,
@@ -591,33 +600,33 @@ int decimal2bin(decimal *from, char *to, int precision, int frac)
fsize1=frac1*sizeof(dec1)+dig2bytes[frac1x];
/* removing leading zeroes */
- intg1=((intg1x-1) % DIG_PER_DEC1)+1;
- while (intg1x > 0 && *buf1 == 0)
+ intg1=((from_intg-1) % DIG_PER_DEC1)+1;
+ while (from_intg > 0 && *buf1 == 0)
{
- intg1x-=intg1;
+ from_intg-=intg1;
intg1=DIG_PER_DEC1;
buf1++;
}
- if (intg1x > 0)
+ if (from_intg > 0)
{
- for (intg1=(intg1x-1) % DIG_PER_DEC1; *buf1 < powers10[intg1--]; intg1x--) ;
- DBUG_ASSERT(intg1x > 0);
+ for (intg1=(from_intg-1) % DIG_PER_DEC1; *buf1 < powers10[intg1--]; from_intg--) ;
+ DBUG_ASSERT(from_intg > 0);
}
else
- intg1x=0;
+ from_intg=0;
- if (unlikely(intg1x+fsize1==0))
+ if (unlikely(from_intg+fsize1==0))
{
mask=0; /* just in case */
intg=1;
buf1=&mask;
}
- intg1=intg1x/DIG_PER_DEC1;
- intg1x=intg1x-intg1*DIG_PER_DEC1;
+ intg1=from_intg/DIG_PER_DEC1;
+ intg1x=from_intg-intg1*DIG_PER_DEC1;
isize1=intg1*sizeof(dec1)+dig2bytes[intg1x];
- if (isize0 < isize1)
+ if (intg < from_intg)
{
buf1+=intg1-intg0+(intg1x>0)-(intg0x>0);
intg1=intg0; intg1x=intg0x;
@@ -867,7 +876,7 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode
error=E_DEC_TRUNCATED;
}
- if (scale+from->intg <=0)
+ if (scale+from->intg < 0)
{
decimal_make_zero(to);
return E_DEC_OK;
@@ -881,7 +890,7 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode
buf0=from->buf;
buf1=to->buf;
to->sign=from->sign;
- to->intg=min(from->intg, len*DIG_PER_DEC1);
+ to->intg=min(intg0, len)*DIG_PER_DEC1;
}
if (frac0 > frac1)
@@ -895,19 +904,26 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode
if (scale >= from->frac)
goto done; /* nothing to do */
- DBUG_ASSERT(frac0+intg0 > 0);
buf0+=intg0+frac0-1;
buf1+=intg0+frac0-1;
if (scale == frac0*DIG_PER_DEC1)
{
+ DBUG_ASSERT(frac0+intg0 >= 0);
x=buf0[1]/DIG_MASK;
if (x > round_digit ||
- (round_digit == 5 && x == 5 && (mode == HALF_UP || *buf0 & 1)))
- (*buf1)++;
+ (round_digit == 5 && x == 5 && (mode == HALF_UP ||
+ (frac0+intg0 > 0 && *buf0 & 1))))
+ {
+ if (frac0+intg0>0)
+ (*buf1)++;
+ else
+ *(++buf1)=DIG_BASE;
+ }
}
else
{
int pos=frac0*DIG_PER_DEC1-scale-1;
+ DBUG_ASSERT(frac0+intg0 > 0);
x=*buf1 / powers10[pos];
y=x % 10;
if (y > round_digit ||
@@ -915,6 +931,12 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode
x+=10;
*buf1=powers10[pos]*(x-y);
}
+ if (frac0 < 0)
+ {
+ dec1 *end=to->buf+intg0, *buf=buf1+1;
+ while (buf < end)
+ *buf++=0;
+ }
if (*buf1 >= DIG_BASE)
{
carry=1;
@@ -930,11 +952,22 @@ int decimal_round(decimal *from, decimal *to, int scale, decimal_round_mode mode
scale=frac0*DIG_PER_DEC1;
error=E_DEC_TRUNCATED; /* XXX */
}
- for (buf1=to->buf+frac0+intg0; buf1 > to->buf; buf1--)
+ for (buf1=to->buf+intg0+max(frac0,0); buf1 > to->buf; buf1--)
{
buf1[0]=buf1[-1];
}
*buf1=1;
+ to->intg++;
+ }
+ }
+ else
+ {
+ while (unlikely(*buf1 == 0) && buf1 >= to->buf)
+ buf1--;
+ if (buf1 < to->buf)
+ {
+ decimal_make_zero(to);
+ return E_DEC_OK;
}
}
if (scale<0) scale=0;
@@ -1150,6 +1183,8 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to)
buf1=start1+intg1+frac1;
stop1=start1+intg1+frac2;
buf2=start2+intg2+frac2;
+ while (frac0-- > frac1)
+ *--buf0=0;
while (buf1 > stop1)
*--buf0=*--buf1;
}
@@ -1158,6 +1193,8 @@ static int do_sub(decimal *from1, decimal *from2, decimal *to)
buf1=start1+intg1+frac1;
buf2=start2+intg2+frac2;
stop2=start2+intg2+frac1;
+ while (frac0-- > frac2)
+ *--buf0=0;
while (buf2 > stop2)
{
SUB(*--buf0, 0, *--buf2, carry);
@@ -1206,6 +1243,16 @@ int decimal_cmp(decimal *from1, decimal *from2)
return from1->sign > from2->sign ? -1 : 1;
}
+int decimal_is_zero(decimal *from)
+{
+ dec1 *buf1=from->buf,
+ *end=buf1+ROUND_UP(from->intg)+ROUND_UP(from->frac);
+ while (buf1 < end)
+ if (*buf1++)
+ return 0;
+ return 1;
+}
+
/*
multiply two decimals
@@ -1305,11 +1352,13 @@ static int do_div_mod(decimal *from1, decimal *from2,
{
int frac1=ROUND_UP(from1->frac)*DIG_PER_DEC1, prec1=from1->intg+frac1,
frac2=ROUND_UP(from2->frac)*DIG_PER_DEC1, prec2=from2->intg+frac2,
- error, i, intg0, frac0, len1, len2, dlen1, dintg;
+ error, i, intg0, frac0, len1, len2, dlen1, dintg, div=(!mod);
dec1 *buf0, *buf1=from1->buf, *buf2=from2->buf, *tmp1,
*start2, *stop2, *stop1, *stop0, norm2, carry, *start1;
dec2 norm_factor, x, guess, y;
+ LINT_INIT(error);
+
if (mod)
to=mod;
@@ -1387,8 +1436,9 @@ static int do_div_mod(decimal *from1, decimal *from2,
}
buf0=to->buf;
stop0=buf0+intg0+frac0;
- while (dintg++ < 0)
- *buf0++=0;
+ if (likely(div))
+ while (dintg++ < 0)
+ *buf0++=0;
len1=(i=ROUND_UP(prec1))+ROUND_UP(2*frac2+scale_incr+1);
set_if_bigger(len1, 3);
@@ -1427,7 +1477,8 @@ static int do_div_mod(decimal *from1, decimal *from2,
if (unlikely(*start1 == 0))
{
start1++;
- *buf0=0;
+ if (likely(div))
+ *buf0=0;
continue;
}
@@ -1493,7 +1544,8 @@ static int do_div_mod(decimal *from1, decimal *from2,
}
DBUG_ASSERT(carry==1);
}
- *buf0=(dec1)guess;
+ if (likely(div))
+ *buf0=(dec1)guess;
if (*start1 == 0)
start1++;
}
@@ -1508,6 +1560,11 @@ static int do_div_mod(decimal *from1, decimal *from2,
intg0=ROUND_UP(prec1-frac1)-(start1-tmp1);
frac0=ROUND_UP(to->frac);
error=E_DEC_OK;
+ if (unlikely(frac0==0 && intg0==0))
+ {
+ decimal_make_zero(to);
+ goto done;
+ }
if (intg0<=0)
{
if (unlikely(-intg0 >= to->len))
@@ -1618,7 +1675,7 @@ void dump_decimal(decimal *d)
printf("%09d} */ ", d->buf[i]);
}
-void print_decimal(decimal *d)
+void print_decimal(decimal *d, char *orig)
{
char s[100];
int slen=sizeof(s);
@@ -1626,6 +1683,11 @@ void print_decimal(decimal *d)
if (full) dump_decimal(d);
decimal2string(d, s, &slen);
printf("'%s'", s);
+ if (orig && strcmp(orig, s))
+ {
+ printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
+ exit(1);
+ }
}
void test_d2s()
@@ -1664,12 +1726,12 @@ void test_d2s()
dump_decimal(&a); printf(" --> res=%d str='%s' len=%d\n", res, s, slen);
}
-void test_s2d(char *s)
+void test_s2d(char *s, char *orig)
{
char s1[100];
sprintf(s1, "'%s'", s);
printf("len=%2d %-30s => res=%d ", a.len, s1, string2decimal(s, &a, 0));
- print_decimal(&a);
+ print_decimal(&a, orig);
printf("\n");
}
@@ -1686,7 +1748,7 @@ void test_d2f(char *s)
printf("%-40s => res=%d %.*g\n", s1, res, a.intg+a.frac, x);
}
-void test_d2b2d(char *str, int p, int s)
+void test_d2b2d(char *str, int p, int s, char *orig)
{
char s1[100], buf[100];
double x;
@@ -1704,7 +1766,7 @@ void test_d2b2d(char *str, int p, int s)
}
res=bin2decimal(buf, &a, p, s);
printf(" => res=%d ", res);
- print_decimal(&a);
+ print_decimal(&a, orig);
printf("\n");
}
void test_f2d(double from)
@@ -1713,11 +1775,11 @@ void test_f2d(double from)
res=double2decimal(from, &a);
printf("%-40.*f => res=%d ", DBL_DIG-2, from, res);
- print_decimal(&a);
+ print_decimal(&a, 0);
printf("\n");
}
-void test_ull2d(ulonglong from)
+void test_ull2d(ulonglong from, char *orig)
{
char s[100];
int res;
@@ -1725,11 +1787,11 @@ void test_ull2d(ulonglong from)
res=ulonglong2decimal(from, &a);
longlong10_to_str(from,s,10);
printf("%-40s => res=%d ", s, res);
- print_decimal(&a);
+ print_decimal(&a, orig);
printf("\n");
}
-void test_ll2d(longlong from)
+void test_ll2d(longlong from, char *orig)
{
char s[100];
int res;
@@ -1737,11 +1799,11 @@ void test_ll2d(longlong from)
res=longlong2decimal(from, &a);
longlong10_to_str(from,s,-10);
printf("%-40s => res=%d ", s, res);
- print_decimal(&a);
+ print_decimal(&a, orig);
printf("\n");
}
-void test_d2ull(char *s)
+void test_d2ull(char *s, char *orig)
{
char s1[100];
ulonglong x;
@@ -1752,9 +1814,14 @@ void test_d2ull(char *s)
if (full) dump_decimal(&a);
longlong10_to_str(x,s1,10);
printf("%-40s => res=%d %s\n", s, res, s1);
+ if (orig && strcmp(orig, s1))
+ {
+ printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
+ exit(1);
+ }
}
-void test_d2ll(char *s)
+void test_d2ll(char *s, char *orig)
{
char s1[100];
longlong x;
@@ -1765,9 +1832,14 @@ void test_d2ll(char *s)
if (full) dump_decimal(&a);
longlong10_to_str(x,s1,-10);
printf("%-40s => res=%d %s\n", s, res, s1);
+ if (orig && strcmp(orig, s1))
+ {
+ printf("\n^^^^^^^^^^^^^ must've been '%s'\n", orig);
+ exit(1);
+ }
}
-void test_da(char *s1, char *s2)
+void test_da(char *s1, char *s2, char *orig)
{
char s[100];
int res;
@@ -1776,11 +1848,11 @@ void test_da(char *s1, char *s2)
string2decimal(s2, &b, 0);
res=decimal_add(&a, &b, &c);
printf("%-40s => res=%d ", s, res);
- print_decimal(&c);
+ print_decimal(&c, orig);
printf("\n");
}
-void test_ds(char *s1, char *s2)
+void test_ds(char *s1, char *s2, char *orig)
{
char s[100];
int res;
@@ -1789,11 +1861,11 @@ void test_ds(char *s1, char *s2)
string2decimal(s2, &b, 0);
res=decimal_sub(&a, &b, &c);
printf("%-40s => res=%d ", s, res);
- print_decimal(&c);
+ print_decimal(&c, orig);
printf("\n");
}
-void test_dc(char *s1, char *s2)
+void test_dc(char *s1, char *s2, int orig)
{
char s[100];
int res;
@@ -1802,9 +1874,14 @@ void test_dc(char *s1, char *s2)
string2decimal(s2, &b, 0);
res=decimal_cmp(&a, &b);
printf("%-40s => res=%d\n", s, res);
+ if (orig != res)
+ {
+ printf("\n^^^^^^^^^^^^^ must've been %d\n", orig);
+ exit(1);
+ }
}
-void test_dm(char *s1, char *s2)
+void test_dm(char *s1, char *s2, char *orig)
{
char s[100];
int res;
@@ -1813,11 +1890,11 @@ void test_dm(char *s1, char *s2)
string2decimal(s2, &b, 0);
res=decimal_mul(&a, &b, &c);
printf("%-40s => res=%d ", s, res);
- print_decimal(&c);
+ print_decimal(&c, orig);
printf("\n");
}
-void test_dv(char *s1, char *s2)
+void test_dv(char *s1, char *s2, char *orig)
{
char s[100];
int res;
@@ -1829,11 +1906,11 @@ void test_dv(char *s1, char *s2)
if (res == E_DEC_DIV_ZERO)
printf("E_DEC_DIV_ZERO");
else
- print_decimal(&c);
+ print_decimal(&c, orig);
printf("\n");
}
-void test_md(char *s1, char *s2)
+void test_md(char *s1, char *s2, char *orig)
{
char s[100];
int res;
@@ -1845,13 +1922,13 @@ void test_md(char *s1, char *s2)
if (res == E_DEC_DIV_ZERO)
printf("E_DEC_DIV_ZERO");
else
- print_decimal(&c);
+ print_decimal(&c, orig);
printf("\n");
}
char *round_mode[]={"TRUNCATE", "HALF_EVEN", "HALF_UP", "CEILING", "FLOOR"};
-void test_ro(char *s1, int n, decimal_round_mode mode)
+void test_ro(char *s1, int n, decimal_round_mode mode, char *orig)
{
char s[100];
int res;
@@ -1859,7 +1936,7 @@ void test_ro(char *s1, int n, decimal_round_mode mode)
string2decimal(s1, &a, 0);
res=decimal_round(&a, &b, n, mode);
printf("%-40s => res=%d ", s, res);
- print_decimal(&b);
+ print_decimal(&b, orig);
printf("\n");
}
@@ -1876,17 +1953,17 @@ main()
test_d2s();
printf("==== string2decimal ====\n");
- test_s2d("12345");
- test_s2d("12345.");
- test_s2d("123.45");
- test_s2d("-123.45");
- test_s2d(".00012345000098765");
- test_s2d(".12345000098765");
- test_s2d("-.000000012345000098765");
- test_s2d("1234500009876.5");
+ test_s2d("12345", "12345");
+ test_s2d("12345.", "12345");
+ test_s2d("123.45", "123.45");
+ test_s2d("-123.45", "-123.45");
+ test_s2d(".00012345000098765", ".00012345000098765");
+ test_s2d(".12345000098765", ".12345000098765");
+ test_s2d("-.000000012345000098765", "-.000000012345000098765");
+ test_s2d("1234500009876.5", "1234500009876.5");
a.len=1;
- test_s2d("123450000098765");
- test_s2d("123450.000098765");
+ test_s2d("123450000098765", "98765");
+ test_s2d("123450.000098765", "123450");
a.len=sizeof(buf1)/sizeof(dec1);
printf("==== decimal2double ====\n");
@@ -1904,147 +1981,163 @@ main()
test_f2d(1234500009876.5);
printf("==== ulonglong2decimal ====\n");
- test_ull2d(ULL(12345));
- test_ull2d(ULL(0));
- test_ull2d(ULL(18446744073709551615));
+ test_ull2d(ULL(12345), "12345");
+ test_ull2d(ULL(0), "0");
+ test_ull2d(ULL(18446744073709551615), "18446744073709551615");
printf("==== decimal2ulonglong ====\n");
- test_d2ull("12345");
- test_d2ull("0");
- test_d2ull("18446744073709551615");
- test_d2ull("18446744073709551616");
- test_d2ull("-1");
- test_d2ull("1.23");
+ test_d2ull("12345", "12345");
+ test_d2ull("0", "0");
+ test_d2ull("18446744073709551615", "18446744073709551615");
+ test_d2ull("18446744073709551616", "18446744073");
+ test_d2ull("-1", "0");
+ test_d2ull("1.23", "1");
+ test_d2ull("9999999999999999999999999.000", "9999999999999999");
printf("==== longlong2decimal ====\n");
- test_ll2d(LL(-12345));
- test_ll2d(LL(-1));
- test_ll2d(LL(-9223372036854775807));
- test_ll2d(ULL(9223372036854775808));
+ test_ll2d(LL(-12345), "-12345");
+ test_ll2d(LL(-1), "-1");
+ test_ll2d(LL(-9223372036854775807), "-9223372036854775807");
+ test_ll2d(ULL(9223372036854775808), "-9223372036854775808");
printf("==== decimal2longlong ====\n");
- test_d2ll("18446744073709551615");
- test_d2ll("-1");
- test_d2ll("-1.23");
- test_d2ll("-9223372036854775807");
- test_d2ll("-9223372036854775808");
- test_d2ll("9223372036854775808");
+ test_d2ll("18446744073709551615", "18446744073");
+ test_d2ll("-1", "-1");
+ test_d2ll("-1.23", "-1");
+ test_d2ll("-9223372036854775807", "-9223372036854775807");
+ test_d2ll("-9223372036854775808", "-9223372036854775808");
+ test_d2ll("9223372036854775808", "9223372036854775807");
printf("==== do_add ====\n");
- test_da(".00012345000098765" ,"123.45");
- test_da(".1" ,".45");
- test_da("1234500009876.5" ,".00012345000098765");
- test_da("9999909999999.5" ,".555");
- test_da("99999999" ,"1");
- test_da("989999999" ,"1");
- test_da("999999999" ,"1");
- test_da("12345" ,"123.45");
- test_da("-12345" ,"-123.45");
- test_ds("-12345" ,"123.45");
- test_ds("12345" ,"-123.45");
+ test_da(".00012345000098765" ,"123.45", "123.45012345000098765");
+ test_da(".1" ,".45", ".55");
+ test_da("1234500009876.5" ,".00012345000098765", "1234500009876.50012345000098765");
+ test_da("9999909999999.5" ,".555", "9999910000000.055");
+ test_da("99999999" ,"1", "100000000");
+ test_da("989999999" ,"1", "990000000");
+ test_da("999999999" ,"1", "1000000000");
+ test_da("12345" ,"123.45", "12468.45");
+ test_da("-12345" ,"-123.45", "-12468.45");
+ test_ds("-12345" ,"123.45", "-12468.45");
+ test_ds("12345" ,"-123.45", "12468.45");
printf("==== do_sub ====\n");
- test_ds(".00012345000098765", "123.45");
- test_ds("1234500009876.5", ".00012345000098765");
- test_ds("9999900000000.5", ".555");
- test_ds("1111.5551", "1111.555");
- test_ds(".555", ".555");
- test_ds("10000000", "1");
- test_ds("1000001000", ".1");
- test_ds("1000000000", ".1");
- test_ds("12345", "123.45");
- test_ds("-12345", "-123.45");
- test_da("-12345", "123.45");
- test_da("12345", "-123.45");
- test_ds("123.45", "12345");
- test_ds("-123.45", "-12345");
- test_da("123.45", "-12345");
- test_da("-123.45", "12345");
+ test_ds(".00012345000098765", "123.45","-123.44987654999901235");
+ test_ds("1234500009876.5", ".00012345000098765","1234500009876.49987654999901235");
+ test_ds("9999900000000.5", ".555","9999899999999.945");
+ test_ds("1111.5551", "1111.555",".0001");
+ test_ds(".555", ".555","0");
+ test_ds("10000000", "1","9999999");
+ test_ds("1000001000", ".1","1000000999.9");
+ test_ds("1000000000", ".1","999999999.9");
+ test_ds("12345", "123.45","12221.55");
+ test_ds("-12345", "-123.45","-12221.55");
+ test_da("-12345", "123.45","-12221.55");
+ test_da("12345", "-123.45","12221.55");
+ test_ds("123.45", "12345","-12221.55");
+ test_ds("-123.45", "-12345","12221.55");
+ test_da("123.45", "-12345","-12221.55");
+ test_da("-123.45", "12345","12221.55");
+ test_da("5", "-6.0","-1.0");
printf("==== decimal_mul ====\n");
- test_dm("12", "10");
- test_dm("-123.456", "98765.4321");
- test_dm("-123456000000", "98765432100000");
- test_dm("123456", "987654321");
- test_dm("123456", "9876543210");
- test_dm("123", "0.01");
- test_dm("123", "0");
+ test_dm("12", "10","120");
+ test_dm("-123.456", "98765.4321","-12193185.1853376");
+ test_dm("-123456000000", "98765432100000","-12193185185337600000000000");
+ test_dm("123456", "987654321","121931851853376");
+ test_dm("123456", "9876543210","1219318518533760");
+ test_dm("123", "0.01","1.23");
+ test_dm("123", "0","0");
printf("==== decimal_div ====\n");
- test_dv("120", "10");
- test_dv("123", "0.01");
- test_dv("120", "100000000000.00000");
- test_dv("123", "0");
- test_dv("-12193185.1853376", "98765.4321");
- test_dv("121931851853376", "987654321");
- test_dv("0", "987");
- test_dv("1", "3");
- test_dv("1.000000000000", "3");
- test_dv("1", "1");
- test_dv("0.0123456789012345678912345", "9999999999");
+ test_dv("120", "10","12.000000000");
+ test_dv("123", "0.01","12300.000000000");
+ test_dv("120", "100000000000.00000",".000000001200000000");
+ test_dv("123", "0","");
+ test_dv("-12193185.1853376", "98765.4321","-123.456000000000000000");
+ test_dv("121931851853376", "987654321","123456.000000000");
+ test_dv("0", "987","0");
+ test_dv("1", "3",".333333333");
+ test_dv("1.000000000000", "3",".333333333333333333");
+ test_dv("1", "1","1.000000000");
+ test_dv("0.0123456789012345678912345", "9999999999",".000000000001234567890246913578148141");
printf("==== decimal_mod ====\n");
- test_md("234","10");
- test_md("234.567","10.555");
- test_md("-234.567","10.555");
- test_md("234.567","-10.555");
+ test_md("234","10","4");
+ test_md("234.567","10.555","2.357");
+ test_md("-234.567","10.555","-2.357");
+ test_md("234.567","-10.555","2.357");
+ if (full)
+ {
+ c.buf[1]=0x3ABECA;
+ test_md("99999999999999999999999999999999999999","3","0");
+ printf("%X\n", c.buf[1]);
+ }
printf("==== decimal2bin/bin2decimal ====\n");
- test_d2b2d("-10.55", 4, 2);
- test_d2b2d("0.0123456789012345678912345", 30, 25);
- test_d2b2d("12345", 5, 0);
- test_d2b2d("12345", 10, 3);
- test_d2b2d("123.45", 10, 3);
- test_d2b2d("-123.45", 20, 10);
- test_d2b2d(".00012345000098765", 15, 14);
- test_d2b2d(".00012345000098765", 22, 20);
- test_d2b2d(".12345000098765", 30, 20);
- test_d2b2d("-.000000012345000098765", 30, 20);
- test_d2b2d("1234500009876.5", 30, 5);
+ test_d2b2d("-10.55", 4, 2,"-10.55");
+ test_d2b2d("0.0123456789012345678912345", 30, 25,".0123456789012345678912345");
+ test_d2b2d("12345", 5, 0,"12345");
+ test_d2b2d("12345", 10, 3,"12345.000");
+ test_d2b2d("123.45", 10, 3,"123.450");
+ test_d2b2d("-123.45", 20, 10,"-123.4500000000");
+ test_d2b2d(".00012345000098765", 15, 14,".00012345000098");
+ test_d2b2d(".00012345000098765", 22, 20,".00012345000098765000");
+ test_d2b2d(".12345000098765", 30, 20,".12345000098765000000");
+ test_d2b2d("-.000000012345000098765", 30, 20,"-.00000001234500009876");
+ test_d2b2d("1234500009876.5", 30, 5,"1234500009876.50000");
+ test_d2b2d("111111111.11", 10, 2,"11111111.11");
printf("==== decimal_cmp ====\n");
- test_dc("12","13");
- test_dc("13","12");
- test_dc("-10","10");
- test_dc("10","-10");
- test_dc("-12","-13");
- test_dc("0","12");
- test_dc("-10","0");
- test_dc("4","4");
+ test_dc("12","13",-1);
+ test_dc("13","12",1);
+ test_dc("-10","10",-1);
+ test_dc("10","-10",1);
+ test_dc("-12","-13",1);
+ test_dc("0","12",-1);
+ test_dc("-10","0",-1);
+ test_dc("4","4",0);
printf("==== decimal_round ====\n");
- test_ro("5678.123451",-4,TRUNCATE);
- test_ro("5678.123451",-3,TRUNCATE);
- test_ro("5678.123451",-2,TRUNCATE);
- test_ro("5678.123451",-1,TRUNCATE);
- test_ro("5678.123451",0,TRUNCATE);
- test_ro("5678.123451",1,TRUNCATE);
- test_ro("5678.123451",2,TRUNCATE);
- test_ro("5678.123451",3,TRUNCATE);
- test_ro("5678.123451",4,TRUNCATE);
- test_ro("5678.123451",5,TRUNCATE);
- test_ro("5678.123451",6,TRUNCATE);
- test_ro("-5678.123451",-4,TRUNCATE);
- test_ro("99999999999999999999999999999999999999",-31,TRUNCATE);
- test_ro("15.1",0,HALF_UP);
- test_ro("15.5",0,HALF_UP);
- test_ro("15.9",0,HALF_UP);
- test_ro("-15.1",0,HALF_UP);
- test_ro("-15.5",0,HALF_UP);
- test_ro("-15.9",0,HALF_UP);
- test_ro("15.1",1,HALF_UP);
- test_ro("-15.1",1,HALF_UP);
- test_ro("15.17",1,HALF_UP);
- test_ro("15.4",-1,HALF_UP);
- test_ro("-15.4",-1,HALF_UP);
- test_ro("15.1",0,HALF_EVEN);
- test_ro("15.5",0,HALF_EVEN);
- test_ro("14.5",0,HALF_EVEN);
- test_ro("15.9",0,HALF_EVEN);
- test_ro("15.1",0,CEILING);
- test_ro("-15.1",0,CEILING);
- test_ro("15.1",0,FLOOR);
- test_ro("-15.1",0,FLOOR);
+ test_ro("5678.123451",-4,TRUNCATE,"0");
+ test_ro("5678.123451",-3,TRUNCATE,"5000");
+ test_ro("5678.123451",-2,TRUNCATE,"5600");
+ test_ro("5678.123451",-1,TRUNCATE,"5670");
+ test_ro("5678.123451",0,TRUNCATE,"5678");
+ test_ro("5678.123451",1,TRUNCATE,"5678.1");
+ test_ro("5678.123451",2,TRUNCATE,"5678.12");
+ test_ro("5678.123451",3,TRUNCATE,"5678.123");
+ test_ro("5678.123451",4,TRUNCATE,"5678.1234");
+ test_ro("5678.123451",5,TRUNCATE,"5678.12345");
+ test_ro("5678.123451",6,TRUNCATE,"5678.123451");
+ test_ro("-5678.123451",-4,TRUNCATE,"0");
+ memset(buf2, 33, sizeof(buf2));
+ test_ro("99999999999999999999999999999999999999",-31,TRUNCATE,"99999990000000000000000000000000000000");
+ test_ro("15.1",0,HALF_UP,"15");
+ test_ro("15.5",0,HALF_UP,"16");
+ test_ro("15.9",0,HALF_UP,"16");
+ test_ro("-15.1",0,HALF_UP,"-15");
+ test_ro("-15.5",0,HALF_UP,"-16");
+ test_ro("-15.9",0,HALF_UP,"-16");
+ test_ro("15.1",1,HALF_UP,"15.1");
+ test_ro("-15.1",1,HALF_UP,"-15.1");
+ test_ro("15.17",1,HALF_UP,"15.2");
+ test_ro("15.4",-1,HALF_UP,"20");
+ test_ro("-15.4",-1,HALF_UP,"-20");
+ test_ro("5.4",-1,HALF_UP,"10");
+ test_ro(".999", 0, HALF_UP, "1");
+ memset(buf2, 33, sizeof(buf2));
+ test_ro("999999999", -9, HALF_UP, "1000000000");
+ test_ro("15.1",0,HALF_EVEN,"15");
+ test_ro("15.5",0,HALF_EVEN,"16");
+ test_ro("14.5",0,HALF_EVEN,"14");
+ test_ro("15.9",0,HALF_EVEN,"16");
+ test_ro("15.1",0,CEILING,"16");
+ test_ro("-15.1",0,CEILING,"-15");
+ test_ro("15.1",0,FLOOR,"15");
+ test_ro("-15.1",0,FLOOR,"-16");
+ test_ro("999999999999999999999.999", 0, CEILING,"1000000000000000000000");
+ test_ro("-999999999999999999999.999", 0, FLOOR,"-1000000000000000000000");
return 0;
}
diff --git a/strings/my_vsnprintf.c b/strings/my_vsnprintf.c
index 268f7d18f2a..4d7c17e977c 100644
--- a/strings/my_vsnprintf.c
+++ b/strings/my_vsnprintf.c
@@ -52,15 +52,30 @@ int my_vsnprintf(char *to, size_t n, const char* fmt, va_list ap)
if (*fmt == '-')
fmt++;
length= width= pre_zero= have_long= 0;
- for (;my_isdigit(&my_charset_latin1,*fmt); fmt++)
+ if (*fmt == '*')
{
- length=length*10+ (uint) (*fmt-'0');
- if (!length)
- pre_zero= 1; /* first digit was 0 */
+ fmt++;
+ length= va_arg(ap, int);
}
+ else
+ for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
+ {
+ length= length * 10 + (uint)(*fmt - '0');
+ if (!length)
+ pre_zero= 1; /* first digit was 0 */
+ }
if (*fmt == '.')
- for (fmt++;my_isdigit(&my_charset_latin1,*fmt); fmt++)
- width=width*10+ (uint) (*fmt-'0');
+ {
+ fmt++;
+ if (*fmt == '*')
+ {
+ fmt++;
+ width= va_arg(ap, int);
+ }
+ else
+ for (; my_isdigit(&my_charset_latin1, *fmt); fmt++)
+ width= width * 10 + (uint)(*fmt - '0');
+ }
else
width= ~0;
if (*fmt == 'l')
diff --git a/strings/uca-dump.c b/strings/uca-dump.c
index 6836c321526..dd3b74a55e8 100644
--- a/strings/uca-dump.c
+++ b/strings/uca-dump.c
@@ -23,13 +23,14 @@ struct uca_item_st
#define MY_UCA_PSHIFT 8
#endif
+static char *pname[]= {"", "2", "3"};
+
int main(int ac, char **av)
{
char str[256];
char *weights[64];
struct uca_item_st uca[64*1024];
- size_t code, page, w;
- int pagemaxlen[MY_UCA_NPAGES];
+ size_t code, w;
int pageloaded[MY_UCA_NPAGES];
bzero(uca, sizeof(uca));
@@ -155,14 +156,20 @@ int main(int ac, char **av)
printf("#define MY_UCA_CMASK %d\n",MY_UCA_CMASK);
printf("#define MY_UCA_PSHIFT %d\n",MY_UCA_PSHIFT);
- for (w=0; w<1; w++)
+ for (w=0; w<3; w++)
{
+ size_t page;
+ int pagemaxlen[MY_UCA_NPAGES];
+
for (page=0; page < MY_UCA_NPAGES; page++)
{
size_t offs;
size_t maxnum= 0;
size_t nchars= 0;
size_t mchars;
+ size_t ndefs= 0;
+
+ pagemaxlen[page]= 0;
/*
Skip this page if no weights were loaded
@@ -183,15 +190,36 @@ int main(int ac, char **av)
code= page*MY_UCA_NCHARS+offs;
/* Calculate only non-zero weights */
- num=0;
- for (i=0; i < uca[code].num; i++)
+ for (num=0, i=0; i < uca[code].num; i++)
if (uca[code].weight[w][i])
num++;
maxnum= maxnum < num ? num : maxnum;
+
+ /* Check if default weight */
+ if (w == 1 && num == 1)
+ {
+ /* 0020 0000 ... */
+ if (uca[code].weight[w][0] == 0x0020)
+ ndefs++;
+ }
+ else if (w == 2 && num == 1)
+ {
+ /* 0002 0000 ... */
+ if (uca[code].weight[w][0] == 0x0002)
+ ndefs++;
+ }
}
maxnum++;
+ /*
+ If the page have only default weights
+ then no needs to dump it, skip.
+ */
+ if (ndefs == MY_UCA_NCHARS)
+ {
+ continue;
+ }
switch (maxnum)
{
case 0: mchars= 8; break;
@@ -210,8 +238,8 @@ int main(int ac, char **av)
*/
- printf("uint16 page%03Xdata[]= { /* %04X (%d weights per char) */\n",
- page, page*MY_UCA_NCHARS, maxnum);
+ printf("uint16 page%03Xdata%s[]= { /* %04X (%d weights per char) */\n",
+ page, pname[w], page*MY_UCA_NCHARS, maxnum);
for (offs=0; offs < MY_UCA_NCHARS; offs++)
{
@@ -234,7 +262,17 @@ int main(int ac, char **av)
for (i=0; i < maxnum; i++)
{
- printf("0x%04X",(int)weight[i]);
+ /*
+ Invert weights for secondary level to
+ sort upper case letters before their
+ lower case counter part.
+ */
+ int tmp= weight[i];
+ if (w == 2 && tmp)
+ tmp= (int)(0x20 - weight[i]);
+
+
+ printf("0x%04X", tmp);
if ((offs+1 != MY_UCA_NCHARS) || (i+1!=maxnum))
printf(",");
nchars++;
@@ -251,25 +289,28 @@ int main(int ac, char **av)
}
printf("};\n\n");
}
- }
- printf("uchar ucal[%d]={\n",MY_UCA_NPAGES);
- for (page=0; page < MY_UCA_NPAGES; page++)
- {
- printf("%d%s%s",pagemaxlen[page],page<MY_UCA_NPAGES-1?",":"",(page+1) % 16 ? "":"\n");
- }
- printf("};\n");
-
-
- printf("uint16 *ucaw[%d]={\n",MY_UCA_NPAGES);
- for (page=0; page < MY_UCA_NPAGES; page++)
- {
- if (!pageloaded[page])
- printf("NULL %s%s",page<MY_UCA_NPAGES-1?",":"", (page+1) % 4 ? "":"\n");
- else
- printf("page%03Xdata%s%s",page,page<MY_UCA_NPAGES-1?",":"", (page+1) % 4 ? "":"\n");
+ printf("uchar uca_length%s[%d]={\n", pname[w], MY_UCA_NPAGES);
+ for (page=0; page < MY_UCA_NPAGES; page++)
+ {
+ printf("%d%s%s",pagemaxlen[page],page<MY_UCA_NPAGES-1?",":"",(page+1) % 16 ? "":"\n");
+ }
+ printf("};\n");
+
+
+ printf("uint16 *uca_weight%s[%d]={\n", pname[w], MY_UCA_NPAGES);
+ for (page=0; page < MY_UCA_NPAGES; page++)
+ {
+ const char *comma= page < MY_UCA_NPAGES-1 ? "," : "";
+ const char *nline= (page+1) % 4 ? "" : "\n";
+ if (!pagemaxlen[page])
+ printf("NULL %s%s%s", w ? " ": "", comma , nline);
+ else
+ printf("page%03Xdata%s%s%s", page, pname[w], comma, nline);
+ }
+ printf("};\n");
}
- printf("};\n");
+
printf("int main(void){ return 0;};\n");
return 0;
diff --git a/tests/client_test.c b/tests/client_test.c
index 0ef8bd1ea66..e6a530f786a 100644
--- a/tests/client_test.c
+++ b/tests/client_test.c
@@ -1,4 +1,4 @@
-/* Copyright (C) 2003 MySQL AB
+/* Copyright (C) 2003-2004 MySQL AB
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,12 +21,19 @@
Main author: venu ( venu@mysql.com )
***************************************************************************/
+/*
+ XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
+ DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
+*/
+
+
#include <my_global.h>
#include <my_sys.h>
#include <mysql.h>
#include <my_getopt.h>
#include <m_string.h>
+#define VER "2.1"
#define MAX_TEST_QUERY_LENGTH 300 /* MAX QUERY BUFFER LENGTH */
#define MAX_KEY 64
@@ -38,7 +45,7 @@ static char *opt_password= 0;
static char *opt_host= 0;
static char *opt_unix_socket= 0;
static unsigned int opt_port;
-static my_bool tty_password= 0;
+static my_bool tty_password= 0, opt_silent= 0;
static MYSQL *mysql= 0;
static char query[MAX_TEST_QUERY_LENGTH];
@@ -52,7 +59,14 @@ static double total_time;
const char *default_dbug_option= "d:t:o,/tmp/client_test.trace";
+struct my_tests_st
+{
+ const char *name;
+ void (*function)();
+};
+
#define myheader(str) \
+if (opt_silent < 2) \
{ \
fprintf(stdout, "\n\n#####################################\n"); \
fprintf(stdout, "%d of (%d/%d): %s", test_count++, iter_count, \
@@ -60,6 +74,7 @@ const char *default_dbug_option= "d:t:o,/tmp/client_test.trace";
fprintf(stdout, " \n#####################################\n"); \
}
#define myheader_r(str) \
+if (!opt_silent) \
{ \
fprintf(stdout, "\n\n#####################################\n"); \
fprintf(stdout, "%s", str); \
@@ -95,11 +110,12 @@ void die(const char *file, int line, const char *expr)
#define myerror(msg) print_error(msg)
#define mysterror(stmt, msg) print_st_error(stmt, msg)
-#define myquery(r) \
+#define myquery(RES) \
{ \
-if (r) \
- myerror(NULL); \
- DIE_UNLESS(r == 0); \
+ int r= (RES); \
+ if (r) \
+ myerror(NULL); \
+ DIE_UNLESS(r == 0); \
}
#define myquery_r(r) \
@@ -145,32 +161,39 @@ DIE_UNLESS(stmt == 0);\
static void print_error(const char *msg)
{
- if (mysql && mysql_errno(mysql))
+ if (!opt_silent)
{
- if (mysql->server_version)
- fprintf(stdout, "\n [MySQL-%s]", mysql->server_version);
- else
- fprintf(stdout, "\n [MySQL]");
- fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql));
+ if (mysql && mysql_errno(mysql))
+ {
+ if (mysql->server_version)
+ fprintf(stdout, "\n [MySQL-%s]", mysql->server_version);
+ else
+ fprintf(stdout, "\n [MySQL]");
+ fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql));
+ }
+ else if (msg)
+ fprintf(stderr, " [MySQL] %s\n", msg);
}
- else if (msg) fprintf(stderr, " [MySQL] %s\n", msg);
}
static void print_st_error(MYSQL_STMT *stmt, const char *msg)
{
- if (stmt && mysql_stmt_errno(stmt))
+ if (!opt_silent)
{
- if (stmt->mysql && stmt->mysql->server_version)
- fprintf(stdout, "\n [MySQL-%s]", stmt->mysql->server_version);
- else
- fprintf(stdout, "\n [MySQL]");
+ if (stmt && mysql_stmt_errno(stmt))
+ {
+ if (stmt->mysql && stmt->mysql->server_version)
+ fprintf(stdout, "\n [MySQL-%s]", stmt->mysql->server_version);
+ else
+ fprintf(stdout, "\n [MySQL]");
- fprintf(stdout, "[%d] %s\n", mysql_stmt_errno(stmt),
- mysql_stmt_error(stmt));
+ fprintf(stdout, "[%d] %s\n", mysql_stmt_errno(stmt),
+ mysql_stmt_error(stmt));
+ }
+ else if (msg)
+ fprintf(stderr, " [MySQL] %s\n", msg);
}
- else if (msg)
- fprintf(stderr, " [MySQL] %s\n", msg);
}
@@ -199,11 +222,13 @@ static void client_connect()
int rc;
myheader_r("client_connect");
- fprintf(stdout, "\n Establishing a connection to '%s' ...",
- opt_host ? opt_host : "");
+ if (!opt_silent)
+ fprintf(stdout, "\n Establishing a connection to '%s' ...",
+ opt_host ? opt_host : "");
if (!(mysql= mysql_init(NULL)))
{
+ opt_silent= 0;
myerror("mysql_init() failed");
exit(1);
}
@@ -212,18 +237,21 @@ static void client_connect()
opt_password, opt_db ? opt_db:"test", opt_port,
opt_unix_socket, 0)))
{
+ opt_silent= 0;
myerror("connection failed");
mysql_close(mysql);
fprintf(stdout, "\n Check the connection options using --help or -?\n");
exit(1);
}
- fprintf(stdout, " OK");
+ if (!opt_silent)
+ fprintf(stdout, " OK");
/* set AUTOCOMMIT to ON*/
mysql_autocommit(mysql, TRUE);
- fprintf(stdout, "\n Creating a test database '%s' ...", current_db);
+ if (!opt_silent)
+ fprintf(stdout, "\n Creating a test database '%s' ...", current_db);
strxmov(query, "CREATE DATABASE IF NOT EXISTS ", current_db, NullS);
rc= mysql_query(mysql, query);
@@ -233,7 +261,8 @@ static void client_connect()
rc= mysql_query(mysql, query);
myquery(rc);
- fprintf(stdout, " OK");
+ if (!opt_silent)
+ fprintf(stdout, " OK");
}
@@ -245,13 +274,16 @@ static void client_disconnect()
if (mysql)
{
- fprintf(stdout, "\n dropping the test database '%s' ...", current_db);
+ if (!opt_silent)
+ fprintf(stdout, "\n dropping the test database '%s' ...", current_db);
strxmov(query, "DROP DATABASE IF EXISTS ", current_db, NullS);
mysql_query(mysql, query);
- fprintf(stdout, " OK");
+ if (!opt_silent)
+ fprintf(stdout, " OK");
- fprintf(stdout, "\n closing the connection ...");
+ if (!opt_silent)
+ fprintf(stdout, "\n closing the connection ...");
mysql_close(mysql);
fprintf(stdout, " OK\n");
}
@@ -266,38 +298,40 @@ static void client_query()
myheader("client_query");
- rc= mysql_query(mysql, "DROP TABLE IF EXISTS myclient_test");
+ rc= mysql_query(mysql, "DROP TABLE IF EXISTS t1");
myquery(rc);
- rc= mysql_query(mysql, "CREATE TABLE myclient_test("
+ rc= mysql_query(mysql, "CREATE TABLE t1("
"id int primary key auto_increment, "
"name varchar(20))");
myquery(rc);
- rc= mysql_query(mysql, "CREATE TABLE myclient_test(id int, name varchar(20))");
+ rc= mysql_query(mysql, "CREATE TABLE t1(id int, name varchar(20))");
myquery_r(rc);
- rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('mysql')");
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('mysql')");
myquery(rc);
- rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('monty')");
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('monty')");
myquery(rc);
- rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('venu')");
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('venu')");
myquery(rc);
- rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('deleted')");
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')");
myquery(rc);
- rc= mysql_query(mysql, "INSERT INTO myclient_test(name) VALUES('deleted')");
+ rc= mysql_query(mysql, "INSERT INTO t1(name) VALUES('deleted')");
myquery(rc);
- rc= mysql_query(mysql, "UPDATE myclient_test SET name= 'updated' "
+ rc= mysql_query(mysql, "UPDATE t1 SET name= 'updated' "
"WHERE name= 'deleted'");
myquery(rc);
- rc= mysql_query(mysql, "UPDATE myclient_test SET id= 3 WHERE name= 'updated'");
+ rc= mysql_query(mysql, "UPDATE t1 SET id= 3 WHERE name= 'updated'");
myquery_r(rc);
+
+ myquery(mysql_query(mysql, "drop table t1"));
}
@@ -332,8 +366,11 @@ static void my_print_result_metadata(MYSQL_RES *result)
unsigned int field_count;
mysql_field_seek(result, 0);
- fputc('\n', stdout);
- fputc('\n', stdout);
+ if (!opt_silent)
+ {
+ fputc('\n', stdout);
+ fputc('\n', stdout);
+ }
field_count= mysql_num_fields(result);
for(i= 0; i< field_count; i++)
@@ -346,18 +383,25 @@ static void my_print_result_metadata(MYSQL_RES *result)
j= 4;
field->max_length= j;
}
- my_print_dashes(result);
- fputc('\t', stdout);
- fputc('|', stdout);
+ if (!opt_silent)
+ {
+ my_print_dashes(result);
+ fputc('\t', stdout);
+ fputc('|', stdout);
+ }
mysql_field_seek(result, 0);
for(i= 0; i< field_count; i++)
{
field= mysql_fetch_field(result);
- fprintf(stdout, " %-*s |", (int) field->max_length, field->name);
+ if (!opt_silent)
+ fprintf(stdout, " %-*s |", (int) field->max_length, field->name);
+ }
+ if (!opt_silent)
+ {
+ fputc('\n', stdout);
+ my_print_dashes(result);
}
- fputc('\n', stdout);
- my_print_dashes(result);
}
@@ -378,31 +422,43 @@ int my_process_result_set(MYSQL_RES *result)
while ((row= mysql_fetch_row(result)) != NULL)
{
mysql_field_seek(result, 0);
- fputc('\t', stdout);
- fputc('|', stdout);
+ if (!opt_silent)
+ {
+ fputc('\t', stdout);
+ fputc('|', stdout);
+ }
for(i= 0; i< mysql_num_fields(result); i++)
{
field= mysql_fetch_field(result);
- if (row[i] == NULL)
- fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
- else if (IS_NUM(field->type))
- fprintf(stdout, " %*s |", (int) field->max_length, row[i]);
- else
- fprintf(stdout, " %-*s |", (int) field->max_length, row[i]);
+ if (!opt_silent)
+ {
+ if (row[i] == NULL)
+ fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
+ else if (IS_NUM(field->type))
+ fprintf(stdout, " %*s |", (int) field->max_length, row[i]);
+ else
+ fprintf(stdout, " %-*s |", (int) field->max_length, row[i]);
+ }
+ }
+ if (!opt_silent)
+ {
+ fputc('\t', stdout);
+ fputc('\n', stdout);
}
- fputc('\t', stdout);
- fputc('\n', stdout);
row_count++;
}
- if (row_count)
- my_print_dashes(result);
+ if (!opt_silent)
+ {
+ if (row_count)
+ my_print_dashes(result);
- if (mysql_errno(mysql) != 0)
- fprintf(stderr, "\n\tmysql_fetch_row() failed\n");
- else
- fprintf(stdout, "\n\t%d %s returned\n", row_count,
- row_count == 1 ? "row" : "rows");
+ if (mysql_errno(mysql) != 0)
+ fprintf(stderr, "\n\tmysql_fetch_row() failed\n");
+ else
+ fprintf(stdout, "\n\t%d %s returned\n", row_count,
+ row_count == 1 ? "row" : "rows");
+ }
return row_count;
}
@@ -471,34 +527,44 @@ int my_process_stmt_result(MYSQL_STMT *stmt)
mysql_field_seek(result, 0);
while (mysql_stmt_fetch(stmt) == 0)
{
- fputc('\t', stdout);
- fputc('|', stdout);
-
+ if (!opt_silent)
+ {
+ fputc('\t', stdout);
+ fputc('|', stdout);
+ }
mysql_field_seek(result, 0);
for (i= 0; i < field_count; i++)
{
field= mysql_fetch_field(result);
- if (is_null[i])
- fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
- else if (length[i] == 0)
+ if (!opt_silent)
{
- data[i][0]= '\0'; /* unmodified buffer */
- fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
+ if (is_null[i])
+ fprintf(stdout, " %-*s |", (int) field->max_length, "NULL");
+ else if (length[i] == 0)
+ {
+ data[i][0]= '\0'; /* unmodified buffer */
+ fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
+ }
+ else if (IS_NUM(field->type))
+ fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
+ else
+ fprintf(stdout, " %-*s |", (int) field->max_length, data[i]);
}
- else if (IS_NUM(field->type))
- fprintf(stdout, " %*s |", (int) field->max_length, data[i]);
- else
- fprintf(stdout, " %-*s |", (int) field->max_length, data[i]);
}
- fputc('\t', stdout);
- fputc('\n', stdout);
+ if (!opt_silent)
+ {
+ fputc('\t', stdout);
+ fputc('\n', stdout);
+ }
row_count++;
}
- if (row_count)
- my_print_dashes(result);
-
- fprintf(stdout, "\n\t%d %s returned\n", row_count,
- row_count == 1 ? "row" : "rows");
+ if (!opt_silent)
+ {
+ if (row_count)
+ my_print_dashes(result);
+ fprintf(stdout, "\n\t%d %s returned\n", row_count,
+ row_count == 1 ? "row" : "rows");
+ }
mysql_free_result(result);
return row_count;
}
@@ -512,7 +578,8 @@ int my_stmt_result(const char *buff)
int row_count;
int rc;
- fprintf(stdout, "\n\n %s", buff);
+ if (!opt_silent)
+ fprintf(stdout, "\n\n %s", buff);
stmt= mysql_simple_prepare(mysql, buff);
check_stmt(stmt);
@@ -538,7 +605,8 @@ static void verify_col_data(const char *table, const char *col,
if (table && col)
{
strxmov(query, "SELECT ", col, " FROM ", table, " LIMIT 1", NullS);
- fprintf(stdout, "\n %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
@@ -566,42 +634,77 @@ static void verify_col_data(const char *table, const char *col,
/* Utility function to verify the field members */
static void verify_prepare_field(MYSQL_RES *result,
- unsigned int no, const char *name, const char *org_name,
- enum enum_field_types type, const char *table,
- const char *org_table, const char *db,
- unsigned long length, const char *def)
+ unsigned int no, const char *name,
+ const char *org_name,
+ enum enum_field_types type,
+ const char *table,
+ const char *org_table, const char *db,
+ unsigned long length, const char *def)
{
MYSQL_FIELD *field;
+ CHARSET_INFO *cs;
if (!(field= mysql_fetch_field_direct(result, no)))
{
fprintf(stdout, "\n *** ERROR: FAILED TO GET THE RESULT ***");
exit(1);
}
- fprintf(stdout, "\n field[%d]:", no);
- fprintf(stdout, "\n name :`%s`\t(expected: `%s`)", field->name, name);
- fprintf(stdout, "\n org_name :`%s`\t(expected: `%s`)",
- field->org_name, org_name);
- fprintf(stdout, "\n type :`%d`\t(expected: `%d`)", field->type, type);
- fprintf(stdout, "\n table :`%s`\t(expected: `%s`)",
- field->table, table);
- fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)",
- field->org_table, org_table);
- fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db);
- fprintf(stdout, "\n length :`%ld`\t(expected: `%ld`)",
- field->length, length);
- fprintf(stdout, "\n maxlength:`%ld`", field->max_length);
- fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr);
- fprintf(stdout, "\n default :`%s`\t(expected: `%s`)",
- field->def ? field->def : "(null)", def ? def: "(null)");
- fprintf(stdout, "\n");
+ cs= get_charset(field->charsetnr, 0);
+ DIE_UNLESS(cs);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n field[%d]:", no);
+ fprintf(stdout, "\n name :`%s`\t(expected: `%s`)", field->name, name);
+ fprintf(stdout, "\n org_name :`%s`\t(expected: `%s`)",
+ field->org_name, org_name);
+ fprintf(stdout, "\n type :`%d`\t(expected: `%d`)", field->type, type);
+ if (table)
+ fprintf(stdout, "\n table :`%s`\t(expected: `%s`)",
+ field->table, table);
+ if (org_table)
+ fprintf(stdout, "\n org_table:`%s`\t(expected: `%s`)",
+ field->org_table, org_table);
+ fprintf(stdout, "\n database :`%s`\t(expected: `%s`)", field->db, db);
+ fprintf(stdout, "\n length :`%ld`\t(expected: `%ld`)",
+ field->length, length * cs->mbmaxlen);
+ fprintf(stdout, "\n maxlength:`%ld`", field->max_length);
+ fprintf(stdout, "\n charsetnr:`%d`", field->charsetnr);
+ fprintf(stdout, "\n default :`%s`\t(expected: `%s`)",
+ field->def ? field->def : "(null)", def ? def: "(null)");
+ fprintf(stdout, "\n");
+ }
DIE_UNLESS(strcmp(field->name, name) == 0);
DIE_UNLESS(strcmp(field->org_name, org_name) == 0);
- DIE_UNLESS(field->type == type);
- DIE_UNLESS(strcmp(field->table, table) == 0);
- DIE_UNLESS(strcmp(field->org_table, org_table) == 0);
+ /*
+ XXX: silent column specification change works based on number of
+ bytes a column occupies. So CHAR -> VARCHAR upgrade is possible even
+ for CHAR(2) column if its character set is multibyte.
+ VARCHAR -> CHAR downgrade won't work for VARCHAR(3) as one would
+ expect.
+ */
+ if (cs->mbmaxlen == 1)
+ {
+ if (field->type != type)
+ {
+ fprintf(stderr, "Expected field type: %d, got type: %d\n",
+ (int) type, (int) field->type);
+ DIE_UNLESS(field->type == type);
+ }
+ }
+ if (table)
+ DIE_UNLESS(strcmp(field->table, table) == 0);
+ if (org_table)
+ DIE_UNLESS(strcmp(field->org_table, org_table) == 0);
DIE_UNLESS(strcmp(field->db, db) == 0);
- DIE_UNLESS(field->length == length);
+ /*
+ Character set should be taken into account for multibyte encodings, such
+ as utf8. Field length is calculated as number of characters * maximum
+ number of bytes a character can occupy.
+ */
+#ifndef EMBEDDED_LIBRARY
+ if (length)
+ DIE_UNLESS(field->length == length * cs->mbmaxlen);
+#endif
if (def)
DIE_UNLESS(strcmp(field->def, def) == 0);
}
@@ -612,8 +715,9 @@ static void verify_prepare_field(MYSQL_RES *result,
static void verify_param_count(MYSQL_STMT *stmt, long exp_count)
{
long param_count= mysql_stmt_param_count(stmt);
- fprintf(stdout, "\n total parameters in stmt: `%ld` (expected: `%ld`)",
- param_count, exp_count);
+ if (!opt_silent)
+ fprintf(stdout, "\n total parameters in stmt: `%ld` (expected: `%ld`)",
+ param_count, exp_count);
DIE_UNLESS(param_count == exp_count);
}
@@ -623,8 +727,9 @@ static void verify_param_count(MYSQL_STMT *stmt, long exp_count)
static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count)
{
ulonglong affected_rows= mysql_stmt_affected_rows(stmt);
- fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
- affected_rows, exp_count);
+ if (!opt_silent)
+ fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
+ affected_rows, exp_count);
DIE_UNLESS(affected_rows == exp_count);
}
@@ -634,7 +739,8 @@ static void verify_st_affected_rows(MYSQL_STMT *stmt, ulonglong exp_count)
static void verify_affected_rows(ulonglong exp_count)
{
ulonglong affected_rows= mysql_affected_rows(mysql);
- fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
+ if (!opt_silent)
+ fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
affected_rows, exp_count);
DIE_UNLESS(affected_rows == exp_count);
}
@@ -645,8 +751,9 @@ static void verify_affected_rows(ulonglong exp_count)
static void verify_field_count(MYSQL_RES *result, uint exp_count)
{
uint field_count= mysql_num_fields(result);
- fprintf(stdout, "\n total fields in the result set: `%d` (expected: `%d`)",
- field_count, exp_count);
+ if (!opt_silent)
+ fprintf(stdout, "\n total fields in the result set: `%d` (expected: `%d`)",
+ field_count, exp_count);
DIE_UNLESS(field_count == exp_count);
}
@@ -666,8 +773,9 @@ static void execute_prepare_query(const char *query, ulonglong exp_count)
myquery(rc);
affected_rows= mysql_stmt_affected_rows(stmt);
- fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
- affected_rows, exp_count);
+ if (!opt_silent)
+ fprintf(stdout, "\n total affected rows: `%lld` (expected: `%lld`)",
+ affected_rows, exp_count);
DIE_UNLESS(affected_rows == exp_count);
mysql_stmt_close(stmt);
@@ -683,7 +791,7 @@ static void client_store_result()
myheader("client_store_result");
- rc= mysql_query(mysql, "SELECT * FROM myclient_test");
+ rc= mysql_query(mysql, "SELECT * FROM t1");
myquery(rc);
/* get the result */
@@ -703,7 +811,7 @@ static void client_use_result()
int rc;
myheader("client_use_result");
- rc= mysql_query(mysql, "SELECT * FROM myclient_test");
+ rc= mysql_query(mysql, "SELECT * FROM t1");
myquery(rc);
/* get the result */
@@ -724,12 +832,14 @@ void fill_tables(const char **query_list, unsigned query_count)
{
int rc;
const char **query;
+ DBUG_ENTER("fill_tables");
for (query= query_list; query < query_list + query_count;
++query)
{
rc= mysql_query(mysql, *query);
myquery(rc);
}
+ DBUG_VOID_RETURN;
}
/*
@@ -766,6 +876,7 @@ void stmt_fetch_init(Stmt_fetch *fetch, unsigned stmt_no_arg,
int rc;
unsigned i;
MYSQL_RES *metadata;
+ DBUG_ENTER("stmt_fetch_init");
/* Save query and statement number for error messages */
fetch->stmt_no= stmt_no_arg;
@@ -817,6 +928,7 @@ void stmt_fetch_init(Stmt_fetch *fetch, unsigned stmt_no_arg,
fetch->is_open= TRUE;
/* Ready for reading rows */
+ DBUG_VOID_RETURN;
}
@@ -826,26 +938,30 @@ int stmt_fetch_fetch_row(Stmt_fetch *fetch)
{
int rc;
unsigned i;
+ DBUG_ENTER("stmt_fetch_fetch_row");
if ((rc= mysql_stmt_fetch(fetch->handle)) == 0)
{
++fetch->row_count;
- printf("Stmt %d fetched row %d:\n", fetch->stmt_no, fetch->row_count);
+ if (!opt_silent)
+ printf("Stmt %d fetched row %d:\n", fetch->stmt_no, fetch->row_count);
for (i= 0; i < fetch->column_count; ++i)
{
fetch->out_data[i][fetch->out_data_length[i]]= '\0';
- printf("column %d: %s\n", i+1, fetch->out_data[i]);
+ if (!opt_silent)
+ printf("column %d: %s\n", i+1, fetch->out_data[i]);
}
}
else
fetch->is_open= FALSE;
- return rc;
+ DBUG_RETURN(rc);
}
void stmt_fetch_close(Stmt_fetch *fetch)
{
unsigned i;
+ DBUG_ENTER("stmt_fetch_close");
for (i= 0; i < fetch->column_count; ++i)
free(fetch->out_data[i]);
@@ -853,6 +969,7 @@ void stmt_fetch_close(Stmt_fetch *fetch)
free(fetch->out_data_length);
free(fetch->bind_array);
mysql_stmt_close(fetch->handle);
+ DBUG_VOID_RETURN;
}
/*
@@ -862,13 +979,14 @@ void stmt_fetch_close(Stmt_fetch *fetch)
reading from the rest.
*/
-bool fetch_n(const char **query_list, unsigned query_count)
+my_bool fetch_n(const char **query_list, unsigned query_count)
{
unsigned open_statements= query_count;
int rc, error_count= 0;
Stmt_fetch *fetch_array= (Stmt_fetch*) calloc(1, sizeof(Stmt_fetch) *
query_count);
Stmt_fetch *fetch;
+ DBUG_ENTER("fetch_n");
for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
{
@@ -883,7 +1001,7 @@ bool fetch_n(const char **query_list, unsigned query_count)
{
if (fetch->is_open && (rc= stmt_fetch_fetch_row(fetch)))
{
- --open_statements;
+ open_statements--;
/*
We try to fetch from the rest of the statements in case of
error
@@ -895,7 +1013,7 @@ bool fetch_n(const char **query_list, unsigned query_count)
"query is: %s,\n"
"error message: %s", fetch - fetch_array, fetch->query,
mysql_stmt_error(fetch->handle));
- ++error_count;
+ error_count++;
}
}
}
@@ -907,12 +1025,13 @@ bool fetch_n(const char **query_list, unsigned query_count)
unsigned total_row_count= 0;
for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
total_row_count+= fetch->row_count;
- printf("Success, total rows fetched: %d\n", total_row_count);
+ if (!opt_silent)
+ printf("Success, total rows fetched: %d\n", total_row_count);
}
for (fetch= fetch_array; fetch < fetch_array + query_count; ++fetch)
stmt_fetch_close(fetch);
free(fetch_array);
- return error_count != 0;
+ DBUG_RETURN(error_count != 0);
}
/* Separate thread query to test some cases */
@@ -923,7 +1042,8 @@ static my_bool thread_query(char *query)
my_bool error;
error= 0;
- fprintf(stdout, "\n in thread_query(%s)", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n in thread_query(%s)", query);
if (!(l_mysql= mysql_init(NULL)))
{
myerror("mysql_init() failed");
@@ -1234,7 +1354,8 @@ static void test_prepare_field_result()
my_print_result_metadata(result);
- fprintf(stdout, "\n\n field attributes:\n");
+ if (!opt_silent)
+ fprintf(stdout, "\n\n field attributes:\n");
verify_prepare_field(result, 0, "int_c", "int_c", MYSQL_TYPE_LONG,
"t1", "test_prepare_field_result", current_db, 11, 0);
verify_prepare_field(result, 1, "var_c", "var_c", MYSQL_TYPE_VAR_STRING,
@@ -1408,17 +1529,19 @@ static void test_prepare()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n");
-
- fprintf(stdout, "\n\t tiny : %d (%lu)", tiny_data, length[0]);
- fprintf(stdout, "\n\t short : %d (%lu)", small_data, length[3]);
- fprintf(stdout, "\n\t int : %d (%lu)", int_data, length[2]);
- fprintf(stdout, "\n\t big : %lld (%lu)", big_data, length[4]);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n");
+ fprintf(stdout, "\n\t tiny : %d (%lu)", tiny_data, length[0]);
+ fprintf(stdout, "\n\t short : %d (%lu)", small_data, length[3]);
+ fprintf(stdout, "\n\t int : %d (%lu)", int_data, length[2]);
+ fprintf(stdout, "\n\t big : %lld (%lu)", big_data, length[4]);
- fprintf(stdout, "\n\t float : %f (%lu)", real_data, length[5]);
- fprintf(stdout, "\n\t double : %f (%lu)", double_data, length[6]);
+ fprintf(stdout, "\n\t float : %f (%lu)", real_data, length[5]);
+ fprintf(stdout, "\n\t double : %f (%lu)", double_data, length[6]);
- fprintf(stdout, "\n\t str : %s (%lu)", str_data, length[1]);
+ fprintf(stdout, "\n\t str : %s (%lu)", str_data, length[1]);
+ }
DIE_UNLESS(tiny_data == o_tiny_data);
DIE_UNLESS(is_null[0] == 0);
@@ -1779,11 +1902,13 @@ static void test_fetch_null()
rc++;
for (i= 0; i < 10; i++)
{
- fprintf(stdout, "\n data[%d] : %s", i,
- is_null[i] ? "NULL" : "NOT NULL");
+ if (!opt_silent)
+ fprintf(stdout, "\n data[%d] : %s", i,
+ is_null[i] ? "NULL" : "NOT NULL");
DIE_UNLESS(is_null[i]);
}
- fprintf(stdout, "\n data[%d]: %d", i, nData);
+ if (!opt_silent)
+ fprintf(stdout, "\n data[%d]: %d", i, nData);
DIE_UNLESS(nData == 1000 || nData == 88 || nData == 389789);
DIE_UNLESS(is_null[i] == 0);
DIE_UNLESS(length[i] == 4);
@@ -2568,7 +2693,8 @@ static void test_long_data()
/* execute */
rc= mysql_stmt_execute(stmt);
- fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
+ if (!opt_silent)
+ fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
check_execute(stmt, rc);
rc= mysql_commit(mysql);
@@ -2651,7 +2777,8 @@ static void test_long_data_str()
}
/* execute */
rc= mysql_stmt_execute(stmt);
- fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
+ if (!opt_silent)
+ fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
check_execute(stmt, rc);
mysql_stmt_close(stmt);
@@ -2742,7 +2869,8 @@ static void test_long_data_str1()
/* execute */
rc= mysql_stmt_execute(stmt);
- fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
+ if (!opt_silent)
+ fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
check_execute(stmt, rc);
mysql_stmt_close(stmt);
@@ -2893,7 +3021,8 @@ static void test_long_data_bin()
}
/* execute */
rc= mysql_stmt_execute(stmt);
- fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
+ if (!opt_silent)
+ fprintf(stdout, " mysql_stmt_execute() returned %d\n", rc);
check_execute(stmt, rc);
mysql_stmt_close(stmt);
@@ -3200,7 +3329,8 @@ static void test_bind_result()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 1: %d, %s(%lu)", nData, szData, length1);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 1: %d, %s(%lu)", nData, szData, length1);
DIE_UNLESS(nData == 10);
DIE_UNLESS(strcmp(szData, "venu") == 0);
DIE_UNLESS(length1 == 4);
@@ -3208,7 +3338,8 @@ static void test_bind_result()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 2: %d, %s(%lu)", nData, szData, length1);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 2: %d, %s(%lu)", nData, szData, length1);
DIE_UNLESS(nData == 20);
DIE_UNLESS(strcmp(szData, "MySQL") == 0);
DIE_UNLESS(length1 == 5);
@@ -3217,7 +3348,7 @@ static void test_bind_result()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- if (is_null[0])
+ if (!opt_silent && is_null[0])
fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1);
DIE_UNLESS(is_null[0]);
DIE_UNLESS(strcmp(szData, "monty") == 0);
@@ -3315,19 +3446,21 @@ static void test_bind_result_ext()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data (tiny) : %d", t_data);
- fprintf(stdout, "\n data (short) : %d", s_data);
- fprintf(stdout, "\n data (int) : %d", i_data);
- fprintf(stdout, "\n data (big) : %lld", b_data);
-
- fprintf(stdout, "\n data (float) : %f", f_data);
- fprintf(stdout, "\n data (double) : %f", d_data);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n data (tiny) : %d", t_data);
+ fprintf(stdout, "\n data (short) : %d", s_data);
+ fprintf(stdout, "\n data (int) : %d", i_data);
+ fprintf(stdout, "\n data (big) : %lld", b_data);
- fprintf(stdout, "\n data (str) : %s(%lu)", szData, szLength);
+ fprintf(stdout, "\n data (float) : %f", f_data);
+ fprintf(stdout, "\n data (double) : %f", d_data);
- bData[bLength]= '\0'; /* bData is binary */
- fprintf(stdout, "\n data (bin) : %s(%lu)", bData, bLength);
+ fprintf(stdout, "\n data (str) : %s(%lu)", szData, szLength);
+ bData[bLength]= '\0'; /* bData is binary */
+ fprintf(stdout, "\n data (bin) : %s(%lu)", bData, bLength);
+ }
DIE_UNLESS(t_data == 19);
DIE_UNLESS(s_data == 2999);
@@ -3435,16 +3568,19 @@ static void test_bind_result_ext1()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data (tiny) : %s(%lu)", t_data, length[0]);
- fprintf(stdout, "\n data (short) : %f(%lu)", s_data, length[1]);
- fprintf(stdout, "\n data (int) : %d(%lu)", i_data, length[2]);
- fprintf(stdout, "\n data (big) : %d(%lu)", b_data, length[3]);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n data (tiny) : %s(%lu)", t_data, length[0]);
+ fprintf(stdout, "\n data (short) : %f(%lu)", s_data, length[1]);
+ fprintf(stdout, "\n data (int) : %d(%lu)", i_data, length[2]);
+ fprintf(stdout, "\n data (big) : %d(%lu)", b_data, length[3]);
- fprintf(stdout, "\n data (float) : %d(%lu)", f_data, length[4]);
- fprintf(stdout, "\n data (double) : %s(%lu)", d_data, length[5]);
+ fprintf(stdout, "\n data (float) : %d(%lu)", f_data, length[4]);
+ fprintf(stdout, "\n data (double) : %s(%lu)", d_data, length[5]);
- fprintf(stdout, "\n data (bin) : %ld(%lu)", bData, length[6]);
- fprintf(stdout, "\n data (str) : %g(%lu)", szData, length[7]);
+ fprintf(stdout, "\n data (bin) : %ld(%lu)", bData, length[6]);
+ fprintf(stdout, "\n data (str) : %g(%lu)", szData, length[7]);
+ }
DIE_UNLESS(strcmp(t_data, "120") == 0);
DIE_UNLESS(i_data == 3999);
@@ -3569,15 +3705,17 @@ static void bind_fetch(int row_count)
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n");
- fprintf(stdout, "\n tiny : %ld(%lu)", (ulong) i8_data, length[0]);
- fprintf(stdout, "\n short : %ld(%lu)", (ulong) i16_data, length[1]);
- fprintf(stdout, "\n int : %ld(%lu)", (ulong) i32_data, length[2]);
- fprintf(stdout, "\n longlong : %ld(%lu)", (ulong) i64_data, length[3]);
- fprintf(stdout, "\n float : %f(%lu)", f_data, length[4]);
- fprintf(stdout, "\n double : %g(%lu)", d_data, length[5]);
- fprintf(stdout, "\n char : %s(%lu)", s_data, length[6]);
-
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n");
+ fprintf(stdout, "\n tiny : %ld(%lu)", (ulong) i8_data, length[0]);
+ fprintf(stdout, "\n short : %ld(%lu)", (ulong) i16_data, length[1]);
+ fprintf(stdout, "\n int : %ld(%lu)", (ulong) i32_data, length[2]);
+ fprintf(stdout, "\n longlong : %ld(%lu)", (ulong) i64_data, length[3]);
+ fprintf(stdout, "\n float : %f(%lu)", f_data, length[4]);
+ fprintf(stdout, "\n double : %g(%lu)", d_data, length[5]);
+ fprintf(stdout, "\n char : %s(%lu)", s_data, length[6]);
+ }
rc= 10+row_count;
/* TINY */
@@ -3719,13 +3857,16 @@ static void test_fetch_date()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n date : %s(%lu)", date, d_length);
- fprintf(stdout, "\n time : %s(%lu)", time, t_length);
- fprintf(stdout, "\n ts : %s(%lu)", ts, ts_length);
- fprintf(stdout, "\n year : %d(%lu)", year, y_length);
- fprintf(stdout, "\n dt : %s(%lu)", dt, dt_length);
- fprintf(stdout, "\n ts(4) : %s(%lu)", ts_4, ts4_length);
- fprintf(stdout, "\n ts(6) : %s(%lu)", ts_6, ts6_length);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n date : %s(%lu)", date, d_length);
+ fprintf(stdout, "\n time : %s(%lu)", time, t_length);
+ fprintf(stdout, "\n ts : %s(%lu)", ts, ts_length);
+ fprintf(stdout, "\n year : %d(%lu)", year, y_length);
+ fprintf(stdout, "\n dt : %s(%lu)", dt, dt_length);
+ fprintf(stdout, "\n ts(4) : %s(%lu)", ts_4, ts4_length);
+ fprintf(stdout, "\n ts(6) : %s(%lu)", ts_6, ts6_length);
+ }
DIE_UNLESS(strcmp(date, "2002-01-02") == 0);
DIE_UNLESS(d_length == 10);
@@ -4052,7 +4193,8 @@ static void test_field_names()
myheader("test_field_names");
- fprintf(stdout, "\n %d, %d, %d", MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NEWDATE, MYSQL_TYPE_ENUM);
+ if (!opt_silent)
+ fprintf(stdout, "\n %d, %d, %d", MYSQL_TYPE_DECIMAL, MYSQL_TYPE_NEWDATE, MYSQL_TYPE_ENUM);
rc= mysql_query(mysql, "DROP TABLE IF EXISTS test_field_names1");
myquery(rc);
@@ -4103,7 +4245,8 @@ static void test_warnings()
rc= mysql_query(mysql, "DROP TABLE if exists test_non_exists");
myquery(rc);
- fprintf(stdout, "\n total warnings: %d", mysql_warning_count(mysql));
+ if (!opt_silent)
+ fprintf(stdout, "\n total warnings: %d", mysql_warning_count(mysql));
rc= mysql_query(mysql, "SHOW WARNINGS");
myquery(rc);
@@ -4285,23 +4428,27 @@ static void test_field_flags()
mytest(result);
mysql_field_seek(result, 0);
- fputc('\n', stdout);
+ if (!opt_silent)
+ fputc('\n', stdout);
for(i= 0; i< mysql_num_fields(result); i++)
{
field= mysql_fetch_field(result);
- fprintf(stdout, "\n field:%d", i);
- if (field->flags & NOT_NULL_FLAG)
- fprintf(stdout, "\n NOT_NULL_FLAG");
- if (field->flags & PRI_KEY_FLAG)
- fprintf(stdout, "\n PRI_KEY_FLAG");
- if (field->flags & UNIQUE_KEY_FLAG)
- fprintf(stdout, "\n UNIQUE_KEY_FLAG");
- if (field->flags & MULTIPLE_KEY_FLAG)
- fprintf(stdout, "\n MULTIPLE_KEY_FLAG");
- if (field->flags & AUTO_INCREMENT_FLAG)
- fprintf(stdout, "\n AUTO_INCREMENT_FLAG");
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n field:%d", i);
+ if (field->flags & NOT_NULL_FLAG)
+ fprintf(stdout, "\n NOT_NULL_FLAG");
+ if (field->flags & PRI_KEY_FLAG)
+ fprintf(stdout, "\n PRI_KEY_FLAG");
+ if (field->flags & UNIQUE_KEY_FLAG)
+ fprintf(stdout, "\n UNIQUE_KEY_FLAG");
+ if (field->flags & MULTIPLE_KEY_FLAG)
+ fprintf(stdout, "\n MULTIPLE_KEY_FLAG");
+ if (field->flags & AUTO_INCREMENT_FLAG)
+ fprintf(stdout, "\n AUTO_INCREMENT_FLAG");
+ }
}
mysql_free_result(result);
}
@@ -4320,7 +4467,8 @@ static void test_stmt_close()
myheader("test_stmt_close");
- fprintf(stdout, "\n Establishing a test connection ...");
+ if (!opt_silent)
+ fprintf(stdout, "\n Establishing a test connection ...");
if (!(lmysql= mysql_init(NULL)))
{
myerror("mysql_init() failed");
@@ -4333,7 +4481,8 @@ static void test_stmt_close()
myerror("connection failed");
exit(1);
}
- fprintf(stdout, " OK");
+ if (!opt_silent)
+ fprintf(stdout, " OK");
/* set AUTOCOMMIT to ON*/
@@ -4370,7 +4519,8 @@ static void test_stmt_close()
verify_param_count(stmt2, 1);
rc= mysql_stmt_close(stmt1);
- fprintf(stdout, "\n mysql_close_stmt(1) returned: %d", rc);
+ if (!opt_silent)
+ fprintf(stdout, "\n mysql_close_stmt(1) returned: %d", rc);
DIE_UNLESS(rc == 0);
/*
@@ -4404,7 +4554,8 @@ static void test_stmt_close()
verify_st_affected_rows(stmt_x, 1);
rc= mysql_stmt_close(stmt_x);
- fprintf(stdout, "\n mysql_close_stmt(x) returned: %d", rc);
+ if (!opt_silent)
+ fprintf(stdout, "\n mysql_close_stmt(x) returned: %d", rc);
DIE_UNLESS( rc == 0);
rc= mysql_query(mysql, "SELECT id FROM test_stmt_close");
@@ -4463,7 +4614,8 @@ static void test_set_variable()
rc= mysql_stmt_fetch(stmt1);
check_execute(stmt1, rc);
- fprintf(stdout, "\n max_error_count(default): %d", get_count);
+ if (!opt_silent)
+ fprintf(stdout, "\n max_error_count(default): %d", get_count);
def_count= get_count;
DIE_UNLESS(strcmp(var, "max_error_count") == 0);
@@ -4493,7 +4645,8 @@ static void test_set_variable()
rc= mysql_stmt_fetch(stmt1);
check_execute(stmt1, rc);
- fprintf(stdout, "\n max_error_count : %d", get_count);
+ if (!opt_silent)
+ fprintf(stdout, "\n max_error_count : %d", get_count);
DIE_UNLESS(get_count == set_count);
rc= mysql_stmt_fetch(stmt1);
@@ -4510,7 +4663,8 @@ static void test_set_variable()
rc= mysql_stmt_fetch(stmt1);
check_execute(stmt1, rc);
- fprintf(stdout, "\n max_error_count(default): %d", get_count);
+ if (!opt_silent)
+ fprintf(stdout, "\n max_error_count(default): %d", get_count);
DIE_UNLESS(get_count == set_count);
rc= mysql_stmt_fetch(stmt1);
@@ -4568,12 +4722,14 @@ static void test_insert_meta()
mysql_field_seek(result, 0);
field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col1");
+ if (!opt_silent)
+ fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col1");
DIE_UNLESS(strcmp(field->name, "col1") == 0);
field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col3");
+ if (!opt_silent)
+ fprintf(stdout, "\n obtained: `%s` (expected: `%s`)", field->name, "col3");
DIE_UNLESS(strcmp(field->name, "col3") == 0);
field= mysql_fetch_field(result);
@@ -4630,15 +4786,21 @@ static void test_update_meta()
mysql_field_seek(result, 0);
field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
- fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
+ }
DIE_UNLESS(strcmp(field->name, "col1") == 0);
DIE_UNLESS(strcmp(field->table, "test_prep_update") == 0);
field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col3");
- fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col3");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_update");
+ }
DIE_UNLESS(strcmp(field->name, "col3") == 0);
DIE_UNLESS(strcmp(field->table, "test_prep_update") == 0);
@@ -4694,15 +4856,21 @@ static void test_select_meta()
mysql_field_seek(result, 0);
field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
- fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col1");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
+ }
DIE_UNLESS(strcmp(field->name, "col1") == 0);
DIE_UNLESS(strcmp(field->table, "test_prep_select") == 0);
field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col2");
- fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n col obtained: `%s` (expected: `%s`)", field->name, "col2");
+ fprintf(stdout, "\n tab obtained: `%s` (expected: `%s`)", field->table, "test_prep_select");
+ }
DIE_UNLESS(strcmp(field->name, "col2") == 0);
DIE_UNLESS(strcmp(field->table, "test_prep_select") == 0);
@@ -4746,8 +4914,9 @@ static void test_func_fields()
field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table,
- "test_dateformat");
+ if (!opt_silent)
+ fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table,
+ "test_dateformat");
DIE_UNLESS(strcmp(field->table, "test_dateformat") == 0);
field= mysql_fetch_field(result);
@@ -4764,7 +4933,8 @@ static void test_func_fields()
field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table, "");
+ if (!opt_silent)
+ fprintf(stdout, "\n table name: `%s` (expected: `%s`)", field->table, "");
DIE_UNLESS(field->table[0] == '\0');
field= mysql_fetch_field(result);
@@ -4781,8 +4951,11 @@ static void test_func_fields()
field= mysql_fetch_field(result);
mytest(field);
- fprintf(stdout, "\n field name: `%s` (expected: `%s`)", field->name, "YEAR");
- fprintf(stdout, "\n field org name: `%s` (expected: `%s`)", field->org_name, "");
+ if (!opt_silent)
+ {
+ printf("\n field name: `%s` (expected: `%s`)", field->name, "YEAR");
+ printf("\n field org name: `%s` (expected: `%s`)", field->org_name, "");
+ }
DIE_UNLESS(strcmp(field->name, "YEAR") == 0);
DIE_UNLESS(field->org_name[0] == '\0');
@@ -4859,8 +5032,11 @@ static void test_multi_stmt()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]);
- fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]);
+ fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
+ }
DIE_UNLESS(id == 10);
DIE_UNLESS(strcmp(name, "mysql") == 0);
@@ -4888,8 +5064,11 @@ static void test_multi_stmt()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]);
- fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n int_data: %lu(%lu)", (ulong) id, length[0]);
+ fprintf(stdout, "\n str_data: %s(%lu)", name, length[1]);
+ }
DIE_UNLESS(id == 10);
DIE_UNLESS(strcmp(name, "updated") == 0);
@@ -4963,12 +5142,14 @@ static void test_manual_sample()
fprintf(stderr, "\n %s", mysql_error(mysql));
exit(1);
}
- fprintf(stdout, "\n prepare, insert successful");
+ if (!opt_silent)
+ fprintf(stdout, "\n prepare, insert successful");
/* Get the parameter count from the statement */
param_count= mysql_stmt_param_count(stmt);
- fprintf(stdout, "\n total parameters in insert: %d", param_count);
+ if (!opt_silent)
+ fprintf(stdout, "\n total parameters in insert: %d", param_count);
if (param_count != 3) /* validate parameter count */
{
fprintf(stderr, "\n invalid parameter count returned by MySQL");
@@ -5024,7 +5205,8 @@ static void test_manual_sample()
/* Get the total rows affected */
affected_rows= mysql_stmt_affected_rows(stmt);
- fprintf(stdout, "\n total affected rows: %lld", affected_rows);
+ if (!opt_silent)
+ fprintf(stdout, "\n total affected rows: %lld", affected_rows);
if (affected_rows != 1) /* validate affected rows */
{
fprintf(stderr, "\n invalid affected rows by MySQL");
@@ -5048,7 +5230,8 @@ static void test_manual_sample()
/* Get the total rows affected */
affected_rows= mysql_stmt_affected_rows(stmt);
- fprintf(stdout, "\n total affected rows: %lld", affected_rows);
+ if (!opt_silent)
+ fprintf(stdout, "\n total affected rows: %lld", affected_rows);
if (affected_rows != 1) /* validate affected rows */
{
fprintf(stderr, "\n invalid affected rows by MySQL");
@@ -5072,7 +5255,8 @@ static void test_manual_sample()
fprintf(stderr, "\n %s", mysql_error(mysql));
exit(1);
}
- fprintf(stdout, "Success !!!");
+ if (!opt_silent)
+ fprintf(stdout, "Success !!!");
}
@@ -5194,13 +5378,14 @@ DROP TABLE IF EXISTS test_multi_tab";
for (count= 0 ; count < array_elements(rows) ; count++)
{
- fprintf(stdout, "\n Query %d: ", count);
+ if (!opt_silent)
+ fprintf(stdout, "\n Query %d: ", count);
if ((result= mysql_store_result(mysql_local)))
{
(void) my_process_result_set(result);
mysql_free_result(result);
}
- else
+ else if (!opt_silent)
fprintf(stdout, "OK, %lld row(s) affected, %d warning(s)\n",
mysql_affected_rows(mysql_local),
mysql_warning_count(mysql_local));
@@ -5208,7 +5393,7 @@ DROP TABLE IF EXISTS test_multi_tab";
exp_value= (uint) mysql_affected_rows(mysql_local);
if (rows[count] != exp_value)
{
- fprintf(stdout, "row %d had affected rows: %d, should be %d\n",
+ fprintf(stderr, "row %d had affected rows: %d, should be %d\n",
count, exp_value, rows[count]);
exit(1);
}
@@ -5284,7 +5469,7 @@ static void test_prepare_multi_statements()
if (!(mysql_local= mysql_init(NULL)))
{
- fprintf(stdout, "\n mysql_init() failed");
+ fprintf(stderr, "\n mysql_init() failed");
exit(1);
}
@@ -5292,7 +5477,7 @@ static void test_prepare_multi_statements()
opt_password, current_db, opt_port,
opt_unix_socket, CLIENT_MULTI_STATEMENTS)))
{
- fprintf(stdout, "\n connection failed(%s)", mysql_error(mysql_local));
+ fprintf(stderr, "\n connection failed(%s)", mysql_error(mysql_local));
exit(1);
}
strmov(query, "select 1; select 'another value'");
@@ -5360,7 +5545,8 @@ static void test_store_result()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1);
DIE_UNLESS(nData == 10);
DIE_UNLESS(strcmp(szData, "venu") == 0);
DIE_UNLESS(length1 == 4);
@@ -5368,7 +5554,8 @@ static void test_store_result()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1);
DIE_UNLESS(nData == 20);
DIE_UNLESS(strcmp(szData, "mysql") == 0);
DIE_UNLESS(length1 == 5);
@@ -5377,7 +5564,7 @@ static void test_store_result()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- if (is_null[0])
+ if (!opt_silent && is_null[0])
fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1);
DIE_UNLESS(is_null[0]);
DIE_UNLESS(strcmp(szData, "monty") == 0);
@@ -5395,7 +5582,8 @@ static void test_store_result()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 1: %ld, %s(%lu)", (long) nData, szData, length1);
DIE_UNLESS(nData == 10);
DIE_UNLESS(strcmp(szData, "venu") == 0);
DIE_UNLESS(length1 == 4);
@@ -5403,7 +5591,8 @@ static void test_store_result()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 2: %ld, %s(%lu)", (long) nData, szData, length1);
DIE_UNLESS(nData == 20);
DIE_UNLESS(strcmp(szData, "mysql") == 0);
DIE_UNLESS(length1 == 5);
@@ -5412,7 +5601,7 @@ static void test_store_result()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- if (is_null[0])
+ if (!opt_silent && is_null[0])
fprintf(stdout, "\n row 3: NULL, %s(%lu)", szData, length1);
DIE_UNLESS(is_null[0]);
DIE_UNLESS(strcmp(szData, "monty") == 0);
@@ -5461,7 +5650,8 @@ static void test_store_result1()
rc= 0;
while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
rc++;
- fprintf(stdout, "\n total rows: %d", rc);
+ if (!opt_silent)
+ fprintf(stdout, "\n total rows: %d", rc);
DIE_UNLESS(rc == 3);
rc= mysql_stmt_execute(stmt);
@@ -5473,7 +5663,8 @@ static void test_store_result1()
rc= 0;
while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
rc++;
- fprintf(stdout, "\n total rows: %d", rc);
+ if (!opt_silent)
+ fprintf(stdout, "\n total rows: %d", rc);
DIE_UNLESS(rc == 3);
mysql_stmt_close(stmt);
@@ -5539,7 +5730,8 @@ static void test_store_result2()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 1: %d", nData);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 1: %d", nData);
DIE_UNLESS(nData == 10);
rc= mysql_stmt_fetch(stmt);
@@ -5556,7 +5748,8 @@ static void test_store_result2()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 1: %d", nData);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 1: %d", nData);
DIE_UNLESS(nData == 20);
rc= mysql_stmt_fetch(stmt);
@@ -5660,7 +5853,8 @@ static void test_subselect()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 1: %d", id);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 1: %d", id);
DIE_UNLESS(id == 1);
rc= mysql_stmt_fetch(stmt);
@@ -5673,7 +5867,8 @@ static void test_subselect()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 1: %d", id);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 1: %d", id);
DIE_UNLESS(id == 0);
rc= mysql_stmt_fetch(stmt);
@@ -5790,21 +5985,21 @@ static void test_bind_date_conv(uint row_count)
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n");
+ if (!opt_silent)
+ fprintf(stdout, "\n");
for (i= 0; i < array_elements(bind); i++)
{
- fprintf(stdout, "\n");
- fprintf(stdout, " time[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu",
- i, tm[i].year, tm[i].month, tm[i].day,
- tm[i].hour, tm[i].minute, tm[i].second,
- tm[i].second_part);
-
+ if (!opt_silent)
+ fprintf(stdout, "\ntime[%d]: %02d-%02d-%02d %02d:%02d:%02d.%02lu",
+ i, tm[i].year, tm[i].month, tm[i].day,
+ tm[i].hour, tm[i].minute, tm[i].second,
+ tm[i].second_part);
DIE_UNLESS(tm[i].year == 0 || tm[i].year == year+count);
DIE_UNLESS(tm[i].month == 0 || tm[i].month == month+count);
DIE_UNLESS(tm[i].day == 0 || tm[i].day == day+count);
DIE_UNLESS(tm[i].hour == 0 || tm[i].hour == hour+count);
-#if 0
+#ifdef NOT_USED
/*
minute causes problems from date<->time, don't assert, instead
validate separatly in another routine
@@ -6059,7 +6254,8 @@ static void test_buffers()
buffer[1]= 'X';
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data: %s (%lu)", buffer, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n data: %s (%lu)", buffer, length);
DIE_UNLESS(buffer[0] == 'M');
DIE_UNLESS(buffer[1] == 'X');
DIE_UNLESS(length == 5);
@@ -6070,7 +6266,8 @@ static void test_buffers()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data: %s (%lu)", buffer, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n data: %s (%lu)", buffer, length);
DIE_UNLESS(strncmp(buffer, "Database", 8) == 0);
DIE_UNLESS(length == 8);
@@ -6080,7 +6277,8 @@ static void test_buffers()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data: %s (%lu)", buffer, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n data: %s (%lu)", buffer, length);
DIE_UNLESS(strcmp(buffer, "Open-Source") == 0);
DIE_UNLESS(length == 11);
@@ -6090,7 +6288,8 @@ static void test_buffers()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data: %s (%lu)", buffer, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n data: %s (%lu)", buffer, length);
DIE_UNLESS(strncmp(buffer, "Popula", 6) == 0);
DIE_UNLESS(length == 7);
@@ -6221,7 +6420,8 @@ static void test_fetch_nobuffs()
while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
rc++;
- fprintf(stdout, "\n total rows : %d", rc);
+ if (!opt_silent)
+ fprintf(stdout, "\n total rows : %d", rc);
DIE_UNLESS(rc == 1);
bind[0].buffer_type= MYSQL_TYPE_STRING;
@@ -6244,12 +6444,16 @@ static void test_fetch_nobuffs()
while (mysql_stmt_fetch(stmt) != MYSQL_NO_DATA)
{
rc++;
- fprintf(stdout, "\n CURRENT_DATABASE(): %s", str[0]);
- fprintf(stdout, "\n CURRENT_USER() : %s", str[1]);
- fprintf(stdout, "\n CURRENT_DATE() : %s", str[2]);
- fprintf(stdout, "\n CURRENT_TIME() : %s", str[3]);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n CURRENT_DATABASE(): %s", str[0]);
+ fprintf(stdout, "\n CURRENT_USER() : %s", str[1]);
+ fprintf(stdout, "\n CURRENT_DATE() : %s", str[2]);
+ fprintf(stdout, "\n CURRENT_TIME() : %s", str[3]);
+ }
}
- fprintf(stdout, "\n total rows : %d", rc);
+ if (!opt_silent)
+ fprintf(stdout, "\n total rows : %d", rc);
DIE_UNLESS(rc == 1);
mysql_stmt_close(stmt);
@@ -6316,10 +6520,13 @@ static void test_ushort_bug()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n ushort : %d (%ld)", short_value, s_length);
- fprintf(stdout, "\n ulong : %lu (%ld)", (ulong) long_value, l_length);
- fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
- fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n ushort : %d (%ld)", short_value, s_length);
+ fprintf(stdout, "\n ulong : %lu (%ld)", (ulong) long_value, l_length);
+ fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
+ }
DIE_UNLESS(short_value == 35999);
DIE_UNLESS(s_length == 2);
@@ -6400,10 +6607,13 @@ static void test_sshort_bug()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length);
- fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length);
- fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
- fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length);
+ fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length);
+ fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
+ }
DIE_UNLESS(short_value == -5999);
DIE_UNLESS(s_length == 2);
@@ -6484,10 +6694,13 @@ static void test_stiny_bug()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length);
- fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length);
- fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
- fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "\n sshort : %d (%ld)", short_value, s_length);
+ fprintf(stdout, "\n slong : %ld (%ld)", (long) long_value, l_length);
+ fprintf(stdout, "\n longlong : %lld (%ld)", longlong_value, ll_length);
+ fprintf(stdout, "\n tinyint : %d (%ld)", tiny_value, t_length);
+ }
DIE_UNLESS(short_value == -128);
DIE_UNLESS(s_length == 2);
@@ -6576,7 +6789,8 @@ static void test_field_misc()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n default table type: %s(%ld)", table_type, type_length);
+ if (!opt_silent)
+ fprintf(stdout, "\n default table type: %s(%ld)", table_type, type_length);
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
@@ -6597,7 +6811,8 @@ static void test_field_misc()
verify_prepare_field(result, 0,
"@@table_type", "", /* field and its org name */
- MYSQL_TYPE_STRING, /* field type */
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
"", "", /* table and its org name */
"", type_length*3, 0); /* db name, length */
@@ -6696,7 +6911,8 @@ static void test_set_option()
rc= mysql_query(mysql, "INSERT INTO test_limit VALUES(10), (20), (30), (40)");
myquery(rc);
- fprintf(stdout, "\n with SQL_SELECT_LIMIT= 2 (direct)");
+ if (!opt_silent)
+ fprintf(stdout, "\n with SQL_SELECT_LIMIT= 2 (direct)");
rc= mysql_query(mysql, "SELECT * FROM test_limit");
myquery(rc);
@@ -6708,7 +6924,8 @@ static void test_set_option()
mysql_free_result(result);
- fprintf(stdout, "\n with SQL_SELECT_LIMIT=2 (prepare)");
+ if (!opt_silent)
+ fprintf(stdout, "\n with SQL_SELECT_LIMIT=2 (prepare)");
stmt= mysql_simple_prepare(mysql, "SELECT * FROM test_limit");
check_stmt(stmt);
@@ -6721,7 +6938,8 @@ static void test_set_option()
mysql_stmt_close(stmt);
/* RESET the LIMIT the rows count to 0 */
- fprintf(stdout, "\n with SQL_SELECT_LIMIT=DEFAULT (prepare)");
+ if (!opt_silent)
+ fprintf(stdout, "\n with SQL_SELECT_LIMIT=DEFAULT (prepare)");
rc= mysql_query(mysql, "SET OPTION SQL_SELECT_LIMIT=DEFAULT");
myquery(rc);
@@ -6779,7 +6997,8 @@ static void test_prepare_grant()
MYSQL *org_mysql= mysql, *lmysql;
MYSQL_STMT *stmt;
- fprintf(stdout, "\n Establishing a test connection ...");
+ if (!opt_silent)
+ fprintf(stdout, "\n Establishing a test connection ...");
if (!(lmysql= mysql_init(NULL)))
{
myerror("mysql_init() failed");
@@ -6793,7 +7012,8 @@ static void test_prepare_grant()
mysql_close(lmysql);
exit(1);
}
- fprintf(stdout, " OK");
+ if (!opt_silent)
+ fprintf(stdout, " OK");
mysql= lmysql;
rc= mysql_query(mysql, "INSERT INTO test_grant VALUES(NULL)");
@@ -6880,14 +7100,16 @@ static void test_frm_bug()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data directory: %s", data_dir);
+ if (!opt_silent)
+ fprintf(stdout, "\n data directory: %s", data_dir);
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
strxmov(test_frm, data_dir, "/", current_db, "/", "test_frm_bug.frm", NullS);
- fprintf(stdout, "\n test_frm: %s", test_frm);
+ if (!opt_silent)
+ fprintf(stdout, "\n test_frm: %s", test_frm);
if (!(test_file= my_fopen(test_frm, (int) (O_RDWR | O_CREAT), MYF(MY_WME))))
{
@@ -6895,7 +7117,8 @@ static void test_frm_bug()
fprintf(stdout, "\n test cancelled");
exit(1);
}
- fprintf(test_file, "this is a junk file for test");
+ if (!opt_silent)
+ fprintf(test_file, "this is a junk file for test");
rc= mysql_query(mysql, "SHOW TABLE STATUS like 'test_frm_bug'");
myquery(rc);
@@ -6911,7 +7134,8 @@ static void test_frm_bug()
row= mysql_fetch_row(result);
mytest(row);
- fprintf(stdout, "\n Comment: %s", row[17]);
+ if (!opt_silent)
+ fprintf(stdout, "\n Comment: %s", row[17]);
DIE_UNLESS(row[17] != 0);
mysql_free_result(result);
@@ -6974,7 +7198,8 @@ static void test_decimal_bug()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data: %s", data);
+ if (!opt_silent)
+ fprintf(stdout, "\n data: %s", data);
DIE_UNLESS(strcmp(data, "8.00") == 0);
rc= mysql_stmt_fetch(stmt);
@@ -6991,7 +7216,8 @@ static void test_decimal_bug()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data: %s", data);
+ if (!opt_silent)
+ fprintf(stdout, "\n data: %s", data);
DIE_UNLESS(strcmp(data, "5.61") == 0);
rc= mysql_stmt_fetch(stmt);
@@ -7015,7 +7241,8 @@ static void test_decimal_bug()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n data: %s", data);
+ if (!opt_silent)
+ fprintf(stdout, "\n data: %s", data);
DIE_UNLESS(strcmp(data, "10.22") == 0);
rc= mysql_stmt_fetch(stmt);
@@ -7055,27 +7282,38 @@ static void test_explain_bug()
result= mysql_stmt_result_metadata(stmt);
mytest(result);
- fprintf(stdout, "\n total fields in the result: %d",
- mysql_num_fields(result));
+ if (!opt_silent)
+ fprintf(stdout, "\n total fields in the result: %d",
+ mysql_num_fields(result));
DIE_UNLESS(6 == mysql_num_fields(result));
- verify_prepare_field(result, 0, "Field", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", NAME_LEN, 0);
+ verify_prepare_field(result, 0, "Field", "COLUMN_NAME",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 192, 0);
- verify_prepare_field(result, 1, "Type", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", 40, 0);
+ verify_prepare_field(result, 1, "Type", "COLUMN_TYPE",
+ MYSQL_TYPE_BLOB, 0, 0, "", 0, 0);
- verify_prepare_field(result, 2, "Null", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", 1, 0);
+ verify_prepare_field(result, 2, "Null", "IS_NULLABLE",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 9, 0);
- verify_prepare_field(result, 3, "Key", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", 3, 0);
+ verify_prepare_field(result, 3, "Key", "COLUMN_KEY",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 9, 0);
- verify_prepare_field(result, 4, "Default", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", NAME_LEN, 0);
+ verify_prepare_field(result, 4, "Default", "COLUMN_DEFAULT",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 192, 0);
- verify_prepare_field(result, 5, "Extra", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", 20, 0);
+ verify_prepare_field(result, 5, "Extra", "EXTRA",
+ mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_STRING : MYSQL_TYPE_VAR_STRING,
+ 0, 0, "", 60, 0);
mysql_free_result(result);
mysql_stmt_close(stmt);
@@ -7092,8 +7330,9 @@ static void test_explain_bug()
result= mysql_stmt_result_metadata(stmt);
mytest(result);
- fprintf(stdout, "\n total fields in the result: %d",
- mysql_num_fields(result));
+ if (!opt_silent)
+ fprintf(stdout, "\n total fields in the result: %d",
+ mysql_num_fields(result));
DIE_UNLESS(10 == mysql_num_fields(result));
verify_prepare_field(result, 0, "id", "", MYSQL_TYPE_LONGLONG,
@@ -7114,8 +7353,12 @@ static void test_explain_bug()
verify_prepare_field(result, 5, "key", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN, 0);
- verify_prepare_field(result, 6, "key_len", "", MYSQL_TYPE_VAR_STRING,
- "", "", "", NAME_LEN*MAX_KEY, 0);
+ verify_prepare_field(result, 6, "key_len", "",
+ (mysql_get_server_version(mysql) <= 50000 ?
+ MYSQL_TYPE_LONGLONG : MYSQL_TYPE_VAR_STRING),
+ "", "", "",
+ (mysql_get_server_version(mysql) <= 50000 ? 3 : 4096),
+ 0);
verify_prepare_field(result, 7, "ref", "", MYSQL_TYPE_VAR_STRING,
"", "", "", NAME_LEN*16, 0);
@@ -7141,11 +7384,14 @@ static void test_explain_bug()
static void check_errcode(const unsigned int err)
{
- if (mysql->server_version)
- fprintf(stdout, "\n [MySQL-%s]", mysql->server_version);
- else
- fprintf(stdout, "\n [MySQL]");
- fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql));
+ if (!opt_silent || mysql_errno(mysql) != err)
+ {
+ if (mysql->server_version)
+ fprintf(stdout, "\n [MySQL-%s]", mysql->server_version);
+ else
+ fprintf(stdout, "\n [MySQL]");
+ fprintf(stdout, "[%d] %s\n", mysql_errno(mysql), mysql_error(mysql));
+ }
DIE_UNLESS(mysql_errno(mysql) == err);
}
@@ -7191,7 +7437,8 @@ static void test_drop_temp()
{
MYSQL *org_mysql= mysql, *lmysql;
- fprintf(stdout, "\n Establishing a test connection ...");
+ if (!opt_silent)
+ fprintf(stdout, "\n Establishing a test connection ...");
if (!(lmysql= mysql_init(NULL)))
{
myerror("mysql_init() failed");
@@ -7210,7 +7457,8 @@ static void test_drop_temp()
mysql_close(lmysql);
exit(1);
}
- fprintf(stdout, " OK");
+ if (!opt_silent)
+ fprintf(stdout, " OK");
mysql= lmysql;
rc= mysql_query(mysql, "INSERT INTO t1 VALUES(10, 'C')");
@@ -7279,14 +7527,16 @@ static void test_cuted_rows()
myquery(rc);
count= mysql_warning_count(mysql);
- fprintf(stdout, "\n total warnings: %d", count);
+ if (!opt_silent)
+ fprintf(stdout, "\n total warnings: %d", count);
DIE_UNLESS(count == 0);
rc= mysql_query(mysql, "INSERT INTO t2 SELECT * FROM t1");
myquery(rc);
count= mysql_warning_count(mysql);
- fprintf(stdout, "\n total warnings: %d", count);
+ if (!opt_silent)
+ fprintf(stdout, "\n total warnings: %d", count);
DIE_UNLESS(count == 2);
rc= mysql_query(mysql, "SHOW WARNINGS");
@@ -7303,7 +7553,8 @@ static void test_cuted_rows()
myquery(rc);
count= mysql_warning_count(mysql);
- fprintf(stdout, "\n total warnings: %d", count);
+ if (!opt_silent)
+ fprintf(stdout, "\n total warnings: %d", count);
DIE_UNLESS(count == 2);
rc= mysql_query(mysql, "SHOW WARNINGS");
@@ -7416,17 +7667,21 @@ static void test_logs()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n id : %d", id);
- fprintf(stdout, "\n name : %s(%ld)", data, length);
+ if (!opt_silent)
+ {
+ fprintf(stdout, "id : %d\n", id);
+ fprintf(stdout, "name : %s(%ld)\n", data, length);
+ }
DIE_UNLESS(id == 9876);
- DIE_UNLESS(length == 19); /* Due to VARCHAR(20) */
- DIE_UNLESS(strcmp(data, "MySQL - Open Source") == 0);
+ DIE_UNLESS(length == 19 || length == 20); /* Due to VARCHAR(20) */
+ DIE_UNLESS(is_prefix(data, "MySQL - Open Source") == 1);
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n name : %s(%ld)", data, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n name : %s(%ld)", data, length);
DIE_UNLESS(length == 1);
DIE_UNLESS(strcmp(data, "'") == 0);
@@ -7434,7 +7689,8 @@ static void test_logs()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n name : %s(%ld)", data, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n name : %s(%ld)", data, length);
DIE_UNLESS(length == 1);
DIE_UNLESS(strcmp(data, "\"") == 0);
@@ -7442,7 +7698,8 @@ static void test_logs()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n name : %s(%ld)", data, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n name : %s(%ld)", data, length);
DIE_UNLESS(length == 7);
DIE_UNLESS(strcmp(data, "my\'sql\'") == 0);
@@ -7450,7 +7707,8 @@ static void test_logs()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n name : %s(%ld)", data, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n name : %s(%ld)", data, length);
DIE_UNLESS(length == 7);
/*DIE_UNLESS(strcmp(data, "my\"sql\"") == 0); */
@@ -7496,7 +7754,8 @@ static void test_nstmts()
for (i= 0; i < total_stmts; i++)
{
- fprintf(stdout, "\r stmt: %d", i);
+ if (!opt_silent)
+ fprintf(stdout, "\r stmt: %d", i);
strmov(query, "insert into test_nstmts values(?)");
stmt= mysql_simple_prepare(mysql, query);
@@ -7523,7 +7782,8 @@ static void test_nstmts()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n total rows: %d", i);
+ if (!opt_silent)
+ fprintf(stdout, "\n total rows: %d", i);
DIE_UNLESS( i == total_stmts);
rc= mysql_stmt_fetch(stmt);
@@ -7548,17 +7808,17 @@ static void test_fetch_seek()
char c2[11], c3[20];
myheader("test_fetch_seek");
+ rc= mysql_query(mysql, "drop table if exists t1");
- rc= mysql_query(mysql, "drop table if exists test_seek");
myquery(rc);
- rc= mysql_query(mysql, "create table test_seek(c1 int primary key auto_increment, c2 char(10), c3 timestamp(14))");
+ rc= mysql_query(mysql, "create table t1(c1 int primary key auto_increment, c2 char(10), c3 timestamp(14))");
myquery(rc);
- rc= mysql_query(mysql, "insert into test_seek(c2) values('venu'), ('mysql'), ('open'), ('source')");
+ rc= mysql_query(mysql, "insert into t1(c2) values('venu'), ('mysql'), ('open'), ('source')");
myquery(rc);
- stmt= mysql_simple_prepare(mysql, "select * from test_seek");
+ stmt= mysql_simple_prepare(mysql, "select * from t1");
check_stmt(stmt);
bind[0].buffer_type= MYSQL_TYPE_LONG;
@@ -7589,7 +7849,8 @@ static void test_fetch_seek()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3);
row= mysql_stmt_row_tell(stmt);
@@ -7598,21 +7859,24 @@ static void test_fetch_seek()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3);
row= mysql_stmt_row_seek(stmt, row);
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 2: %ld, %s, %s", (long) c1, c2, c3);
mysql_stmt_data_seek(stmt, 0);
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 0: %ld, %s, %s", (long) c1, c2, c3);
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
@@ -7627,6 +7891,7 @@ static void test_fetch_seek()
DIE_UNLESS(rc == MYSQL_NO_DATA);
mysql_stmt_close(stmt);
+ myquery(mysql_query(mysql, "drop table t1"));
}
@@ -7644,16 +7909,16 @@ static void test_fetch_offset()
myheader("test_fetch_offset");
- rc= mysql_query(mysql, "drop table if exists test_column");
+ rc= mysql_query(mysql, "drop table if exists t1");
myquery(rc);
- rc= mysql_query(mysql, "create table test_column(a char(10))");
+ rc= mysql_query(mysql, "create table t1(a char(10))");
myquery(rc);
- rc= mysql_query(mysql, "insert into test_column values('abcdefghij'), (null)");
+ rc= mysql_query(mysql, "insert into t1 values('abcdefghij'), (null)");
myquery(rc);
- stmt= mysql_simple_prepare(mysql, "select * from test_column");
+ stmt= mysql_simple_prepare(mysql, "select * from t1");
check_stmt(stmt);
bind[0].buffer_type= MYSQL_TYPE_STRING;
@@ -7680,17 +7945,20 @@ static void test_fetch_offset()
data[0]= '\0';
rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 1: %s (%ld)", data, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 1: %s (%ld)", data, length);
DIE_UNLESS(strncmp(data, "abcd", 4) == 0 && length == 10);
rc= mysql_stmt_fetch_column(stmt, bind, 0, 5);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 1: %s (%ld)", data, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 1: %s (%ld)", data, length);
DIE_UNLESS(strncmp(data, "fg", 2) == 0 && length == 10);
rc= mysql_stmt_fetch_column(stmt, bind, 0, 9);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 0: %s (%ld)", data, length);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 0: %s (%ld)", data, length);
DIE_UNLESS(strncmp(data, "j", 1) == 0 && length == 10);
rc= mysql_stmt_fetch(stmt);
@@ -7710,6 +7978,8 @@ static void test_fetch_offset()
check_execute_r(stmt, rc);
mysql_stmt_close(stmt);
+
+ myquery(mysql_query(mysql, "drop table t1"));
}
@@ -7725,16 +7995,16 @@ static void test_fetch_column()
myheader("test_fetch_column");
- rc= mysql_query(mysql, "drop table if exists test_column");
+ rc= mysql_query(mysql, "drop table if exists t1");
myquery(rc);
- rc= mysql_query(mysql, "create table test_column(c1 int primary key auto_increment, c2 char(10))");
+ rc= mysql_query(mysql, "create table t1(c1 int primary key auto_increment, c2 char(10))");
myquery(rc);
- rc= mysql_query(mysql, "insert into test_column(c2) values('venu'), ('mysql')");
+ rc= mysql_query(mysql, "insert into t1(c2) values('venu'), ('mysql')");
myquery(rc);
- stmt= mysql_simple_prepare(mysql, "select * from test_column order by c2 desc");
+ stmt= mysql_simple_prepare(mysql, "select * from t1 order by c2 desc");
check_stmt(stmt);
bind[0].buffer_type= MYSQL_TYPE_LONG;
@@ -7763,7 +8033,8 @@ static void test_fetch_column()
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 0: %d, %s", bc1, bc2);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 0: %d, %s", bc1, bc2);
c2[0]= '\0'; l2= 0;
bind[0].buffer_type= MYSQL_TYPE_STRING;
@@ -7774,13 +8045,15 @@ static void test_fetch_column()
rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
DIE_UNLESS(strncmp(c2, "venu", 4) == 0 && l2 == 4);
c2[0]= '\0'; l2= 0;
rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
DIE_UNLESS(strcmp(c2, "venu") == 0 && l2 == 4);
c1= 0;
@@ -7792,13 +8065,15 @@ static void test_fetch_column()
rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 0: %d(%ld)", c1, l1);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 0: %d(%ld)", c1, l1);
DIE_UNLESS(c1 == 1 && l1 == 4);
rc= mysql_stmt_fetch(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "\n row 1: %d, %s", bc1, bc2);
+ if (!opt_silent)
+ fprintf(stdout, "\n row 1: %d, %s", bc1, bc2);
c2[0]= '\0'; l2= 0;
bind[0].buffer_type= MYSQL_TYPE_STRING;
@@ -7809,13 +8084,15 @@ static void test_fetch_column()
rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
DIE_UNLESS(strncmp(c2, "mysq", 4) == 0 && l2 == 5);
c2[0]= '\0'; l2= 0;
rc= mysql_stmt_fetch_column(stmt, bind, 1, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 1: %si(%ld)", c2, l2);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 1: %si(%ld)", c2, l2);
DIE_UNLESS(strcmp(c2, "mysql") == 0 && l2 == 5);
c1= 0;
@@ -7827,7 +8104,8 @@ static void test_fetch_column()
rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 0: %d(%ld)", c1, l1);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 0: %d(%ld)", c1, l1);
DIE_UNLESS(c1 == 2 && l1 == 4);
rc= mysql_stmt_fetch(stmt);
@@ -7837,6 +8115,7 @@ static void test_fetch_column()
check_execute_r(stmt, rc);
mysql_stmt_close(stmt);
+ myquery(mysql_query(mysql, "drop table t1"));
}
@@ -7848,27 +8127,28 @@ static void test_list_fields()
int rc;
myheader("test_list_fields");
- rc= mysql_query(mysql, "drop table if exists test_list_fields");
+ rc= mysql_query(mysql, "drop table if exists t1");
myquery(rc);
- rc= mysql_query(mysql, "create table test_list_fields(c1 int primary key auto_increment, c2 char(10) default 'mysql')");
+ rc= mysql_query(mysql, "create table t1(c1 int primary key auto_increment, c2 char(10) default 'mysql')");
myquery(rc);
- result= mysql_list_fields(mysql, "test_list_fields", NULL);
+ result= mysql_list_fields(mysql, "t1", NULL);
mytest(result);
rc= my_process_result_set(result);
DIE_UNLESS(rc == 0);
verify_prepare_field(result, 0, "c1", "c1", MYSQL_TYPE_LONG,
- "test_list_fields", "test_list_fields",
+ "t1", "t1",
current_db, 11, "0");
verify_prepare_field(result, 1, "c2", "c2", MYSQL_TYPE_STRING,
- "test_list_fields", "test_list_fields",
+ "t1", "t1",
current_db, 10, "mysql");
mysql_free_result(result);
+ myquery(mysql_query(mysql, "drop table t1"));
}
@@ -7881,7 +8161,6 @@ static void test_mem_overun()
MYSQL_RES *field_res;
int rc, i, length;
-
myheader("test_mem_overun");
/*
@@ -7931,7 +8210,8 @@ static void test_mem_overun()
field_res= mysql_stmt_result_metadata(stmt);
mytest(field_res);
- fprintf(stdout, "\n total fields : %d", mysql_num_fields(field_res));
+ if (!opt_silent)
+ fprintf(stdout, "\n total fields : %d", mysql_num_fields(field_res));
DIE_UNLESS( 1000 == mysql_num_fields(field_res));
rc= mysql_stmt_store_result(stmt);
@@ -7998,7 +8278,8 @@ static void test_free_result()
rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 0: %s(%ld)", c2, l2);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 0: %s(%ld)", c2, l2);
DIE_UNLESS(strncmp(c2, "1", 1) == 0 && l2 == 1);
rc= mysql_stmt_fetch(stmt);
@@ -8013,7 +8294,8 @@ static void test_free_result()
rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 0: %d(%ld)", c1, l2);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 0: %d(%ld)", c1, l2);
DIE_UNLESS(c1 == 2 && l2 == 4);
rc= mysql_query(mysql, "drop table test_free_result");
@@ -8080,7 +8362,8 @@ static void test_free_store_result()
rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 1: %s(%ld)", c2, l2);
DIE_UNLESS(strncmp(c2, "1", 1) == 0 && l2 == 1);
rc= mysql_stmt_fetch(stmt);
@@ -8095,7 +8378,8 @@ static void test_free_store_result()
rc= mysql_stmt_fetch_column(stmt, bind, 0, 0);
check_execute(stmt, rc);
- fprintf(stdout, "\n col 0: %d(%ld)", c1, l2);
+ if (!opt_silent)
+ fprintf(stdout, "\n col 0: %d(%ld)", c1, l2);
DIE_UNLESS(c1 == 2 && l2 == 4);
rc= mysql_stmt_free_result(stmt);
@@ -8127,16 +8411,19 @@ static void test_sqlmode()
/* PIPES_AS_CONCAT */
strcpy(query, "SET SQL_MODE= \"PIPES_AS_CONCAT\"");
- fprintf(stdout, "\n With %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n With %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
- fprintf(stdout, "\n query: %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt));
+ if (!opt_silent)
+ fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt));
/*
We need to bzero bind structure because mysql_stmt_bind_param checks all
@@ -8166,21 +8453,25 @@ static void test_sqlmode()
myquery(rc);
strcpy(query, "SELECT connection_id ()");
- fprintf(stdout, "\n query: %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
check_stmt_r(stmt);
/* ANSI */
strcpy(query, "SET SQL_MODE= \"ANSI\"");
- fprintf(stdout, "\n With %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n With %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
strcpy(query, "INSERT INTO test_piping VALUES(?||?)");
- fprintf(stdout, "\n query: %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
- fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt));
+ if (!opt_silent)
+ fprintf(stdout, "\n total parameters: %ld", mysql_stmt_param_count(stmt));
rc= mysql_stmt_bind_param(stmt, bind);
check_execute(stmt, rc);
@@ -8194,7 +8485,8 @@ static void test_sqlmode()
/* ANSI mode spaces ... */
strcpy(query, "SELECT connection_id ()");
- fprintf(stdout, "\n query: %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
@@ -8206,18 +8498,21 @@ static void test_sqlmode()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
- fprintf(stdout, "\n returned 1 row\n");
+ if (!opt_silent)
+ fprintf(stdout, "\n returned 1 row\n");
mysql_stmt_close(stmt);
/* IGNORE SPACE MODE */
strcpy(query, "SET SQL_MODE= \"IGNORE_SPACE\"");
- fprintf(stdout, "\n With %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n With %s", query);
rc= mysql_query(mysql, query);
myquery(rc);
strcpy(query, "SELECT connection_id ()");
- fprintf(stdout, "\n query: %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n query: %s", query);
stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
@@ -8229,7 +8524,8 @@ static void test_sqlmode()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
- fprintf(stdout, "\n returned 1 row");
+ if (!opt_silent)
+ fprintf(stdout, "\n returned 1 row");
mysql_stmt_close(stmt);
}
@@ -8321,7 +8617,8 @@ static void test_ts()
sprintf(query, "SELECT a, b, c FROM test_ts WHERE %c=?", name);
- fprintf(stdout, "\n %s", query);
+ if (!opt_silent)
+ fprintf(stdout, "\n %s", query);
stmt= mysql_simple_prepare(mysql, query);
check_stmt(stmt);
@@ -8334,7 +8631,8 @@ static void test_ts()
while (mysql_stmt_fetch(stmt) == 0)
row_count++;
- fprintf(stdout, "\n returned '%d' rows", row_count);
+ if (!opt_silent)
+ fprintf(stdout, "\n returned '%d' rows", row_count);
DIE_UNLESS(row_count == 2);
mysql_stmt_close(stmt);
}
@@ -8476,7 +8774,8 @@ static void test_bug1946()
check_stmt(stmt);
rc= mysql_real_query(mysql, query, strlen(query));
DIE_UNLESS(rc != 0);
- fprintf(stdout, "Got error (as expected):\n");
+ if (!opt_silent)
+ fprintf(stdout, "Got error (as expected):\n");
myerror(NULL);
mysql_stmt_close(stmt);
@@ -8494,19 +8793,23 @@ static void test_parse_error_and_bad_length()
rc= mysql_query(mysql, "SHOW DATABAAAA");
DIE_UNLESS(rc);
- fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
+ if (!opt_silent)
+ fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
rc= mysql_real_query(mysql, "SHOW DATABASES", 100);
DIE_UNLESS(rc);
- fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
+ if (!opt_silent)
+ fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
stmt= mysql_simple_prepare(mysql, "SHOW DATABAAAA");
DIE_UNLESS(!stmt);
- fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
+ if (!opt_silent)
+ fprintf(stdout, "Got error (as expected): '%s'\n", mysql_error(mysql));
stmt= mysql_stmt_init(mysql);
DIE_UNLESS(stmt);
rc= mysql_stmt_prepare(stmt, "SHOW DATABASES", 100);
DIE_UNLESS(rc != 0);
- fprintf(stdout, "Got error (as expected): '%s'\n", mysql_stmt_error(stmt));
+ if (!opt_silent)
+ fprintf(stdout, "Got error (as expected): '%s'\n", mysql_stmt_error(stmt));
mysql_stmt_close(stmt);
}
@@ -8527,7 +8830,8 @@ static void test_bug2247()
myheader("test_bug2247");
- fprintf(stdout, "\nChecking if stmt_affected_rows is not affected by\n"
+ if (!opt_silent)
+ fprintf(stdout, "\nChecking if stmt_affected_rows is not affected by\n"
"mysql_query ... ");
/* create table and insert few rows */
rc= mysql_query(mysql, drop);
@@ -8584,7 +8888,8 @@ static void test_bug2247()
DIE_UNLESS(mysql_stmt_affected_rows(stmt) == exp_count);
mysql_stmt_close(stmt);
- fprintf(stdout, "OK");
+ if (!opt_silent)
+ fprintf(stdout, "OK");
}
@@ -8862,7 +9167,8 @@ static void test_bug3117()
check_execute(stmt, rc);
DIE_UNLESS(is_null == 0 && lii == 1);
- fprintf(stdout, "\n\tLAST_INSERT_ID()= 1 ok\n");
+ if (!opt_silent)
+ fprintf(stdout, "\n\tLAST_INSERT_ID()= 1 ok\n");
rc= mysql_query(mysql, "INSERT INTO t1 VALUES (NULL)");
myquery(rc);
@@ -8874,7 +9180,8 @@ static void test_bug3117()
check_execute(stmt, rc);
DIE_UNLESS(is_null == 0 && lii == 2);
- fprintf(stdout, "\tLAST_INSERT_ID()= 2 ok\n");
+ if (!opt_silent)
+ fprintf(stdout, "\tLAST_INSERT_ID()= 2 ok\n");
mysql_stmt_close(stmt);
@@ -9024,7 +9331,8 @@ static void test_create_drop()
{
rc= mysql_stmt_execute(stmt_create);
check_execute(stmt_create, rc);
- fprintf(stdout, "created %i\n", i);
+ if (!opt_silent)
+ fprintf(stdout, "created %i\n", i);
rc= mysql_stmt_execute(stmt_select);
check_execute(stmt_select, rc);
@@ -9033,11 +9341,13 @@ static void test_create_drop()
rc= mysql_stmt_execute(stmt_drop);
check_execute(stmt_drop, rc);
- fprintf(stdout, "droped %i\n", i);
+ if (!opt_silent)
+ fprintf(stdout, "droped %i\n", i);
rc= mysql_stmt_execute(stmt_create_select);
check_execute(stmt_create, rc);
- fprintf(stdout, "created select %i\n", i);
+ if (!opt_silent)
+ fprintf(stdout, "created select %i\n", i);
rc= mysql_stmt_execute(stmt_select);
check_execute(stmt_select, rc);
@@ -9046,7 +9356,8 @@ static void test_create_drop()
rc= mysql_stmt_execute(stmt_drop);
check_execute(stmt_drop, rc);
- fprintf(stdout, "droped %i\n", i);
+ if (!opt_silent)
+ fprintf(stdout, "droped %i\n", i);
}
mysql_stmt_close(stmt_create);
@@ -9077,25 +9388,29 @@ static void test_rename()
rc= mysql_stmt_execute(stmt);
check_execute_r(stmt, rc);
- fprintf(stdout, "rename without t3\n");
+ if (!opt_silent)
+ fprintf(stdout, "rename without t3\n");
rc= mysql_query(mysql, "create table t3 (a int)");
myquery(rc);
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "rename with t3\n");
+ if (!opt_silent)
+ fprintf(stdout, "rename with t3\n");
rc= mysql_stmt_execute(stmt);
check_execute_r(stmt, rc);
- fprintf(stdout, "rename renamed\n");
+ if (!opt_silent)
+ fprintf(stdout, "rename renamed\n");
rc= mysql_query(mysql, "rename table t2 to t1, t4 to t3");
myquery(rc);
rc= mysql_stmt_execute(stmt);
check_execute(stmt, rc);
- fprintf(stdout, "rename reverted\n");
+ if (!opt_silent)
+ fprintf(stdout, "rename reverted\n");
mysql_stmt_close(stmt);
@@ -9129,10 +9444,12 @@ static void test_do_set()
{
rc= mysql_stmt_execute(stmt_do);
check_execute(stmt_do, rc);
- fprintf(stdout, "do %i\n", i);
+ if (!opt_silent)
+ fprintf(stdout, "do %i\n", i);
rc= mysql_stmt_execute(stmt_set);
check_execute(stmt_set, rc);
- fprintf(stdout, "set %i\n", i);
+ if (!opt_silent)
+ fprintf(stdout, "set %i\n", i);
}
mysql_stmt_close(stmt_do);
@@ -9198,11 +9515,13 @@ static void test_multi()
rc= mysql_stmt_execute(stmt_update);
check_execute(stmt_update, rc);
- fprintf(stdout, "update %ld\n", (long) param);
+ if (!opt_silent)
+ fprintf(stdout, "update %ld\n", (long) param);
rc= mysql_stmt_execute(stmt_delete);
check_execute(stmt_delete, rc);
- fprintf(stdout, "delete %ld\n", (long) param);
+ if (!opt_silent)
+ fprintf(stdout, "delete %ld\n", (long) param);
rc= mysql_stmt_execute(stmt_select1);
check_execute(stmt_select1, rc);
@@ -9258,7 +9577,8 @@ static void test_insert_select()
{
rc= mysql_stmt_execute(stmt_insert);
check_execute(stmt_insert, rc);
- fprintf(stdout, "insert %u\n", i);
+ if (!opt_silent)
+ fprintf(stdout, "insert %u\n", i);
rc= mysql_stmt_execute(stmt_select);
check_execute(stmt_select, rc);
@@ -10118,7 +10438,8 @@ static void test_bug3796()
mysql_stmt_bind_result(stmt, bind);
rc= mysql_stmt_fetch(stmt);
- printf("Concat result: '%s'\n", out_buff);
+ if (!opt_silent)
+ printf("Concat result: '%s'\n", out_buff);
check_execute(stmt, rc);
strcpy(canonical_buff, concat_arg0);
strcat(canonical_buff, "ONE");
@@ -10130,7 +10451,8 @@ static void test_bug3796()
strcpy(canonical_buff + strlen(concat_arg0), "TWO");
DIE_UNLESS(strlen(canonical_buff) == out_length &&
strncmp(out_buff, canonical_buff, out_length) == 0);
- printf("Concat result: '%s'\n", out_buff);
+ if (!opt_silent)
+ printf("Concat result: '%s'\n", out_buff);
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == MYSQL_NO_DATA);
@@ -10204,12 +10526,15 @@ static void test_bug4026()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == 0);
- printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second,
- time_out.second_part);
- printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month,
- datetime_out.day, datetime_out.hour,
- datetime_out.minute, datetime_out.second,
- datetime_out.second_part);
+ if (!opt_silent)
+ {
+ printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second,
+ time_out.second_part);
+ printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month,
+ datetime_out.day, datetime_out.hour,
+ datetime_out.minute, datetime_out.second,
+ datetime_out.second_part);
+ }
DIE_UNLESS(memcmp(&time_in, &time_out, sizeof(time_in)) == 0);
DIE_UNLESS(memcmp(&datetime_in, &datetime_out, sizeof(datetime_in)) == 0);
mysql_stmt_close(stmt);
@@ -10252,8 +10577,9 @@ static void test_bug4079()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc != 0 && rc != MYSQL_NO_DATA);
- printf("Got error from mysql_stmt_fetch (as expected):\n%s\n",
- mysql_stmt_error(stmt));
+ if (!opt_silent)
+ printf("Got error from mysql_stmt_fetch (as expected):\n%s\n",
+ mysql_stmt_error(stmt));
/* buggy version of libmysql hanged up here */
mysql_stmt_close(stmt);
}
@@ -10347,13 +10673,16 @@ static void test_bug4030()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == 0);
- printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second,
- time_out.second_part);
- printf("%d-%d-%d\n", date_out.year, date_out.month, date_out.day);
- printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month,
- datetime_out.day, datetime_out.hour,
- datetime_out.minute, datetime_out.second,
- datetime_out.second_part);
+ if (!opt_silent)
+ {
+ printf("%d:%d:%d.%lu\n", time_out.hour, time_out.minute, time_out.second,
+ time_out.second_part);
+ printf("%d-%d-%d\n", date_out.year, date_out.month, date_out.day);
+ printf("%d-%d-%d %d:%d:%d.%lu\n", datetime_out.year, datetime_out.month,
+ datetime_out.day, datetime_out.hour,
+ datetime_out.minute, datetime_out.second,
+ datetime_out.second_part);
+ }
DIE_UNLESS(memcmp(&time_canonical, &time_out, sizeof(time_out)) == 0);
DIE_UNLESS(memcmp(&date_canonical, &date_out, sizeof(date_out)) == 0);
DIE_UNLESS(memcmp(&datetime_canonical, &datetime_out, sizeof(datetime_out)) == 0);
@@ -10755,7 +11084,8 @@ static void test_bug5126()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == 0);
DIE_UNLESS(c1 == 8386608 && c2 == 1);
- printf("%ld, %ld\n", (long) c1, (long) c2);
+ if (!opt_silent)
+ printf("%ld, %ld\n", (long) c1, (long) c2);
mysql_stmt_close(stmt);
}
@@ -10861,7 +11191,8 @@ static void test_bug5399()
check_execute(*stmt, rc);
mysql_stmt_bind_result(*stmt, bind);
}
- printf("%d statements prepared.\n", NUM_OF_USED_STMT);
+ if (!opt_silent)
+ printf("%d statements prepared.\n", NUM_OF_USED_STMT);
for (stmt= stmt_list; stmt != stmt_list + NUM_OF_USED_STMT; ++stmt)
{
@@ -11033,15 +11364,17 @@ static void test_bug5194()
rc= mysql_stmt_prepare(stmt, query, query_ptr - query);
if (rc && nrows * COLUMN_COUNT > uint16_max)
{
- printf("Failed to prepare a statement with %d placeholders "
- "(as expected).\n", nrows * COLUMN_COUNT);
+ if (!opt_silent)
+ printf("Failed to prepare a statement with %d placeholders "
+ "(as expected).\n", nrows * COLUMN_COUNT);
break;
}
else
check_execute(stmt, rc);
- printf("Insert: query length= %d, row count= %d, param count= %lu\n",
- strlen(query), nrows, mysql_stmt_param_count(stmt));
+ if (!opt_silent)
+ printf("Insert: query length= %d, row count= %d, param count= %lu\n",
+ strlen(query), nrows, mysql_stmt_param_count(stmt));
/* bind the parameter array and execute the query */
rc= mysql_stmt_bind_param(stmt, bind);
@@ -11077,7 +11410,10 @@ static void test_bug5315()
rc= mysql_stmt_execute(stmt);
DIE_UNLESS(rc != 0);
if (rc)
- printf("Got error (as expected):\n%s", mysql_stmt_error(stmt));
+ {
+ if (!opt_silent)
+ printf("Got error (as expected):\n%s", mysql_stmt_error(stmt));
+ }
/* check that connection is OK */
mysql_stmt_close(stmt);
stmt= mysql_stmt_init(mysql);
@@ -11125,8 +11461,11 @@ static void test_bug6049()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == 0);
- printf("Result from query: %s\n", row[0]);
- printf("Result from prepared statement: %s\n", (char*) buffer);
+ if (!opt_silent)
+ {
+ printf("Result from query: %s\n", row[0]);
+ printf("Result from prepared statement: %s\n", (char*) buffer);
+ }
DIE_UNLESS(strcmp(row[0], (char*) buffer) == 0);
@@ -11171,8 +11510,11 @@ static void test_bug6058()
rc= mysql_stmt_fetch(stmt);
DIE_UNLESS(rc == 0);
- printf("Result from query: %s\n", row[0]);
- printf("Result from prepared statement: %s\n", buffer);
+ if (!opt_silent)
+ {
+ printf("Result from query: %s\n", row[0]);
+ printf("Result from prepared statement: %s\n", buffer);
+ }
DIE_UNLESS(strcmp(row[0], buffer) == 0);
@@ -11211,17 +11553,17 @@ static void test_bug6046()
stmt_text= "DROP TABLE IF EXISTS t1";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
- stmt_text= "CREATE TABLE a1 (a int, b int)";
+ stmt_text= "CREATE TABLE t1 (a int, b int)";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
- stmt_text= "INSERT INTO a1 VALUES (1,1),(2,2),(3,1),(4,2)";
+ stmt_text= "INSERT INTO t1 VALUES (1,1),(2,2),(3,1),(4,2)";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
stmt= mysql_stmt_init(mysql);
- stmt_text= "SELECT a1.a FROM a1 NATURAL JOIN a1 as X1 "
- "WHERE a1.b > ? ORDER BY a1.a";
+ stmt_text= "SELECT t1.a FROM t1 NATURAL JOIN t1 as X1 "
+ "WHERE t1.b > ? ORDER BY t1.a";
rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
check_execute(stmt, rc);
@@ -11279,11 +11621,13 @@ static void test_basic_cursors()
"SELECT * FROM t2"
};
+ DBUG_ENTER("test_basic_cursors");
myheader("test_basic_cursors");
fill_tables(basic_tables, sizeof(basic_tables)/sizeof(*basic_tables));
fetch_n(queries, sizeof(queries)/sizeof(*queries));
+ DBUG_VOID_RETURN;
}
@@ -11381,22 +11725,25 @@ static void test_bug6096()
/* Print out and check the metadata */
- printf(" ---------------------------------------------------------------\n");
- printf(" | Metadata \n");
- printf(" ---------------------------------------------------------------\n");
- printf(" | Query | Prepared statement \n");
- printf(" ---------------------------------------------------------------\n");
- printf(" field name | length | max_length | length | max_length \n");
- printf(" ---------------------------------------------------------------\n");
-
- for (i= 0; i < query_field_count; ++i)
+ if (!opt_silent)
{
- MYSQL_FIELD *f1= &query_field_list[i], *f2= &stmt_field_list[i];
- printf(" %-11s | %9lu | %10lu | %9lu | %10lu \n",
- f1->name, f1->length, f1->max_length, f2->length, f2->max_length);
- DIE_UNLESS(f1->length == f2->length);
+ printf(" ------------------------------------------------------------\n");
+ printf(" | Metadata \n");
+ printf(" ------------------------------------------------------------\n");
+ printf(" | Query | Prepared statement \n");
+ printf(" ------------------------------------------------------------\n");
+ printf(" field name | length | max_length | length | max_length\n");
+ printf(" ------------------------------------------------------------\n");
+
+ for (i= 0; i < query_field_count; ++i)
+ {
+ MYSQL_FIELD *f1= &query_field_list[i], *f2= &stmt_field_list[i];
+ printf(" %-11s | %9lu | %10lu | %9lu | %10lu \n",
+ f1->name, f1->length, f1->max_length, f2->length, f2->max_length);
+ DIE_UNLESS(f1->length == f2->length);
+ }
+ printf(" ---------------------------------------------------------------\n");
}
- printf(" ---------------------------------------------------------------\n");
/* Bind and fetch the data */
@@ -11419,6 +11766,7 @@ static void test_bug6096()
free(bind[i].buffer);
mysql_stmt_close(stmt);
mysql_free_result(query_result);
+ mysql_free_result(stmt_metadata);
stmt_text= "drop table t1";
rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
myquery(rc);
@@ -11426,6 +11774,273 @@ static void test_bug6096()
/*
+ Test of basic checks that are performed in server for components
+ of MYSQL_TIME parameters.
+*/
+
+static void test_datetime_ranges()
+{
+ const char *stmt_text;
+ int rc, i;
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[6];
+ MYSQL_TIME tm[6];
+
+ myheader("test_datetime_ranges");
+
+ stmt_text= "drop table if exists t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "create table t1 (year datetime, month datetime, day datetime, "
+ "hour datetime, min datetime, sec datetime)";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt= mysql_simple_prepare(mysql,
+ "INSERT INTO t1 VALUES (?, ?, ?, ?, ?, ?)");
+ check_stmt(stmt);
+ verify_param_count(stmt, 6);
+
+ bzero(bind, sizeof(bind));
+ for (i= 0; i < 6; i++)
+ {
+ bind[i].buffer_type= MYSQL_TYPE_DATETIME;
+ bind[i].buffer= &tm[i];
+ }
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ tm[0].year= 2004; tm[0].month= 11; tm[0].day= 10;
+ tm[0].hour= 12; tm[0].minute= 30; tm[0].second= 30;
+ tm[0].second_part= 0; tm[0].neg= 0;
+
+ tm[5]= tm[4]= tm[3]= tm[2]= tm[1]= tm[0];
+ tm[0].year= 10000; tm[1].month= 13; tm[2].day= 32;
+ tm[3].hour= 24; tm[4].minute= 60; tm[5].second= 60;
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ DIE_UNLESS(mysql_warning_count(mysql) != 6);
+
+ verify_col_data("t1", "year", "0000-00-00 00:00:00");
+ verify_col_data("t1", "month", "0000-00-00 00:00:00");
+ verify_col_data("t1", "day", "0000-00-00 00:00:00");
+ verify_col_data("t1", "hour", "0000-00-00 00:00:00");
+ verify_col_data("t1", "min", "0000-00-00 00:00:00");
+ verify_col_data("t1", "sec", "0000-00-00 00:00:00");
+
+ mysql_stmt_close(stmt);
+
+ stmt_text= "delete from t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt= mysql_simple_prepare(mysql, "INSERT INTO t1 (year, month, day) "
+ "VALUES (?, ?, ?)");
+ check_stmt(stmt);
+ verify_param_count(stmt, 3);
+
+ /*
+ We reuse contents of bind and tm arrays left from previous part of test.
+ */
+ for (i= 0; i < 3; i++)
+ bind[i].buffer_type= MYSQL_TYPE_DATE;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ DIE_UNLESS(mysql_warning_count(mysql) != 3);
+
+ verify_col_data("t1", "year", "0000-00-00 00:00:00");
+ verify_col_data("t1", "month", "0000-00-00 00:00:00");
+ verify_col_data("t1", "day", "0000-00-00 00:00:00");
+
+ mysql_stmt_close(stmt);
+
+ stmt_text= "drop table t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt_text= "create table t1 (day_ovfl time, day time, hour time, min time, sec time)";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt= mysql_simple_prepare(mysql,
+ "INSERT INTO t1 VALUES (?, ?, ?, ?, ?)");
+ check_stmt(stmt);
+ verify_param_count(stmt, 5);
+
+ /*
+ Again we reuse what we can from previous part of test.
+ */
+ for (i= 0; i < 5; i++)
+ bind[i].buffer_type= MYSQL_TYPE_TIME;
+
+ rc= mysql_stmt_bind_param(stmt, bind);
+ check_execute(stmt, rc);
+
+ tm[0].year= 0; tm[0].month= 0; tm[0].day= 10;
+ tm[0].hour= 12; tm[0].minute= 30; tm[0].second= 30;
+ tm[0].second_part= 0; tm[0].neg= 0;
+
+ tm[4]= tm[3]= tm[2]= tm[1]= tm[0];
+ tm[0].day= 35; tm[1].day= 34; tm[2].hour= 30; tm[3].minute= 60; tm[4].second= 60;
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+ DIE_UNLESS(mysql_warning_count(mysql) != 2);
+
+ verify_col_data("t1", "day_ovfl", "838:59:59");
+ verify_col_data("t1", "day", "828:30:30");
+ verify_col_data("t1", "hour", "270:30:30");
+ verify_col_data("t1", "min", "00:00:00");
+ verify_col_data("t1", "sec", "00:00:00");
+
+ mysql_stmt_close(stmt);
+
+ stmt_text= "drop table t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+}
+
+
+static void test_bug4172()
+{
+ MYSQL_STMT *stmt;
+ MYSQL_BIND bind[3];
+ const char *stmt_text;
+ MYSQL_RES *res;
+ MYSQL_ROW row;
+ int rc;
+ char f[100], d[100], e[100];
+ long f_len, d_len, e_len;
+
+ myheader("test_bug4172");
+
+ mysql_query(mysql, "DROP TABLE IF EXISTS t1");
+ mysql_query(mysql, "CREATE TABLE t1 (f float, d double, e decimal(10,4))");
+ mysql_query(mysql, "INSERT INTO t1 VALUES (12345.1234, 123456.123456, "
+ "123456.1234)");
+
+ stmt= mysql_stmt_init(mysql);
+ stmt_text= "SELECT f, d, e FROM t1";
+
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bzero(bind, sizeof(bind));
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+ bind[0].buffer= f;
+ bind[0].buffer_length= sizeof(f);
+ bind[0].length= &f_len;
+ bind[1].buffer_type= MYSQL_TYPE_STRING;
+ bind[1].buffer= d;
+ bind[1].buffer_length= sizeof(d);
+ bind[1].length= &d_len;
+ bind[2].buffer_type= MYSQL_TYPE_STRING;
+ bind[2].buffer= e;
+ bind[2].buffer_length= sizeof(e);
+ bind[2].length= &e_len;
+
+ mysql_stmt_bind_result(stmt, bind);
+
+ mysql_stmt_store_result(stmt);
+ rc= mysql_stmt_fetch(stmt);
+ check_execute(stmt, rc);
+
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ res= mysql_store_result(mysql);
+ row= mysql_fetch_row(res);
+
+ if (!opt_silent)
+ {
+ printf("Binary protocol: float=%s, double=%s, decimal(10,4)=%s\n",
+ f, d, e);
+ printf("Text protocol: float=%s, double=%s, decimal(10,4)=%s\n",
+ row[0], row[1], row[2]);
+ }
+ DIE_UNLESS(!strcmp(f, row[0]) && !strcmp(d, row[1]) && !strcmp(e, row[2]));
+
+ mysql_free_result(res);
+ mysql_stmt_close(stmt);
+}
+
+
+static void test_conversion()
+{
+ MYSQL_STMT *stmt;
+ const char *stmt_text;
+ int rc;
+ MYSQL_BIND bind[1];
+ char buff[4];
+ ulong length;
+
+ myheader("test_conversion");
+
+ stmt_text= "DROP TABLE IF EXISTS t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "CREATE TABLE t1 (a TEXT) DEFAULT CHARSET latin1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "SET character_set_connection=utf8, character_set_client=utf8, "
+ " character_set_results=latin1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+
+ stmt= mysql_stmt_init(mysql);
+
+ stmt_text= "INSERT INTO t1 (a) VALUES (?)";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+
+ bzero(bind, sizeof(bind));
+ bind[0].buffer= buff;
+ bind[0].length= &length;
+ bind[0].buffer_type= MYSQL_TYPE_STRING;
+
+ mysql_stmt_bind_param(stmt, bind);
+
+ buff[0]= 0xC3;
+ buff[1]= 0xA0;
+ length= 2;
+
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ stmt_text= "SELECT a FROM t1";
+ rc= mysql_stmt_prepare(stmt, stmt_text, strlen(stmt_text));
+ check_execute(stmt, rc);
+ rc= mysql_stmt_execute(stmt);
+ check_execute(stmt, rc);
+
+ bind[0].buffer_length= sizeof(buff);
+ mysql_stmt_bind_result(stmt, bind);
+
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == 0);
+ DIE_UNLESS(length == 1);
+ DIE_UNLESS((uchar) buff[0] == 0xE0);
+ rc= mysql_stmt_fetch(stmt);
+ DIE_UNLESS(rc == MYSQL_NO_DATA);
+
+ mysql_stmt_close(stmt);
+ stmt_text= "DROP TABLE t1";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+ stmt_text= "SET NAMES DEFAULT";
+ rc= mysql_real_query(mysql, stmt_text, strlen(stmt_text));
+ myquery(rc);
+}
+
+
+/*
Read and parse arguments and MySQL options from my.cnf
*/
@@ -11434,62 +12049,214 @@ static char **defaults_argv;
static struct my_option client_test_long_options[] =
{
- {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
- 0, 0, 0, 0, 0},
+ {"count", 't', "Number of times test to be executed", (char **) &opt_count,
+ (char **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
{"database", 'D', "Database to use", (char **) &opt_db, (char **) &opt_db,
0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"debug", '#', "Output debug log", (gptr*) &default_dbug_option,
(gptr*) &default_dbug_option, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
- {"host", 'h', "Connect to host", (char **) &opt_host, (char **) &opt_host, 0, GET_STR_ALLOC,
- REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"help", '?', "Display this help and exit", 0, 0, 0, GET_NO_ARG, NO_ARG, 0,
+ 0, 0, 0, 0, 0},
+ {"host", 'h', "Connect to host", (char **) &opt_host, (char **) &opt_host,
+ 0, GET_STR_ALLOC, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
{"password", 'p',
"Password to use when connecting to server. If password is not given it's asked from the tty.",
0, 0, 0, GET_STR, OPT_ARG, 0, 0, 0, 0, 0, 0},
+ {"port", 'P', "Port number to use for connection", (char **) &opt_port,
+ (char **) &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"show-tests", 'T', "Show all tests' names", 0, 0, 0, GET_NO_ARG, NO_ARG,
+ 0, 0, 0, 0, 0, 0},
+ {"silent", 's', "Be more silent", 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0,
+ 0},
+ {"socket", 'S', "Socket file to use for connection",
+ (char **) &opt_unix_socket, (char **) &opt_unix_socket, 0, GET_STR,
+ REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
+ {"testcase", 'c',
+ "May disable some code when runs as mysql-test-run testcase.",
+ 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
#ifndef DONT_ALLOW_USER_CHANGE
{"user", 'u', "User for login if not current user", (char **) &opt_user,
(char **) &opt_user, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
#endif
- {"port", 'P', "Port number to use for connection", (char **) &opt_port,
- (char **) &opt_port, 0, GET_UINT, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"socket", 'S', "Socket file to use for connection", (char **) &opt_unix_socket,
- (char **) &opt_unix_socket, 0, GET_STR, REQUIRED_ARG, 0, 0, 0, 0, 0, 0},
- {"testcase", 'c', "May disable some code when runs as mysql-test-run testcase.",
- 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0},
- {"count", 't', "Number of times test to be executed", (char **) &opt_count,
- (char **) &opt_count, 0, GET_UINT, REQUIRED_ARG, 1, 0, 0, 0, 0, 0},
{ 0, 0, 0, 0, 0, 0, GET_NO_ARG, NO_ARG, 0, 0, 0, 0, 0, 0}
};
-static void client_test_print_version(void)
-{
- fprintf(stdout, "%s Distrib %s, for %s (%s)\n\n",
- my_progname, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
-}
-
static void usage(void)
{
- /*
- * show the usage string when the user asks for this
- */
+ /* show the usage string when the user asks for this */
putc('\n', stdout);
- puts("***********************************************************************\n");
- puts(" Test for client-server protocol 4.1");
- puts(" By Monty & Venu \n");
- puts("This software comes with ABSOLUTELY NO WARRANTY. This is free software, ");
- puts("and you are welcome to modify and redistribute it under the GPL license\n");
- puts(" Copyright (C) 1995-2003 MySQL AB ");
- puts("-----------------------------------------------------------------------\n");
- client_test_print_version();
- fprintf(stdout, "Usage: %s [OPTIONS]\n\n", my_progname);
-
+ printf("%s Ver %s Distrib %s, for %s (%s)\n",
+ my_progname, VER, MYSQL_SERVER_VERSION, SYSTEM_TYPE, MACHINE_TYPE);
+ puts("By Monty, Venu, Kent and others\n");
+ printf("\
+Copyright (C) 2002-2004 MySQL AB\n\
+This software comes with ABSOLUTELY NO WARRANTY. This is free software,\n\
+and you are welcome to modify and redistribute it under the GPL license\n");
+ printf("Usage: %s [OPTIONS] [TESTNAME1 TESTNAME2...]\n", my_progname);
my_print_help(client_test_long_options);
print_defaults("my", client_test_load_default_groups);
my_print_variables(client_test_long_options);
-
- puts("***********************************************************************\n");
}
+
+static struct my_tests_st my_tests[]= {
+ { "client_query", client_query },
+#if NOT_YET_WORKING
+ { "test_drop_temp", test_drop_temp },
+#endif
+ { "test_fetch_seek", test_fetch_seek },
+ { "test_fetch_nobuffs", test_fetch_nobuffs },
+ { "test_open_direct", test_open_direct },
+ { "test_fetch_null", test_fetch_null },
+ { "test_ps_null_param", test_ps_null_param },
+ { "test_fetch_date", test_fetch_date },
+ { "test_fetch_str", test_fetch_str },
+ { "test_fetch_long", test_fetch_long },
+ { "test_fetch_short", test_fetch_short },
+ { "test_fetch_tiny", test_fetch_tiny },
+ { "test_fetch_bigint", test_fetch_bigint },
+ { "test_fetch_float", test_fetch_float },
+ { "test_fetch_double", test_fetch_double },
+ { "test_bind_result_ext", test_bind_result_ext },
+ { "test_bind_result_ext1", test_bind_result_ext1 },
+ { "test_select_direct", test_select_direct },
+ { "test_select_prepare", test_select_prepare },
+ { "test_select", test_select },
+ { "test_select_version", test_select_version },
+ { "test_ps_conj_select", test_ps_conj_select },
+ { "test_select_show_table", test_select_show_table },
+ { "test_func_fields", test_func_fields },
+ { "test_long_data", test_long_data },
+ { "test_insert", test_insert },
+ { "test_set_variable", test_set_variable },
+ { "test_select_show", test_select_show },
+ { "test_prepare_noparam", test_prepare_noparam },
+ { "test_bind_result", test_bind_result },
+ { "test_prepare_simple", test_prepare_simple },
+ { "test_prepare", test_prepare },
+ { "test_null", test_null },
+ { "test_debug_example", test_debug_example },
+ { "test_update", test_update },
+ { "test_simple_update", test_simple_update },
+ { "test_simple_delete", test_simple_delete },
+ { "test_double_compare", test_double_compare },
+ { "client_store_result", client_store_result },
+ { "client_use_result", client_use_result },
+ { "test_tran_bdb", test_tran_bdb },
+ { "test_tran_innodb", test_tran_innodb },
+ { "test_prepare_ext", test_prepare_ext },
+ { "test_prepare_syntax", test_prepare_syntax },
+ { "test_field_names", test_field_names },
+ { "test_field_flags", test_field_flags },
+ { "test_long_data_str", test_long_data_str },
+ { "test_long_data_str1", test_long_data_str1 },
+ { "test_long_data_bin", test_long_data_bin },
+ { "test_warnings", test_warnings },
+ { "test_errors", test_errors },
+ { "test_prepare_resultset", test_prepare_resultset },
+ { "test_stmt_close", test_stmt_close },
+ { "test_prepare_field_result", test_prepare_field_result },
+ { "test_multi_stmt", test_multi_stmt },
+ { "test_multi_statements", test_multi_statements },
+ { "test_prepare_multi_statements", test_prepare_multi_statements },
+ { "test_store_result", test_store_result },
+ { "test_store_result1", test_store_result1 },
+ { "test_store_result2", test_store_result2 },
+ { "test_subselect", test_subselect },
+ { "test_date", test_date },
+ { "test_date_date", test_date_date },
+ { "test_date_time", test_date_time },
+ { "test_date_ts", test_date_ts },
+ { "test_date_dt", test_date_dt },
+ { "test_prepare_alter", test_prepare_alter },
+ { "test_manual_sample", test_manual_sample },
+ { "test_pure_coverage", test_pure_coverage },
+ { "test_buffers", test_buffers },
+ { "test_ushort_bug", test_ushort_bug },
+ { "test_sshort_bug", test_sshort_bug },
+ { "test_stiny_bug", test_stiny_bug },
+ { "test_field_misc", test_field_misc },
+ { "test_set_option", test_set_option },
+#ifndef EMBEDDED_LIBRARY
+ { "test_prepare_grant", test_prepare_grant },
+#endif
+ { "test_frm_bug", test_frm_bug },
+ { "test_explain_bug", test_explain_bug },
+ { "test_decimal_bug", test_decimal_bug },
+ { "test_nstmts", test_nstmts },
+ { "test_logs;", test_logs },
+ { "test_cuted_rows", test_cuted_rows },
+ { "test_fetch_offset", test_fetch_offset },
+ { "test_fetch_column", test_fetch_column },
+ { "test_mem_overun", test_mem_overun },
+ { "test_list_fields", test_list_fields },
+ { "test_free_result", test_free_result },
+ { "test_free_store_result", test_free_store_result },
+ { "test_sqlmode", test_sqlmode },
+ { "test_ts", test_ts },
+ { "test_bug1115", test_bug1115 },
+ { "test_bug1180", test_bug1180 },
+ { "test_bug1500", test_bug1500 },
+ { "test_bug1644", test_bug1644 },
+ { "test_bug1946", test_bug1946 },
+ { "test_bug2248", test_bug2248 },
+ { "test_parse_error_and_bad_length", test_parse_error_and_bad_length },
+ { "test_bug2247", test_bug2247 },
+ { "test_subqueries", test_subqueries },
+ { "test_bad_union", test_bad_union },
+ { "test_distinct", test_distinct },
+ { "test_subqueries_ref", test_subqueries_ref },
+ { "test_union", test_union },
+ { "test_bug3117", test_bug3117 },
+ { "test_join", test_join },
+ { "test_selecttmp", test_selecttmp },
+ { "test_create_drop", test_create_drop },
+ { "test_rename", test_rename },
+ { "test_do_set", test_do_set },
+ { "test_multi", test_multi },
+ { "test_insert_select", test_insert_select },
+ { "test_bind_nagative", test_bind_nagative },
+ { "test_derived", test_derived },
+ { "test_xjoin", test_xjoin },
+ { "test_bug3035", test_bug3035 },
+ { "test_union2", test_union2 },
+ { "test_bug1664", test_bug1664 },
+ { "test_union_param", test_union_param },
+ { "test_order_param", test_order_param },
+ { "test_ps_i18n", test_ps_i18n },
+ { "test_bug3796", test_bug3796 },
+ { "test_bug4026", test_bug4026 },
+ { "test_bug4079", test_bug4079 },
+ { "test_bug4236", test_bug4236 },
+ { "test_bug4030", test_bug4030 },
+ { "test_bug5126", test_bug5126 },
+ { "test_bug4231", test_bug4231 },
+ { "test_bug5399", test_bug5399 },
+ { "test_bug5194", test_bug5194 },
+ { "test_bug5315", test_bug5315 },
+ { "test_bug6049", test_bug6049 },
+ { "test_bug6058", test_bug6058 },
+ { "test_bug6059", test_bug6059 },
+ { "test_bug6046", test_bug6046 },
+ { "test_bug6081", test_bug6081 },
+ { "test_bug6096", test_bug6096 },
+ { "test_datetime_ranges", test_datetime_ranges },
+ { "test_bug4172", test_bug4172 },
+ { "test_conversion", test_conversion },
+ { "test_view", test_view },
+ { "test_view_where", test_view_where },
+ { "test_view_2where", test_view_2where },
+ { "test_view_star", test_view_star },
+ { "test_view_insert", test_view_insert },
+ { "test_left_join_view", test_left_join_view },
+ { "test_view_insert_fields", test_view_insert_fields },
+ { "test_basic_cursors", test_basic_cursors },
+ { "test_cursors_with_union", test_cursors_with_union },
+ { 0, 0 }
+};
+
+
static my_bool
get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
char *argument)
@@ -11514,6 +12281,22 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
else
tty_password= 1;
break;
+ case 's':
+ if (argument == disabled_my_option)
+ opt_silent= 0;
+ else
+ opt_silent++;
+ break;
+ case 'T':
+ {
+ struct my_tests_st *fptr;
+
+ printf("All possible test names:\n\n");
+ for (fptr= my_tests; fptr->name; fptr++)
+ printf("%s\n", fptr->name);
+ exit(0);
+ break;
+ }
case '?':
case 'I': /* Info */
usage();
@@ -11523,11 +12306,11 @@ get_one_option(int optid, const struct my_option *opt __attribute__((unused)),
return 0;
}
-static void get_options(int argc, char **argv)
+static void get_options(int *argc, char ***argv)
{
int ho_error;
- if ((ho_error= handle_options(&argc, &argv, client_test_long_options,
+ if ((ho_error= handle_options(argc, argv, client_test_long_options,
get_one_option)))
exit(ho_error);
@@ -11542,14 +12325,17 @@ static void get_options(int argc, char **argv)
static void print_test_output()
{
- fprintf(stdout, "\n\n");
- fprintf(stdout, "All '%d' tests were successful (in '%d' iterations)",
- test_count-1, opt_count);
- fprintf(stdout, "\n Total execution time: %g SECS", total_time);
- if (opt_count > 1)
- fprintf(stdout, " (Avg: %g SECS)", total_time/opt_count);
-
- fprintf(stdout, "\n\n!!! SUCCESS !!!\n");
+ if (opt_silent < 3)
+ {
+ fprintf(stdout, "\n\n");
+ fprintf(stdout, "All '%d' tests were successful (in '%d' iterations)",
+ test_count-1, opt_count);
+ fprintf(stdout, "\n Total execution time: %g SECS", total_time);
+ if (opt_count > 1)
+ fprintf(stdout, " (Avg: %g SECS)", total_time/opt_count);
+
+ fprintf(stdout, "\n\n!!! SUCCESS !!!\n");
+ }
}
@@ -11557,14 +12343,17 @@ static void print_test_output()
main routine
***************************************************************************/
+
int main(int argc, char **argv)
{
+ struct my_tests_st *fptr;
+
DEBUGGER_OFF;
MY_INIT(argv[0]);
-
+
load_defaults("my", client_test_load_default_groups, &argc, &argv);
defaults_argv= argv;
- get_options(argc, argv);
+ get_options(&argc, &argv);
client_connect(); /* connect to server */
@@ -11573,187 +12362,35 @@ int main(int argc, char **argv)
{
/* Start of tests */
test_count= 1;
-
start_time= time((time_t *)0);
-
- client_query(); /* simple client query test */
-#if NOT_YET_WORKING
- /* Used for internal new development debugging */
- test_drop_temp(); /* Test DROP TEMPORARY TABLE Access checks */
-#endif
- test_fetch_seek(); /* Test stmt seek() functions */
- test_fetch_nobuffs(); /* to fecth without prior bound buffers */
- test_open_direct(); /* direct execution in the middle of open stmts */
- test_fetch_null(); /* to fetch null data */
- test_ps_null_param(); /* Fetch value of null parameter */
- test_fetch_date(); /* to fetch date, time and timestamp */
- test_fetch_str(); /* to fetch string to all types */
- test_fetch_long(); /* to fetch long to all types */
- test_fetch_short(); /* to fetch short to all types */
- test_fetch_tiny(); /* to fetch tiny to all types */
- test_fetch_bigint(); /* to fetch bigint to all types */
- test_fetch_float(); /* to fetch float to all types */
- test_fetch_double(); /* to fetch double to all types */
- test_bind_result_ext(); /* result bind test - extension */
- test_bind_result_ext1(); /* result bind test - extension */
- test_select_direct(); /* direct select - protocol_simple debug */
- test_select_prepare(); /* prepare select - protocol_prep debug */
- test_select(); /* simple select test */
- test_select_version(); /* select with variables */
- test_ps_conj_select(); /* prepare select with "where a=? or b=?" */
- test_select_show_table();/* simple show prepare */
-#if NOT_USED
- /*
- Enable this tests from 4.1.1 when mysql_param_result() is
- supported
- */
- test_select_meta(); /* select param meta information */
- test_update_meta(); /* update param meta information */
- test_insert_meta(); /* insert param meta information */
-#endif
- test_func_fields(); /* test for new 4.1 MYSQL_FIELD members */
- test_long_data(); /* test for sending text data in chunks */
- test_insert(); /* simple insert test - prepare */
- test_set_variable(); /* prepare with set variables */
- test_select_show(); /* prepare - show test */
- test_prepare_noparam(); /* prepare without parameters */
- test_bind_result(); /* result bind test */
- test_prepare_simple(); /* simple prepare */
- test_prepare(); /* prepare test */
- test_null(); /* test null data handling */
- test_debug_example(); /* some debugging case */
- test_update(); /* prepare-update test */
- test_simple_update(); /* simple prepare with update */
- test_simple_delete(); /* prepare with delete */
- test_double_compare(); /* float comparision */
- client_store_result(); /* usage of mysql_store_result() */
- client_use_result(); /* usage of mysql_use_result() */
- test_tran_bdb(); /* transaction test on BDB table type */
- test_tran_innodb(); /* transaction test on InnoDB table type */
- test_prepare_ext(); /* test prepare with all types
- conversion -- TODO */
- test_prepare_syntax(); /* syntax check for prepares */
- test_field_names(); /* test for field names */
- test_field_flags(); /* test to help .NET provider team */
- test_long_data_str(); /* long data handling */
- test_long_data_str1(); /* yet another long data handling */
- test_long_data_bin(); /* long binary insertion */
- test_warnings(); /* show warnings test */
- test_errors(); /* show errors test */
- test_prepare_resultset();/* prepare meta info test */
- test_stmt_close(); /* mysql_stmt_close() test -- hangs */
- test_prepare_field_result(); /* prepare meta info */
- test_multi_stmt(); /* multi stmt test */
- test_multi_statements();/* test multi statement execution */
- test_prepare_multi_statements(); /* check that multi statements are
- disabled in PS */
- test_store_result(); /* test the store_result */
- test_store_result1(); /* test store result without buffers */
- test_store_result2(); /* test store result for misc case */
- test_subselect(); /* test subselect prepare -TODO*/
- test_date(); /* test the MYSQL_TIME conversion */
- test_date_date(); /* test conversion from DATE to all */
- test_date_time(); /* test conversion from TIME to all */
- test_date_ts() ; /* test conversion from TIMESTAMP to all */
- test_date_dt() ; /* test conversion from DATETIME to all */
- test_prepare_alter(); /* change table schema in middle of prepare */
- test_manual_sample(); /* sample in the manual */
- test_pure_coverage(); /* keep pure coverage happy */
- test_buffers(); /* misc buffer handling */
- test_ushort_bug(); /* test a simple conv bug from php */
- test_sshort_bug(); /* test a simple conv bug from php */
- test_stiny_bug(); /* test a simple conv bug from php */
- test_field_misc(); /* check the field info for misc case, bug: #74 */
- test_set_option(); /* test the SET OPTION feature, bug #85 */
- /*TODO HF: here should be NO_EMBEDDED_ACCESS_CHECKS*/
-#ifndef EMBEDDED_LIBRARY
- test_prepare_grant(); /* Test the GRANT command, bug #89 */
-#endif
- test_frm_bug(); /* test the crash when .frm is invalid, bug #93 */
- test_explain_bug(); /* test for the EXPLAIN, bug #115 */
- test_decimal_bug(); /* test for the decimal bug */
- test_nstmts(); /* test n statements */
- test_logs(); ; /* Test logs */
- test_cuted_rows(); /* Test for WARNINGS from cuted rows */
- test_fetch_offset(); /* Test mysql_stmt_fetch_column with offset */
- test_fetch_column(); /* Test mysql_stmt_fetch_column */
- test_mem_overun(); /* test DBD ovverun bug */
- test_list_fields(); /* test COM_LIST_FIELDS for DEFAULT */
- test_free_result(); /* test mysql_stmt_free_result() */
- test_free_store_result(); /* test to make sure stmt results are cleared
- during stmt_free_result() */
- test_sqlmode(); /* test for SQL_MODE */
- test_ts(); /* test for timestamp BR#819 */
- test_bug1115(); /* BUG#1115 */
- test_bug1180(); /* BUG#1180 */
- test_bug1500(); /* BUG#1500 */
- test_bug1644(); /* BUG#1644 */
- test_bug1946(); /* test that placeholders are allowed only in
- prepared queries */
- test_bug2248(); /* BUG#2248 */
- test_parse_error_and_bad_length(); /* test if bad length param in
- mysql_stmt_prepare() triggers error */
- test_bug2247(); /* test that mysql_stmt_affected_rows() returns
- number of rows affected by last prepared
- statement execution */
- test_subqueries(); /* repeatable subqueries */
- test_bad_union(); /* correct setup of UNION */
- test_distinct(); /* distinct aggregate functions */
- test_subqueries_ref(); /* outer reference in subqueries converted
- Item_field -> Item_ref */
- test_union(); /* test union with prepared statements */
- test_bug3117(); /* BUG#3117: LAST_INSERT_ID() */
- test_join(); /* different kinds of join, BUG#2794 */
- test_selecttmp(); /* temporary table used in select execution */
- test_create_drop(); /* some table manipulation BUG#2811 */
- test_rename(); /* rename test */
- test_do_set(); /* DO & SET commands test BUG#3393 */
- test_multi(); /* test of multi delete & update */
- test_insert_select(); /* test INSERT ... SELECT */
- test_bind_nagative(); /* bind negative to unsigned BUG#3223 */
- test_derived(); /* derived table with parameter BUG#3020 */
- test_xjoin(); /* complex join test */
- test_bug3035(); /* inserts of INT32_MAX/UINT32_MAX */
- test_union2(); /* repeatable execution of union (Bug #3577) */
- test_bug1664(); /* test for bugs in mysql_stmt_send_long_data()
- call (Bug #1664) */
- test_union_param();
- test_order_param(); /* ORDER BY with parameters in select list
- (Bug #3686 */
- test_ps_i18n(); /* test for i18n support in binary protocol */
- test_bug3796(); /* test for select concat(?, <string>) */
- test_bug4026(); /* test microseconds precision of time types */
- test_bug4079(); /* erroneous subquery in prepared statement */
- test_bug4236(); /* init -> execute */
- test_bug4030(); /* test conversion string -> time types in
- libmysql */
- test_bug5126(); /* support for mediumint type in libmysql */
- test_bug4231(); /* proper handling of all-zero times and
- dates in the server */
- test_bug5399(); /* check that statement id uniquely identifies
- statement */
- test_bug5194(); /* bulk inserts in prepared mode */
- test_bug5315(); /* check that mysql_change_user closes all
- prepared statements */
- test_bug6049(); /* check support for negative TIME values */
- test_bug6058(); /* check support for 0000-00-00 dates */
- test_bug6059(); /* correct metadata for SELECT ... INTO OUTFILE */
- test_bug6046(); /* NATURAL JOIN transformation works in PS */
- test_bug6081(); /* test of mysql_create_db()/mysql_rm_db() */
- test_bug6096(); /* max_length for numeric columns */
- test_view(); /* Test of VIEWS with prepared statements */
- test_view_where(); /* VIEW with WHERE clause & merge algorithm */
- test_view_2where(); /* VIEW with WHERE * SELECt with WHERE */
- test_view_star(); /* using query with * from VIEW */
- test_view_insert(); /* inserting in VIEW without field list */
- test_left_join_view(); /* left join on VIEW with WHERE condition */
- test_view_insert_fields(); /* insert into VIOEW with fields list */
- test_basic_cursors();
- test_cursors_with_union();
- /*
- XXX: PLEASE RUN THIS PROGRAM UNDER VALGRIND AND VERIFY THAT YOUR TEST
- DOESN'T CONTAIN WARNINGS/ERRORS BEFORE YOU PUSH.
- */
+ if (!argc)
+ {
+ for (fptr= my_tests; fptr->name; fptr++)
+ (*fptr->function)();
+ }
+ else
+ {
+ for ( ; *argv ; argv++)
+ {
+ for (fptr= my_tests; fptr->name; fptr++)
+ {
+ if (!strcmp(fptr->name, *argv))
+ {
+ (*fptr->function)();
+ break;
+ }
+ }
+ if (!fptr->name)
+ {
+ fprintf(stderr, "\n\nGiven test not found: '%s'\n", *argv);
+ fprintf(stderr, "See legal test names with %s -T\n\nAborting!\n",
+ my_progname);
+ client_disconnect();
+ free_defaults(defaults_argv);
+ exit(1);
+ }
+ }
+ }
end_time= time((time_t *)0);
total_time+= difftime(end_time, start_time);
diff --git a/tests/grant.pl b/tests/grant.pl
index eb2d00f3e1d..cd6a2eb80de 100644
--- a/tests/grant.pl
+++ b/tests/grant.pl
@@ -74,9 +74,9 @@ safe_query("revoke select(user) on mysql.user from $user");
safe_query("grant select on *.* to $user");
safe_query("set password FOR ${opt_user}2\@$opt_host = password('test')",1);
-safe_query("set password FOR $opt_user=password('test')");
+safe_query("set password FOR $opt_user\@$opt_host=password('test')");
user_connect(1);
-safe_query("set password FOR $opt_user=''");
+safe_query("set password FOR $opt_user\@$opt_host=''");
user_connect(0);
user_query("select * from mysql.user where user = '$opt_user'");
user_query("select * from mysql.db where user = '$opt_user'");