mirror of
				https://github.com/MariaDB/server.git
				synced 2025-11-03 14:33:32 +03:00 
			
		
		
		
	Changed header to GPL version 2 only BUILD/Makefile.am: Changed header to GPL version 2 only Docs/Makefile.am: Changed header to GPL version 2 only Makefile.am: Changed header to GPL version 2 only SSL/Makefile.am: Changed header to GPL version 2 only bdb/Makefile.in: Changed header to GPL version 2 only client/Makefile.am: Changed header to GPL version 2 only client/client_priv.h: Changed header to GPL version 2 only client/completion_hash.cc: Changed header to GPL version 2 only client/completion_hash.h: Changed header to GPL version 2 only client/get_password.c: Changed header to GPL version 2 only client/my_readline.h: Changed header to GPL version 2 only client/mysql.cc: Changed header to GPL version 2 only client/mysql_upgrade.c: Changed header to GPL version 2 only client/mysqladmin.cc: Changed header to GPL version 2 only client/mysqlbinlog.cc: Changed header to GPL version 2 only client/mysqlcheck.c: Changed header to GPL version 2 only client/mysqldump.c: Changed header to GPL version 2 only client/mysqlimport.c: Changed header to GPL version 2 only client/mysqlmanager-pwgen.c: Changed header to GPL version 2 only client/mysqlmanagerc.c: Changed header to GPL version 2 only client/mysqlshow.c: Changed header to GPL version 2 only client/mysqltest.c: Changed header to GPL version 2 only client/readline.cc: Changed header to GPL version 2 only client/sql_string.cc: Changed header to GPL version 2 only client/sql_string.h: Changed header to GPL version 2 only cmd-line-utils/Makefile.am: Changed header to GPL version 2 only dbug/Makefile.am: Changed header to GPL version 2 only extra/Makefile.am: Changed header to GPL version 2 only extra/charset2html.c: Changed header to GPL version 2 only extra/comp_err.c: Changed header to GPL version 2 only extra/innochecksum.c: Changed header to GPL version 2 only extra/my_print_defaults.c: Changed header to GPL version 2 only extra/mysql_waitpid.c: Changed header to GPL version 2 only extra/perror.c: Changed header to GPL version 2 only extra/replace.c: Changed header to GPL version 2 only extra/resolve_stack_dump.c: Changed header to GPL version 2 only extra/resolveip.c: Changed header to GPL version 2 only heap/Makefile.am: Changed header to GPL version 2 only heap/_check.c: Changed header to GPL version 2 only heap/_rectest.c: Changed header to GPL version 2 only heap/heapdef.h: Changed header to GPL version 2 only heap/hp_block.c: Changed header to GPL version 2 only heap/hp_clear.c: Changed header to GPL version 2 only heap/hp_close.c: Changed header to GPL version 2 only heap/hp_create.c: Changed header to GPL version 2 only heap/hp_delete.c: Changed header to GPL version 2 only heap/hp_extra.c: Changed header to GPL version 2 only heap/hp_hash.c: Changed header to GPL version 2 only heap/hp_info.c: Changed header to GPL version 2 only heap/hp_open.c: Changed header to GPL version 2 only heap/hp_panic.c: Changed header to GPL version 2 only heap/hp_rename.c: Changed header to GPL version 2 only heap/hp_rfirst.c: Changed header to GPL version 2 only heap/hp_rkey.c: Changed header to GPL version 2 only heap/hp_rlast.c: Changed header to GPL version 2 only heap/hp_rnext.c: Changed header to GPL version 2 only heap/hp_rprev.c: Changed header to GPL version 2 only heap/hp_rrnd.c: Changed header to GPL version 2 only heap/hp_rsame.c: Changed header to GPL version 2 only heap/hp_scan.c: Changed header to GPL version 2 only heap/hp_static.c: Changed header to GPL version 2 only heap/hp_test1.c: Changed header to GPL version 2 only heap/hp_test2.c: Changed header to GPL version 2 only heap/hp_update.c: Changed header to GPL version 2 only heap/hp_write.c: Changed header to GPL version 2 only include/Makefile.am: Changed header to GPL version 2 only include/base64.h: Changed header to GPL version 2 only include/config-netware.h: Changed header to GPL version 2 only include/config-os2.h: Changed header to GPL version 2 only include/config-win.h: Changed header to GPL version 2 only include/decimal.h: Changed header to GPL version 2 only include/errmsg.h: Changed header to GPL version 2 only include/ft_global.h: Changed header to GPL version 2 only include/hash.h: Changed header to GPL version 2 only include/heap.h: Changed header to GPL version 2 only include/keycache.h: Changed header to GPL version 2 only include/m_ctype.h: Changed header to GPL version 2 only include/m_string.h: Changed header to GPL version 2 only include/md5.h: Changed header to GPL version 2 only include/my_aes.h: Changed header to GPL version 2 only include/my_alarm.h: Changed header to GPL version 2 only include/my_alloc.h: Changed header to GPL version 2 only include/my_base.h: Changed header to GPL version 2 only include/my_bitmap.h: Changed header to GPL version 2 only include/my_dbug.h: Changed header to GPL version 2 only include/my_dir.h: Changed header to GPL version 2 only include/my_getopt.h: Changed header to GPL version 2 only include/my_global.h: Changed header to GPL version 2 only include/my_handler.h: Changed header to GPL version 2 only include/my_libwrap.h: Changed header to GPL version 2 only include/my_list.h: Changed header to GPL version 2 only include/my_net.h: Changed header to GPL version 2 only include/my_no_pthread.h: Changed header to GPL version 2 only include/my_nosys.h: Changed header to GPL version 2 only include/my_pthread.h: Changed header to GPL version 2 only include/my_sys.h: Changed header to GPL version 2 only include/my_time.h: Changed header to GPL version 2 only include/my_tree.h: Changed header to GPL version 2 only include/my_user.h: Changed header to GPL version 2 only include/my_xml.h: Changed header to GPL version 2 only include/myisam.h: Changed header to GPL version 2 only include/myisammrg.h: Changed header to GPL version 2 only include/myisampack.h: Changed header to GPL version 2 only include/mysql.h: Changed header to GPL version 2 only include/mysql_com.h: Changed header to GPL version 2 only include/mysql_embed.h: Changed header to GPL version 2 only include/mysql_time.h: Changed header to GPL version 2 only include/mysys_err.h: Changed header to GPL version 2 only include/queues.h: Changed header to GPL version 2 only include/raid.h: Changed header to GPL version 2 only include/rijndael.h: Changed header to GPL version 2 only include/sha1.h: Changed header to GPL version 2 only include/sql_common.h: Changed header to GPL version 2 only include/sslopt-case.h: Changed header to GPL version 2 only include/sslopt-longopts.h: Changed header to GPL version 2 only include/sslopt-vars.h: Changed header to GPL version 2 only include/t_ctype.h: Changed header to GPL version 2 only include/thr_alarm.h: Changed header to GPL version 2 only include/thr_lock.h: Changed header to GPL version 2 only include/typelib.h: Changed header to GPL version 2 only include/violite.h: Changed header to GPL version 2 only innobase/Makefile.am: Changed header to GPL version 2 only innobase/btr/Makefile.am: Changed header to GPL version 2 only innobase/buf/Makefile.am: Changed header to GPL version 2 only innobase/data/Makefile.am: Changed header to GPL version 2 only innobase/dict/Makefile.am: Changed header to GPL version 2 only innobase/dyn/Makefile.am: Changed header to GPL version 2 only innobase/eval/Makefile.am: Changed header to GPL version 2 only innobase/fil/Makefile.am: Changed header to GPL version 2 only innobase/fsp/Makefile.am: Changed header to GPL version 2 only innobase/fut/Makefile.am: Changed header to GPL version 2 only innobase/ha/Makefile.am: Changed header to GPL version 2 only innobase/ibuf/Makefile.am: Changed header to GPL version 2 only innobase/include/Makefile.am: Changed header to GPL version 2 only innobase/lock/Makefile.am: Changed header to GPL version 2 only innobase/log/Makefile.am: Changed header to GPL version 2 only innobase/mach/Makefile.am: Changed header to GPL version 2 only innobase/mem/Makefile.am: Changed header to GPL version 2 only innobase/mtr/Makefile.am: Changed header to GPL version 2 only innobase/os/Makefile.am: Changed header to GPL version 2 only innobase/page/Makefile.am: Changed header to GPL version 2 only innobase/pars/Makefile.am: Changed header to GPL version 2 only innobase/que/Makefile.am: Changed header to GPL version 2 only innobase/read/Makefile.am: Changed header to GPL version 2 only innobase/rem/Makefile.am: Changed header to GPL version 2 only innobase/row/Makefile.am: Changed header to GPL version 2 only innobase/srv/Makefile.am: Changed header to GPL version 2 only innobase/sync/Makefile.am: Changed header to GPL version 2 only innobase/thr/Makefile.am: Changed header to GPL version 2 only innobase/trx/Makefile.am: Changed header to GPL version 2 only innobase/usr/Makefile.am: Changed header to GPL version 2 only innobase/ut/Makefile.am: Changed header to GPL version 2 only libmysql/client_settings.h: Changed header to GPL version 2 only libmysqld/Makefile.am: Changed header to GPL version 2 only libmysqld/emb_qcache.cc: Changed header to GPL version 2 only libmysqld/emb_qcache.h: Changed header to GPL version 2 only libmysqld/embedded_priv.h: Changed header to GPL version 2 only libmysqld/examples/Makefile.am: Changed header to GPL version 2 only libmysqld/libmysqld.c: Changed header to GPL version 2 only man/Makefile.am: Changed header to GPL version 2 only myisam/Makefile.am: Changed header to GPL version 2 only myisam/ft_boolean_search.c: Changed header to GPL version 2 only myisam/ft_eval.c: Changed header to GPL version 2 only myisam/ft_eval.h: Changed header to GPL version 2 only myisam/ft_nlq_search.c: Changed header to GPL version 2 only myisam/ft_parser.c: Changed header to GPL version 2 only myisam/ft_static.c: Changed header to GPL version 2 only myisam/ft_stem.c: Changed header to GPL version 2 only myisam/ft_stopwords.c: Changed header to GPL version 2 only myisam/ft_test1.c: Changed header to GPL version 2 only myisam/ft_test1.h: Changed header to GPL version 2 only myisam/ft_update.c: Changed header to GPL version 2 only myisam/ftdefs.h: Changed header to GPL version 2 only myisam/fulltext.h: Changed header to GPL version 2 only myisam/mi_cache.c: Changed header to GPL version 2 only myisam/mi_changed.c: Changed header to GPL version 2 only myisam/mi_check.c: Changed header to GPL version 2 only myisam/mi_checksum.c: Changed header to GPL version 2 only myisam/mi_close.c: Changed header to GPL version 2 only myisam/mi_create.c: Changed header to GPL version 2 only myisam/mi_dbug.c: Changed header to GPL version 2 only myisam/mi_delete.c: Changed header to GPL version 2 only myisam/mi_delete_all.c: Changed header to GPL version 2 only myisam/mi_delete_table.c: Changed header to GPL version 2 only myisam/mi_dynrec.c: Changed header to GPL version 2 only myisam/mi_extra.c: Changed header to GPL version 2 only myisam/mi_info.c: Changed header to GPL version 2 only myisam/mi_key.c: Changed header to GPL version 2 only myisam/mi_keycache.c: Changed header to GPL version 2 only myisam/mi_locking.c: Changed header to GPL version 2 only myisam/mi_log.c: Changed header to GPL version 2 only myisam/mi_open.c: Changed header to GPL version 2 only myisam/mi_packrec.c: Changed header to GPL version 2 only myisam/mi_page.c: Changed header to GPL version 2 only myisam/mi_panic.c: Changed header to GPL version 2 only myisam/mi_preload.c: Changed header to GPL version 2 only myisam/mi_range.c: Changed header to GPL version 2 only myisam/mi_rename.c: Changed header to GPL version 2 only myisam/mi_rfirst.c: Changed header to GPL version 2 only myisam/mi_rkey.c: Changed header to GPL version 2 only myisam/mi_rlast.c: Changed header to GPL version 2 only myisam/mi_rnext.c: Changed header to GPL version 2 only myisam/mi_rnext_same.c: Changed header to GPL version 2 only myisam/mi_rprev.c: Changed header to GPL version 2 only myisam/mi_rrnd.c: Changed header to GPL version 2 only myisam/mi_rsame.c: Changed header to GPL version 2 only myisam/mi_rsamepos.c: Changed header to GPL version 2 only myisam/mi_scan.c: Changed header to GPL version 2 only myisam/mi_search.c: Changed header to GPL version 2 only myisam/mi_static.c: Changed header to GPL version 2 only myisam/mi_statrec.c: Changed header to GPL version 2 only myisam/mi_test1.c: Changed header to GPL version 2 only myisam/mi_test2.c: Changed header to GPL version 2 only myisam/mi_test3.c: Changed header to GPL version 2 only myisam/mi_unique.c: Changed header to GPL version 2 only myisam/mi_update.c: Changed header to GPL version 2 only myisam/mi_write.c: Changed header to GPL version 2 only myisam/myisam_ftdump.c: Changed header to GPL version 2 only myisam/myisamchk.c: Changed header to GPL version 2 only myisam/myisamdef.h: Changed header to GPL version 2 only myisam/myisamlog.c: Changed header to GPL version 2 only myisam/myisampack.c: Changed header to GPL version 2 only myisam/rt_index.c: Changed header to GPL version 2 only myisam/rt_index.h: Changed header to GPL version 2 only myisam/rt_key.c: Changed header to GPL version 2 only myisam/rt_key.h: Changed header to GPL version 2 only myisam/rt_mbr.c: Changed header to GPL version 2 only myisam/rt_mbr.h: Changed header to GPL version 2 only myisam/rt_split.c: Changed header to GPL version 2 only myisam/rt_test.c: Changed header to GPL version 2 only myisam/sort.c: Changed header to GPL version 2 only myisam/sp_defs.h: Changed header to GPL version 2 only myisam/sp_key.c: Changed header to GPL version 2 only myisam/sp_test.c: Changed header to GPL version 2 only myisammrg/Makefile.am: Changed header to GPL version 2 only myisammrg/myrg_close.c: Changed header to GPL version 2 only myisammrg/myrg_create.c: Changed header to GPL version 2 only myisammrg/myrg_def.h: Changed header to GPL version 2 only myisammrg/myrg_delete.c: Changed header to GPL version 2 only myisammrg/myrg_extra.c: Changed header to GPL version 2 only myisammrg/myrg_info.c: Changed header to GPL version 2 only myisammrg/myrg_locking.c: Changed header to GPL version 2 only myisammrg/myrg_open.c: Changed header to GPL version 2 only myisammrg/myrg_panic.c: Changed header to GPL version 2 only myisammrg/myrg_queue.c: Changed header to GPL version 2 only myisammrg/myrg_range.c: Changed header to GPL version 2 only myisammrg/myrg_rfirst.c: Changed header to GPL version 2 only myisammrg/myrg_rkey.c: Changed header to GPL version 2 only myisammrg/myrg_rlast.c: Changed header to GPL version 2 only myisammrg/myrg_rnext.c: Changed header to GPL version 2 only myisammrg/myrg_rnext_same.c: Changed header to GPL version 2 only myisammrg/myrg_rprev.c: Changed header to GPL version 2 only myisammrg/myrg_rrnd.c: Changed header to GPL version 2 only myisammrg/myrg_rsame.c: Changed header to GPL version 2 only myisammrg/myrg_static.c: Changed header to GPL version 2 only myisammrg/myrg_update.c: Changed header to GPL version 2 only myisammrg/myrg_write.c: Changed header to GPL version 2 only mysql-test/Makefile.am: Changed header to GPL version 2 only mysys/Makefile.am: Changed header to GPL version 2 only mysys/array.c: Changed header to GPL version 2 only mysys/base64.c: Changed header to GPL version 2 only mysys/charset-def.c: Changed header to GPL version 2 only mysys/charset.c: Changed header to GPL version 2 only mysys/checksum.c: Changed header to GPL version 2 only mysys/default.c: Changed header to GPL version 2 only mysys/default_modify.c: Changed header to GPL version 2 only mysys/errors.c: Changed header to GPL version 2 only mysys/hash.c: Changed header to GPL version 2 only mysys/list.c: Changed header to GPL version 2 only mysys/make-conf.c: Changed header to GPL version 2 only mysys/md5.c: Changed header to GPL version 2 only mysys/mf_brkhant.c: Changed header to GPL version 2 only mysys/mf_cache.c: Changed header to GPL version 2 only mysys/mf_dirname.c: Changed header to GPL version 2 only mysys/mf_fn_ext.c: Changed header to GPL version 2 only mysys/mf_format.c: Changed header to GPL version 2 only mysys/mf_getdate.c: Changed header to GPL version 2 only mysys/mf_iocache.c: Changed header to GPL version 2 only mysys/mf_iocache2.c: Changed header to GPL version 2 only mysys/mf_keycache.c: Changed header to GPL version 2 only mysys/mf_keycaches.c: Changed header to GPL version 2 only mysys/mf_loadpath.c: Changed header to GPL version 2 only mysys/mf_pack.c: Changed header to GPL version 2 only mysys/mf_path.c: Changed header to GPL version 2 only mysys/mf_qsort.c: Changed header to GPL version 2 only mysys/mf_qsort2.c: Changed header to GPL version 2 only mysys/mf_radix.c: Changed header to GPL version 2 only mysys/mf_same.c: Changed header to GPL version 2 only mysys/mf_sort.c: Changed header to GPL version 2 only mysys/mf_soundex.c: Changed header to GPL version 2 only mysys/mf_strip.c: Changed header to GPL version 2 only mysys/mf_tempdir.c: Changed header to GPL version 2 only mysys/mf_tempfile.c: Changed header to GPL version 2 only mysys/mf_unixpath.c: Changed header to GPL version 2 only mysys/mf_util.c: Changed header to GPL version 2 only mysys/mf_wcomp.c: Changed header to GPL version 2 only mysys/mf_wfile.c: Changed header to GPL version 2 only mysys/mulalloc.c: Changed header to GPL version 2 only mysys/my_access.c: Changed header to GPL version 2 only mysys/my_aes.c: Changed header to GPL version 2 only mysys/my_alarm.c: Changed header to GPL version 2 only mysys/my_alloc.c: Changed header to GPL version 2 only mysys/my_append.c: Changed header to GPL version 2 only mysys/my_bit.c: Changed header to GPL version 2 only mysys/my_bitmap.c: Changed header to GPL version 2 only mysys/my_chsize.c: Changed header to GPL version 2 only mysys/my_clock.c: Changed header to GPL version 2 only mysys/my_compress.c: Changed header to GPL version 2 only mysys/my_conio.c: Changed header to GPL version 2 only mysys/my_copy.c: Changed header to GPL version 2 only mysys/my_crc32.c: Changed header to GPL version 2 only mysys/my_create.c: Changed header to GPL version 2 only mysys/my_delete.c: Changed header to GPL version 2 only mysys/my_div.c: Changed header to GPL version 2 only mysys/my_dup.c: Changed header to GPL version 2 only mysys/my_error.c: Changed header to GPL version 2 only mysys/my_file.c: Changed header to GPL version 2 only mysys/my_fopen.c: Changed header to GPL version 2 only mysys/my_fstream.c: Changed header to GPL version 2 only mysys/my_gethostbyname.c: Changed header to GPL version 2 only mysys/my_gethwaddr.c: Changed header to GPL version 2 only mysys/my_getopt.c: Changed header to GPL version 2 only mysys/my_getpagesize.c: Changed header to GPL version 2 only mysys/my_getsystime.c: Changed header to GPL version 2 only mysys/my_getwd.c: Changed header to GPL version 2 only mysys/my_handler.c: Changed header to GPL version 2 only mysys/my_init.c: Changed header to GPL version 2 only mysys/my_largepage.c: Changed header to GPL version 2 only mysys/my_lib.c: Changed header to GPL version 2 only mysys/my_libwrap.c: Changed header to GPL version 2 only mysys/my_lock.c: Changed header to GPL version 2 only mysys/my_lockmem.c: Changed header to GPL version 2 only mysys/my_lread.c: Changed header to GPL version 2 only mysys/my_lwrite.c: Changed header to GPL version 2 only mysys/my_malloc.c: Changed header to GPL version 2 only mysys/my_messnc.c: Changed header to GPL version 2 only mysys/my_mkdir.c: Changed header to GPL version 2 only mysys/my_mmap.c: Changed header to GPL version 2 only mysys/my_net.c: Changed header to GPL version 2 only mysys/my_netware.c: Changed header to GPL version 2 only mysys/my_new.cc: Changed header to GPL version 2 only mysys/my_once.c: Changed header to GPL version 2 only mysys/my_open.c: Changed header to GPL version 2 only mysys/my_os2cond.c: Changed header to GPL version 2 only mysys/my_os2dirsrch.c: Changed header to GPL version 2 only mysys/my_os2dirsrch.h: Changed header to GPL version 2 only mysys/my_os2dlfcn.c: Changed header to GPL version 2 only mysys/my_os2dlfcn.h0: Changed header to GPL version 2 only mysys/my_os2file64.c: Changed header to GPL version 2 only mysys/my_os2thread.c: Changed header to GPL version 2 only mysys/my_os2tls.c: Changed header to GPL version 2 only mysys/my_port.c: Changed header to GPL version 2 only mysys/my_pread.c: Changed header to GPL version 2 only mysys/my_pthread.c: Changed header to GPL version 2 only mysys/my_quick.c: Changed header to GPL version 2 only mysys/my_read.c: Changed header to GPL version 2 only mysys/my_realloc.c: Changed header to GPL version 2 only mysys/my_redel.c: Changed header to GPL version 2 only mysys/my_rename.c: Changed header to GPL version 2 only mysys/my_seek.c: Changed header to GPL version 2 only mysys/my_semaphore.c: Changed header to GPL version 2 only mysys/my_sleep.c: Changed header to GPL version 2 only mysys/my_static.c: Changed header to GPL version 2 only mysys/my_static.h: Changed header to GPL version 2 only mysys/my_symlink.c: Changed header to GPL version 2 only mysys/my_symlink2.c: Changed header to GPL version 2 only mysys/my_sync.c: Changed header to GPL version 2 only mysys/my_thr_init.c: Changed header to GPL version 2 only mysys/my_wincond.c: Changed header to GPL version 2 only mysys/my_windac.c: Changed header to GPL version 2 only mysys/my_winthread.c: Changed header to GPL version 2 only mysys/my_write.c: Changed header to GPL version 2 only mysys/mysys_priv.h: Changed header to GPL version 2 only mysys/ptr_cmp.c: Changed header to GPL version 2 only mysys/queues.c: Changed header to GPL version 2 only mysys/raid.cc: Changed header to GPL version 2 only mysys/raid2.c: Changed header to GPL version 2 only mysys/rijndael.c: Changed header to GPL version 2 only mysys/safemalloc.c: Changed header to GPL version 2 only mysys/sha1.c: Changed header to GPL version 2 only mysys/string.c: Changed header to GPL version 2 only mysys/test_charset.c: Changed header to GPL version 2 only mysys/test_dir.c: Changed header to GPL version 2 only mysys/test_fn.c: Changed header to GPL version 2 only mysys/test_xml.c: Changed header to GPL version 2 only mysys/testhash.c: Changed header to GPL version 2 only mysys/thr_alarm.c: Changed header to GPL version 2 only mysys/thr_lock.c: Changed header to GPL version 2 only mysys/thr_mutex.c: Changed header to GPL version 2 only mysys/thr_rwlock.c: Changed header to GPL version 2 only mysys/tree.c: Changed header to GPL version 2 only mysys/typelib.c: Changed header to GPL version 2 only ndb/include/debugger/DebuggerNames.hpp: Changed header to GPL version 2 only ndb/include/debugger/EventLogger.hpp: Changed header to GPL version 2 only ndb/include/debugger/GrepError.hpp: Changed header to GPL version 2 only ndb/include/debugger/SignalLoggerManager.hpp: Changed header to GPL version 2 only ndb/include/editline/editline.h: Changed header to GPL version 2 only ndb/include/kernel/AttributeDescriptor.hpp: Changed header to GPL version 2 only ndb/include/kernel/AttributeHeader.hpp: Changed header to GPL version 2 only ndb/include/kernel/AttributeList.hpp: Changed header to GPL version 2 only ndb/include/kernel/BlockNumbers.h: Changed header to GPL version 2 only ndb/include/kernel/GlobalSignalNumbers.h: Changed header to GPL version 2 only ndb/include/kernel/GrepEvent.hpp: Changed header to GPL version 2 only ndb/include/kernel/Interpreter.hpp: Changed header to GPL version 2 only ndb/include/kernel/LogLevel.hpp: Changed header to GPL version 2 only ndb/include/kernel/NodeBitmask.hpp: Changed header to GPL version 2 only ndb/include/kernel/NodeInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/NodeState.hpp: Changed header to GPL version 2 only ndb/include/kernel/RefConvert.hpp: Changed header to GPL version 2 only ndb/include/kernel/kernel_types.h: Changed header to GPL version 2 only ndb/include/kernel/ndb_limits.h: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AbortAll.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AccFrag.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AccLock.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AccScan.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AccSizeAltReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AlterIndx.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AlterTab.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AlterTable.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AlterTrig.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ApiBroadcast.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ApiRegSignalData.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ApiVersion.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ArbitSignalData.hpp: Changed header to GPL version 2 only ndb/include/kernel/trigger_definitions.h: Changed header to GPL version 2 only ndb/include/ndb_constants.h: Changed header to GPL version 2 only ndb/include/ndb_global.h.in: Changed header to GPL version 2 only ndb/include/ndb_init.h: Changed header to GPL version 2 only ndb/include/ndb_types.h.in: Changed header to GPL version 2 only ndb/include/ndb_version.h.in: Changed header to GPL version 2 only ndb/include/kernel/signaldata/AttrInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/BackupContinueB.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/BackupImpl.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/BackupSignalData.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/BlockCommitOrd.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/BuildIndx.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CheckNodeGroups.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CloseComReqConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CmInit.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CmRegSignalData.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CmvmiCfgConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CntrMasterConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CntrMasterReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ConfigParamId.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ContinueFragmented.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CopyActive.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CopyFrag.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CopyGCIReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CreateEvnt.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CreateFrag.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CreateFragmentation.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CreateIndx.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CreateTab.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CreateTable.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/CreateTrig.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DiAddTab.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DiGetNodes.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DictLock.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DictSchemaInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DictSizeAltReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DictStart.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DictTabInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DihAddFrag.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DihContinueB.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DihSizeAltReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DihStartTab.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DihSwitchReplica.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DisconnectRep.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DropIndx.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DropTab.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DropTabFile.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DropTable.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DropTrig.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/DumpStateOrd.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/EmptyLcp.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/EndTo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/EventReport.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/EventSubscribeReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ExecFragReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/FailRep.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/FireTrigOrd.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/FsAppendReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/FsCloseReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/FsConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/FsOpenReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/FsReadWriteReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/FsRef.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/FsRemoveReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/GCPSave.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/GetTabInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/GetTableId.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/GrepImpl.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/HotSpareRep.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/IndxAttrInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/IndxKeyInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/InvalidateNodeLCPConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/InvalidateNodeLCPReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/KeyInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/LCP.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ListTables.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/LqhFrag.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/LqhKey.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/LqhSizeAltReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/LqhTransConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ManagementServer.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/MasterGCP.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/MasterLCP.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/NFCompleteRep.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/NdbSttor.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/NdbfsContinueB.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/NextScan.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/NodeFailRep.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/NodeStateSignalData.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/PackedSignal.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/PrepDropTab.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/PrepFailReqRef.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ReadNodesConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/RelTabMem.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/RepImpl.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ResumeReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ScanFrag.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/ScanTab.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/SetLogLevelOrd.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/SetVarReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/SignalData.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/SignalDataPrint.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/SignalDroppedRep.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/SrFragidConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StartFragReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StartInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StartMe.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StartOrd.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StartPerm.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StartRec.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StartTo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StopMe.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StopPerm.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/StopReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/SumaImpl.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/SystemError.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TamperOrd.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcCommit.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcContinueB.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcHbRep.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcIndx.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcKeyConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcKeyFailConf.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcKeyRef.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcKeyReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcRollbackRep.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TcSizeAltReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TestOrd.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TransIdAI.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TrigAttrInfo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TupCommit.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TupFrag.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TupKey.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TupSizeAltReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TuxBound.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TuxContinueB.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TuxMaint.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/TuxSizeAltReq.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/UpdateTo.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/UtilDelete.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/UtilExecute.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/UtilLock.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/UtilPrepare.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/UtilRelease.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/UtilSequence.hpp: Changed header to GPL version 2 only ndb/include/kernel/signaldata/WaitGCP.hpp: Changed header to GPL version 2 only ndb/include/logger/ConsoleLogHandler.hpp: Changed header to GPL version 2 only ndb/include/logger/FileLogHandler.hpp: Changed header to GPL version 2 only ndb/include/logger/LogHandler.hpp: Changed header to GPL version 2 only ndb/include/logger/Logger.hpp: Changed header to GPL version 2 only ndb/include/logger/SysLogHandler.hpp: Changed header to GPL version 2 only ndb/include/mgmapi/mgmapi.h: Changed header to GPL version 2 only ndb/include/mgmapi/mgmapi_debug.h: Changed header to GPL version 2 only ndb/include/mgmapi/ndb_logevent.h: Changed header to GPL version 2 only ndb/include/mgmapi/ndbd_exit_codes.h: Changed header to GPL version 2 only ndb/include/mgmcommon/ConfigRetriever.hpp: Changed header to GPL version 2 only ndb/include/mgmcommon/IPCConfig.hpp: Changed header to GPL version 2 only ndb/include/mgmcommon/MgmtErrorReporter.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/Ndb.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbApi.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbBlob.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbDictionary.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbError.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbEventOperation.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbIndexOperation.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbIndexScanOperation.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbOperation.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbPool.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbRecAttr.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbReceiver.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbScanFilter.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbScanOperation.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/NdbTransaction.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/ndb_cluster_connection.hpp: Changed header to GPL version 2 only ndb/include/ndbapi/ndb_opt_defaults.h: Changed header to GPL version 2 only ndb/include/ndbapi/ndbapi_limits.h: Changed header to GPL version 2 only ndb/include/ndbapi/ndberror.h: Changed header to GPL version 2 only ndb/include/newtonapi/dba.h: Changed header to GPL version 2 only ndb/include/newtonapi/defs/pcn_types.h: Changed header to GPL version 2 only ndb/include/portlib/NdbCondition.h: Changed header to GPL version 2 only ndb/include/portlib/NdbConfig.h: Changed header to GPL version 2 only ndb/include/portlib/NdbDaemon.h: Changed header to GPL version 2 only ndb/include/portlib/NdbEnv.h: Changed header to GPL version 2 only ndb/include/portlib/NdbHost.h: Changed header to GPL version 2 only ndb/include/portlib/NdbMain.h: Changed header to GPL version 2 only ndb/include/portlib/NdbMem.h: Changed header to GPL version 2 only ndb/include/portlib/NdbMutex.h: Changed header to GPL version 2 only ndb/include/portlib/NdbSleep.h: Changed header to GPL version 2 only ndb/include/portlib/NdbTCP.h: Changed header to GPL version 2 only ndb/include/portlib/NdbThread.h: Changed header to GPL version 2 only ndb/include/portlib/NdbTick.h: Changed header to GPL version 2 only ndb/include/portlib/PortDefs.h: Changed header to GPL version 2 only ndb/include/portlib/prefetch.h: Changed header to GPL version 2 only ndb/include/transporter/TransporterCallback.hpp: Changed header to GPL version 2 only ndb/include/transporter/TransporterDefinitions.hpp: Changed header to GPL version 2 only ndb/include/transporter/TransporterRegistry.hpp: Changed header to GPL version 2 only ndb/include/util/BaseString.hpp: Changed header to GPL version 2 only ndb/include/util/Bitmask.hpp: Changed header to GPL version 2 only ndb/include/util/File.hpp: Changed header to GPL version 2 only ndb/include/util/InputStream.hpp: Changed header to GPL version 2 only ndb/include/util/NdbAutoPtr.hpp: Changed header to GPL version 2 only ndb/include/util/NdbOut.hpp: Changed header to GPL version 2 only ndb/include/util/NdbSqlUtil.hpp: Changed header to GPL version 2 only ndb/include/util/OutputStream.hpp: Changed header to GPL version 2 only ndb/include/util/Parser.hpp: Changed header to GPL version 2 only ndb/include/util/Properties.hpp: Changed header to GPL version 2 only ndb/include/util/SimpleProperties.hpp: Changed header to GPL version 2 only ndb/include/util/SocketAuthenticator.hpp: Changed header to GPL version 2 only ndb/include/util/SocketClient.hpp: Changed header to GPL version 2 only ndb/include/util/SocketServer.hpp: Changed header to GPL version 2 only ndb/include/util/UtilBuffer.hpp: Changed header to GPL version 2 only ndb/include/util/Vector.hpp: Changed header to GPL version 2 only ndb/include/util/basestring_vsnprintf.h: Changed header to GPL version 2 only ndb/include/util/md5_hash.hpp: Changed header to GPL version 2 only ndb/include/util/ndb_opts.h: Changed header to GPL version 2 only ndb/include/util/random.h: Changed header to GPL version 2 only ndb/include/util/socket_io.h: Changed header to GPL version 2 only ndb/include/util/uucode.h: Changed header to GPL version 2 only ndb/include/util/version.h: Changed header to GPL version 2 only ndb/ndbapi-examples/mgmapi_logevent_example/mgmapi_logevent.cpp: Changed header to GPL version 2 only ndb/ndbapi-examples/ndbapi_async_example/ndbapi_async.cpp: Changed header to GPL version 2 only ndb/ndbapi-examples/ndbapi_async_example1/ndbapi_async1.cpp: Changed header to GPL version 2 only ndb/ndbapi-examples/ndbapi_event_example/ndbapi_event.cpp: Changed header to GPL version 2 only ndb/ndbapi-examples/ndbapi_retries_example/ndbapi_retries.cpp: Changed header to GPL version 2 only ndb/ndbapi-examples/ndbapi_scan_example/ndbapi_scan.cpp: Changed header to GPL version 2 only ndb/ndbapi-examples/ndbapi_simple_example/ndbapi_simple.cpp: Changed header to GPL version 2 only ndb/ndbapi-examples/ndbapi_simple_index_example/ndbapi_simple_index.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/BlockNames.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/DebuggerNames.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/EventLogger.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/GrepError.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/SignalLoggerManager.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/AccLock.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/AlterIndx.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/AlterTab.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/AlterTable.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/AlterTrig.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/BackupImpl.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/BackupSignalData.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/CloseComReqConf.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/ContinueB.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/CopyGCI.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/CreateEvnt.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/CreateFragmentation.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/CreateIndx.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/CreateTrig.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/DictTabInfo.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/DihContinueB.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/DihSwitchReplicaReq.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/DisconnectRep.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/DropIndx.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/DropTab.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/DropTrig.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/FailRep.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/FireTrigOrd.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/FsAppendReq.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/FsCloseReq.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/FsConf.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/FsOpenReq.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/FsReadWriteReq.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/FsRef.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/GCPSave.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/IndxAttrInfo.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/IndxKeyInfo.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/LCP.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/LqhFrag.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/LqhKey.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/LqhTrans.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/MasterLCP.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/NFCompleteRep.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/NdbSttor.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/NdbfsContinueB.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/PackedSignal.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/PrepDropTab.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/PrepFailReqRef.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/ScanFrag.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/ScanTab.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/SignalDataPrint.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/SignalDroppedRep.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/SignalNames.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/StartRec.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/SumaImpl.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/SystemError.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/TcIndx.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/TcKeyConf.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/TcKeyRef.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/TcKeyReq.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/TcRollbackRep.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/TrigAttrInfo.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/TupCommit.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/TupKey.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/TuxMaint.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/UtilDelete.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/UtilExecute.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/UtilLock.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/UtilPrepare.cpp: Changed header to GPL version 2 only ndb/src/common/debugger/signaldata/UtilSequence.cpp: Changed header to GPL version 2 only ndb/src/common/logger/ConsoleLogHandler.cpp: Changed header to GPL version 2 only ndb/src/common/logger/FileLogHandler.cpp: Changed header to GPL version 2 only ndb/src/common/logger/LogHandler.cpp: Changed header to GPL version 2 only ndb/src/common/logger/LogHandlerList.cpp: Changed header to GPL version 2 only ndb/src/common/logger/LogHandlerList.hpp: Changed header to GPL version 2 only ndb/src/common/logger/Logger.cpp: Changed header to GPL version 2 only ndb/src/common/logger/SysLogHandler.cpp: Changed header to GPL version 2 only ndb/src/common/logger/listtest/LogHandlerListUnitTest.cpp: Changed header to GPL version 2 only ndb/src/common/logger/listtest/LogHandlerListUnitTest.hpp: Changed header to GPL version 2 only ndb/src/common/logger/loggertest/LoggerUnitTest.cpp: Changed header to GPL version 2 only ndb/src/common/logger/loggertest/LoggerUnitTest.hpp: Changed header to GPL version 2 only ndb/src/common/mgmcommon/ConfigRetriever.cpp: Changed header to GPL version 2 only ndb/src/common/mgmcommon/IPCConfig.cpp: Changed header to GPL version 2 only ndb/src/common/mgmcommon/printConfig/printConfig.cpp: Changed header to GPL version 2 only ndb/src/common/portlib/NdbCondition.c: Changed header to GPL version 2 only ndb/src/common/portlib/NdbConfig.c: Changed header to GPL version 2 only ndb/src/common/portlib/NdbDaemon.c: Changed header to GPL version 2 only ndb/src/common/portlib/NdbEnv.c: Changed header to GPL version 2 only ndb/src/common/portlib/NdbHost.c: Changed header to GPL version 2 only ndb/src/common/portlib/NdbMem.c: Changed header to GPL version 2 only ndb/src/common/portlib/NdbMutex.c: Changed header to GPL version 2 only ndb/src/common/portlib/NdbPortLibTest.cpp: Changed header to GPL version 2 only ndb/src/common/portlib/NdbSleep.c: Changed header to GPL version 2 only ndb/src/common/portlib/NdbTCP.cpp: Changed header to GPL version 2 only ndb/src/common/portlib/NdbThread.c: Changed header to GPL version 2 only ndb/src/common/portlib/NdbTick.c: Changed header to GPL version 2 only ndb/src/common/portlib/memtest.c: Changed header to GPL version 2 only ndb/src/common/portlib/mmslist.cpp: Changed header to GPL version 2 only ndb/src/common/portlib/mmstest.cpp: Changed header to GPL version 2 only ndb/src/common/portlib/munmaptest.cpp: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbCondition.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbConditionOSE.h: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbEnv.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbHost.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbMem.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbMem_SoftOse.cpp: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbMutex.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbOut.cpp: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbSleep.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbTCP.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbThread.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/ose/NdbTick.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbCondition.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbDaemon.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbEnv.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbHost.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbMem.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbMutex.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbSleep.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbTCP.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbThread.c: Changed header to GPL version 2 only ndb/src/common/portlib/old_dirs/win32/NdbTick.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbCondition.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbDaemon.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbEnv.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbHost.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbMem.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbMutex.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbSleep.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbTCP.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbThread.c: Changed header to GPL version 2 only ndb/src/common/portlib/win32/NdbTick.c: Changed header to GPL version 2 only ndb/src/common/transporter/OSE_Receiver.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/OSE_Receiver.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/OSE_Signals.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/OSE_Transporter.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/OSE_Transporter.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/Packer.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/Packer.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/SCI_Transporter.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/SCI_Transporter.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/SHM_Buffer.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/SHM_Transporter.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/SHM_Transporter.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/SHM_Transporter.unix.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/SHM_Transporter.win32.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/SendBuffer.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/SendBuffer.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/TCP_Transporter.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/TCP_Transporter.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/Transporter.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/Transporter.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/TransporterInternalDefinitions.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/TransporterRegistry.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/basictest/basicTransporterTest.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/buddy.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/buddy.hpp: Changed header to GPL version 2 only ndb/src/common/transporter/failoverSCI/failoverSCI.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/perftest/perfTransporterTest.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/priotest/prioSCI/prioSCI.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/priotest/prioSHM/prioSHM.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/priotest/prioTCP/prioTCP.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/priotest/prioTransporterTest.cpp: Changed header to GPL version 2 only ndb/src/common/transporter/priotest/prioTransporterTest.hpp: Changed header to GPL version 2 only ndb/src/common/util/BaseString.cpp: Changed header to GPL version 2 only ndb/src/common/util/File.cpp: Changed header to GPL version 2 only ndb/src/common/util/InputStream.cpp: Changed header to GPL version 2 only ndb/src/common/util/NdbErrHnd.cpp: Changed header to GPL version 2 only ndb/src/common/util/NdbOut.cpp: Changed header to GPL version 2 only ndb/src/common/util/NdbSqlUtil.cpp: Changed header to GPL version 2 only ndb/src/common/util/OutputStream.cpp: Changed header to GPL version 2 only ndb/src/common/util/Parser.cpp: Changed header to GPL version 2 only ndb/src/common/util/Properties.cpp: Changed header to GPL version 2 only ndb/src/common/util/SimpleProperties.cpp: Changed header to GPL version 2 only ndb/src/common/util/SocketAuthenticator.cpp: Changed header to GPL version 2 only ndb/src/common/util/SocketClient.cpp: Changed header to GPL version 2 only ndb/src/common/util/SocketServer.cpp: Changed header to GPL version 2 only ndb/src/common/util/basestring_vsnprintf.c: Changed header to GPL version 2 only ndb/src/common/util/filetest/FileUnitTest.cpp: Changed header to GPL version 2 only ndb/src/common/util/filetest/FileUnitTest.hpp: Changed header to GPL version 2 only ndb/src/common/util/md5_hash.cpp: Changed header to GPL version 2 only ndb/src/common/util/ndb_init.c: Changed header to GPL version 2 only ndb/src/common/util/random.c: Changed header to GPL version 2 only ndb/src/common/util/socket_io.cpp: Changed header to GPL version 2 only ndb/src/common/util/strdup.c: Changed header to GPL version 2 only ndb/src/common/util/testProperties/testProperties.cpp: Changed header to GPL version 2 only ndb/src/common/util/testSimpleProperties/sp_test.cpp: Changed header to GPL version 2 only ndb/src/common/util/uucode.c: Changed header to GPL version 2 only ndb/src/common/util/version.c: Changed header to GPL version 2 only ndb/src/cw/cpcc-win32/C++/CPC_GUI.cpp: Changed header to GPL version 2 only ndb/src/cw/cpcc-win32/C++/CPC_GUI.h: Changed header to GPL version 2 only ndb/src/cw/cpcc-win32/C++/NdbControls.cpp: Changed header to GPL version 2 only ndb/src/cw/cpcc-win32/C++/StdAfx.cpp: Changed header to GPL version 2 only ndb/src/cw/cpcc-win32/C++/StdAfx.h: Changed header to GPL version 2 only ndb/src/cw/cpcc-win32/C++/TreeView.cpp: Changed header to GPL version 2 only ndb/src/cw/cpcc-win32/C++/TreeView.h: Changed header to GPL version 2 only ndb/src/cw/cpcc-win32/C++/resource.h: Changed header to GPL version 2 only ndb/src/cw/cpcd/APIService.cpp: Changed header to GPL version 2 only ndb/src/cw/cpcd/APIService.hpp: Changed header to GPL version 2 only ndb/src/cw/cpcd/CPCD.cpp: Changed header to GPL version 2 only ndb/src/cw/cpcd/CPCD.hpp: Changed header to GPL version 2 only ndb/src/cw/cpcd/Monitor.cpp: Changed header to GPL version 2 only ndb/src/cw/cpcd/Process.cpp: Changed header to GPL version 2 only ndb/src/cw/cpcd/common.cpp: Changed header to GPL version 2 only ndb/src/cw/cpcd/common.hpp: Changed header to GPL version 2 only ndb/src/cw/cpcd/main.cpp: Changed header to GPL version 2 only ndb/src/cw/test/socketclient/socketClientTest.cpp: Changed header to GPL version 2 only ndb/src/cw/util/ClientInterface.cpp: Changed header to GPL version 2 only ndb/src/cw/util/ClientInterface.hpp: Changed header to GPL version 2 only ndb/src/cw/util/SocketRegistry.cpp: Changed header to GPL version 2 only ndb/src/cw/util/SocketRegistry.hpp: Changed header to GPL version 2 only ndb/src/cw/util/SocketService.cpp: Changed header to GPL version 2 only ndb/src/cw/util/SocketService.hpp: Changed header to GPL version 2 only ndb/src/kernel/SimBlockList.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/backup/Backup.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/backup/Backup.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/backup/BackupFormat.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/backup/BackupInit.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/backup/FsBuffer.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/backup/read.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/cmvmi/Cmvmi.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/cmvmi/Cmvmi.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbacc/Dbacc.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbacc/DbaccInit.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbacc/DbaccMain.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/mutexes.hpp: Changed header to GPL version 2 only ndb/src/kernel/main.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbdict/Dbdict.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbdict/Dbdict.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbdict/SchemaFile.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbdict/printSchemaFile.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbdih/Dbdih.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbdih/DbdihInit.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbdih/DbdihMain.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbdih/Sysfile.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbdih/printSysfile/printSysfile.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dblqh/Dblqh.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dblqh/DblqhInit.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dblqh/DblqhMain.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dblqh/redoLogReader/records.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dblqh/redoLogReader/records.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dblqh/redoLogReader/redoLogFileReader.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtc/Dbtc.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtc/DbtcInit.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtc/DbtcMain.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/AttributeOffset.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/Dbtup.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupAbort.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupBuffer.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupCommit.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupDebug.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupExecQuery.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupFixAlloc.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupGen.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupIndex.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupLCP.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupMeta.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupPagMan.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupPageMap.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupRoutines.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupScan.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupStoredProcDef.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupSystemRestart.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupTabDesMan.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupTrigger.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtup/DbtupUndoLog.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/Dbtux.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/DbtuxCmp.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/DbtuxDebug.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/DbtuxGen.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/DbtuxMaint.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/DbtuxMeta.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/DbtuxNode.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/DbtuxScan.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/DbtuxSearch.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbtux/DbtuxTree.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbutil/DbUtil.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/dbutil/DbUtil.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbcntr/Ndbcntr.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbcntr/NdbcntrInit.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbcntr/NdbcntrMain.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbcntr/NdbcntrSysTable.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/AsyncFile.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/AsyncFile.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/AsyncFileTest/AsyncFileTest.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/CircularIndex.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/CircularIndex.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/Filename.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/Filename.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/MemoryChannel.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/MemoryChannel.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/MemoryChannelOSE.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/MemoryChannelTest/MemoryChannelTest.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/Ndbfs.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/Ndbfs.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/OpenFiles.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/Pool.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/ndbfs/VoidFs.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/qmgr/Qmgr.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/qmgr/QmgrInit.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/qmgr/QmgrMain.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/qmgr/timer.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/suma/Suma.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/suma/Suma.hpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/suma/SumaInit.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/trix/Trix.cpp: Changed header to GPL version 2 only ndb/src/kernel/blocks/trix/Trix.hpp: Changed header to GPL version 2 only ndb/src/kernel/error/ErrorHandlingMacros.hpp: Changed header to GPL version 2 only ndb/src/kernel/error/ErrorReporter.cpp: Changed header to GPL version 2 only ndb/src/kernel/error/ErrorReporter.hpp: Changed header to GPL version 2 only ndb/src/kernel/error/TimeModule.cpp: Changed header to GPL version 2 only ndb/src/kernel/error/TimeModule.hpp: Changed header to GPL version 2 only ndb/src/kernel/error/ndbd_exit_codes.c: Changed header to GPL version 2 only ndb/src/kernel/vm/Array.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/ArrayFifoList.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/ArrayList.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/ArrayPool.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/CArray.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/Callback.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/ClusterConfiguration.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/ClusterConfiguration.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/Configuration.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/Configuration.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/DLFifoList.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/DLHashTable.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/DLHashTable2.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/DLList.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/DataBuffer.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/Emulator.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/Emulator.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/FastScheduler.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/FastScheduler.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/GlobalData.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/KeyDescriptor.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/KeyTable.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/KeyTable2.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/LongSignal.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/MetaData.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/MetaData.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/Mutex.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/Mutex.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/Prio.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/RequestTracker.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SLList.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SafeCounter.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SafeCounter.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SectionReader.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SectionReader.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SignalCounter.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SimBlockList.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SimplePropertiesSection.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SimulatedBlock.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SimulatedBlock.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SuperPool.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/SuperPool.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/ThreadConfig.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/ThreadConfig.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/TimeQueue.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/TimeQueue.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/TransporterCallback.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/VMSignal.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/VMSignal.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/WaitQueue.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/WatchDog.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/WatchDog.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/al_test/arrayListTest.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/al_test/arrayPoolTest.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/al_test/main.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/ndbd_malloc.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/ndbd_malloc.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/pc.hpp: Changed header to GPL version 2 only ndb/src/kernel/vm/testCopy/rr.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/testCopy/testCopy.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/testDataBuffer/testDataBuffer.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/testLongSig/testLongSig.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/testSimplePropertiesSection/test.cpp: Changed header to GPL version 2 only ndb/src/kernel/vm/testSuperPool.cpp: Changed header to GPL version 2 only ndb/src/mgmapi/LocalConfig.cpp: Changed header to GPL version 2 only ndb/src/mgmapi/LocalConfig.hpp: Changed header to GPL version 2 only ndb/src/mgmapi/mgmapi.cpp: Changed header to GPL version 2 only ndb/src/mgmapi/mgmapi_configuration.hpp: Changed header to GPL version 2 only ndb/src/mgmapi/mgmapi_internal.h: Changed header to GPL version 2 only ndb/src/mgmapi/ndb_logevent.cpp: Changed header to GPL version 2 only ndb/src/mgmapi/ndb_logevent.hpp: Changed header to GPL version 2 only ndb/src/mgmapi/test/keso.c: Changed header to GPL version 2 only ndb/src/mgmapi/test/mgmSrvApi.cpp: Changed header to GPL version 2 only ndb/src/mgmclient/CommandInterpreter.cpp: Changed header to GPL version 2 only ndb/src/mgmclient/main.cpp: Changed header to GPL version 2 only ndb/src/mgmclient/ndb_mgmclient.hpp: Changed header to GPL version 2 only ndb/src/mgmclient/ndb_mgmclient.h: Changed header to GPL version 2 only ndb/src/mgmclient/test_cpcd/test_cpcd.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/Config.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/Config.hpp: Changed header to GPL version 2 only ndb/src/mgmsrv/ConfigInfo.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/ConfigInfo.hpp: Changed header to GPL version 2 only ndb/src/mgmsrv/InitConfigFileParser.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/InitConfigFileParser.hpp: Changed header to GPL version 2 only ndb/src/mgmsrv/MgmtSrvr.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/MgmtSrvr.hpp: Changed header to GPL version 2 only ndb/src/mgmsrv/MgmtSrvrConfig.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/MgmtSrvrGeneralSignalHandling.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/Services.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/Services.hpp: Changed header to GPL version 2 only ndb/src/mgmsrv/SignalQueue.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/SignalQueue.hpp: Changed header to GPL version 2 only ndb/src/mgmsrv/convertStrToInt.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/convertStrToInt.hpp: Changed header to GPL version 2 only ndb/src/mgmsrv/main.cpp: Changed header to GPL version 2 only ndb/src/mgmsrv/mkconfig/mkconfig.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/API.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/ClusterMgr.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/ClusterMgr.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/DictCache.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/DictCache.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/Ndb.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbApiSignal.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbApiSignal.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbBlob.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbBlobImpl.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbDictionary.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbDictionaryImpl.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbDictionaryImpl.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbErrorOut.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbEventOperation.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbEventOperationImpl.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbEventOperationImpl.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbImpl.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbIndexOperation.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbLinHash.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbOperation.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbOperationDefine.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbOperationExec.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbOperationInt.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbOperationScan.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbOperationSearch.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbPool.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbPoolImpl.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbPoolImpl.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbRecAttr.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbReceiver.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbScanFilter.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbScanOperation.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbTransaction.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbTransactionScan.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbUtil.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbUtil.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/NdbWaiter.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/Ndberr.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/Ndbif.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/Ndbinit.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/Ndblist.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/ObjectMap.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/SignalSender.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/SignalSender.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/TransporterFacade.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/TransporterFacade.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/ndb_cluster_connection.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/ndb_cluster_connection_impl.hpp: Changed header to GPL version 2 only ndb/src/ndbapi/ndberror.c: Changed header to GPL version 2 only ndb/src/ndbapi/signal-sender/SignalSender.cpp: Changed header to GPL version 2 only ndb/src/ndbapi/signal-sender/SignalSender.hpp: Changed header to GPL version 2 only ndb/test/include/CpcClient.hpp: Changed header to GPL version 2 only ndb/test/include/HugoAsynchTransactions.hpp: Changed header to GPL version 2 only ndb/test/include/HugoCalculator.hpp: Changed header to GPL version 2 only ndb/test/include/HugoOperations.hpp: Changed header to GPL version 2 only ndb/test/include/HugoTransactions.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT_DataSet.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT_DataSetTransaction.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT_Error.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT_Output.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT_ResultRow.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT_ReturnCodes.h: Changed header to GPL version 2 only ndb/test/include/NDBT_Stats.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT_Table.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT_Tables.hpp: Changed header to GPL version 2 only ndb/test/include/NDBT_Test.hpp: Changed header to GPL version 2 only ndb/test/include/NdbBackup.hpp: Changed header to GPL version 2 only ndb/test/include/NdbConfig.hpp: Changed header to GPL version 2 only ndb/test/include/NdbGrep.hpp: Changed header to GPL version 2 only ndb/test/include/NdbRestarter.hpp: Changed header to GPL version 2 only ndb/test/include/NdbRestarts.hpp: Changed header to GPL version 2 only ndb/test/include/NdbSchemaCon.hpp: Changed header to GPL version 2 only ndb/test/include/NdbSchemaOp.hpp: Changed header to GPL version 2 only ndb/test/include/NdbTest.hpp: Changed header to GPL version 2 only ndb/test/include/NdbTimer.hpp: Changed header to GPL version 2 only ndb/test/include/TestNdbEventOperation.hpp: Changed header to GPL version 2 only ndb/test/include/UtilTransactions.hpp: Changed header to GPL version 2 only ndb/test/include/getarg.h: Changed header to GPL version 2 only ndb/test/ndbapi/InsertRecs.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ScanFilter.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/ScanFunctions.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/ScanInterpretTest.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/TraceNdbApi.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/VerifyNdbApi.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/acid.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/acid2.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/adoInsertRecs.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/asyncGenerator.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/benchronja.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bulk_copy.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/cdrserver.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/celloDb.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/create_all_tabs.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/create_tab.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/drop_all_tabs.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/flexAsynch.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/flexBench.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/flexHammer.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/flexScan.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/flexTT.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/flexTimedAsynch.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/flex_bench_mysql.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/index.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/index2.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/initronja.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/interpreterInTup.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/mainAsyncGenerator.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/msa.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ndb_async1.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ndb_async2.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ndb_user_populate.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ndb_user_transaction.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ndb_user_transaction2.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ndb_user_transaction3.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ndb_user_transaction4.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ndb_user_transaction5.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/ndb_user_transaction6.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/restarter.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/restarter2.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/restarts.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/size.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testBackup.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testBasic.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testBasicAsynch.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testBlobs.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testDataBuffers.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testDeadlock.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testDict.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testGrepVerify.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testIndex.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testInterpreter.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testMgm.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testNdbApi.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testNodeRestart.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testOIBasic.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testOperations.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testOrderedIndex.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testPartitioning.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testReadPerf.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testRestartGci.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testSRBank.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testScan.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testScanInterpreter.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testScanPerf.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testSystemRestart.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/Bank.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/Bank.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/BankLoad.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/bankCreator.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/bankMakeGL.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/bankSumAccounts.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/bankTimer.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/bankTransactionMaker.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/bankValidateAllGLs.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bank/testBank.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/asyncGenerator.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/dbGenerator.h: Changed header to GPL version 2 only ndb/test/ndbapi/bench/dbPopulate.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/dbPopulate.h: Changed header to GPL version 2 only ndb/test/ndbapi/bench/macros.h: Changed header to GPL version 2 only ndb/test/ndbapi/bench/mainAsyncGenerator.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/mainPopulate.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_async1.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_async2.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_error.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_schema.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_user_transaction.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_user_transaction2.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_user_transaction3.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_user_transaction4.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_user_transaction5.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/ndb_user_transaction6.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/testData.h: Changed header to GPL version 2 only ndb/test/ndbapi/bench/testDefinitions.h: Changed header to GPL version 2 only ndb/test/ndbapi/bench/userInterface.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/bench/userInterface.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/acid2/TraceNdbApi.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/acid2/VerifyNdbApi.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/dbGenerator.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/testData.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/async-src/include/userInterface.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/macros.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/async-src/user/ndb_error.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/include/ndb_schema.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/include/testDefinitions.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/dbGenerator.c: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/dbGenerator.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/generator/mainGenerator.c: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/include/testData.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/include/userInterface.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/dbPopulate.c: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/dbPopulate.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/populator/mainPopulate.c: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/user/localDbPrepare.c: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/user/macros.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/user/ndb_error.hpp: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userHandle.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userInterface.c: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userHandle.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userInterface.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/user/userTransaction.c: Changed header to GPL version 2 only ndb/test/ndbapi/testTimeout.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/testTransactions.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/test_event.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/test_event_merge.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/test_event_multi_table.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/userInterface.cpp: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/lmc-bench/src/user/old/userTransaction.c: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/vw_test/bcd.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/vw_test/utv.h: Changed header to GPL version 2 only ndb/test/ndbapi/old_dirs/vw_test/vcdrfunc.h: Changed header to GPL version 2 only ndb/test/newtonapi/basic_test/basic/basic.cpp: Changed header to GPL version 2 only ndb/test/newtonapi/basic_test/bulk_read/br_test.cpp: Changed header to GPL version 2 only ndb/test/newtonapi/basic_test/common.cpp: Changed header to GPL version 2 only ndb/test/newtonapi/basic_test/common.hpp: Changed header to GPL version 2 only ndb/test/newtonapi/basic_test/ptr_binding/ptr_binding_test.cpp: Changed header to GPL version 2 only ndb/test/newtonapi/basic_test/too_basic.cpp: Changed header to GPL version 2 only ndb/test/newtonapi/perf_test/perf.cpp: Changed header to GPL version 2 only ndb/test/odbc/SQL99_test/SQL99_test.cpp: Changed header to GPL version 2 only ndb/test/odbc/SQL99_test/SQL99_test.h: Changed header to GPL version 2 only ndb/test/odbc/client/NDBT_ALLOCHANDLE.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/NDBT_ALLOCHANDLE_HDBC.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/NDBT_SQLConnect.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/NDBT_SQLPrepare.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLAllocEnvTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLAllocHandleTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLAllocHandleTest_bf.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLBindColTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLBindParameterTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLCancelTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLCloseCursorTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLColAttributeTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLColAttributeTest1.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLColAttributeTest2.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLColAttributeTest3.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLConnectTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLCopyDescTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLDescribeColTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLDisconnectTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLDriverConnectTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLEndTranTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLErrorTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLExecDirectTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLExecuteTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLFetchScrollTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLFetchTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLFreeHandleTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLFreeStmtTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetConnectAttrTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetCursorNameTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetDataTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetDescFieldTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetDescRecTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetDiagFieldTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetDiagRecSimpleTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetDiagRecTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetEnvAttrTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetFunctionsTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetInfoTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetStmtAttrTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLGetTypeInfoTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLMoreResultsTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLNumResultColsTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLParamDataTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLPrepareTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLPutDataTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLRowCountTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLSetConnectAttrTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLSetCursorNameTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLSetDescFieldTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLSetDescRecTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLSetEnvAttrTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLSetStmtAttrTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLTablesTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/SQLTransactTest.cpp: Changed header to GPL version 2 only ndb/test/odbc/client/common.hpp: Changed header to GPL version 2 only ndb/test/odbc/client/main.cpp: Changed header to GPL version 2 only ndb/test/odbc/driver/testOdbcDriver.cpp: Changed header to GPL version 2 only ndb/test/odbc/test_compiler/test_compiler.cpp: Changed header to GPL version 2 only ndb/test/run-test/main.cpp: Changed header to GPL version 2 only ndb/test/run-test/run-test.hpp: Changed header to GPL version 2 only ndb/test/src/CpcClient.cpp: Changed header to GPL version 2 only ndb/test/src/HugoAsynchTransactions.cpp: Changed header to GPL version 2 only ndb/test/src/HugoCalculator.cpp: Changed header to GPL version 2 only ndb/test/src/HugoOperations.cpp: Changed header to GPL version 2 only ndb/test/src/HugoTransactions.cpp: Changed header to GPL version 2 only ndb/test/src/NDBT_Error.cpp: Changed header to GPL version 2 only ndb/test/src/NDBT_Output.cpp: Changed header to GPL version 2 only ndb/test/src/NDBT_ResultRow.cpp: Changed header to GPL version 2 only ndb/test/src/NDBT_ReturnCodes.cpp: Changed header to GPL version 2 only ndb/test/src/NDBT_Table.cpp: Changed header to GPL version 2 only ndb/test/src/NDBT_Tables.cpp: Changed header to GPL version 2 only ndb/test/src/NDBT_Test.cpp: Changed header to GPL version 2 only ndb/test/src/NdbBackup.cpp: Changed header to GPL version 2 only ndb/test/src/NdbConfig.cpp: Changed header to GPL version 2 only ndb/test/src/NdbGrep.cpp: Changed header to GPL version 2 only ndb/test/src/NdbRestarter.cpp: Changed header to GPL version 2 only ndb/test/src/NdbRestarts.cpp: Changed header to GPL version 2 only ndb/test/src/NdbSchemaCon.cpp: Changed header to GPL version 2 only ndb/test/src/NdbSchemaOp.cpp: Changed header to GPL version 2 only ndb/test/src/UtilTransactions.cpp: Changed header to GPL version 2 only ndb/test/tools/copy_tab.cpp: Changed header to GPL version 2 only ndb/test/tools/cpcc.cpp: Changed header to GPL version 2 only ndb/test/tools/create_index.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoCalculator.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoFill.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoLoad.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoLockRecords.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoPkDelete.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoPkRead.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoPkReadRecord.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoPkUpdate.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoScanRead.cpp: Changed header to GPL version 2 only ndb/test/tools/hugoScanUpdate.cpp: Changed header to GPL version 2 only ndb/test/tools/old_dirs/waiter/waiter.cpp: Changed header to GPL version 2 only ndb/test/tools/restart.cpp: Changed header to GPL version 2 only ndb/test/tools/transproxy.cpp: Changed header to GPL version 2 only ndb/test/tools/verify_index.cpp: Changed header to GPL version 2 only ndb/tools/delete_all.cpp: Changed header to GPL version 2 only ndb/tools/desc.cpp: Changed header to GPL version 2 only ndb/tools/drop_index.cpp: Changed header to GPL version 2 only ndb/tools/drop_tab.cpp: Changed header to GPL version 2 only ndb/tools/listTables.cpp: Changed header to GPL version 2 only ndb/tools/ndb_config.cpp: Changed header to GPL version 2 only ndb/tools/ndb_test_platform.cpp: Changed header to GPL version 2 only ndb/tools/ndbsql.cpp: Changed header to GPL version 2 only ndb/tools/restore/Restore.cpp: Changed header to GPL version 2 only ndb/tools/restore/Restore.hpp: Changed header to GPL version 2 only ndb/tools/restore/consumer.cpp: Changed header to GPL version 2 only ndb/tools/restore/consumer.hpp: Changed header to GPL version 2 only ndb/tools/restore/consumer_printer.cpp: Changed header to GPL version 2 only ndb/tools/restore/consumer_printer.hpp: Changed header to GPL version 2 only ndb/tools/restore/consumer_restore.cpp: Changed header to GPL version 2 only ndb/tools/restore/consumer_restore.hpp: Changed header to GPL version 2 only ndb/tools/select_all.cpp: Changed header to GPL version 2 only ndb/tools/select_count.cpp: Changed header to GPL version 2 only ndb/tools/waiter.cpp: Changed header to GPL version 2 only ndb/tools/restore/consumer_restorem.cpp: Changed header to GPL version 2 only ndb/tools/restore/restore_main.cpp: Changed header to GPL version 2 only netware/mysql_fix_privilege_tables.pl: Changed header to GPL version 2 only netware/mysql_secure_installation.pl: Changed header to GPL version 2 only os2/Makefile.am: Changed header to GPL version 2 only os2/include/Makefile.am: Changed header to GPL version 2 only os2/include/sys/Makefile.am: Changed header to GPL version 2 only pstack/Makefile.am: Changed header to GPL version 2 only regex/Makefile.am: Changed header to GPL version 2 only scripts/Makefile.am: Changed header to GPL version 2 only scripts/fill_help_tables.sh: Changed header to GPL version 2 only scripts/mysql_config.sh: Changed header to GPL version 2 only scripts/mysql_secure_installation.sh: Changed header to GPL version 2 only server-tools/instance-manager/Makefile.am: Changed header to GPL version 2 only server-tools/instance-manager/buffer.cc: Changed header to GPL version 2 only server-tools/instance-manager/buffer.h: Changed header to GPL version 2 only server-tools/instance-manager/command.cc: Changed header to GPL version 2 only server-tools/instance-manager/command.h: Changed header to GPL version 2 only server-tools/instance-manager/commands.cc: Changed header to GPL version 2 only server-tools/instance-manager/commands.h: Changed header to GPL version 2 only server-tools/instance-manager/guardian.cc: Changed header to GPL version 2 only server-tools/instance-manager/guardian.h: Changed header to GPL version 2 only server-tools/instance-manager/instance.cc: Changed header to GPL version 2 only server-tools/instance-manager/instance.h: Changed header to GPL version 2 only server-tools/instance-manager/instance_map.cc: Changed header to GPL version 2 only server-tools/instance-manager/instance_map.h: Changed header to GPL version 2 only server-tools/instance-manager/instance_options.cc: Changed header to GPL version 2 only server-tools/instance-manager/instance_options.h: Changed header to GPL version 2 only server-tools/instance-manager/listener.cc: Changed header to GPL version 2 only server-tools/instance-manager/listener.h: Changed header to GPL version 2 only server-tools/instance-manager/log.cc: Changed header to GPL version 2 only server-tools/instance-manager/log.h: Changed header to GPL version 2 only server-tools/instance-manager/manager.cc: Changed header to GPL version 2 only server-tools/instance-manager/manager.h: Changed header to GPL version 2 only server-tools/instance-manager/messages.cc: Changed header to GPL version 2 only server-tools/instance-manager/messages.h: Changed header to GPL version 2 only server-tools/instance-manager/mysql_connection.cc: Changed header to GPL version 2 only server-tools/instance-manager/mysql_connection.h: Changed header to GPL version 2 only server-tools/instance-manager/mysql_manager_error.h: Changed header to GPL version 2 only server-tools/instance-manager/mysqlmanager.cc: Changed header to GPL version 2 only server-tools/instance-manager/options.cc: Changed header to GPL version 2 only server-tools/instance-manager/options.h: Changed header to GPL version 2 only server-tools/instance-manager/parse.cc: Changed header to GPL version 2 only server-tools/instance-manager/parse.h: Changed header to GPL version 2 only server-tools/instance-manager/parse_output.cc: Changed header to GPL version 2 only server-tools/instance-manager/parse_output.h: Changed header to GPL version 2 only server-tools/instance-manager/priv.cc: Changed header to GPL version 2 only server-tools/instance-manager/priv.h: Changed header to GPL version 2 only server-tools/instance-manager/protocol.cc: Changed header to GPL version 2 only server-tools/instance-manager/protocol.h: Changed header to GPL version 2 only server-tools/instance-manager/thread_registry.cc: Changed header to GPL version 2 only server-tools/instance-manager/thread_registry.h: Changed header to GPL version 2 only server-tools/instance-manager/user_map.cc: Changed header to GPL version 2 only server-tools/instance-manager/user_map.h: Changed header to GPL version 2 only sql/Makefile.am: Changed header to GPL version 2 only sql/client_settings.h: Changed header to GPL version 2 only sql/custom_conf.h: Changed header to GPL version 2 only sql/derror.cc: Changed header to GPL version 2 only sql/des_key_file.cc: Changed header to GPL version 2 only sql/discover.cc: Changed header to GPL version 2 only sql/field.cc: Changed header to GPL version 2 only sql/field.h: Changed header to GPL version 2 only sql/field_conv.cc: Changed header to GPL version 2 only sql/filesort.cc: Changed header to GPL version 2 only sql/frm_crypt.cc: Changed header to GPL version 2 only sql/gen_lex_hash.cc: Changed header to GPL version 2 only sql/gstream.cc: Changed header to GPL version 2 only sql/gstream.h: Changed header to GPL version 2 only sql/ha_archive.cc: Changed header to GPL version 2 only sql/ha_archive.h: Changed header to GPL version 2 only sql/ha_berkeley.cc: Changed header to GPL version 2 only sql/ha_berkeley.h: Changed header to GPL version 2 only sql/ha_blackhole.cc: Changed header to GPL version 2 only sql/ha_blackhole.h: Changed header to GPL version 2 only sql/ha_federated.cc: Changed header to GPL version 2 only sql/ha_federated.h: Changed header to GPL version 2 only sql/ha_heap.cc: Changed header to GPL version 2 only sql/ha_heap.h: Changed header to GPL version 2 only sql/ha_innodb.cc: Changed header to GPL version 2 only sql/ha_innodb.h: Changed header to GPL version 2 only sql/ha_myisam.cc: Changed header to GPL version 2 only sql/ha_myisam.h: Changed header to GPL version 2 only sql/ha_myisammrg.cc: Changed header to GPL version 2 only sql/ha_myisammrg.h: Changed header to GPL version 2 only sql/ha_ndbcluster.cc: Changed header to GPL version 2 only sql/ha_ndbcluster.h: Changed header to GPL version 2 only sql/handler.cc: Changed header to GPL version 2 only sql/handler.h: Changed header to GPL version 2 only sql/hash_filo.cc: Changed header to GPL version 2 only sql/hash_filo.h: Changed header to GPL version 2 only sql/hostname.cc: Changed header to GPL version 2 only sql/init.cc: Changed header to GPL version 2 only sql/item.cc: Changed header to GPL version 2 only sql/item.h: Changed header to GPL version 2 only sql/item_buff.cc: Changed header to GPL version 2 only sql/item_cmpfunc.cc: Changed header to GPL version 2 only sql/item_cmpfunc.h: Changed header to GPL version 2 only sql/item_create.cc: Changed header to GPL version 2 only sql/item_create.h: Changed header to GPL version 2 only sql/item_func.cc: Changed header to GPL version 2 only sql/item_func.h: Changed header to GPL version 2 only sql/item_geofunc.cc: Changed header to GPL version 2 only sql/item_geofunc.h: Changed header to GPL version 2 only sql/item_row.cc: Changed header to GPL version 2 only sql/item_row.h: Changed header to GPL version 2 only sql/item_strfunc.cc: Changed header to GPL version 2 only sql/item_strfunc.h: Changed header to GPL version 2 only sql/item_subselect.cc: Changed header to GPL version 2 only sql/item_subselect.h: Changed header to GPL version 2 only sql/item_sum.cc: Changed header to GPL version 2 only sql/item_sum.h: Changed header to GPL version 2 only sql/item_timefunc.cc: Changed header to GPL version 2 only sql/item_timefunc.h: Changed header to GPL version 2 only sql/item_uniq.cc: Changed header to GPL version 2 only sql/item_uniq.h: Changed header to GPL version 2 only sql/key.cc: Changed header to GPL version 2 only sql/lex.h: Changed header to GPL version 2 only sql/lex_symbol.h: Changed header to GPL version 2 only sql/lock.cc: Changed header to GPL version 2 only sql/log.cc: Changed header to GPL version 2 only sql/log_event.cc: Changed header to GPL version 2 only sql/log_event.h: Changed header to GPL version 2 only sql/matherr.c: Changed header to GPL version 2 only sql/mf_iocache.cc: Changed header to GPL version 2 only sql/my_decimal.cc: Changed header to GPL version 2 only sql/my_decimal.h: Changed header to GPL version 2 only sql/my_lock.c: Changed header to GPL version 2 only sql/mysql_priv.h: Changed header to GPL version 2 only sql/mysqld.cc: Changed header to GPL version 2 only sql/mysqld_suffix.h: Changed header to GPL version 2 only sql/net_serv.cc: Changed header to GPL version 2 only sql/opt_range.cc: Changed header to GPL version 2 only sql/opt_range.h: Changed header to GPL version 2 only sql/opt_sum.cc: Changed header to GPL version 2 only sql/parse_file.cc: Changed header to GPL version 2 only sql/parse_file.h: Changed header to GPL version 2 only sql/password.c: Changed header to GPL version 2 only sql/procedure.cc: Changed header to GPL version 2 only sql/procedure.h: Changed header to GPL version 2 only sql/protocol.cc: Changed header to GPL version 2 only sql/protocol.h: Changed header to GPL version 2 only sql/records.cc: Changed header to GPL version 2 only sql/repl_failsafe.cc: Changed header to GPL version 2 only sql/repl_failsafe.h: Changed header to GPL version 2 only sql/set_var.cc: Changed header to GPL version 2 only sql/set_var.h: Changed header to GPL version 2 only sql/slave.cc: Changed header to GPL version 2 only sql/slave.h: Changed header to GPL version 2 only sql/sp.cc: Changed header to GPL version 2 only sql/sp.h: Changed header to GPL version 2 only sql/sp_cache.cc: Changed header to GPL version 2 only sql/sp_cache.h: Changed header to GPL version 2 only sql/sp_head.cc: Changed header to GPL version 2 only sql/sp_head.h: Changed header to GPL version 2 only sql/sp_pcontext.cc: Changed header to GPL version 2 only sql/sp_pcontext.h: Changed header to GPL version 2 only sql/sp_rcontext.cc: Changed header to GPL version 2 only sql/sp_rcontext.h: Changed header to GPL version 2 only sql/spatial.cc: Changed header to GPL version 2 only sql/spatial.h: Changed header to GPL version 2 only sql/sql_acl.cc: Changed header to GPL version 2 only sql/sql_acl.h: Changed header to GPL version 2 only sql/sql_analyse.cc: Changed header to GPL version 2 only sql/sql_analyse.h: Changed header to GPL version 2 only sql/sql_array.h: Changed header to GPL version 2 only sql/sql_base.cc: Changed header to GPL version 2 only sql/sql_bitmap.h: Changed header to GPL version 2 only sql/sql_cache.cc: Changed header to GPL version 2 only sql/sql_cache.h: Changed header to GPL version 2 only sql/sql_class.cc: Changed header to GPL version 2 only sql/sql_class.h: Changed header to GPL version 2 only sql/sql_client.cc: Changed header to GPL version 2 only sql/sql_crypt.cc: Changed header to GPL version 2 only sql/sql_crypt.h: Changed header to GPL version 2 only sql/sql_cursor.cc: Changed header to GPL version 2 only sql/sql_cursor.h: Changed header to GPL version 2 only sql/sql_db.cc: Changed header to GPL version 2 only sql/sql_delete.cc: Changed header to GPL version 2 only sql/sql_derived.cc: Changed header to GPL version 2 only sql/sql_do.cc: Changed header to GPL version 2 only sql/sql_error.cc: Changed header to GPL version 2 only sql/sql_error.h: Changed header to GPL version 2 only sql/sql_handler.cc: Changed header to GPL version 2 only sql/sql_help.cc: Changed header to GPL version 2 only sql/sql_insert.cc: Changed header to GPL version 2 only sql/sql_lex.cc: Changed header to GPL version 2 only sql/sql_lex.h: Changed header to GPL version 2 only sql/sql_list.cc: Changed header to GPL version 2 only sql/sql_list.h: Changed header to GPL version 2 only sql/sql_load.cc: Changed header to GPL version 2 only sql/sql_locale.cc: Changed header to GPL version 2 only sql/sql_manager.cc: Changed header to GPL version 2 only sql/sql_manager.h: Changed header to GPL version 2 only sql/sql_map.cc: Changed header to GPL version 2 only sql/sql_map.h: Changed header to GPL version 2 only sql/sql_olap.cc: Changed header to GPL version 2 only sql/sql_parse.cc: Changed header to GPL version 2 only sql/sql_prepare.cc: Changed header to GPL version 2 only sql/sql_rename.cc: Changed header to GPL version 2 only sql/sql_repl.cc: Changed header to GPL version 2 only sql/sql_repl.h: Changed header to GPL version 2 only sql/sql_select.cc: Changed header to GPL version 2 only sql/sql_select.h: Changed header to GPL version 2 only sql/sql_show.cc: Changed header to GPL version 2 only sql/sql_sort.h: Changed header to GPL version 2 only sql/sql_state.c: Changed header to GPL version 2 only sql/sql_string.cc: Changed header to GPL version 2 only sql/sql_string.h: Changed header to GPL version 2 only sql/sql_table.cc: Changed header to GPL version 2 only sql/sql_test.cc: Changed header to GPL version 2 only sql/sql_trigger.cc: Changed header to GPL version 2 only sql/sql_trigger.h: Changed header to GPL version 2 only sql/sql_udf.cc: Changed header to GPL version 2 only sql/sql_udf.h: Changed header to GPL version 2 only sql/sql_union.cc: Changed header to GPL version 2 only sql/sql_update.cc: Changed header to GPL version 2 only sql-bench/Makefile.am: Changed header to GPL version 2 only sql-bench/as3ap.sh: Changed header to GPL version 2 only sql-bench/bench-count-distinct.sh: Changed header to GPL version 2 only sql-bench/bench-init.pl.sh: Changed header to GPL version 2 only sql-bench/compare-results.sh: Changed header to GPL version 2 only sql-bench/copy-db.sh: Changed header to GPL version 2 only sql-bench/crash-me.sh: Changed header to GPL version 2 only sql-bench/print-limit-table: Changed header to GPL version 2 only sql-bench/run-all-tests.sh: Changed header to GPL version 2 only sql/examples/ha_example.cc: Changed header to GPL version 2 only sql/examples/ha_example.h: Changed header to GPL version 2 only sql/examples/ha_tina.cc: Changed header to GPL version 2 only sql/examples/ha_tina.h: Changed header to GPL version 2 only sql/share/Makefile.am: Changed header to GPL version 2 only sql/share/charsets/Index.xml: Changed header to GPL version 2 only sql/share/charsets/armscii8.xml: Changed header to GPL version 2 only sql/share/charsets/ascii.xml: Changed header to GPL version 2 only sql/share/charsets/cp1250.xml: Changed header to GPL version 2 only sql/share/charsets/cp1251.xml: Changed header to GPL version 2 only sql/share/charsets/cp1256.xml: Changed header to GPL version 2 only sql/share/charsets/cp1257.xml: Changed header to GPL version 2 only sql/share/charsets/cp850.xml: Changed header to GPL version 2 only sql/share/charsets/cp852.xml: Changed header to GPL version 2 only sql/share/charsets/cp866.xml: Changed header to GPL version 2 only sql/share/charsets/dec8.xml: Changed header to GPL version 2 only sql/share/charsets/geostd8.xml: Changed header to GPL version 2 only sql/share/charsets/greek.xml: Changed header to GPL version 2 only sql/share/charsets/hebrew.xml: Changed header to GPL version 2 only sql/share/charsets/hp8.xml: Changed header to GPL version 2 only sql/share/charsets/keybcs2.xml: Changed header to GPL version 2 only sql/share/charsets/koi8r.xml: Changed header to GPL version 2 only sql/share/charsets/koi8u.xml: Changed header to GPL version 2 only sql/share/charsets/latin1.xml: Changed header to GPL version 2 only sql/share/charsets/latin2.xml: Changed header to GPL version 2 only sql/share/charsets/latin5.xml: Changed header to GPL version 2 only sql/share/charsets/latin7.xml: Changed header to GPL version 2 only sql/share/charsets/macce.xml: Changed header to GPL version 2 only sql/share/charsets/macroman.xml: Changed header to GPL version 2 only sql/share/charsets/swe7.xml: Changed header to GPL version 2 only sql/sql_view.cc: Changed header to GPL version 2 only sql/sql_view.h: Changed header to GPL version 2 only sql/sql_yacc.yy: Changed header to GPL version 2 only sql/stacktrace.c: Changed header to GPL version 2 only sql/stacktrace.h: Changed header to GPL version 2 only sql/strfunc.cc: Changed header to GPL version 2 only sql/structs.h: Changed header to GPL version 2 only sql/table.cc: Changed header to GPL version 2 only sql/table.h: Changed header to GPL version 2 only sql/thr_malloc.cc: Changed header to GPL version 2 only sql/time.cc: Changed header to GPL version 2 only sql/tzfile.h: Changed header to GPL version 2 only sql/tztime.cc: Changed header to GPL version 2 only sql/tztime.h: Changed header to GPL version 2 only sql/udf_example.c: Changed header to GPL version 2 only sql/uniques.cc: Changed header to GPL version 2 only sql/unireg.cc: Changed header to GPL version 2 only sql/unireg.h: Changed header to GPL version 2 only sql-bench/server-cfg.sh: Changed header to GPL version 2 only sql-bench/test-ATIS.sh: Changed header to GPL version 2 only sql-bench/test-alter-table.sh: Changed header to GPL version 2 only sql-bench/test-big-tables.sh: Changed header to GPL version 2 only sql-bench/test-connect.sh: Changed header to GPL version 2 only sql-bench/test-create.sh: Changed header to GPL version 2 only sql-bench/test-insert.sh: Changed header to GPL version 2 only sql-bench/test-select.sh: Changed header to GPL version 2 only sql-bench/test-transactions.sh: Changed header to GPL version 2 only sql-bench/test-wisconsin.sh: Changed header to GPL version 2 only sql-common/Makefile.am: Changed header to GPL version 2 only sql-common/client.c: Changed header to GPL version 2 only sql-common/my_time.c: Changed header to GPL version 2 only sql-common/my_user.c: Changed header to GPL version 2 only sql-common/pack.c: Changed header to GPL version 2 only strings/Makefile.am: Changed header to GPL version 2 only strings/bchange.c: Changed header to GPL version 2 only strings/bcmp.c: Changed header to GPL version 2 only strings/bcopy-duff.c: Changed header to GPL version 2 only strings/bfill.c: Changed header to GPL version 2 only strings/bmove.c: Changed header to GPL version 2 only strings/bmove512.c: Changed header to GPL version 2 only strings/bmove_upp-sparc.s: Changed header to GPL version 2 only strings/bmove_upp.c: Changed header to GPL version 2 only strings/bzero.c: Changed header to GPL version 2 only strings/conf_to_src.c: Changed header to GPL version 2 only strings/ctype-big5.c: Changed header to GPL version 2 only strings/ctype-bin.c: Changed header to GPL version 2 only strings/ctype-cp932.c: Changed header to GPL version 2 only strings/ctype-czech.c: Changed header to GPL version 2 only strings/ctype-euc_kr.c: Changed header to GPL version 2 only strings/ctype-eucjpms.c: Changed header to GPL version 2 only strings/ctype-gb2312.c: Changed header to GPL version 2 only strings/ctype-gbk.c: Changed header to GPL version 2 only strings/ctype-latin1.c: Changed header to GPL version 2 only strings/ctype-mb.c: Changed header to GPL version 2 only strings/ctype-simple.c: Changed header to GPL version 2 only strings/ctype-sjis.c: Changed header to GPL version 2 only strings/ctype-tis620.c: Changed header to GPL version 2 only strings/ctype-uca.c: Changed header to GPL version 2 only strings/ctype-ucs2.c: Changed header to GPL version 2 only strings/ctype-ujis.c: Changed header to GPL version 2 only strings/ctype-utf8.c: Changed header to GPL version 2 only strings/ctype-win1250ch.c: Changed header to GPL version 2 only strings/ctype.c: Changed header to GPL version 2 only strings/decimal.c: Changed header to GPL version 2 only strings/do_ctype.c: Changed header to GPL version 2 only strings/int2str.c: Changed header to GPL version 2 only strings/is_prefix.c: Changed header to GPL version 2 only strings/llstr.c: Changed header to GPL version 2 only strings/longlong2str-x86.s: Changed header to GPL version 2 only strings/longlong2str.c: Changed header to GPL version 2 only strings/longlong2str_asm.c: Changed header to GPL version 2 only strings/macros.asm: Changed header to GPL version 2 only strings/memcmp.c: Changed header to GPL version 2 only strings/memcpy.c: Changed header to GPL version 2 only strings/memset.c: Changed header to GPL version 2 only strings/my_strtoll10-x86.s: Changed header to GPL version 2 only strings/my_strtoll10.c: Changed header to GPL version 2 only strings/my_vsnprintf.c: Changed header to GPL version 2 only strings/ptr_cmp.asm: Changed header to GPL version 2 only strings/r_strinstr.c: Changed header to GPL version 2 only strings/str2int.c: Changed header to GPL version 2 only strings/str_alloc.c: Changed header to GPL version 2 only strings/str_test.c: Changed header to GPL version 2 only strings/strappend-sparc.s: Changed header to GPL version 2 only strings/strappend.c: Changed header to GPL version 2 only strings/strcat.c: Changed header to GPL version 2 only strings/strcend.c: Changed header to GPL version 2 only strings/strchr.c: Changed header to GPL version 2 only strings/strcmp.c: Changed header to GPL version 2 only strings/strcont.c: Changed header to GPL version 2 only strings/strend-sparc.s: Changed header to GPL version 2 only strings/strend.c: Changed header to GPL version 2 only strings/strfill.c: Changed header to GPL version 2 only strings/strings-not-used.h: Changed header to GPL version 2 only strings/strings-x86.s: Changed header to GPL version 2 only strings/strings.asm: Changed header to GPL version 2 only strings/strinstr-sparc.s: Changed header to GPL version 2 only strings/strinstr.c: Changed header to GPL version 2 only strings/strlen.c: Changed header to GPL version 2 only strings/strmake-sparc.s: Changed header to GPL version 2 only strings/strmake.c: Changed header to GPL version 2 only strings/strmov-sparc.s: Changed header to GPL version 2 only strings/strmov.c: Changed header to GPL version 2 only strings/strnlen.c: Changed header to GPL version 2 only strings/strnmov-sparc.s: Changed header to GPL version 2 only strings/strnmov.c: Changed header to GPL version 2 only strings/strrchr.c: Changed header to GPL version 2 only strings/strstr-sparc.s: Changed header to GPL version 2 only strings/strstr.c: Changed header to GPL version 2 only strings/strto.c: Changed header to GPL version 2 only strings/strtol.c: Changed header to GPL version 2 only strings/strtoll.c: Changed header to GPL version 2 only strings/strtoul.c: Changed header to GPL version 2 only strings/strtoull.c: Changed header to GPL version 2 only strings/strxmov-sparc.s: Changed header to GPL version 2 only strings/strxmov.asm: Changed header to GPL version 2 only strings/strxmov.c: Changed header to GPL version 2 only strings/strxnmov.c: Changed header to GPL version 2 only strings/t_ctype.h: Changed header to GPL version 2 only strings/udiv.c: Changed header to GPL version 2 only strings/xml.c: Changed header to GPL version 2 only support-files/MacOSX/Makefile.am: Changed header to GPL version 2 only support-files/Makefile.am: Changed header to GPL version 2 only support-files/MySQL-shared-compat.spec.sh: Changed header to GPL version 2 only tests/Makefile.am: Changed header to GPL version 2 only tests/connect_test.c: Changed header to GPL version 2 only tests/deadlock_test.c: Changed header to GPL version 2 only tests/insert_test.c: Changed header to GPL version 2 only tests/list_test.c: Changed header to GPL version 2 only tests/mysql_client_test.c: Changed header to GPL version 2 only tests/select_test.c: Changed header to GPL version 2 only tests/showdb_test.c: Changed header to GPL version 2 only tests/ssl_test.c: Changed header to GPL version 2 only tests/thread_test.c: Changed header to GPL version 2 only tools/Makefile.am: Changed header to GPL version 2 only tools/mysqlmanager.c: Changed header to GPL version 2 only vio/Makefile.am: Changed header to GPL version 2 only vio/test-ssl.c: Changed header to GPL version 2 only vio/test-sslclient.c: Changed header to GPL version 2 only vio/test-sslserver.c: Changed header to GPL version 2 only vio/vio.c: Changed header to GPL version 2 only vio/vio_priv.h: Changed header to GPL version 2 only vio/viosocket.c: Changed header to GPL version 2 only vio/viossl.c: Changed header to GPL version 2 only vio/viosslfactories.c: Changed header to GPL version 2 only vio/viotest-ssl.c: Changed header to GPL version 2 only win/Makefile.am: Changed header to GPL version 2 only zlib/Makefile.am: Changed header to GPL version 2 only
		
			
				
	
	
		
			7326 lines
		
	
	
		
			213 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			7326 lines
		
	
	
		
			213 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
/* Copyright (C) 2000-2005 MySQL AB & Innobase Oy
 | 
						|
 | 
						|
   This program is free software; you can redistribute it and/or modify
 | 
						|
   it under the terms of the GNU General Public License as published by
 | 
						|
   the Free Software Foundation; version 2 of the License.
 | 
						|
 | 
						|
   This program is distributed in the hope that it will be useful,
 | 
						|
   but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
						|
   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
						|
   GNU General Public License for more details.
 | 
						|
 | 
						|
   You should have received a copy of the GNU General Public License
 | 
						|
   along with this program; if not, write to the Free Software
 | 
						|
   Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA */
 | 
						|
 | 
						|
/* This file defines the InnoDB handler: the interface between MySQL and InnoDB
 | 
						|
NOTE: You can only use noninlined InnoDB functions in this file, because we
 | 
						|
have disables the InnoDB inlining in this file. */
 | 
						|
 | 
						|
/* TODO list for the InnoDB handler in 5.0:
 | 
						|
  - Remove the flag trx->active_trans and look at the InnoDB
 | 
						|
    trx struct state field
 | 
						|
  - fix savepoint functions to use savepoint storage area
 | 
						|
  - Find out what kind of problems the OS X case-insensitivity causes to
 | 
						|
    table and database names; should we 'normalize' the names like we do
 | 
						|
    in Windows?
 | 
						|
*/
 | 
						|
 | 
						|
#ifdef USE_PRAGMA_IMPLEMENTATION
 | 
						|
#pragma implementation				// gcc: Class implementation
 | 
						|
#endif
 | 
						|
 | 
						|
#include "mysql_priv.h"
 | 
						|
#include "slave.h"
 | 
						|
 | 
						|
#ifdef HAVE_INNOBASE_DB
 | 
						|
#include <m_ctype.h>
 | 
						|
#include <hash.h>
 | 
						|
#include <myisampack.h>
 | 
						|
#include <mysys_err.h>
 | 
						|
#include <my_sys.h>
 | 
						|
 | 
						|
#define MAX_ULONG_BIT ((ulong) 1 << (sizeof(ulong)*8-1))
 | 
						|
 | 
						|
#include "ha_innodb.h"
 | 
						|
 | 
						|
pthread_mutex_t innobase_share_mutex, /* to protect innobase_open_files */
 | 
						|
                prepare_commit_mutex; /* to force correct commit order in
 | 
						|
				      binlog */
 | 
						|
ulong commit_threads= 0;
 | 
						|
pthread_mutex_t commit_threads_m;
 | 
						|
pthread_cond_t commit_cond;
 | 
						|
pthread_mutex_t commit_cond_m;
 | 
						|
bool innodb_inited= 0;
 | 
						|
 | 
						|
/*-----------------------------------------------------------------*/
 | 
						|
/* These variables are used to implement (semi-)synchronous MySQL binlog
 | 
						|
replication for InnoDB tables. */
 | 
						|
 | 
						|
pthread_cond_t  innobase_repl_cond;             /* Posix cond variable;
 | 
						|
                                                this variable is signaled
 | 
						|
                                                when enough binlog has been
 | 
						|
                                                sent to slave, so that a
 | 
						|
                                                waiting trx can return the
 | 
						|
                                                'ok' message to the client
 | 
						|
                                                for a commit */
 | 
						|
pthread_mutex_t innobase_repl_cond_mutex;       /* Posix cond variable mutex
 | 
						|
                                                that also protects the next
 | 
						|
                                                innobase_repl_... variables */
 | 
						|
uint            innobase_repl_state;            /* 1 if synchronous replication
 | 
						|
                                                is switched on and is working
 | 
						|
                                                ok; else 0 */
 | 
						|
uint            innobase_repl_file_name_inited  = 0; /* This is set to 1 when
 | 
						|
                                                innobase_repl_file_name
 | 
						|
                                                contains meaningful data */
 | 
						|
char*           innobase_repl_file_name;        /* The binlog name up to which
 | 
						|
                                                we have sent some binlog to
 | 
						|
                                                the slave */
 | 
						|
my_off_t        innobase_repl_pos;              /* The position in that file
 | 
						|
                                                up to which we have sent the
 | 
						|
                                                binlog to the slave */
 | 
						|
uint            innobase_repl_n_wait_threads    = 0; /* This tells how many
 | 
						|
                                                transactions currently are
 | 
						|
                                                waiting for the binlog to be
 | 
						|
                                                sent to the client */
 | 
						|
uint            innobase_repl_wait_file_name_inited = 0; /* This is set to 1
 | 
						|
                                                when we know the 'smallest'
 | 
						|
                                                wait position */
 | 
						|
char*           innobase_repl_wait_file_name;   /* NULL, or the 'smallest'
 | 
						|
                                                innobase_repl_file_name that
 | 
						|
                                                a transaction is waiting for */
 | 
						|
my_off_t        innobase_repl_wait_pos;         /* The smallest position in
 | 
						|
                                                that file that a trx is
 | 
						|
                                                waiting for: the trx can
 | 
						|
                                                proceed and send an 'ok' to
 | 
						|
                                                the client when MySQL has sent
 | 
						|
                                                the binlog up to this position
 | 
						|
                                                to the slave */
 | 
						|
/*-----------------------------------------------------------------*/
 | 
						|
 | 
						|
 | 
						|
 | 
						|
/* Store MySQL definition of 'byte': in Linux it is char while InnoDB
 | 
						|
uses unsigned char; the header univ.i which we include next defines
 | 
						|
'byte' as a macro which expands to 'unsigned char' */
 | 
						|
 | 
						|
typedef byte	mysql_byte;
 | 
						|
 | 
						|
#define INSIDE_HA_INNOBASE_CC
 | 
						|
 | 
						|
/* Include necessary InnoDB headers */
 | 
						|
extern "C" {
 | 
						|
#include "../innobase/include/univ.i"
 | 
						|
#include "../innobase/include/os0file.h"
 | 
						|
#include "../innobase/include/os0thread.h"
 | 
						|
#include "../innobase/include/srv0start.h"
 | 
						|
#include "../innobase/include/srv0srv.h"
 | 
						|
#include "../innobase/include/trx0roll.h"
 | 
						|
#include "../innobase/include/trx0trx.h"
 | 
						|
#include "../innobase/include/trx0sys.h"
 | 
						|
#include "../innobase/include/mtr0mtr.h"
 | 
						|
#include "../innobase/include/row0ins.h"
 | 
						|
#include "../innobase/include/row0mysql.h"
 | 
						|
#include "../innobase/include/row0sel.h"
 | 
						|
#include "../innobase/include/row0upd.h"
 | 
						|
#include "../innobase/include/log0log.h"
 | 
						|
#include "../innobase/include/lock0lock.h"
 | 
						|
#include "../innobase/include/dict0crea.h"
 | 
						|
#include "../innobase/include/btr0cur.h"
 | 
						|
#include "../innobase/include/btr0btr.h"
 | 
						|
#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 */
 | 
						|
#define HA_INNOBASE_RANGE_COUNT	  100
 | 
						|
 | 
						|
ulong 	innobase_large_page_size = 0;
 | 
						|
 | 
						|
/* The default values for the following, type long or longlong, start-up
 | 
						|
parameters are declared in mysqld.cc: */
 | 
						|
 | 
						|
long innobase_mirrored_log_groups, innobase_log_files_in_group,
 | 
						|
     innobase_log_buffer_size, innobase_buffer_pool_awe_mem_mb,
 | 
						|
     innobase_additional_mem_pool_size, innobase_file_io_threads,
 | 
						|
     innobase_lock_wait_timeout, innobase_force_recovery,
 | 
						|
     innobase_open_files;
 | 
						|
 | 
						|
longlong innobase_buffer_pool_size, innobase_log_file_size;
 | 
						|
 | 
						|
/* The default values for the following char* start-up parameters
 | 
						|
are determined in innobase_init below: */
 | 
						|
 | 
						|
char*	innobase_data_home_dir			= NULL;
 | 
						|
char*	innobase_data_file_path 		= NULL;
 | 
						|
char*	innobase_log_group_home_dir		= NULL;
 | 
						|
char*	innobase_log_arch_dir			= NULL;/* unused */
 | 
						|
/* The following has a misleading name: starting from 4.0.5, this also
 | 
						|
affects Windows: */
 | 
						|
char*	innobase_unix_file_flush_method		= NULL;
 | 
						|
 | 
						|
/* Below we have boolean-valued start-up parameters, and their default
 | 
						|
values */
 | 
						|
 | 
						|
ulong	innobase_fast_shutdown			= 1;
 | 
						|
my_bool innobase_log_archive			= FALSE;/* unused */
 | 
						|
my_bool innobase_use_doublewrite    = TRUE;
 | 
						|
my_bool innobase_use_checksums      = TRUE;
 | 
						|
my_bool innobase_use_large_pages    = FALSE;
 | 
						|
my_bool	innobase_use_native_aio			= FALSE;
 | 
						|
my_bool	innobase_file_per_table			= FALSE;
 | 
						|
my_bool innobase_locks_unsafe_for_binlog        = FALSE;
 | 
						|
my_bool innobase_rollback_on_timeout		= FALSE;
 | 
						|
my_bool innobase_create_status_file		= FALSE;
 | 
						|
 | 
						|
static char *internal_innobase_data_file_path	= NULL;
 | 
						|
 | 
						|
/* The following counter is used to convey information to InnoDB
 | 
						|
about server activity: in selects it is not sensible to call
 | 
						|
srv_active_wake_master_thread after each fetch or search, we only do
 | 
						|
it every INNOBASE_WAKE_INTERVAL'th step. */
 | 
						|
 | 
						|
#define INNOBASE_WAKE_INTERVAL	32
 | 
						|
ulong	innobase_active_counter	= 0;
 | 
						|
 | 
						|
static HASH 	innobase_open_tables;
 | 
						|
 | 
						|
#ifdef __NETWARE__  	/* some special cleanup for NetWare */
 | 
						|
bool nw_panic = FALSE;
 | 
						|
#endif
 | 
						|
 | 
						|
static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
 | 
						|
			      my_bool not_used __attribute__((unused)));
 | 
						|
static INNOBASE_SHARE *get_share(const char *table_name);
 | 
						|
static void free_share(INNOBASE_SHARE *share);
 | 
						|
static int innobase_close_connection(THD* thd);
 | 
						|
static int innobase_commit(THD* thd, bool all);
 | 
						|
static int innobase_rollback(THD* thd, bool all);
 | 
						|
static int innobase_rollback_to_savepoint(THD* thd, void *savepoint);
 | 
						|
static int innobase_savepoint(THD* thd, void *savepoint);
 | 
						|
static int innobase_release_savepoint(THD* thd, void *savepoint);
 | 
						|
 | 
						|
handlerton innobase_hton = {
 | 
						|
  "InnoDB",
 | 
						|
  SHOW_OPTION_YES,
 | 
						|
  "Supports transactions, row-level locking, and foreign keys",
 | 
						|
  DB_TYPE_INNODB,
 | 
						|
  innobase_init,
 | 
						|
  0,				/* slot */
 | 
						|
  sizeof(trx_named_savept_t),	/* savepoint size. TODO: use it */
 | 
						|
  innobase_close_connection,
 | 
						|
  innobase_savepoint,
 | 
						|
  innobase_rollback_to_savepoint,
 | 
						|
  innobase_release_savepoint,
 | 
						|
  innobase_commit,		/* commit */
 | 
						|
  innobase_rollback,		/* rollback */
 | 
						|
  innobase_xa_prepare,		/* prepare */
 | 
						|
  innobase_xa_recover,		/* recover */
 | 
						|
  innobase_commit_by_xid,	/* commit_by_xid */
 | 
						|
  innobase_rollback_by_xid,     /* rollback_by_xid */
 | 
						|
  innobase_create_cursor_view,
 | 
						|
  innobase_set_cursor_view,
 | 
						|
  innobase_close_cursor_view,
 | 
						|
  HTON_NO_FLAGS
 | 
						|
};
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
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},
 | 
						|
  {"row_lock_current_waits",
 | 
						|
  (char*) &export_vars.innodb_row_lock_current_waits,     SHOW_LONG},
 | 
						|
  {"row_lock_time",
 | 
						|
  (char*) &export_vars.innodb_row_lock_time,              SHOW_LONGLONG},
 | 
						|
  {"row_lock_time_avg",
 | 
						|
  (char*) &export_vars.innodb_row_lock_time_avg,          SHOW_LONG},
 | 
						|
  {"row_lock_time_max",
 | 
						|
  (char*) &export_vars.innodb_row_lock_time_max,          SHOW_LONG},
 | 
						|
  {"row_lock_waits",
 | 
						|
  (char*) &export_vars.innodb_row_lock_waits,             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 */
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Save some CPU by testing the value of srv_thread_concurrency in inline
 | 
						|
functions. */
 | 
						|
inline
 | 
						|
void
 | 
						|
innodb_srv_conc_enter_innodb(
 | 
						|
/*=========================*/
 | 
						|
	trx_t*	trx)	/* in: transaction handle */
 | 
						|
{
 | 
						|
	if (UNIV_LIKELY(!srv_thread_concurrency)) {
 | 
						|
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	srv_conc_enter_innodb(trx);
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Save some CPU by testing the value of srv_thread_concurrency in inline
 | 
						|
functions. */
 | 
						|
inline
 | 
						|
void
 | 
						|
innodb_srv_conc_exit_innodb(
 | 
						|
/*========================*/
 | 
						|
	trx_t*	trx)	/* in: transaction handle */
 | 
						|
{
 | 
						|
	if (UNIV_LIKELY(!srv_thread_concurrency)) {
 | 
						|
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	srv_conc_exit_innodb(trx);
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Releases possible search latch and InnoDB thread FIFO ticket. These should
 | 
						|
be released at each SQL statement end, and also when mysqld passes the
 | 
						|
control to the client. It does no harm to release these also in the middle
 | 
						|
of an SQL statement. */
 | 
						|
inline
 | 
						|
void
 | 
						|
innobase_release_stat_resources(
 | 
						|
/*============================*/
 | 
						|
	trx_t*	trx)	/* in: transaction object */
 | 
						|
{
 | 
						|
	if (trx->has_search_latch) {
 | 
						|
		trx_search_latch_release_if_reserved(trx);
 | 
						|
	}
 | 
						|
 | 
						|
	if (trx->declared_to_be_inside_innodb) {
 | 
						|
		/* Release our possible ticket in the FIFO */
 | 
						|
 | 
						|
		srv_conc_force_exit_innodb(trx);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
Call this function when mysqld passes control to the client. That is to
 | 
						|
avoid deadlocks on the adaptive hash S-latch possibly held by thd. For more
 | 
						|
documentation, see handler.cc. */
 | 
						|
 | 
						|
void
 | 
						|
innobase_release_temporary_latches(
 | 
						|
/*===============================*/
 | 
						|
        THD *thd)
 | 
						|
{
 | 
						|
	trx_t*	trx;
 | 
						|
 | 
						|
	if (!innodb_inited) {
 | 
						|
 | 
						|
		return;
 | 
						|
	}
 | 
						|
 | 
						|
	trx = (trx_t*) thd->ha_data[innobase_hton.slot];
 | 
						|
 | 
						|
	if (trx) {
 | 
						|
        	innobase_release_stat_resources(trx);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
Increments innobase_active_counter and every INNOBASE_WAKE_INTERVALth
 | 
						|
time calls srv_active_wake_master_thread. This function should be used
 | 
						|
when a single database operation may introduce a small need for
 | 
						|
server utility activity, like checkpointing. */
 | 
						|
inline
 | 
						|
void
 | 
						|
innobase_active_small(void)
 | 
						|
/*=======================*/
 | 
						|
{
 | 
						|
	innobase_active_counter++;
 | 
						|
 | 
						|
	if ((innobase_active_counter % INNOBASE_WAKE_INTERVAL) == 0) {
 | 
						|
		srv_active_wake_master_thread();
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
Converts an InnoDB error code to a MySQL error code and also tells to MySQL
 | 
						|
about a possible transaction rollback inside InnoDB caused by a lock wait
 | 
						|
timeout or a deadlock. */
 | 
						|
static
 | 
						|
int
 | 
						|
convert_error_code_to_mysql(
 | 
						|
/*========================*/
 | 
						|
			/* out: MySQL error code */
 | 
						|
	int	error,	/* in: InnoDB error code */
 | 
						|
	THD*	thd)	/* in: user thread handle or NULL */
 | 
						|
{
 | 
						|
	if (error == DB_SUCCESS) {
 | 
						|
 | 
						|
		return(0);
 | 
						|
 | 
						|
  	} else if (error == (int) DB_DUPLICATE_KEY) {
 | 
						|
 | 
						|
    		return(HA_ERR_FOUND_DUPP_KEY);
 | 
						|
 | 
						|
 	} else if (error == (int) DB_RECORD_NOT_FOUND) {
 | 
						|
 | 
						|
    		return(HA_ERR_NO_ACTIVE_RECORD);
 | 
						|
 | 
						|
 	} else if (error == (int) DB_ERROR) {
 | 
						|
 | 
						|
    		return(-1); /* unspecified error */
 | 
						|
 | 
						|
 	} else if (error == (int) DB_DEADLOCK) {
 | 
						|
 		/* Since we rolled back the whole transaction, we must
 | 
						|
 		tell it also to MySQL so that MySQL knows to empty the
 | 
						|
 		cached binlog for this transaction */
 | 
						|
 | 
						|
 		if (thd) {
 | 
						|
 			ha_rollback(thd);
 | 
						|
 		}
 | 
						|
 | 
						|
    		return(HA_ERR_LOCK_DEADLOCK);
 | 
						|
 | 
						|
 	} else if (error == (int) DB_LOCK_WAIT_TIMEOUT) {
 | 
						|
 | 
						|
		/* Starting from 5.0.13, we let MySQL just roll back the
 | 
						|
		latest SQL statement in a lock wait timeout. Previously, we
 | 
						|
		rolled back the whole transaction. */
 | 
						|
 | 
						|
		if (thd && row_rollback_on_timeout) {
 | 
						|
			ha_rollback(thd);
 | 
						|
		}
 | 
						|
 | 
						|
   		return(HA_ERR_LOCK_WAIT_TIMEOUT);
 | 
						|
 | 
						|
 	} else if (error == (int) DB_NO_REFERENCED_ROW) {
 | 
						|
 | 
						|
    		return(HA_ERR_NO_REFERENCED_ROW);
 | 
						|
 | 
						|
 	} else if (error == (int) DB_ROW_IS_REFERENCED) {
 | 
						|
 | 
						|
    		return(HA_ERR_ROW_IS_REFERENCED);
 | 
						|
 | 
						|
        } else if (error == (int) DB_CANNOT_ADD_CONSTRAINT) {
 | 
						|
 | 
						|
    		return(HA_ERR_CANNOT_ADD_FOREIGN);
 | 
						|
 | 
						|
        } else if (error == (int) DB_CANNOT_DROP_CONSTRAINT) {
 | 
						|
 | 
						|
    		return(HA_ERR_ROW_IS_REFERENCED); /* TODO: This is a bit
 | 
						|
						misleading, a new MySQL error
 | 
						|
						code should be introduced */
 | 
						|
        } else if (error == (int) DB_COL_APPEARS_TWICE_IN_INDEX) {
 | 
						|
 | 
						|
    		return(HA_ERR_CRASHED);
 | 
						|
 | 
						|
 	} else if (error == (int) DB_OUT_OF_FILE_SPACE) {
 | 
						|
 | 
						|
    		return(HA_ERR_RECORD_FILE_FULL);
 | 
						|
 | 
						|
 	} else if (error == (int) DB_TABLE_IS_BEING_USED) {
 | 
						|
 | 
						|
    		return(HA_ERR_WRONG_COMMAND);
 | 
						|
 | 
						|
 	} else if (error == (int) DB_TABLE_NOT_FOUND) {
 | 
						|
 | 
						|
    		return(HA_ERR_KEY_NOT_FOUND);
 | 
						|
 | 
						|
  	} else if (error == (int) DB_TOO_BIG_RECORD) {
 | 
						|
 | 
						|
    		return(HA_ERR_TO_BIG_ROW);
 | 
						|
 | 
						|
  	} else if (error == (int) DB_CORRUPTION) {
 | 
						|
 | 
						|
    		return(HA_ERR_CRASHED);
 | 
						|
  	} else if (error == (int) DB_NO_SAVEPOINT) {
 | 
						|
 | 
						|
    		return(HA_ERR_NO_SAVEPOINT);
 | 
						|
  	} else if (error == (int) DB_LOCK_TABLE_FULL) {
 | 
						|
 		/* Since we rolled back the whole transaction, we must
 | 
						|
 		tell it also to MySQL so that MySQL knows to empty the
 | 
						|
 		cached binlog for this transaction */
 | 
						|
 | 
						|
 		if (thd) {
 | 
						|
 			ha_rollback(thd);
 | 
						|
 		}
 | 
						|
 | 
						|
    		return(HA_ERR_LOCK_TABLE_FULL);
 | 
						|
    	} else {
 | 
						|
    		return(-1);			// Unknown error
 | 
						|
    	}
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************
 | 
						|
If you want to print a thd that is not associated with the current thread,
 | 
						|
you must call this function before reserving the InnoDB kernel_mutex, to
 | 
						|
protect MySQL from setting thd->query NULL. If you print a thd of the current
 | 
						|
thread, we know that MySQL cannot modify thd->query, and it is not necessary
 | 
						|
to call this. Call innobase_mysql_end_print_arbitrary_thd() after you release
 | 
						|
the kernel_mutex.
 | 
						|
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
 | 
						|
function! */
 | 
						|
extern "C"
 | 
						|
void
 | 
						|
innobase_mysql_prepare_print_arbitrary_thd(void)
 | 
						|
/*============================================*/
 | 
						|
{
 | 
						|
	VOID(pthread_mutex_lock(&LOCK_thread_count));
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************
 | 
						|
Releases the mutex reserved by innobase_mysql_prepare_print_arbitrary_thd().
 | 
						|
NOTE that /mysql/innobase/lock/lock0lock.c must contain the prototype for this
 | 
						|
function! */
 | 
						|
extern "C"
 | 
						|
void
 | 
						|
innobase_mysql_end_print_arbitrary_thd(void)
 | 
						|
/*========================================*/
 | 
						|
{
 | 
						|
	VOID(pthread_mutex_unlock(&LOCK_thread_count));
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************
 | 
						|
Prints info of a THD object (== user session thread) to the given file.
 | 
						|
NOTE that /mysql/innobase/trx/trx0trx.c must contain the prototype for
 | 
						|
this function! */
 | 
						|
extern "C"
 | 
						|
void
 | 
						|
innobase_mysql_print_thd(
 | 
						|
/*=====================*/
 | 
						|
	FILE*   f,		/* in: output stream */
 | 
						|
	void*   input_thd,	/* in: pointer to a MySQL THD object */
 | 
						|
	uint	max_query_len)	/* in: max query length to print, or 0 to
 | 
						|
				   use the default max length */
 | 
						|
{
 | 
						|
	const THD*	thd;
 | 
						|
        const Security_context *sctx;
 | 
						|
	const char*	s;
 | 
						|
 | 
						|
        thd = (const THD*) input_thd;
 | 
						|
        /* We probably want to have original user as part of debug output. */
 | 
						|
        sctx = &thd->main_security_ctx;
 | 
						|
 | 
						|
 | 
						|
  	fprintf(f, "MySQL thread id %lu, query id %lu",
 | 
						|
		thd->thread_id, (ulong) thd->query_id);
 | 
						|
	if (sctx->host) {
 | 
						|
		putc(' ', f);
 | 
						|
		fputs(sctx->host, f);
 | 
						|
	}
 | 
						|
 | 
						|
	if (sctx->ip) {
 | 
						|
		putc(' ', f);
 | 
						|
		fputs(sctx->ip, f);
 | 
						|
	}
 | 
						|
 | 
						|
        if (sctx->user) {
 | 
						|
		putc(' ', f);
 | 
						|
		fputs(sctx->user, f);
 | 
						|
  	}
 | 
						|
 | 
						|
	if ((s = thd->proc_info)) {
 | 
						|
		putc(' ', f);
 | 
						|
		fputs(s, f);
 | 
						|
	}
 | 
						|
 | 
						|
	if ((s = thd->query)) {
 | 
						|
		/* 3100 is chosen because currently 3000 is the maximum
 | 
						|
		   max_query_len we ever give this. */
 | 
						|
		char	buf[3100];
 | 
						|
		uint	len;
 | 
						|
 | 
						|
		/* If buf is too small, we dynamically allocate storage
 | 
						|
		   in this. */
 | 
						|
		char*	dyn_str = NULL;
 | 
						|
 | 
						|
		/* Points to buf or dyn_str. */
 | 
						|
		char*	str = buf;
 | 
						|
 | 
						|
		if (max_query_len == 0)
 | 
						|
		{
 | 
						|
			/* ADDITIONAL SAFETY: the default is to print at
 | 
						|
			   most 300 chars to reduce the probability of a
 | 
						|
			   seg fault if there is a race in
 | 
						|
			   thd->query_length in MySQL; after May 14, 2004
 | 
						|
			   probably no race any more, but better be
 | 
						|
			   safe */
 | 
						|
			max_query_len = 300;
 | 
						|
		}
 | 
						|
 | 
						|
		len = min(thd->query_length, max_query_len);
 | 
						|
 | 
						|
		if (len > (sizeof(buf) - 1))
 | 
						|
		{
 | 
						|
			dyn_str = my_malloc(len + 1, MYF(0));
 | 
						|
			str = dyn_str;
 | 
						|
		}
 | 
						|
 | 
						|
                /* Use strmake to reduce the timeframe for a race,
 | 
						|
                   compared to fwrite() */
 | 
						|
		len = (uint) (strmake(str, s, len) - str);
 | 
						|
		putc('\n', f);
 | 
						|
		fwrite(str, 1, len, f);
 | 
						|
 | 
						|
		if (dyn_str)
 | 
						|
		{
 | 
						|
			my_free(dyn_str, MYF(0));
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	putc('\n', f);
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Get the variable length bounds of the given character set.
 | 
						|
 | 
						|
NOTE that the exact prototype of this function has to be in
 | 
						|
/innobase/data/data0type.ic! */
 | 
						|
extern "C"
 | 
						|
void
 | 
						|
innobase_get_cset_width(
 | 
						|
/*====================*/
 | 
						|
	ulint	cset,		/* in: MySQL charset-collation code */
 | 
						|
	ulint*	mbminlen,	/* out: minimum length of a char (in bytes) */
 | 
						|
	ulint*	mbmaxlen)	/* out: maximum length of a char (in bytes) */
 | 
						|
{
 | 
						|
	CHARSET_INFO*	cs;
 | 
						|
	ut_ad(cset < 256);
 | 
						|
	ut_ad(mbminlen);
 | 
						|
	ut_ad(mbmaxlen);
 | 
						|
 | 
						|
	cs = all_charsets[cset];
 | 
						|
	if (cs) {
 | 
						|
		*mbminlen = cs->mbminlen;
 | 
						|
		*mbmaxlen = cs->mbmaxlen;
 | 
						|
	} else {
 | 
						|
		ut_a(cset == 0);
 | 
						|
		*mbminlen = *mbmaxlen = 0;
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Compares NUL-terminated UTF-8 strings case insensitively.
 | 
						|
 | 
						|
NOTE that the exact prototype of this function has to be in
 | 
						|
/innobase/dict/dict0dict.c! */
 | 
						|
extern "C"
 | 
						|
int
 | 
						|
innobase_strcasecmp(
 | 
						|
/*================*/
 | 
						|
				/* out: 0 if a=b, <0 if a<b, >1 if a>b */
 | 
						|
	const char*	a,	/* in: first string to compare */
 | 
						|
	const char*	b)	/* in: second string to compare */
 | 
						|
{
 | 
						|
	return(my_strcasecmp(system_charset_info, a, b));
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Makes all characters in a NUL-terminated UTF-8 string lower case.
 | 
						|
 | 
						|
NOTE that the exact prototype of this function has to be in
 | 
						|
/innobase/dict/dict0dict.c! */
 | 
						|
extern "C"
 | 
						|
void
 | 
						|
innobase_casedn_str(
 | 
						|
/*================*/
 | 
						|
	char*	a)	/* in/out: string to put in lower case */
 | 
						|
{
 | 
						|
	my_casedn_str(system_charset_info, a);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Creates a temporary file. */
 | 
						|
extern "C"
 | 
						|
int
 | 
						|
innobase_mysql_tmpfile(void)
 | 
						|
/*========================*/
 | 
						|
			/* out: temporary file descriptor, or < 0 on error */
 | 
						|
{
 | 
						|
	char	filename[FN_REFLEN];
 | 
						|
	int	fd2 = -1;
 | 
						|
	File	fd = create_temp_file(filename, mysql_tmpdir, "ib",
 | 
						|
#ifdef __WIN__
 | 
						|
				O_BINARY | O_TRUNC | O_SEQUENTIAL |
 | 
						|
				O_TEMPORARY | O_SHORT_LIVED |
 | 
						|
#endif /* __WIN__ */
 | 
						|
				O_CREAT | O_EXCL | O_RDWR,
 | 
						|
				MYF(MY_WME));
 | 
						|
	if (fd >= 0) {
 | 
						|
#ifndef __WIN__
 | 
						|
		/* On Windows, open files cannot be removed, but files can be
 | 
						|
		created with the O_TEMPORARY flag to the same effect
 | 
						|
		("delete on close"). */
 | 
						|
		unlink(filename);
 | 
						|
#endif /* !__WIN__ */
 | 
						|
		/* Copy the file descriptor, so that the additional resources
 | 
						|
		allocated by create_temp_file() can be freed by invoking
 | 
						|
		my_close().
 | 
						|
 | 
						|
		Because the file descriptor returned by this function
 | 
						|
		will be passed to fdopen(), it will be closed by invoking
 | 
						|
		fclose(), which in turn will invoke close() instead of
 | 
						|
		my_close(). */
 | 
						|
		fd2 = dup(fd);
 | 
						|
		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_close(fd, MYF(MY_WME));
 | 
						|
	}
 | 
						|
	return(fd2);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Gets the InnoDB transaction handle for a MySQL handler object, creates
 | 
						|
an InnoDB transaction struct if the corresponding MySQL thread struct still
 | 
						|
lacks one. */
 | 
						|
static
 | 
						|
trx_t*
 | 
						|
check_trx_exists(
 | 
						|
/*=============*/
 | 
						|
			/* out: InnoDB transaction handle */
 | 
						|
	THD*	thd)	/* in: user thread handle */
 | 
						|
{
 | 
						|
	trx_t*	trx;
 | 
						|
 | 
						|
	ut_ad(thd == current_thd);
 | 
						|
 | 
						|
        trx = (trx_t*) thd->ha_data[innobase_hton.slot];
 | 
						|
 | 
						|
	if (trx == NULL) {
 | 
						|
	        DBUG_ASSERT(thd != NULL);
 | 
						|
		trx = trx_allocate_for_mysql();
 | 
						|
 | 
						|
		trx->mysql_thd = thd;
 | 
						|
		trx->mysql_query_str = &(thd->query);
 | 
						|
                trx->active_trans = 0;
 | 
						|
 | 
						|
		/* Update the info whether we should skip XA steps that eat
 | 
						|
		CPU time */
 | 
						|
		trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
 | 
						|
 | 
						|
                thd->ha_data[innobase_hton.slot] = trx;
 | 
						|
	} else {
 | 
						|
		if (trx->magic_n != TRX_MAGIC_N) {
 | 
						|
			mem_analyze_corruption((byte*)trx);
 | 
						|
 | 
						|
			ut_a(0);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
 | 
						|
		trx->check_foreigns = FALSE;
 | 
						|
	} else {
 | 
						|
		trx->check_foreigns = TRUE;
 | 
						|
	}
 | 
						|
 | 
						|
	if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
 | 
						|
		trx->check_unique_secondary = FALSE;
 | 
						|
	} else {
 | 
						|
		trx->check_unique_secondary = TRUE;
 | 
						|
	}
 | 
						|
 | 
						|
	return(trx);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Construct ha_innobase handler. */
 | 
						|
 | 
						|
ha_innobase::ha_innobase(TABLE *table_arg)
 | 
						|
  :handler(&innobase_hton, table_arg),
 | 
						|
  int_table_flags(HA_REC_NOT_IN_SEQ |
 | 
						|
                  HA_NULL_IN_KEY |
 | 
						|
                  HA_CAN_INDEX_BLOBS |
 | 
						|
                  HA_CAN_SQL_HANDLER |
 | 
						|
                  HA_NOT_EXACT_COUNT |
 | 
						|
                  HA_PRIMARY_KEY_IN_READ_INDEX |
 | 
						|
                  HA_CAN_GEOMETRY |
 | 
						|
                  HA_TABLE_SCAN_ON_INDEX),
 | 
						|
  start_of_scan(0),
 | 
						|
  num_write_row(0)
 | 
						|
{}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Updates the user_thd field in a handle and also allocates a new InnoDB
 | 
						|
transaction handle if needed, and updates the transaction fields in the
 | 
						|
prebuilt struct. */
 | 
						|
inline
 | 
						|
int
 | 
						|
ha_innobase::update_thd(
 | 
						|
/*====================*/
 | 
						|
			/* out: 0 or error code */
 | 
						|
	THD*	thd)	/* in: thd to use the handle */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	trx_t*		trx;
 | 
						|
 | 
						|
	trx = check_trx_exists(thd);
 | 
						|
 | 
						|
	if (prebuilt->trx != trx) {
 | 
						|
 | 
						|
		row_update_prebuilt_trx(prebuilt, trx);
 | 
						|
	}
 | 
						|
 | 
						|
	user_thd = thd;
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Registers that InnoDB takes part in an SQL statement, so that MySQL knows to
 | 
						|
roll back the statement if the statement results in an error. This MUST be
 | 
						|
called for every SQL statement that may be rolled back by MySQL. Calling this
 | 
						|
several times to register the same statement is allowed, too. */
 | 
						|
inline
 | 
						|
void
 | 
						|
innobase_register_stmt(
 | 
						|
/*===================*/
 | 
						|
	THD*	thd)	/* in: MySQL thd (connection) object */
 | 
						|
{
 | 
						|
        /* Register the statement */
 | 
						|
        trans_register_ha(thd, FALSE, &innobase_hton);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Registers an InnoDB transaction in MySQL, so that the MySQL XA code knows
 | 
						|
to call the InnoDB prepare and commit, or rollback for the transaction. This
 | 
						|
MUST be called for every transaction for which the user may call commit or
 | 
						|
rollback. Calling this several times to register the same transaction is
 | 
						|
allowed, too.
 | 
						|
This function also registers the current SQL statement. */
 | 
						|
inline
 | 
						|
void
 | 
						|
innobase_register_trx_and_stmt(
 | 
						|
/*===========================*/
 | 
						|
	THD*	thd)	/* in: MySQL thd (connection) object */
 | 
						|
{
 | 
						|
	/* NOTE that actually innobase_register_stmt() registers also
 | 
						|
	the transaction in the AUTOCOMMIT=1 mode. */
 | 
						|
 | 
						|
	innobase_register_stmt(thd);
 | 
						|
 | 
						|
        if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 | 
						|
 | 
						|
              /* No autocommit mode, register for a transaction */
 | 
						|
              trans_register_ha(thd, TRUE, &innobase_hton);
 | 
						|
        }
 | 
						|
}
 | 
						|
 | 
						|
/*   BACKGROUND INFO: HOW THE MYSQL QUERY CACHE WORKS WITH INNODB
 | 
						|
     ------------------------------------------------------------
 | 
						|
 | 
						|
1) The use of the query cache for TBL is disabled when there is an
 | 
						|
uncommitted change to TBL.
 | 
						|
 | 
						|
2) When a change to TBL commits, InnoDB stores the current value of
 | 
						|
its global trx id counter, let us denote it by INV_TRX_ID, to the table object
 | 
						|
in the InnoDB data dictionary, and does only allow such transactions whose
 | 
						|
id <= INV_TRX_ID to use the query cache.
 | 
						|
 | 
						|
3) When InnoDB does an INSERT/DELETE/UPDATE to a table TBL, or an implicit
 | 
						|
modification because an ON DELETE CASCADE, we invalidate the MySQL query cache
 | 
						|
of TBL immediately.
 | 
						|
 | 
						|
How this is implemented inside InnoDB:
 | 
						|
 | 
						|
1) Since every modification always sets an IX type table lock on the InnoDB
 | 
						|
table, it is easy to check if there can be uncommitted modifications for a
 | 
						|
table: just check if there are locks in the lock list of the table.
 | 
						|
 | 
						|
2) When a transaction inside InnoDB commits, it reads the global trx id
 | 
						|
counter and stores the value INV_TRX_ID to the tables on which it had a lock.
 | 
						|
 | 
						|
3) If there is an implicit table change from ON DELETE CASCADE or SET NULL,
 | 
						|
InnoDB calls an invalidate method for the MySQL query cache for that table.
 | 
						|
 | 
						|
How this is implemented inside sql_cache.cc:
 | 
						|
 | 
						|
1) The query cache for an InnoDB table TBL is invalidated immediately at an
 | 
						|
INSERT/UPDATE/DELETE, just like in the case of MyISAM. No need to delay
 | 
						|
invalidation to the transaction commit.
 | 
						|
 | 
						|
2) To store or retrieve a value from the query cache of an InnoDB table TBL,
 | 
						|
any query must first ask InnoDB's permission. We must pass the thd as a
 | 
						|
parameter because InnoDB will look at the trx id, if any, associated with
 | 
						|
that thd.
 | 
						|
 | 
						|
3) Use of the query cache for InnoDB tables is now allowed also when
 | 
						|
AUTOCOMMIT==0 or we are inside BEGIN ... COMMIT. Thus transactions no longer
 | 
						|
put restrictions on the use of the query cache.
 | 
						|
*/
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
The MySQL query cache uses this to check from InnoDB if the query cache at
 | 
						|
the moment is allowed to operate on an InnoDB table. The SQL query must
 | 
						|
be a non-locking SELECT.
 | 
						|
 | 
						|
The query cache is allowed to operate on certain query only if this function
 | 
						|
returns TRUE for all tables in the query.
 | 
						|
 | 
						|
If thd is not in the autocommit state, this function also starts a new
 | 
						|
transaction for thd if there is no active trx yet, and assigns a consistent
 | 
						|
read view to it if there is no read view yet.
 | 
						|
 | 
						|
Why a deadlock of threads is not possible: the query cache calls this function
 | 
						|
at the start of a SELECT processing. Then the calling thread cannot be
 | 
						|
holding any InnoDB semaphores. The calling thread is holding the
 | 
						|
query cache mutex, and this function will reserver the InnoDB kernel mutex.
 | 
						|
Thus, the 'rank' in sync0sync.h of the MySQL query cache mutex is above
 | 
						|
the InnoDB kernel mutex. */
 | 
						|
 | 
						|
my_bool
 | 
						|
innobase_query_caching_of_table_permitted(
 | 
						|
/*======================================*/
 | 
						|
				/* out: TRUE if permitted, FALSE if not;
 | 
						|
				note that the value FALSE does not mean
 | 
						|
				we should invalidate the query cache:
 | 
						|
				invalidation is called explicitly */
 | 
						|
	THD*	thd,		/* in: thd of the user who is trying to
 | 
						|
				store a result to the query cache or
 | 
						|
				retrieve it */
 | 
						|
	char*	full_name,	/* in: concatenation of database name,
 | 
						|
				the null character '\0', and the table
 | 
						|
				name */
 | 
						|
	uint	full_name_len,	/* in: length of the full name, i.e.
 | 
						|
				len(dbname) + len(tablename) + 1 */
 | 
						|
        ulonglong *unused)      /* unused for this engine */
 | 
						|
{
 | 
						|
	ibool	is_autocommit;
 | 
						|
	trx_t*	trx;
 | 
						|
	char	norm_name[1000];
 | 
						|
 | 
						|
	ut_a(full_name_len < 999);
 | 
						|
 | 
						|
	if (thd->variables.tx_isolation == ISO_SERIALIZABLE) {
 | 
						|
		/* In the SERIALIZABLE mode we add LOCK IN SHARE MODE to every
 | 
						|
		plain SELECT if AUTOCOMMIT is not on. */
 | 
						|
 | 
						|
		return((my_bool)FALSE);
 | 
						|
	}
 | 
						|
 | 
						|
        trx = check_trx_exists(thd);
 | 
						|
	if (trx->has_search_latch) {
 | 
						|
		ut_print_timestamp(stderr);
 | 
						|
		sql_print_error("The calling thread is holding the adaptive "
 | 
						|
				"search, latch though calling "
 | 
						|
				"innobase_query_caching_of_table_permitted.");
 | 
						|
 | 
						|
		mutex_enter_noninline(&kernel_mutex);
 | 
						|
		trx_print(stderr, trx, 1024);
 | 
						|
		mutex_exit_noninline(&kernel_mutex);
 | 
						|
	}
 | 
						|
 | 
						|
	innobase_release_stat_resources(trx);
 | 
						|
 | 
						|
	if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 | 
						|
 | 
						|
		is_autocommit = TRUE;
 | 
						|
	} else {
 | 
						|
		is_autocommit = FALSE;
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	if (is_autocommit && trx->n_mysql_tables_in_use == 0) {
 | 
						|
		/* We are going to retrieve the query result from the query
 | 
						|
		cache. This cannot be a store operation to the query cache
 | 
						|
		because then MySQL would have locks on tables already.
 | 
						|
 | 
						|
		TODO: if the user has used LOCK TABLES to lock the table,
 | 
						|
		then we open a transaction in the call of row_.. below.
 | 
						|
		That trx can stay open until UNLOCK TABLES. The same problem
 | 
						|
		exists even if we do not use the query cache. MySQL should be
 | 
						|
		modified so that it ALWAYS calls some cleanup function when
 | 
						|
		the processing of a query ends!
 | 
						|
 | 
						|
		We can imagine we instantaneously serialize this consistent
 | 
						|
		read trx to the current trx id counter. If trx2 would have
 | 
						|
		changed the tables of a query result stored in the cache, and
 | 
						|
		trx2 would have already committed, making the result obsolete,
 | 
						|
		then trx2 would have already invalidated the cache. Thus we
 | 
						|
		can trust the result in the cache is ok for this query. */
 | 
						|
 | 
						|
		return((my_bool)TRUE);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Normalize the table name to InnoDB format */
 | 
						|
 | 
						|
	memcpy(norm_name, full_name, full_name_len);
 | 
						|
 | 
						|
	norm_name[strlen(norm_name)] = '/'; /* InnoDB uses '/' as the
 | 
						|
					    separator between db and table */
 | 
						|
	norm_name[full_name_len] = '\0';
 | 
						|
#ifdef __WIN__
 | 
						|
	innobase_casedn_str(norm_name);
 | 
						|
#endif
 | 
						|
	/* The call of row_search_.. will start a new transaction if it is
 | 
						|
	not yet started */
 | 
						|
 | 
						|
        if (trx->active_trans == 0) {
 | 
						|
 | 
						|
                innobase_register_trx_and_stmt(thd);
 | 
						|
                trx->active_trans = 1;
 | 
						|
        }
 | 
						|
 | 
						|
	if (row_search_check_if_query_cache_permitted(trx, norm_name)) {
 | 
						|
 | 
						|
		/* printf("Query cache for %s permitted\n", norm_name); */
 | 
						|
 | 
						|
		return((my_bool)TRUE);
 | 
						|
	}
 | 
						|
 | 
						|
	/* printf("Query cache for %s NOT permitted\n", norm_name); */
 | 
						|
 | 
						|
	return((my_bool)FALSE);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Invalidates the MySQL query cache for the table.
 | 
						|
NOTE that the exact prototype of this function has to be in
 | 
						|
/innobase/row/row0ins.c! */
 | 
						|
extern "C"
 | 
						|
void
 | 
						|
innobase_invalidate_query_cache(
 | 
						|
/*============================*/
 | 
						|
	trx_t*	trx,		/* in: transaction which modifies the table */
 | 
						|
	char*	full_name,	/* in: concatenation of database name, null
 | 
						|
				char '\0', table name, null char'\0';
 | 
						|
				NOTE that in Windows this is always
 | 
						|
				in LOWER CASE! */
 | 
						|
	ulint	full_name_len)	/* in: full name length where also the null
 | 
						|
				chars count */
 | 
						|
{
 | 
						|
	/* Note that the sync0sync.h rank of the query cache mutex is just
 | 
						|
	above the InnoDB kernel mutex. The caller of this function must not
 | 
						|
	have latches of a lower rank. */
 | 
						|
 | 
						|
	/* Argument TRUE below means we are using transactions */
 | 
						|
#ifdef HAVE_QUERY_CACHE
 | 
						|
	query_cache.invalidate((THD*)(trx->mysql_thd),
 | 
						|
					(const char*)full_name,
 | 
						|
					(uint32)full_name_len,
 | 
						|
					TRUE);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Get the quote character to be used in SQL identifiers.
 | 
						|
This definition must match the one in innobase/ut/ut0ut.c! */
 | 
						|
extern "C"
 | 
						|
int
 | 
						|
mysql_get_identifier_quote_char(
 | 
						|
/*============================*/
 | 
						|
				/* out: quote character to be
 | 
						|
				used in SQL identifiers; EOF if none */
 | 
						|
	trx_t*		trx,	/* in: transaction */
 | 
						|
	const char*	name,	/* in: name to print */
 | 
						|
	ulint		namelen)/* in: length of name */
 | 
						|
{
 | 
						|
	if (!trx || !trx->mysql_thd) {
 | 
						|
		return(EOF);
 | 
						|
	}
 | 
						|
	return(get_quote_char_for_identifier((THD*) trx->mysql_thd,
 | 
						|
						name, (int) namelen));
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Determines if the currently running transaction has been interrupted. */
 | 
						|
extern "C"
 | 
						|
ibool
 | 
						|
trx_is_interrupted(
 | 
						|
/*===============*/
 | 
						|
			/* out: TRUE if interrupted */
 | 
						|
	trx_t*	trx)	/* in: transaction */
 | 
						|
{
 | 
						|
	return(trx && trx->mysql_thd && ((THD*) trx->mysql_thd)->killed);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Obtain a pointer to the MySQL THD object, as in current_thd().  This
 | 
						|
definition must match the one in sql/ha_innodb.cc! */
 | 
						|
extern "C"
 | 
						|
void*
 | 
						|
innobase_current_thd(void)
 | 
						|
/*======================*/
 | 
						|
			/* out: MySQL THD object */
 | 
						|
{
 | 
						|
	return(current_thd);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Call this when you have opened a new table handle in HANDLER, before you
 | 
						|
call index_read_idx() etc. Actually, we can let the cursor stay open even
 | 
						|
over a transaction commit! Then you should call this before every operation,
 | 
						|
fetch next etc. This function inits the necessary things even after a
 | 
						|
transaction commit. */
 | 
						|
 | 
						|
void
 | 
						|
ha_innobase::init_table_handle_for_HANDLER(void)
 | 
						|
/*============================================*/
 | 
						|
{
 | 
						|
        row_prebuilt_t* prebuilt;
 | 
						|
 | 
						|
        /* If current thd does not yet have a trx struct, create one.
 | 
						|
        If the current handle does not yet have a prebuilt struct, create
 | 
						|
        one. Update the trx pointers in the prebuilt struct. Normally
 | 
						|
        this operation is done in external_lock. */
 | 
						|
 | 
						|
        update_thd(current_thd);
 | 
						|
 | 
						|
        /* Initialize the prebuilt struct much like it would be inited in
 | 
						|
        external_lock */
 | 
						|
 | 
						|
        prebuilt = (row_prebuilt_t*)innobase_prebuilt;
 | 
						|
 | 
						|
	innobase_release_stat_resources(prebuilt->trx);
 | 
						|
 | 
						|
        /* If the transaction is not started yet, start it */
 | 
						|
 | 
						|
        trx_start_if_not_started_noninline(prebuilt->trx);
 | 
						|
 | 
						|
        /* Assign a read view if the transaction does not have it yet */
 | 
						|
 | 
						|
        trx_assign_read_view(prebuilt->trx);
 | 
						|
 | 
						|
	/* Set the MySQL flag to mark that there is an active transaction */
 | 
						|
 | 
						|
        if (prebuilt->trx->active_trans == 0) {
 | 
						|
 | 
						|
                innobase_register_trx_and_stmt(current_thd);
 | 
						|
 | 
						|
                prebuilt->trx->active_trans = 1;
 | 
						|
        }
 | 
						|
 | 
						|
        /* We did the necessary inits in this function, no need to repeat them
 | 
						|
        in row_search_for_mysql */
 | 
						|
 | 
						|
        prebuilt->sql_stat_start = FALSE;
 | 
						|
 | 
						|
        /* We let HANDLER always to do the reads as consistent reads, even
 | 
						|
        if the trx isolation level would have been specified as SERIALIZABLE */
 | 
						|
 | 
						|
        prebuilt->select_lock_type = LOCK_NONE;
 | 
						|
        prebuilt->stored_select_lock_type = LOCK_NONE;
 | 
						|
 | 
						|
        /* Always fetch all columns in the index record */
 | 
						|
 | 
						|
        prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
 | 
						|
 | 
						|
        /* We want always to fetch all columns in the whole row? Or do
 | 
						|
	we???? */
 | 
						|
 | 
						|
        prebuilt->read_just_key = FALSE;
 | 
						|
 | 
						|
	prebuilt->used_in_HANDLER = TRUE;
 | 
						|
 | 
						|
	prebuilt->keep_other_fields_on_keyread = FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Opens an InnoDB database. */
 | 
						|
 | 
						|
bool
 | 
						|
innobase_init(void)
 | 
						|
/*===============*/
 | 
						|
			/* out: &innobase_hton, or NULL on error */
 | 
						|
{
 | 
						|
	static char	current_dir[3];		/* Set if using current lib */
 | 
						|
	int		err;
 | 
						|
	bool		ret;
 | 
						|
	char 	        *default_path;
 | 
						|
 | 
						|
  	DBUG_ENTER("innobase_init");
 | 
						|
 | 
						|
         if (have_innodb != SHOW_OPTION_YES)
 | 
						|
           goto error;
 | 
						|
 | 
						|
	ut_a(DATA_MYSQL_TRUE_VARCHAR == (ulint)MYSQL_TYPE_VARCHAR);
 | 
						|
 | 
						|
	/* Check that values don't overflow on 32-bit systems. */
 | 
						|
	if (sizeof(ulint) == 4) {
 | 
						|
		if (innobase_buffer_pool_size > UINT_MAX32) {
 | 
						|
			sql_print_error(
 | 
						|
				"innobase_buffer_pool_size can't be over 4GB"
 | 
						|
				" on 32-bit systems");
 | 
						|
 | 
						|
			goto error;
 | 
						|
		}
 | 
						|
 | 
						|
		if (innobase_log_file_size > UINT_MAX32) {
 | 
						|
			sql_print_error(
 | 
						|
				"innobase_log_file_size can't be over 4GB"
 | 
						|
				" on 32-bit systems");
 | 
						|
 | 
						|
			goto error;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
  	os_innodb_umask = (ulint)my_umask;
 | 
						|
 | 
						|
	/* First calculate the default path for innodb_data_home_dir etc.,
 | 
						|
	in case the user has not given any value.
 | 
						|
 | 
						|
	Note that when using the embedded server, the datadirectory is not
 | 
						|
	necessarily the current directory of this program. */
 | 
						|
 | 
						|
	if (mysqld_embedded) {
 | 
						|
		default_path = mysql_real_data_home;
 | 
						|
		fil_path_to_mysql_datadir = mysql_real_data_home;
 | 
						|
	} else {
 | 
						|
	  	/* It's better to use current lib, to keep paths short */
 | 
						|
	  	current_dir[0] = FN_CURLIB;
 | 
						|
	  	current_dir[1] = FN_LIBCHAR;
 | 
						|
	  	current_dir[2] = 0;
 | 
						|
	  	default_path = current_dir;
 | 
						|
	}
 | 
						|
 | 
						|
	ut_a(default_path);
 | 
						|
 | 
						|
	if (specialflag & SPECIAL_NO_PRIOR) {
 | 
						|
	        srv_set_thread_priorities = FALSE;
 | 
						|
	} else {
 | 
						|
	        srv_set_thread_priorities = TRUE;
 | 
						|
	        srv_query_thread_priority = QUERY_PRIOR;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Set InnoDB initialization parameters according to the values
 | 
						|
	read from MySQL .cnf file */
 | 
						|
 | 
						|
	/*--------------- Data files -------------------------*/
 | 
						|
 | 
						|
	/* The default dir for data files is the datadir of MySQL */
 | 
						|
 | 
						|
	srv_data_home = (innobase_data_home_dir ? innobase_data_home_dir :
 | 
						|
			 default_path);
 | 
						|
 | 
						|
	/* Set default InnoDB data file size to 10 MB and let it be
 | 
						|
  	auto-extending. Thus users can use InnoDB in >= 4.0 without having
 | 
						|
	to specify any startup options. */
 | 
						|
 | 
						|
	if (!innobase_data_file_path) {
 | 
						|
  		innobase_data_file_path = (char*) "ibdata1:10M:autoextend";
 | 
						|
	}
 | 
						|
 | 
						|
	/* Since InnoDB edits the argument in the next call, we make another
 | 
						|
	copy of it: */
 | 
						|
 | 
						|
	internal_innobase_data_file_path = my_strdup(innobase_data_file_path,
 | 
						|
						   MYF(MY_FAE));
 | 
						|
 | 
						|
	ret = (bool) srv_parse_data_file_paths_and_sizes(
 | 
						|
				internal_innobase_data_file_path,
 | 
						|
				&srv_data_file_names,
 | 
						|
				&srv_data_file_sizes,
 | 
						|
				&srv_data_file_is_raw_partition,
 | 
						|
				&srv_n_data_files,
 | 
						|
				&srv_auto_extend_last_data_file,
 | 
						|
				&srv_last_file_size_max);
 | 
						|
	if (ret == FALSE) {
 | 
						|
	  	sql_print_error(
 | 
						|
			"InnoDB: syntax error in innodb_data_file_path");
 | 
						|
	  	my_free(internal_innobase_data_file_path,
 | 
						|
						MYF(MY_ALLOW_ZERO_PTR));
 | 
						|
                goto error;
 | 
						|
	}
 | 
						|
 | 
						|
	/* -------------- Log files ---------------------------*/
 | 
						|
 | 
						|
	/* The default dir for log files is the datadir of MySQL */
 | 
						|
 | 
						|
	if (!innobase_log_group_home_dir) {
 | 
						|
	  	innobase_log_group_home_dir = default_path;
 | 
						|
	}
 | 
						|
 | 
						|
#ifdef UNIV_LOG_ARCHIVE
 | 
						|
	/* Since innodb_log_arch_dir has no relevance under MySQL,
 | 
						|
	starting from 4.0.6 we always set it the same as
 | 
						|
	innodb_log_group_home_dir: */
 | 
						|
 | 
						|
	innobase_log_arch_dir = innobase_log_group_home_dir;
 | 
						|
 | 
						|
	srv_arch_dir = innobase_log_arch_dir;
 | 
						|
#endif /* UNIG_LOG_ARCHIVE */
 | 
						|
 | 
						|
	ret = (bool)
 | 
						|
		srv_parse_log_group_home_dirs(innobase_log_group_home_dir,
 | 
						|
						&srv_log_group_home_dirs);
 | 
						|
 | 
						|
	if (ret == FALSE || innobase_mirrored_log_groups != 1) {
 | 
						|
	  sql_print_error("syntax error in innodb_log_group_home_dir, or a "
 | 
						|
			  "wrong number of mirrored log groups");
 | 
						|
 | 
						|
	  	my_free(internal_innobase_data_file_path,
 | 
						|
						MYF(MY_ALLOW_ZERO_PTR));
 | 
						|
                goto error;
 | 
						|
	}
 | 
						|
 | 
						|
	/* --------------------------------------------------*/
 | 
						|
 | 
						|
	srv_file_flush_method_str = innobase_unix_file_flush_method;
 | 
						|
 | 
						|
	srv_n_log_groups = (ulint) innobase_mirrored_log_groups;
 | 
						|
	srv_n_log_files = (ulint) innobase_log_files_in_group;
 | 
						|
	srv_log_file_size = (ulint) innobase_log_file_size;
 | 
						|
 | 
						|
#ifdef UNIV_LOG_ARCHIVE
 | 
						|
	srv_log_archive_on = (ulint) innobase_log_archive;
 | 
						|
#endif /* UNIV_LOG_ARCHIVE */
 | 
						|
	srv_log_buffer_size = (ulint) innobase_log_buffer_size;
 | 
						|
 | 
						|
        /* We set srv_pool_size here in units of 1 kB. InnoDB internally
 | 
						|
        changes the value so that it becomes the number of database pages. */
 | 
						|
 | 
						|
        if (innobase_buffer_pool_awe_mem_mb == 0) {
 | 
						|
                /* Careful here: we first convert the signed long int to ulint
 | 
						|
                and only after that divide */
 | 
						|
 | 
						|
                srv_pool_size = ((ulint) innobase_buffer_pool_size) / 1024;
 | 
						|
        } else {
 | 
						|
                srv_use_awe = TRUE;
 | 
						|
                srv_pool_size = (ulint)
 | 
						|
                                (1024 * innobase_buffer_pool_awe_mem_mb);
 | 
						|
                srv_awe_window_size = (ulint) innobase_buffer_pool_size;
 | 
						|
 | 
						|
                /* Note that what the user specified as
 | 
						|
                innodb_buffer_pool_size is actually the AWE memory window
 | 
						|
                size in this case, and the real buffer pool size is
 | 
						|
                determined by .._awe_mem_mb. */
 | 
						|
        }
 | 
						|
 | 
						|
	srv_mem_pool_size = (ulint) innobase_additional_mem_pool_size;
 | 
						|
 | 
						|
	srv_n_file_io_threads = (ulint) innobase_file_io_threads;
 | 
						|
 | 
						|
	srv_lock_wait_timeout = (ulint) innobase_lock_wait_timeout;
 | 
						|
	srv_force_recovery = (ulint) innobase_force_recovery;
 | 
						|
 | 
						|
	srv_use_doublewrite_buf = (ibool) innobase_use_doublewrite;
 | 
						|
	srv_use_checksums = (ibool) innobase_use_checksums;
 | 
						|
 | 
						|
	os_use_large_pages = (ibool) innobase_use_large_pages;
 | 
						|
	os_large_page_size = (ulint) innobase_large_page_size;
 | 
						|
 | 
						|
	row_rollback_on_timeout = (ibool) innobase_rollback_on_timeout;
 | 
						|
 | 
						|
	srv_file_per_table = (ibool) innobase_file_per_table;
 | 
						|
        srv_locks_unsafe_for_binlog = (ibool) innobase_locks_unsafe_for_binlog;
 | 
						|
 | 
						|
	srv_max_n_open_files = (ulint) innobase_open_files;
 | 
						|
	srv_innodb_status = (ibool) innobase_create_status_file;
 | 
						|
 | 
						|
	srv_print_verbose_log = mysqld_embedded ? 0 : 1;
 | 
						|
 | 
						|
	/* Store the default charset-collation number of this MySQL
 | 
						|
	installation */
 | 
						|
 | 
						|
	data_mysql_default_charset_coll = (ulint)default_charset_info->number;
 | 
						|
 | 
						|
	ut_a(DATA_MYSQL_LATIN1_SWEDISH_CHARSET_COLL ==
 | 
						|
					my_charset_latin1.number);
 | 
						|
	ut_a(DATA_MYSQL_BINARY_CHARSET_COLL == my_charset_bin.number);
 | 
						|
 | 
						|
	/* Store the latin1_swedish_ci character ordering table to InnoDB. For
 | 
						|
	non-latin1_swedish_ci charsets we use the MySQL comparison functions,
 | 
						|
	and consequently we do not need to know the ordering internally in
 | 
						|
	InnoDB. */
 | 
						|
 | 
						|
	ut_a(0 == strcmp((char*)my_charset_latin1.name,
 | 
						|
						(char*)"latin1_swedish_ci"));
 | 
						|
	memcpy(srv_latin1_ordering, my_charset_latin1.sort_order, 256);
 | 
						|
 | 
						|
	/* Since we in this module access directly the fields of a trx
 | 
						|
        struct, and due to different headers and flags it might happen that
 | 
						|
	mutex_t has a different size in this module and in InnoDB
 | 
						|
	modules, we check at run time that the size is the same in
 | 
						|
	these compilation modules. */
 | 
						|
 | 
						|
	srv_sizeof_trx_t_in_ha_innodb_cc = sizeof(trx_t);
 | 
						|
 | 
						|
	err = innobase_start_or_create_for_mysql();
 | 
						|
 | 
						|
	if (err != DB_SUCCESS) {
 | 
						|
	  	my_free(internal_innobase_data_file_path,
 | 
						|
						MYF(MY_ALLOW_ZERO_PTR));
 | 
						|
                goto error;
 | 
						|
	}
 | 
						|
 | 
						|
	(void) hash_init(&innobase_open_tables,system_charset_info, 32, 0, 0,
 | 
						|
			 		(hash_get_key) innobase_get_key, 0, 0);
 | 
						|
        pthread_mutex_init(&innobase_share_mutex, MY_MUTEX_INIT_FAST);
 | 
						|
        pthread_mutex_init(&prepare_commit_mutex, MY_MUTEX_INIT_FAST);
 | 
						|
        pthread_mutex_init(&commit_threads_m, MY_MUTEX_INIT_FAST);
 | 
						|
        pthread_mutex_init(&commit_cond_m, MY_MUTEX_INIT_FAST);
 | 
						|
        pthread_cond_init(&commit_cond, NULL);
 | 
						|
	innodb_inited= 1;
 | 
						|
 | 
						|
	/* If this is a replication slave and we needed to do a crash recovery,
 | 
						|
	set the master binlog position to what InnoDB internally knew about
 | 
						|
	how far we got transactions durable inside InnoDB. There is a
 | 
						|
	problem here: if the user used also MyISAM tables, InnoDB might not
 | 
						|
	know the right position for them.
 | 
						|
 | 
						|
	THIS DOES NOT WORK CURRENTLY because replication seems to initialize
 | 
						|
	glob_mi also after innobase_init. */
 | 
						|
 | 
						|
/*	if (trx_sys_mysql_master_log_pos != -1) {
 | 
						|
		ut_memcpy(glob_mi.log_file_name, trx_sys_mysql_master_log_name,
 | 
						|
				1 + ut_strlen(trx_sys_mysql_master_log_name));
 | 
						|
		glob_mi.pos = trx_sys_mysql_master_log_pos;
 | 
						|
	}
 | 
						|
*/
 | 
						|
	DBUG_RETURN(FALSE);
 | 
						|
error:
 | 
						|
        have_innodb= SHOW_OPTION_DISABLED;	// If we couldn't use handler
 | 
						|
        DBUG_RETURN(TRUE);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Closes an InnoDB database. */
 | 
						|
 | 
						|
bool
 | 
						|
innobase_end(void)
 | 
						|
/*==============*/
 | 
						|
				/* out: TRUE if error */
 | 
						|
{
 | 
						|
	int	err= 0;
 | 
						|
 | 
						|
	DBUG_ENTER("innobase_end");
 | 
						|
 | 
						|
#ifdef __NETWARE__ 	/* some special cleanup for NetWare */
 | 
						|
	if (nw_panic) {
 | 
						|
		set_panic_flag_for_netware();
 | 
						|
	}
 | 
						|
#endif
 | 
						|
	if (innodb_inited) {
 | 
						|
 | 
						|
	        srv_fast_shutdown = (ulint) innobase_fast_shutdown;
 | 
						|
	  	innodb_inited = 0;
 | 
						|
	  	if (innobase_shutdown_for_mysql() != DB_SUCCESS) {
 | 
						|
	    		err = 1;
 | 
						|
		}
 | 
						|
	  	hash_free(&innobase_open_tables);
 | 
						|
	  	my_free(internal_innobase_data_file_path,
 | 
						|
						MYF(MY_ALLOW_ZERO_PTR));
 | 
						|
                pthread_mutex_destroy(&innobase_share_mutex);
 | 
						|
                pthread_mutex_destroy(&prepare_commit_mutex);
 | 
						|
                pthread_mutex_destroy(&commit_threads_m);
 | 
						|
                pthread_mutex_destroy(&commit_cond_m);
 | 
						|
                pthread_cond_destroy(&commit_cond);
 | 
						|
	}
 | 
						|
 | 
						|
  	DBUG_RETURN(err);
 | 
						|
}
 | 
						|
 | 
						|
/********************************************************************
 | 
						|
Flushes InnoDB logs to disk and makes a checkpoint. Really, a commit flushes
 | 
						|
the logs, and the name of this function should be innobase_checkpoint. */
 | 
						|
 | 
						|
bool
 | 
						|
innobase_flush_logs(void)
 | 
						|
/*=====================*/
 | 
						|
				/* out: TRUE if error */
 | 
						|
{
 | 
						|
  	bool 	result = 0;
 | 
						|
 | 
						|
  	DBUG_ENTER("innobase_flush_logs");
 | 
						|
 | 
						|
	log_buffer_flush_to_disk();
 | 
						|
 | 
						|
  	DBUG_RETURN(result);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Commits a transaction in an InnoDB database. */
 | 
						|
 | 
						|
void
 | 
						|
innobase_commit_low(
 | 
						|
/*================*/
 | 
						|
	trx_t*	trx)	/* in: transaction handle */
 | 
						|
{
 | 
						|
        if (trx->conc_state == TRX_NOT_STARTED) {
 | 
						|
 | 
						|
                return;
 | 
						|
        }
 | 
						|
 | 
						|
#ifdef HAVE_REPLICATION
 | 
						|
        THD *thd=current_thd;
 | 
						|
 | 
						|
        if (thd && thd->slave_thread) {
 | 
						|
                /* Update the replication position info inside InnoDB */
 | 
						|
 | 
						|
                trx->mysql_master_log_file_name
 | 
						|
                                        = active_mi->rli.group_master_log_name;
 | 
						|
                trx->mysql_master_log_pos = ((ib_longlong)
 | 
						|
                                active_mi->rli.future_group_master_log_pos);
 | 
						|
        }
 | 
						|
#endif /* HAVE_REPLICATION */
 | 
						|
 | 
						|
	trx_commit_for_mysql(trx);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Creates an InnoDB transaction struct for the thd if it does not yet have one.
 | 
						|
Starts a new InnoDB transaction if a transaction is not yet started. And
 | 
						|
assigns a new snapshot for a consistent read if the transaction does not yet
 | 
						|
have one. */
 | 
						|
 | 
						|
int
 | 
						|
innobase_start_trx_and_assign_read_view(
 | 
						|
/*====================================*/
 | 
						|
			/* out: 0 */
 | 
						|
	THD*	thd)	/* in: MySQL thread handle of the user for whom
 | 
						|
			the transaction should be committed */
 | 
						|
{
 | 
						|
	trx_t*	trx;
 | 
						|
 | 
						|
  	DBUG_ENTER("innobase_start_trx_and_assign_read_view");
 | 
						|
 | 
						|
	/* Create a new trx struct for thd, if it does not yet have one */
 | 
						|
 | 
						|
	trx = check_trx_exists(thd);
 | 
						|
 | 
						|
	/* This is just to play safe: 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 the transaction is not started yet, start it */
 | 
						|
 | 
						|
	trx_start_if_not_started_noninline(trx);
 | 
						|
 | 
						|
	/* Assign a read view if the transaction does not have it yet */
 | 
						|
 | 
						|
	trx_assign_read_view(trx);
 | 
						|
 | 
						|
	/* Set the MySQL flag to mark that there is an active transaction */
 | 
						|
 | 
						|
        if (trx->active_trans == 0) {
 | 
						|
 | 
						|
                innobase_register_trx_and_stmt(current_thd);
 | 
						|
 | 
						|
                trx->active_trans = 1;
 | 
						|
        }
 | 
						|
 | 
						|
	DBUG_RETURN(0);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Commits a transaction in an InnoDB database or marks an SQL statement
 | 
						|
ended. */
 | 
						|
static
 | 
						|
int
 | 
						|
innobase_commit(
 | 
						|
/*============*/
 | 
						|
			/* out: 0 */
 | 
						|
	THD*	thd,	/* in: MySQL thread handle of the user for whom
 | 
						|
			the transaction should be committed */
 | 
						|
        bool    all)    /* in: TRUE - commit transaction
 | 
						|
                               FALSE - the current SQL statement ended */
 | 
						|
{
 | 
						|
	trx_t*		trx;
 | 
						|
 | 
						|
  	DBUG_ENTER("innobase_commit");
 | 
						|
  	DBUG_PRINT("trans", ("ending transaction"));
 | 
						|
 | 
						|
	trx = check_trx_exists(thd);
 | 
						|
 | 
						|
	/* Update the info whether we should skip XA steps that eat CPU time */
 | 
						|
	trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
 | 
						|
 | 
						|
	/* 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. */
 | 
						|
 | 
						|
        if (trx->has_search_latch) {
 | 
						|
                          trx_search_latch_release_if_reserved(trx);
 | 
						|
        }
 | 
						|
 | 
						|
        /* The flag trx->active_trans is set to 1 in
 | 
						|
 | 
						|
	1. ::external_lock(),
 | 
						|
	2. ::start_stmt(),
 | 
						|
	3. innobase_query_caching_of_table_permitted(),
 | 
						|
	4. innobase_savepoint(),
 | 
						|
	5. ::init_table_handle_for_HANDLER(),
 | 
						|
	6. innobase_start_trx_and_assign_read_view(),
 | 
						|
	7. ::transactional_table_lock()
 | 
						|
 | 
						|
	and it is only set to 0 in a commit or a rollback. If it is 0 we know
 | 
						|
	there cannot be resources to be freed and we could return immediately.
 | 
						|
	For the time being, we play safe and do the cleanup though there should
 | 
						|
	be nothing to clean up. */
 | 
						|
 | 
						|
        if (trx->active_trans == 0
 | 
						|
	    && trx->conc_state != TRX_NOT_STARTED) {
 | 
						|
 | 
						|
	  sql_print_error("trx->active_trans == 0, but trx->conc_state != "
 | 
						|
			  "TRX_NOT_STARTED");
 | 
						|
	}
 | 
						|
        if (all
 | 
						|
	    || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
 | 
						|
 | 
						|
 		/* We were instructed to commit the whole transaction, or
 | 
						|
		this is an SQL statement end and autocommit is on */
 | 
						|
 | 
						|
                /* We need current binlog position for ibbackup to work.
 | 
						|
                Note, the position is current because of prepare_commit_mutex */
 | 
						|
retry:
 | 
						|
                if (srv_commit_concurrency > 0)
 | 
						|
                {
 | 
						|
                  pthread_mutex_lock(&commit_cond_m);
 | 
						|
                  commit_threads++;
 | 
						|
                  if (commit_threads > srv_commit_concurrency)
 | 
						|
                  {
 | 
						|
                    commit_threads--;
 | 
						|
                    pthread_cond_wait(&commit_cond, &commit_cond_m);
 | 
						|
                    pthread_mutex_unlock(&commit_cond_m);
 | 
						|
                    goto retry;
 | 
						|
                  }
 | 
						|
                  else
 | 
						|
                    pthread_mutex_unlock(&commit_cond_m);
 | 
						|
                }
 | 
						|
 | 
						|
                trx->mysql_log_file_name = mysql_bin_log.get_log_fname();
 | 
						|
                trx->mysql_log_offset =
 | 
						|
                        (ib_longlong)mysql_bin_log.get_log_file()->pos_in_file;
 | 
						|
 | 
						|
		innobase_commit_low(trx);
 | 
						|
 | 
						|
                if (srv_commit_concurrency > 0)
 | 
						|
                {
 | 
						|
                  pthread_mutex_lock(&commit_cond_m);
 | 
						|
                  commit_threads--;
 | 
						|
                  pthread_cond_signal(&commit_cond);
 | 
						|
                  pthread_mutex_unlock(&commit_cond_m);
 | 
						|
                }
 | 
						|
 | 
						|
                if (trx->active_trans == 2) {
 | 
						|
 | 
						|
                        pthread_mutex_unlock(&prepare_commit_mutex);
 | 
						|
                }
 | 
						|
 | 
						|
                trx->active_trans = 0;
 | 
						|
 | 
						|
	} else {
 | 
						|
	        /* We just mark the SQL statement ended and do not do a
 | 
						|
		transaction commit */
 | 
						|
 | 
						|
		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: */
 | 
						|
        if (trx->declared_to_be_inside_innodb) {
 | 
						|
                          /* Release our possible ticket in the FIFO */
 | 
						|
 | 
						|
                          srv_conc_force_exit_innodb(trx);
 | 
						|
        }
 | 
						|
	srv_active_wake_master_thread();
 | 
						|
 | 
						|
	DBUG_RETURN(0);
 | 
						|
}
 | 
						|
 | 
						|
/* TODO: put the
 | 
						|
MySQL-4.1 functionality back to 5.0. This is needed to get InnoDB Hot Backup
 | 
						|
to work. */
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
This is called when MySQL writes the binlog entry for the current
 | 
						|
transaction. Writes to the InnoDB tablespace info which tells where the
 | 
						|
MySQL binlog entry for the current transaction ended. Also commits the
 | 
						|
transaction inside InnoDB but does NOT flush InnoDB log files to disk.
 | 
						|
To flush you have to call innobase_commit_complete(). We have separated
 | 
						|
flushing to eliminate the bottleneck of LOCK_log in log.cc which disabled
 | 
						|
InnoDB's group commit capability. */
 | 
						|
 | 
						|
int
 | 
						|
innobase_report_binlog_offset_and_commit(
 | 
						|
/*=====================================*/
 | 
						|
                                /* out: 0 */
 | 
						|
        THD*    thd,            /* in: user thread */
 | 
						|
        void*   trx_handle,     /* in: InnoDB trx handle */
 | 
						|
        char*   log_file_name,  /* in: latest binlog file name */
 | 
						|
        my_off_t end_offset)    /* in: the offset in the binlog file
 | 
						|
                                   up to which we wrote */
 | 
						|
{
 | 
						|
	trx_t*	trx;
 | 
						|
 | 
						|
	trx = (trx_t*)trx_handle;
 | 
						|
 | 
						|
	ut_a(trx != NULL);
 | 
						|
 | 
						|
	trx->mysql_log_file_name = log_file_name;
 | 
						|
	trx->mysql_log_offset = (ib_longlong)end_offset;
 | 
						|
 | 
						|
	trx->flush_log_later = TRUE;
 | 
						|
 | 
						|
	innobase_commit(thd, TRUE);
 | 
						|
 | 
						|
	trx->flush_log_later = FALSE;
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
#if 0
 | 
						|
/***********************************************************************
 | 
						|
This function stores the binlog offset and flushes logs. */
 | 
						|
 | 
						|
void
 | 
						|
innobase_store_binlog_offset_and_flush_log(
 | 
						|
/*=======================================*/
 | 
						|
    char *binlog_name,          /* in: binlog name */
 | 
						|
    longlong	offset)		/* in: binlog offset */
 | 
						|
{
 | 
						|
	mtr_t mtr;
 | 
						|
 | 
						|
	assert(binlog_name != NULL);
 | 
						|
 | 
						|
	/* Start a mini-transaction */
 | 
						|
        mtr_start_noninline(&mtr);
 | 
						|
 | 
						|
	/* Update the latest MySQL binlog name and offset info
 | 
						|
        in trx sys header */
 | 
						|
 | 
						|
        trx_sys_update_mysql_binlog_offset(
 | 
						|
            binlog_name,
 | 
						|
            offset,
 | 
						|
            TRX_SYS_MYSQL_LOG_INFO, &mtr);
 | 
						|
 | 
						|
        /* Commits the mini-transaction */
 | 
						|
        mtr_commit(&mtr);
 | 
						|
 | 
						|
	/* Synchronous flush of the log buffer to disk */
 | 
						|
	log_buffer_flush_to_disk();
 | 
						|
}
 | 
						|
#endif
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
This is called after MySQL has written the binlog entry for the current
 | 
						|
transaction. Flushes the InnoDB log files to disk if required. */
 | 
						|
 | 
						|
int
 | 
						|
innobase_commit_complete(
 | 
						|
/*=====================*/
 | 
						|
                                /* out: 0 */
 | 
						|
        THD*    thd)            /* in: user thread */
 | 
						|
{
 | 
						|
	trx_t*	trx;
 | 
						|
 | 
						|
        trx = (trx_t*) thd->ha_data[innobase_hton.slot];
 | 
						|
 | 
						|
        if (trx && trx->active_trans) {
 | 
						|
 | 
						|
                trx->active_trans = 0;
 | 
						|
 | 
						|
                if (UNIV_UNLIKELY(srv_flush_log_at_trx_commit == 0)) {
 | 
						|
 | 
						|
                        return(0);
 | 
						|
                }
 | 
						|
 | 
						|
                trx_commit_complete_for_mysql(trx);
 | 
						|
        }
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Rolls back a transaction or the latest SQL statement. */
 | 
						|
 | 
						|
static int
 | 
						|
innobase_rollback(
 | 
						|
/*==============*/
 | 
						|
			/* out: 0 or error number */
 | 
						|
	THD*	thd,	/* in: handle to the MySQL thread of the user
 | 
						|
			whose transaction should be rolled back */
 | 
						|
        bool    all)    /* in: TRUE - commit transaction
 | 
						|
                               FALSE - the current SQL statement ended */
 | 
						|
{
 | 
						|
	int	error = 0;
 | 
						|
	trx_t*	trx;
 | 
						|
 | 
						|
	DBUG_ENTER("innobase_rollback");
 | 
						|
	DBUG_PRINT("trans", ("aborting transaction"));
 | 
						|
 | 
						|
	trx = check_trx_exists(thd);
 | 
						|
 | 
						|
	/* Update the info whether we should skip XA steps that eat CPU time */
 | 
						|
	trx->support_xa = (ibool)(thd->variables.innodb_support_xa);
 | 
						|
 | 
						|
	/* 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);
 | 
						|
	}
 | 
						|
 | 
						|
        if (all
 | 
						|
	    || (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)))) {
 | 
						|
 | 
						|
		error = trx_rollback_for_mysql(trx);
 | 
						|
                trx->active_trans = 0;
 | 
						|
	} else {
 | 
						|
		error = trx_rollback_last_sql_stat_for_mysql(trx);
 | 
						|
	}
 | 
						|
 | 
						|
	DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
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. */
 | 
						|
 | 
						|
static int
 | 
						|
innobase_rollback_to_savepoint(
 | 
						|
/*===========================*/
 | 
						|
				/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
 | 
						|
				no savepoint with the given name */
 | 
						|
	THD*	thd,		/* in: handle to the MySQL thread of the user
 | 
						|
				whose transaction should be rolled back */
 | 
						|
        void *savepoint)        /* in: savepoint data */
 | 
						|
{
 | 
						|
	ib_longlong mysql_binlog_cache_pos;
 | 
						|
	int	    error = 0;
 | 
						|
	trx_t*	    trx;
 | 
						|
        char 	    name[64];
 | 
						|
 | 
						|
	DBUG_ENTER("innobase_rollback_to_savepoint");
 | 
						|
 | 
						|
	trx = check_trx_exists(thd);
 | 
						|
 | 
						|
	/* 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);
 | 
						|
 | 
						|
        /* TODO: use provided savepoint data area to store savepoint data */
 | 
						|
 | 
						|
        longlong2str((ulint)savepoint, name, 36);
 | 
						|
 | 
						|
        error = (int) trx_rollback_to_savepoint_for_mysql(trx, name,
 | 
						|
						&mysql_binlog_cache_pos);
 | 
						|
	DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Release transaction savepoint name. */
 | 
						|
static
 | 
						|
int
 | 
						|
innobase_release_savepoint(
 | 
						|
/*=======================*/
 | 
						|
				/* out: 0 if success, HA_ERR_NO_SAVEPOINT if
 | 
						|
				no savepoint with the given name */
 | 
						|
	THD*	thd,		/* in: handle to the MySQL thread of the user
 | 
						|
				whose transaction should be rolled back */
 | 
						|
        void*	savepoint)      /* in: savepoint data */
 | 
						|
{
 | 
						|
	int	    error = 0;
 | 
						|
	trx_t*	    trx;
 | 
						|
        char 	    name[64];
 | 
						|
 | 
						|
	DBUG_ENTER("innobase_release_savepoint");
 | 
						|
 | 
						|
	trx = check_trx_exists(thd);
 | 
						|
 | 
						|
        /* TODO: use provided savepoint data area to store savepoint data */
 | 
						|
 | 
						|
        longlong2str((ulint)savepoint, name, 36);
 | 
						|
 | 
						|
	error = (int) trx_release_savepoint_for_mysql(trx, name);
 | 
						|
 | 
						|
	DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Sets a transaction savepoint. */
 | 
						|
static
 | 
						|
int
 | 
						|
innobase_savepoint(
 | 
						|
/*===============*/
 | 
						|
				/* out: always 0, that is, always succeeds */
 | 
						|
	THD*	thd,		/* in: handle to the MySQL thread */
 | 
						|
        void*	savepoint)      /* in: savepoint data */
 | 
						|
{
 | 
						|
	int	error = 0;
 | 
						|
	trx_t*	trx;
 | 
						|
 | 
						|
	DBUG_ENTER("innobase_savepoint");
 | 
						|
 | 
						|
        /*
 | 
						|
          In the autocommit mode there is no sense to set a savepoint
 | 
						|
          (unless we are in sub-statement), so SQL layer ensures that
 | 
						|
          this method is never called in such situation.
 | 
						|
        */
 | 
						|
        DBUG_ASSERT(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN) ||
 | 
						|
                    thd->in_sub_stmt);
 | 
						|
 | 
						|
	trx = check_trx_exists(thd);
 | 
						|
 | 
						|
	/* 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);
 | 
						|
 | 
						|
        /* cannot happen outside of transaction */
 | 
						|
        DBUG_ASSERT(trx->active_trans);
 | 
						|
 | 
						|
        /* TODO: use provided savepoint data area to store savepoint data */
 | 
						|
        char name[64];
 | 
						|
        longlong2str((ulint)savepoint,name,36);
 | 
						|
 | 
						|
        error = (int) trx_savepoint_for_mysql(trx, name, (ib_longlong)0);
 | 
						|
 | 
						|
	DBUG_RETURN(convert_error_code_to_mysql(error, NULL));
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Frees a possible InnoDB trx object associated with the current THD. */
 | 
						|
static
 | 
						|
int
 | 
						|
innobase_close_connection(
 | 
						|
/*======================*/
 | 
						|
			/* out: 0 or error number */
 | 
						|
	THD*	thd)	/* in: handle to the MySQL thread of the user
 | 
						|
			whose resources should be free'd */
 | 
						|
{
 | 
						|
	trx_t*	trx;
 | 
						|
 | 
						|
	trx = (trx_t*)thd->ha_data[innobase_hton.slot];
 | 
						|
 | 
						|
	ut_a(trx);
 | 
						|
 | 
						|
        if (trx->active_trans == 0
 | 
						|
	    && trx->conc_state != TRX_NOT_STARTED) {
 | 
						|
 | 
						|
	  sql_print_error("trx->active_trans == 0, but trx->conc_state != "
 | 
						|
			  "TRX_NOT_STARTED");
 | 
						|
	}
 | 
						|
 | 
						|
 | 
						|
	if (trx->conc_state != TRX_NOT_STARTED &&
 | 
						|
            global_system_variables.log_warnings)
 | 
						|
          sql_print_warning("MySQL is closing a connection that has an active "
 | 
						|
                            "InnoDB transaction.  %lu row modifications will "
 | 
						|
                            "roll back.",
 | 
						|
                            (ulong)trx->undo_no.low);
 | 
						|
 | 
						|
	innobase_rollback_trx(trx);
 | 
						|
 | 
						|
        trx_free_for_mysql(trx);
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*****************************************************************************
 | 
						|
** InnoDB database tables
 | 
						|
*****************************************************************************/
 | 
						|
 | 
						|
/********************************************************************
 | 
						|
Get the record format from the data dictionary. */
 | 
						|
enum row_type
 | 
						|
ha_innobase::get_row_type() const
 | 
						|
/*=============================*/
 | 
						|
			/* out: ROW_TYPE_REDUNDANT or ROW_TYPE_COMPACT */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
 | 
						|
	if (prebuilt && prebuilt->table) {
 | 
						|
		if (prebuilt->table->comp) {
 | 
						|
			return(ROW_TYPE_COMPACT);
 | 
						|
		} else {
 | 
						|
			return(ROW_TYPE_REDUNDANT);
 | 
						|
		}
 | 
						|
	}
 | 
						|
	ut_ad(0);
 | 
						|
	return(ROW_TYPE_NOT_USED);
 | 
						|
}
 | 
						|
 | 
						|
/********************************************************************
 | 
						|
Gives the file extension of an InnoDB single-table tablespace. */
 | 
						|
static const char* ha_innobase_exts[] = {
 | 
						|
  ".ibd",
 | 
						|
  NullS
 | 
						|
};
 | 
						|
 | 
						|
const char**
 | 
						|
ha_innobase::bas_ext() const
 | 
						|
/*========================*/
 | 
						|
				/* out: file extension string */
 | 
						|
{
 | 
						|
  return ha_innobase_exts;
 | 
						|
}
 | 
						|
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Normalizes a table name string. A normalized name consists of the
 | 
						|
database name catenated to '/' and table name. An example:
 | 
						|
test/mytable. On Windows normalization puts both the database name and the
 | 
						|
table name always to lower case. */
 | 
						|
static
 | 
						|
void
 | 
						|
normalize_table_name(
 | 
						|
/*=================*/
 | 
						|
	char*		norm_name,	/* out: normalized name as a
 | 
						|
					null-terminated string */
 | 
						|
	const char*	name)		/* in: table name string */
 | 
						|
{
 | 
						|
	char*	name_ptr;
 | 
						|
	char*	db_ptr;
 | 
						|
	char*	ptr;
 | 
						|
 | 
						|
	/* Scan name from the end */
 | 
						|
 | 
						|
	ptr = strend(name)-1;
 | 
						|
 | 
						|
	while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 | 
						|
		ptr--;
 | 
						|
	}
 | 
						|
 | 
						|
	name_ptr = ptr + 1;
 | 
						|
 | 
						|
	DBUG_ASSERT(ptr > name);
 | 
						|
 | 
						|
	ptr--;
 | 
						|
 | 
						|
	while (ptr >= name && *ptr != '\\' && *ptr != '/') {
 | 
						|
		ptr--;
 | 
						|
	}
 | 
						|
 | 
						|
	db_ptr = ptr + 1;
 | 
						|
 | 
						|
	memcpy(norm_name, db_ptr, strlen(name) + 1 - (db_ptr - name));
 | 
						|
 | 
						|
	norm_name[name_ptr - db_ptr - 1] = '/';
 | 
						|
 | 
						|
#ifdef __WIN__
 | 
						|
	innobase_casedn_str(norm_name);
 | 
						|
#endif
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Creates and opens a handle to a table which already exists in an InnoDB
 | 
						|
database. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::open(
 | 
						|
/*==============*/
 | 
						|
					/* out: 1 if error, 0 if success */
 | 
						|
	const char*	name,		/* in: table name */
 | 
						|
	int 		mode,		/* in: not used */
 | 
						|
	uint 		test_if_locked)	/* in: not used */
 | 
						|
{
 | 
						|
	dict_table_t*	ib_table;
 | 
						|
  	char		norm_name[1000];
 | 
						|
	THD*		thd;
 | 
						|
 | 
						|
	DBUG_ENTER("ha_innobase::open");
 | 
						|
 | 
						|
	UT_NOT_USED(mode);
 | 
						|
	UT_NOT_USED(test_if_locked);
 | 
						|
 | 
						|
	thd = current_thd;
 | 
						|
	normalize_table_name(norm_name, name);
 | 
						|
 | 
						|
	user_thd = NULL;
 | 
						|
 | 
						|
	last_query_id = (ulong)-1;
 | 
						|
 | 
						|
	if (!(share=get_share(name))) {
 | 
						|
 | 
						|
		DBUG_RETURN(1);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Create buffers for packing the fields of a record. Why
 | 
						|
	table->reclength did not work here? Obviously, because char
 | 
						|
	fields when packed actually became 1 byte longer, when we also
 | 
						|
	stored the string length as the first byte. */
 | 
						|
 | 
						|
	upd_and_key_val_buff_len =
 | 
						|
				table->s->reclength + table->s->max_key_length
 | 
						|
							+ MAX_REF_PARTS * 3;
 | 
						|
	if (!(mysql_byte*) my_multi_malloc(MYF(MY_WME),
 | 
						|
				     &upd_buff, upd_and_key_val_buff_len,
 | 
						|
				     &key_val_buff, upd_and_key_val_buff_len,
 | 
						|
				     NullS)) {
 | 
						|
	  	free_share(share);
 | 
						|
 | 
						|
	  	DBUG_RETURN(1);
 | 
						|
  	}
 | 
						|
 | 
						|
	/* Get pointer to a table object in InnoDB dictionary cache */
 | 
						|
 | 
						|
	ib_table = dict_table_get_and_increment_handle_count(
 | 
						|
				      		     norm_name, NULL);
 | 
						|
 	if (NULL == ib_table) {
 | 
						|
	        ut_print_timestamp(stderr);
 | 
						|
		sql_print_error("Cannot find table %s from the internal data "
 | 
						|
				"dictionary\nof InnoDB though the .frm file "
 | 
						|
				"for the table exists. Maybe you\nhave "
 | 
						|
				"deleted and recreated InnoDB data files but "
 | 
						|
				"have forgotten\nto delete the corresponding "
 | 
						|
				".frm files of InnoDB tables, or you\n"
 | 
						|
				"have moved .frm files to another database?\n"
 | 
						|
				"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n"
 | 
						|
				"how you can resolve the problem.\n",
 | 
						|
				norm_name);
 | 
						|
	        free_share(share);
 | 
						|
    		my_free((gptr) upd_buff, MYF(0));
 | 
						|
    		my_errno = ENOENT;
 | 
						|
 | 
						|
    		DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
 | 
						|
  	}
 | 
						|
 | 
						|
 	if (ib_table->ibd_file_missing && !thd->tablespace_op) {
 | 
						|
	        ut_print_timestamp(stderr);
 | 
						|
		sql_print_error("MySQL is trying to open a table handle but "
 | 
						|
				"the .ibd file for\ntable %s does not exist.\n"
 | 
						|
				"Have you deleted the .ibd file from the "
 | 
						|
				"database directory under\nthe MySQL datadir, "
 | 
						|
				"or have you used DISCARD TABLESPACE?\n"
 | 
						|
				"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n"
 | 
						|
				"how you can resolve the problem.\n",
 | 
						|
				norm_name);
 | 
						|
	        free_share(share);
 | 
						|
    		my_free((gptr) upd_buff, MYF(0));
 | 
						|
    		my_errno = ENOENT;
 | 
						|
 | 
						|
		dict_table_decrement_handle_count(ib_table);
 | 
						|
    		DBUG_RETURN(HA_ERR_NO_SUCH_TABLE);
 | 
						|
  	}
 | 
						|
 | 
						|
	innobase_prebuilt = row_create_prebuilt(ib_table);
 | 
						|
 | 
						|
	((row_prebuilt_t*)innobase_prebuilt)->mysql_row_len =
 | 
						|
							table->s->reclength;
 | 
						|
 | 
						|
	/* Looks like MySQL-3.23 sometimes has primary key number != 0 */
 | 
						|
 | 
						|
 	primary_key = table->s->primary_key;
 | 
						|
	key_used_on_scan = primary_key;
 | 
						|
 | 
						|
	/* Allocate a buffer for a 'row reference'. A row reference is
 | 
						|
	a string of bytes of length ref_length which uniquely specifies
 | 
						|
        a row in our table. Note that MySQL may also compare two row
 | 
						|
        references for equality by doing a simple memcmp on the strings
 | 
						|
        of length ref_length! */
 | 
						|
 | 
						|
  	if (!row_table_got_default_clust_index(ib_table)) {
 | 
						|
	        if (primary_key >= MAX_KEY) {
 | 
						|
		  sql_print_error("Table %s has a primary key in InnoDB data "
 | 
						|
				  "dictionary, but not in MySQL!", name);
 | 
						|
		}
 | 
						|
 | 
						|
		((row_prebuilt_t*)innobase_prebuilt)
 | 
						|
				->clust_index_was_generated = FALSE;
 | 
						|
 		/* MySQL allocates the buffer for ref. key_info->key_length
 | 
						|
		includes space for all key columns + one byte for each column
 | 
						|
		that may be NULL. ref_length must be as exact as possible to
 | 
						|
		save space, because all row reference buffers are allocated
 | 
						|
		based on ref_length. */
 | 
						|
 | 
						|
  		ref_length = table->key_info[primary_key].key_length;
 | 
						|
	} else {
 | 
						|
	        if (primary_key != MAX_KEY) {
 | 
						|
		  sql_print_error("Table %s has no primary key in InnoDB data "
 | 
						|
				  "dictionary, but has one in MySQL! If you "
 | 
						|
				  "created the table with a MySQL version < "
 | 
						|
				  "3.23.54 and did not define a primary key, "
 | 
						|
				  "but defined a unique key with all non-NULL "
 | 
						|
				  "columns, then MySQL internally treats that "
 | 
						|
				  "key as the primary key. You can fix this "
 | 
						|
				  "error by dump + DROP + CREATE + reimport "
 | 
						|
				  "of the table.", name);
 | 
						|
		}
 | 
						|
 | 
						|
		((row_prebuilt_t*)innobase_prebuilt)
 | 
						|
				->clust_index_was_generated = TRUE;
 | 
						|
 | 
						|
  		ref_length = DATA_ROW_ID_LEN;
 | 
						|
 | 
						|
		/* If we automatically created the clustered index, then
 | 
						|
		MySQL does not know about it, and MySQL must NOT be aware
 | 
						|
		of the index used on scan, to make it avoid checking if we
 | 
						|
		update the column of the index. That is why we assert below
 | 
						|
		that key_used_on_scan is the undefined value MAX_KEY.
 | 
						|
		The column is the row id in the automatical generation case,
 | 
						|
		and it will never be updated anyway. */
 | 
						|
 | 
						|
		if (key_used_on_scan != MAX_KEY) {
 | 
						|
		  sql_print_warning("Table %s key_used_on_scan is %lu even "
 | 
						|
				    "though there is no primary key inside "
 | 
						|
				    "InnoDB.", name, (ulong) key_used_on_scan);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	block_size = 16 * 1024;	/* Index block size in InnoDB: used by MySQL
 | 
						|
				in query optimization */
 | 
						|
 | 
						|
	/* Init table lock structure */
 | 
						|
	thr_lock_data_init(&share->lock,&lock,(void*) 0);
 | 
						|
 | 
						|
  	info(HA_STATUS_NO_LOCK | HA_STATUS_VARIABLE | HA_STATUS_CONST);
 | 
						|
 | 
						|
  	DBUG_RETURN(0);
 | 
						|
}
 | 
						|
 | 
						|
uint
 | 
						|
ha_innobase::max_supported_key_part_length() const
 | 
						|
{
 | 
						|
	return(DICT_MAX_INDEX_COL_LEN - 1);
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Closes a handle to an InnoDB table. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::close(void)
 | 
						|
/*====================*/
 | 
						|
				/* out: 0 */
 | 
						|
{
 | 
						|
  	DBUG_ENTER("ha_innobase::close");
 | 
						|
 | 
						|
	row_prebuilt_free((row_prebuilt_t*) innobase_prebuilt);
 | 
						|
 | 
						|
    	my_free((gptr) upd_buff, MYF(0));
 | 
						|
        free_share(share);
 | 
						|
 | 
						|
	/* Tell InnoDB server that there might be work for
 | 
						|
	utility threads: */
 | 
						|
 | 
						|
	srv_active_wake_master_thread();
 | 
						|
 | 
						|
  	DBUG_RETURN(0);
 | 
						|
}
 | 
						|
 | 
						|
/* The following accessor functions should really be inside MySQL code! */
 | 
						|
 | 
						|
/******************************************************************
 | 
						|
Gets field offset for a field in a table. */
 | 
						|
inline
 | 
						|
uint
 | 
						|
get_field_offset(
 | 
						|
/*=============*/
 | 
						|
			/* out: offset */
 | 
						|
	TABLE*	table,	/* in: MySQL table object */
 | 
						|
	Field*	field)	/* in: MySQL field object */
 | 
						|
{
 | 
						|
	return((uint) (field->ptr - (char*) table->record[0]));
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************
 | 
						|
Checks if a field in a record is SQL NULL. Uses the record format
 | 
						|
information in table to track the null bit in record. */
 | 
						|
inline
 | 
						|
uint
 | 
						|
field_in_record_is_null(
 | 
						|
/*====================*/
 | 
						|
			/* out: 1 if NULL, 0 otherwise */
 | 
						|
	TABLE*	table,	/* in: MySQL table object */
 | 
						|
	Field*	field,	/* in: MySQL field object */
 | 
						|
	char*	record)	/* in: a row in MySQL format */
 | 
						|
{
 | 
						|
	int	null_offset;
 | 
						|
 | 
						|
	if (!field->null_ptr) {
 | 
						|
 | 
						|
		return(0);
 | 
						|
	}
 | 
						|
 | 
						|
	null_offset = (uint) ((char*) field->null_ptr
 | 
						|
					- (char*) table->record[0]);
 | 
						|
 | 
						|
	if (record[null_offset] & field->null_bit) {
 | 
						|
 | 
						|
		return(1);
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************
 | 
						|
Sets a field in a record to SQL NULL. Uses the record format
 | 
						|
information in table to track the null bit in record. */
 | 
						|
inline
 | 
						|
void
 | 
						|
set_field_in_record_to_null(
 | 
						|
/*========================*/
 | 
						|
	TABLE*	table,	/* in: MySQL table object */
 | 
						|
	Field*	field,	/* in: MySQL field object */
 | 
						|
	char*	record)	/* in: a row in MySQL format */
 | 
						|
{
 | 
						|
	int	null_offset;
 | 
						|
 | 
						|
	null_offset = (uint) ((char*) field->null_ptr
 | 
						|
					- (char*) table->record[0]);
 | 
						|
 | 
						|
	record[null_offset] = record[null_offset] | field->null_bit;
 | 
						|
}
 | 
						|
 | 
						|
extern "C" {
 | 
						|
/*****************************************************************
 | 
						|
InnoDB uses this function to compare two data fields for which the data type
 | 
						|
is such that we must use MySQL code to compare them. NOTE that the prototype
 | 
						|
of this function is in rem0cmp.c in InnoDB source code! If you change this
 | 
						|
function, remember to update the prototype there! */
 | 
						|
 | 
						|
int
 | 
						|
innobase_mysql_cmp(
 | 
						|
/*===============*/
 | 
						|
					/* out: 1, 0, -1, if a is greater,
 | 
						|
					equal, less than b, respectively */
 | 
						|
	int		mysql_type,	/* in: MySQL type */
 | 
						|
	uint		charset_number,	/* in: number of the charset */
 | 
						|
	unsigned char*	a,		/* in: data field */
 | 
						|
	unsigned int	a_length,	/* in: data field length,
 | 
						|
					not UNIV_SQL_NULL */
 | 
						|
	unsigned char*	b,		/* in: data field */
 | 
						|
	unsigned int	b_length)	/* in: data field length,
 | 
						|
					not UNIV_SQL_NULL */
 | 
						|
{
 | 
						|
	CHARSET_INFO*		charset;
 | 
						|
	enum_field_types	mysql_tp;
 | 
						|
	int                     ret;
 | 
						|
 | 
						|
	DBUG_ASSERT(a_length != UNIV_SQL_NULL);
 | 
						|
	DBUG_ASSERT(b_length != UNIV_SQL_NULL);
 | 
						|
 | 
						|
	mysql_tp = (enum_field_types) mysql_type;
 | 
						|
 | 
						|
	switch (mysql_tp) {
 | 
						|
 | 
						|
        case MYSQL_TYPE_BIT:
 | 
						|
	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
 | 
						|
		look at 2 common charsets directly. */
 | 
						|
 | 
						|
		if (charset_number == default_charset_info->number) {
 | 
						|
			charset = default_charset_info;
 | 
						|
		} else if (charset_number == my_charset_latin1.number) {
 | 
						|
			charset = &my_charset_latin1;
 | 
						|
		} else {
 | 
						|
			charset = get_charset(charset_number, MYF(MY_WME));
 | 
						|
 | 
						|
			if (charset == NULL) {
 | 
						|
			  sql_print_error("InnoDB needs charset %lu for doing "
 | 
						|
					  "a comparison, but MySQL cannot "
 | 
						|
					  "find that charset.",
 | 
						|
					  (ulong) charset_number);
 | 
						|
				ut_a(0);
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
                /* Starting from 4.1.3, we use strnncollsp() in comparisons of
 | 
						|
                non-latin1_swedish_ci strings. NOTE that the collation order
 | 
						|
                changes then: 'b\0\0...' is ordered BEFORE 'b  ...'. Users
 | 
						|
                having indexes on such data need to rebuild their tables! */
 | 
						|
 | 
						|
                ret = charset->coll->strnncollsp(charset,
 | 
						|
                                  a, a_length,
 | 
						|
                                                 b, b_length, 0);
 | 
						|
		if (ret < 0) {
 | 
						|
		        return(-1);
 | 
						|
		} else if (ret > 0) {
 | 
						|
		        return(1);
 | 
						|
		} else {
 | 
						|
		        return(0);
 | 
						|
	        }
 | 
						|
	default:
 | 
						|
		assert(0);
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************
 | 
						|
Converts a MySQL type to an InnoDB type. Note that this function returns
 | 
						|
the 'mtype' of InnoDB. InnoDB differentiates between MySQL's old <= 4.1
 | 
						|
VARCHAR and the new true VARCHAR in >= 5.0.3 by the 'prtype'. */
 | 
						|
inline
 | 
						|
ulint
 | 
						|
get_innobase_type_from_mysql_type(
 | 
						|
/*==============================*/
 | 
						|
				/* out: DATA_BINARY, DATA_VARCHAR, ... */
 | 
						|
	ulint*	unsigned_flag,	/* out: DATA_UNSIGNED if an 'unsigned type';
 | 
						|
				at least ENUM and SET, and unsigned integer
 | 
						|
				types are 'unsigned types' */
 | 
						|
	Field*	field)		/* in: MySQL field */
 | 
						|
{
 | 
						|
	/* The following asserts try to check that the MySQL type code fits in
 | 
						|
	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);
 | 
						|
 | 
						|
	if (field->flags & UNSIGNED_FLAG) {
 | 
						|
 | 
						|
		*unsigned_flag = DATA_UNSIGNED;
 | 
						|
	} else {
 | 
						|
		*unsigned_flag = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	if (field->real_type() == FIELD_TYPE_ENUM
 | 
						|
	    || field->real_type() == FIELD_TYPE_SET) {
 | 
						|
 | 
						|
		/* MySQL has field->type() a string type for these, but the
 | 
						|
		data is actually internally stored as an unsigned integer
 | 
						|
		code! */
 | 
						|
 | 
						|
		*unsigned_flag = DATA_UNSIGNED; /* MySQL has its own unsigned
 | 
						|
						flag set to zero, even though
 | 
						|
						internally this is an unsigned
 | 
						|
						integer type */
 | 
						|
		return(DATA_INT);
 | 
						|
	}
 | 
						|
 | 
						|
	switch (field->type()) {
 | 
						|
	        /* NOTE that we only allow string types in DATA_MYSQL
 | 
						|
		and DATA_VARMYSQL */
 | 
						|
                case MYSQL_TYPE_VAR_STRING: /* old <= 4.1 VARCHAR */
 | 
						|
                case MYSQL_TYPE_VARCHAR:    /* new >= 5.0.3 true VARCHAR */
 | 
						|
					if (field->binary()) {
 | 
						|
						return(DATA_BINARY);
 | 
						|
					} else if (strcmp(
 | 
						|
						  field->charset()->name,
 | 
						|
						 "latin1_swedish_ci") == 0) {
 | 
						|
						return(DATA_VARCHAR);
 | 
						|
					} else {
 | 
						|
						return(DATA_VARMYSQL);
 | 
						|
					}
 | 
						|
                case MYSQL_TYPE_BIT:
 | 
						|
		case MYSQL_TYPE_STRING: if (field->binary()) {
 | 
						|
 | 
						|
						return(DATA_FIXBINARY);
 | 
						|
					} else if (strcmp(
 | 
						|
						   field->charset()->name,
 | 
						|
						   "latin1_swedish_ci") == 0) {
 | 
						|
						return(DATA_CHAR);
 | 
						|
					} else {
 | 
						|
						return(DATA_MYSQL);
 | 
						|
					}
 | 
						|
                case FIELD_TYPE_NEWDECIMAL:
 | 
						|
                                        return(DATA_FIXBINARY);
 | 
						|
		case FIELD_TYPE_LONG:
 | 
						|
		case FIELD_TYPE_LONGLONG:
 | 
						|
		case FIELD_TYPE_TINY:
 | 
						|
		case FIELD_TYPE_SHORT:
 | 
						|
		case FIELD_TYPE_INT24:
 | 
						|
		case FIELD_TYPE_DATE:
 | 
						|
		case FIELD_TYPE_DATETIME:
 | 
						|
		case FIELD_TYPE_YEAR:
 | 
						|
		case FIELD_TYPE_NEWDATE:
 | 
						|
		case FIELD_TYPE_TIME:
 | 
						|
		case FIELD_TYPE_TIMESTAMP:
 | 
						|
					return(DATA_INT);
 | 
						|
		case FIELD_TYPE_FLOAT:
 | 
						|
					return(DATA_FLOAT);
 | 
						|
		case FIELD_TYPE_DOUBLE:
 | 
						|
					return(DATA_DOUBLE);
 | 
						|
		case FIELD_TYPE_DECIMAL:
 | 
						|
					return(DATA_DECIMAL);
 | 
						|
		case FIELD_TYPE_GEOMETRY:
 | 
						|
		case FIELD_TYPE_TINY_BLOB:
 | 
						|
		case FIELD_TYPE_MEDIUM_BLOB:
 | 
						|
		case FIELD_TYPE_BLOB:
 | 
						|
		case FIELD_TYPE_LONG_BLOB:
 | 
						|
					return(DATA_BLOB);
 | 
						|
		default:
 | 
						|
					assert(0);
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Writes an unsigned integer value < 64k to 2 bytes, in the little-endian
 | 
						|
storage format. */
 | 
						|
inline
 | 
						|
void
 | 
						|
innobase_write_to_2_little_endian(
 | 
						|
/*==============================*/
 | 
						|
	byte*	buf,	/* in: where to store */
 | 
						|
	ulint	val)	/* in: value to write, must be < 64k */
 | 
						|
{
 | 
						|
	ut_a(val < 256 * 256);
 | 
						|
 | 
						|
	buf[0] = (byte)(val & 0xFF);
 | 
						|
	buf[1] = (byte)(val / 256);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Reads an unsigned integer value < 64k from 2 bytes, in the little-endian
 | 
						|
storage format. */
 | 
						|
inline
 | 
						|
uint
 | 
						|
innobase_read_from_2_little_endian(
 | 
						|
/*===============================*/
 | 
						|
			/* out: value */
 | 
						|
	const mysql_byte*	buf)	/* in: from where to read */
 | 
						|
{
 | 
						|
	return (uint) ((ulint)(buf[0]) + 256 * ((ulint)(buf[1])));
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Stores a key value for a row to a buffer. */
 | 
						|
 | 
						|
uint
 | 
						|
ha_innobase::store_key_val_for_row(
 | 
						|
/*===============================*/
 | 
						|
				/* out: key value length as stored in buff */
 | 
						|
	uint 		keynr,	/* in: key number */
 | 
						|
	char*		buff,	/* in/out: buffer for the key value (in MySQL
 | 
						|
				format) */
 | 
						|
	uint		buff_len,/* in: buffer length */
 | 
						|
	const mysql_byte* record)/* in: row in MySQL format */
 | 
						|
{
 | 
						|
	KEY*		key_info 	= table->key_info + keynr;
 | 
						|
  	KEY_PART_INFO*	key_part	= key_info->key_part;
 | 
						|
  	KEY_PART_INFO*	end		= key_part + key_info->key_parts;
 | 
						|
	char*		buff_start	= buff;
 | 
						|
	enum_field_types mysql_type;
 | 
						|
	Field*		field;
 | 
						|
	ibool		is_null;
 | 
						|
 | 
						|
  	DBUG_ENTER("store_key_val_for_row");
 | 
						|
 | 
						|
	/* The format for storing a key field in MySQL is the following:
 | 
						|
 | 
						|
	1. If the column can be NULL, then in the first byte we put 1 if the
 | 
						|
	field value is NULL, 0 otherwise.
 | 
						|
 | 
						|
	2. If the column is of a BLOB type (it must be a column prefix field
 | 
						|
	in this case), then we put the length of the data in the field to the
 | 
						|
	next 2 bytes, in the little-endian format. If the field is SQL NULL,
 | 
						|
	then these 2 bytes are set to 0. Note that the length of data in the
 | 
						|
	field is <= column prefix length.
 | 
						|
 | 
						|
	3. In a column prefix field, prefix_len next bytes are reserved for
 | 
						|
	data. In a normal field the max field length next bytes are reserved
 | 
						|
	for data. For a VARCHAR(n) the max field length is n. If the stored
 | 
						|
	value is the SQL NULL then these data bytes are set to 0.
 | 
						|
 | 
						|
	4. We always use a 2 byte length for a true >= 5.0.3 VARCHAR. Note that
 | 
						|
	in the MySQL row format, the length is stored in 1 or 2 bytes,
 | 
						|
	depending on the maximum allowed length. But in the MySQL key value
 | 
						|
	format, the length always takes 2 bytes.
 | 
						|
 | 
						|
	We have to zero-fill the buffer so that MySQL is able to use a
 | 
						|
	simple memcmp to compare two key values to determine if they are
 | 
						|
	equal. MySQL does this to compare contents of two 'ref' values. */
 | 
						|
 | 
						|
	bzero(buff, buff_len);
 | 
						|
 | 
						|
  	for (; key_part != end; key_part++) {
 | 
						|
	        is_null = FALSE;
 | 
						|
 | 
						|
    		if (key_part->null_bit) {
 | 
						|
      			if (record[key_part->null_offset]
 | 
						|
						& key_part->null_bit) {
 | 
						|
				*buff = 1;
 | 
						|
				is_null = TRUE;
 | 
						|
      			} else {
 | 
						|
				*buff = 0;
 | 
						|
			}
 | 
						|
			buff++;
 | 
						|
    		}
 | 
						|
 | 
						|
		field = key_part->field;
 | 
						|
		mysql_type = field->type();
 | 
						|
 | 
						|
		if (mysql_type == MYSQL_TYPE_VARCHAR) {
 | 
						|
						/* >= 5.0.3 true VARCHAR */
 | 
						|
			ulint	lenlen;
 | 
						|
			ulint	len;
 | 
						|
			byte*	data;
 | 
						|
			ulint	key_len;
 | 
						|
			ulint	true_len;
 | 
						|
			CHARSET_INFO*	cs;
 | 
						|
			int	error=0;
 | 
						|
 | 
						|
			key_len = key_part->length;
 | 
						|
 | 
						|
			if (is_null) {
 | 
						|
				buff += key_len + 2;
 | 
						|
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
			cs = field->charset();
 | 
						|
 | 
						|
			lenlen = (ulint)
 | 
						|
				(((Field_varstring*)field)->length_bytes);
 | 
						|
 | 
						|
			data = row_mysql_read_true_varchar(&len,
 | 
						|
				(byte*) (record
 | 
						|
				+ (ulint)get_field_offset(table, field)),
 | 
						|
				lenlen);
 | 
						|
 | 
						|
			true_len = len;
 | 
						|
 | 
						|
			/* For multi byte character sets we need to calculate
 | 
						|
			the true length of the key */
 | 
						|
 | 
						|
			if (len > 0 && cs->mbmaxlen > 1) {
 | 
						|
				true_len = (ulint) cs->cset->well_formed_len(cs,
 | 
						|
						(const char *) data,
 | 
						|
						(const char *) data + len,
 | 
						|
						key_len / cs->mbmaxlen,
 | 
						|
						&error);
 | 
						|
			}
 | 
						|
 | 
						|
			/* In a column prefix index, we may need to truncate
 | 
						|
			the stored value: */
 | 
						|
 | 
						|
			if (true_len > key_len) {
 | 
						|
				true_len = key_len;
 | 
						|
			}
 | 
						|
 | 
						|
			/* The length in a key value is always stored in 2
 | 
						|
			bytes */
 | 
						|
 | 
						|
			row_mysql_store_true_var_len((byte*)buff, true_len, 2);
 | 
						|
			buff += 2;
 | 
						|
 | 
						|
			memcpy(buff, data, true_len);
 | 
						|
 | 
						|
			/* Note that we always reserve the maximum possible
 | 
						|
			length of the true VARCHAR in the key value, though
 | 
						|
			only len first bytes after the 2 length bytes contain
 | 
						|
			actual data. The rest of the space was reset to zero
 | 
						|
			in the bzero() call above. */
 | 
						|
 | 
						|
			buff += key_len;
 | 
						|
 | 
						|
		} else if (mysql_type == FIELD_TYPE_TINY_BLOB
 | 
						|
		    || mysql_type == FIELD_TYPE_MEDIUM_BLOB
 | 
						|
		    || mysql_type == FIELD_TYPE_BLOB
 | 
						|
		    || mysql_type == FIELD_TYPE_LONG_BLOB) {
 | 
						|
 | 
						|
			CHARSET_INFO*	cs;
 | 
						|
			ulint		key_len;
 | 
						|
			ulint		true_len;
 | 
						|
			int		error=0;
 | 
						|
			ulint		blob_len;
 | 
						|
			byte*		blob_data;
 | 
						|
 | 
						|
			ut_a(key_part->key_part_flag & HA_PART_KEY_SEG);
 | 
						|
 | 
						|
			key_len = key_part->length;
 | 
						|
 | 
						|
		        if (is_null) {
 | 
						|
				buff += key_len + 2;
 | 
						|
 | 
						|
				continue;
 | 
						|
			}
 | 
						|
 | 
						|
			cs = field->charset();
 | 
						|
 | 
						|
		        blob_data = row_mysql_read_blob_ref(&blob_len,
 | 
						|
				(byte*) (record
 | 
						|
				+ (ulint)get_field_offset(table, field)),
 | 
						|
					(ulint) field->pack_length());
 | 
						|
 | 
						|
			true_len = blob_len;
 | 
						|
 | 
						|
			ut_a(get_field_offset(table, field)
 | 
						|
						     == key_part->offset);
 | 
						|
 | 
						|
			/* For multi byte character sets we need to calculate
 | 
						|
			the true length of the key */
 | 
						|
 | 
						|
			if (blob_len > 0 && cs->mbmaxlen > 1) {
 | 
						|
				true_len = (ulint) cs->cset->well_formed_len(cs,
 | 
						|
						(const char *) blob_data,
 | 
						|
						(const char *) blob_data
 | 
						|
							+ blob_len,
 | 
						|
						key_len / cs->mbmaxlen,
 | 
						|
						&error);
 | 
						|
			}
 | 
						|
 | 
						|
			/* All indexes on BLOB and TEXT are column prefix
 | 
						|
			indexes, and we may need to truncate the data to be
 | 
						|
			stored in the key value: */
 | 
						|
 | 
						|
			if (true_len > key_len) {
 | 
						|
				true_len = key_len;
 | 
						|
			}
 | 
						|
 | 
						|
			/* MySQL reserves 2 bytes for the length and the
 | 
						|
			storage of the number is little-endian */
 | 
						|
 | 
						|
			innobase_write_to_2_little_endian(
 | 
						|
					(byte*)buff, true_len);
 | 
						|
			buff += 2;
 | 
						|
 | 
						|
			memcpy(buff, blob_data, true_len);
 | 
						|
 | 
						|
			/* Note that we always reserve the maximum possible
 | 
						|
			length of the BLOB prefix in the key value. */
 | 
						|
 | 
						|
			buff += key_len;
 | 
						|
		} else {
 | 
						|
			/* Here we handle all other data types except the
 | 
						|
			true VARCHAR, BLOB and TEXT. Note that the column
 | 
						|
			value we store may be also in a column prefix
 | 
						|
			index. */
 | 
						|
 | 
						|
			CHARSET_INFO*		cs;
 | 
						|
			ulint			true_len;
 | 
						|
			ulint			key_len;
 | 
						|
			const mysql_byte*	src_start;
 | 
						|
			int			error=0;
 | 
						|
			enum_field_types	real_type;
 | 
						|
 | 
						|
			key_len = key_part->length;
 | 
						|
 | 
						|
		        if (is_null) {
 | 
						|
				 buff += key_len;
 | 
						|
 | 
						|
				 continue;
 | 
						|
			}
 | 
						|
 | 
						|
			src_start = record + key_part->offset;
 | 
						|
			real_type = field->real_type();
 | 
						|
			true_len = key_len;
 | 
						|
 | 
						|
			/* Character set for the field is defined only
 | 
						|
			to fields whose type is string and real field
 | 
						|
			type is not enum or set. For these fields check
 | 
						|
			if character set is multi byte. */
 | 
						|
 | 
						|
			if (real_type != FIELD_TYPE_ENUM
 | 
						|
				&& real_type != FIELD_TYPE_SET
 | 
						|
				&& ( mysql_type == MYSQL_TYPE_VAR_STRING
 | 
						|
					|| mysql_type == MYSQL_TYPE_STRING)) {
 | 
						|
 | 
						|
				cs = field->charset();
 | 
						|
 | 
						|
				/* For multi byte character sets we need to
 | 
						|
				calculate the true length of the key */
 | 
						|
 | 
						|
				if (key_len > 0 && cs->mbmaxlen > 1) {
 | 
						|
 | 
						|
					true_len = (ulint)
 | 
						|
						cs->cset->well_formed_len(cs,
 | 
						|
							(const char *)src_start,
 | 
						|
							(const char *)src_start
 | 
						|
								+ key_len,
 | 
						|
							key_len / cs->mbmaxlen,
 | 
						|
							&error);
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			memcpy(buff, src_start, true_len);
 | 
						|
			buff += true_len;
 | 
						|
 | 
						|
			/* Pad the unused space with spaces. Note that no
 | 
						|
			padding is ever needed for UCS-2 because in MySQL,
 | 
						|
			all UCS2 characters are 2 bytes, as MySQL does not
 | 
						|
			support surrogate pairs, which are needed to represent
 | 
						|
			characters in the range U+10000 to U+10FFFF. */
 | 
						|
 | 
						|
			if (true_len < key_len) {
 | 
						|
				ulint pad_len = key_len - true_len;
 | 
						|
				memset(buff, ' ', pad_len);
 | 
						|
				buff += pad_len;
 | 
						|
			}
 | 
						|
		}
 | 
						|
  	}
 | 
						|
 | 
						|
	ut_a(buff <= buff_start + buff_len);
 | 
						|
 | 
						|
	DBUG_RETURN((uint)(buff - buff_start));
 | 
						|
}
 | 
						|
 | 
						|
/******************************************************************
 | 
						|
Builds a 'template' to the prebuilt struct. The template is used in fast
 | 
						|
retrieval of just those column values MySQL needs in its processing. */
 | 
						|
static
 | 
						|
void
 | 
						|
build_template(
 | 
						|
/*===========*/
 | 
						|
	row_prebuilt_t*	prebuilt,	/* in: prebuilt struct */
 | 
						|
	THD*		thd,		/* in: current user thread, used
 | 
						|
					only if templ_type is
 | 
						|
					ROW_MYSQL_REC_FIELDS */
 | 
						|
	TABLE*		table,		/* in: MySQL table */
 | 
						|
	ulint		templ_type)	/* in: ROW_MYSQL_WHOLE_ROW or
 | 
						|
					ROW_MYSQL_REC_FIELDS */
 | 
						|
{
 | 
						|
	dict_index_t*	index;
 | 
						|
	dict_index_t*	clust_index;
 | 
						|
	mysql_row_templ_t* templ;
 | 
						|
	Field*		field;
 | 
						|
	ulint		n_fields;
 | 
						|
	ulint		n_requested_fields	= 0;
 | 
						|
	ibool		fetch_all_in_key	= FALSE;
 | 
						|
	ibool		fetch_primary_key_cols	= FALSE;
 | 
						|
	ulint		i;
 | 
						|
	/* byte offset of the end of last requested column */
 | 
						|
	ulint		mysql_prefix_len	= 0;
 | 
						|
 | 
						|
	if (prebuilt->select_lock_type == LOCK_X) {
 | 
						|
		/* We always retrieve the whole clustered index record if we
 | 
						|
		use exclusive row level locks, for example, if the read is
 | 
						|
		done in an UPDATE statement. */
 | 
						|
 | 
						|
	        templ_type = ROW_MYSQL_WHOLE_ROW;
 | 
						|
	}
 | 
						|
 | 
						|
	if (templ_type == ROW_MYSQL_REC_FIELDS) {
 | 
						|
	     if (prebuilt->hint_need_to_fetch_extra_cols
 | 
						|
						== ROW_RETRIEVE_ALL_COLS) {
 | 
						|
 | 
						|
		/* We know we must at least fetch all columns in the key, or
 | 
						|
		all columns in the table */
 | 
						|
 | 
						|
		if (prebuilt->read_just_key) {
 | 
						|
			/* MySQL has instructed us that it is enough to
 | 
						|
			fetch the columns in the key; looks like MySQL
 | 
						|
			can set this flag also when there is only a
 | 
						|
			prefix of the column in the key: in that case we
 | 
						|
			retrieve the whole column from the clustered
 | 
						|
			index */
 | 
						|
 | 
						|
			fetch_all_in_key = TRUE;
 | 
						|
		} else {
 | 
						|
			templ_type = ROW_MYSQL_WHOLE_ROW;
 | 
						|
		}
 | 
						|
	    } else if (prebuilt->hint_need_to_fetch_extra_cols
 | 
						|
						== ROW_RETRIEVE_PRIMARY_KEY) {
 | 
						|
		/* We must at least fetch all primary key cols. Note that if
 | 
						|
		the clustered index was internally generated by InnoDB on the
 | 
						|
		row id (no primary key was defined), then
 | 
						|
		row_search_for_mysql() will always retrieve the row id to a
 | 
						|
		special buffer in the prebuilt struct. */
 | 
						|
 | 
						|
		fetch_primary_key_cols = TRUE;
 | 
						|
	    }
 | 
						|
	}
 | 
						|
 | 
						|
	clust_index = dict_table_get_first_index_noninline(prebuilt->table);
 | 
						|
 | 
						|
	if (templ_type == ROW_MYSQL_REC_FIELDS) {
 | 
						|
		index = prebuilt->index;
 | 
						|
	} else {
 | 
						|
		index = clust_index;
 | 
						|
	}
 | 
						|
 | 
						|
	if (index == clust_index) {
 | 
						|
		prebuilt->need_to_access_clustered = TRUE;
 | 
						|
	} else {
 | 
						|
		prebuilt->need_to_access_clustered = FALSE;
 | 
						|
		/* Below we check column by column if we need to access
 | 
						|
		the clustered index */
 | 
						|
	}
 | 
						|
 | 
						|
	n_fields = (ulint)table->s->fields; /* number of columns */
 | 
						|
 | 
						|
	if (!prebuilt->mysql_template) {
 | 
						|
		prebuilt->mysql_template = (mysql_row_templ_t*)
 | 
						|
						mem_alloc_noninline(
 | 
						|
					n_fields * sizeof(mysql_row_templ_t));
 | 
						|
	}
 | 
						|
 | 
						|
	prebuilt->template_type = templ_type;
 | 
						|
	prebuilt->null_bitmap_len = table->s->null_bytes;
 | 
						|
 | 
						|
	prebuilt->templ_contains_blob = FALSE;
 | 
						|
 | 
						|
	/* Note that in InnoDB, i is the column number. MySQL calls columns
 | 
						|
	'fields'. */
 | 
						|
	for (i = 0; i < n_fields; i++) {
 | 
						|
		templ = prebuilt->mysql_template + n_requested_fields;
 | 
						|
		field = table->field[i];
 | 
						|
 | 
						|
		if (UNIV_LIKELY(templ_type == ROW_MYSQL_REC_FIELDS)) {
 | 
						|
			/* Decide which columns we should fetch
 | 
						|
			and which we can skip. */
 | 
						|
			register const ibool	index_contains_field =
 | 
						|
				dict_index_contains_col_or_prefix(index, i);
 | 
						|
 | 
						|
			if (!index_contains_field && prebuilt->read_just_key) {
 | 
						|
				/* If this is a 'key read', we do not need
 | 
						|
				columns that are not in the key */
 | 
						|
 | 
						|
				goto skip_field;
 | 
						|
			}
 | 
						|
 | 
						|
			if (index_contains_field && fetch_all_in_key) {
 | 
						|
				/* This field is needed in the query */
 | 
						|
 | 
						|
				goto include_field;
 | 
						|
			}
 | 
						|
 | 
						|
			if (thd->query_id == field->query_id) {
 | 
						|
				/* This field is needed in the query */
 | 
						|
 | 
						|
				goto include_field;
 | 
						|
			}
 | 
						|
 | 
						|
			if (fetch_primary_key_cols
 | 
						|
			    && dict_table_col_in_clustered_key(index->table,
 | 
						|
									i)) {
 | 
						|
				/* This field is needed in the query */
 | 
						|
 | 
						|
				goto include_field;
 | 
						|
			}
 | 
						|
 | 
						|
			/* This field is not needed in the query, skip it */
 | 
						|
 | 
						|
			goto skip_field;
 | 
						|
		}
 | 
						|
include_field:
 | 
						|
		n_requested_fields++;
 | 
						|
 | 
						|
		templ->col_no = i;
 | 
						|
 | 
						|
		if (index == clust_index) {
 | 
						|
			templ->rec_field_no = (index->table->cols + i)
 | 
						|
								->clust_pos;
 | 
						|
		} else {
 | 
						|
			templ->rec_field_no = dict_index_get_nth_col_pos(
 | 
						|
								index, i);
 | 
						|
		}
 | 
						|
 | 
						|
		if (templ->rec_field_no == ULINT_UNDEFINED) {
 | 
						|
			prebuilt->need_to_access_clustered = TRUE;
 | 
						|
		}
 | 
						|
 | 
						|
		if (field->null_ptr) {
 | 
						|
			templ->mysql_null_byte_offset =
 | 
						|
				(ulint) ((char*) field->null_ptr
 | 
						|
					- (char*) table->record[0]);
 | 
						|
 | 
						|
			templ->mysql_null_bit_mask = (ulint) field->null_bit;
 | 
						|
		} else {
 | 
						|
			templ->mysql_null_bit_mask = 0;
 | 
						|
		}
 | 
						|
 | 
						|
		templ->mysql_col_offset = (ulint)
 | 
						|
					get_field_offset(table, field);
 | 
						|
 | 
						|
		templ->mysql_col_len = (ulint) field->pack_length();
 | 
						|
		if (mysql_prefix_len < templ->mysql_col_offset
 | 
						|
				+ templ->mysql_col_len) {
 | 
						|
			mysql_prefix_len = templ->mysql_col_offset
 | 
						|
				+ templ->mysql_col_len;
 | 
						|
		}
 | 
						|
		templ->type = index->table->cols[i].type.mtype;
 | 
						|
		templ->mysql_type = (ulint)field->type();
 | 
						|
 | 
						|
		if (templ->mysql_type == DATA_MYSQL_TRUE_VARCHAR) {
 | 
						|
			templ->mysql_length_bytes = (ulint)
 | 
						|
				    (((Field_varstring*)field)->length_bytes);
 | 
						|
		}
 | 
						|
 | 
						|
		templ->charset = dtype_get_charset_coll_noninline(
 | 
						|
				index->table->cols[i].type.prtype);
 | 
						|
		templ->mbminlen = index->table->cols[i].type.mbminlen;
 | 
						|
		templ->mbmaxlen = index->table->cols[i].type.mbmaxlen;
 | 
						|
		templ->is_unsigned = index->table->cols[i].type.prtype
 | 
						|
							& DATA_UNSIGNED;
 | 
						|
		if (templ->type == DATA_BLOB) {
 | 
						|
			prebuilt->templ_contains_blob = TRUE;
 | 
						|
		}
 | 
						|
skip_field:
 | 
						|
		;
 | 
						|
	}
 | 
						|
 | 
						|
	prebuilt->n_template = n_requested_fields;
 | 
						|
	prebuilt->mysql_prefix_len = mysql_prefix_len;
 | 
						|
 | 
						|
	if (index != clust_index && prebuilt->need_to_access_clustered) {
 | 
						|
		/* Change rec_field_no's to correspond to the clustered index
 | 
						|
		record */
 | 
						|
		for (i = 0; i < n_requested_fields; i++) {
 | 
						|
			templ = prebuilt->mysql_template + i;
 | 
						|
 | 
						|
			templ->rec_field_no =
 | 
						|
			    (index->table->cols + templ->col_no)->clust_pos;
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
Stores a row in an InnoDB database, to the table specified in this
 | 
						|
handle. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::write_row(
 | 
						|
/*===================*/
 | 
						|
				/* out: error code */
 | 
						|
	mysql_byte* 	record)	/* in: a row in MySQL format */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
 | 
						|
  	int 		error;
 | 
						|
	longlong	auto_inc;
 | 
						|
	longlong	dummy;
 | 
						|
	ibool           auto_inc_used= FALSE;
 | 
						|
 | 
						|
  	DBUG_ENTER("ha_innobase::write_row");
 | 
						|
 | 
						|
	if (prebuilt->trx !=
 | 
						|
                        (trx_t*) current_thd->ha_data[innobase_hton.slot]) {
 | 
						|
	  sql_print_error("The transaction object for the table handle is at "
 | 
						|
			  "%p, but for the current thread it is at %p",
 | 
						|
			  prebuilt->trx,
 | 
						|
			  (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
		fputs("InnoDB: Dump of 200 bytes around prebuilt: ", stderr);
 | 
						|
		ut_print_buf(stderr, ((const byte*)prebuilt) - 100, 200);
 | 
						|
		fputs("\n"
 | 
						|
			"InnoDB: Dump of 200 bytes around transaction.all: ",
 | 
						|
			stderr);
 | 
						|
		ut_print_buf(stderr,
 | 
						|
           	 ((byte*)(&(current_thd->ha_data[innobase_hton.slot]))) - 100,
 | 
						|
								200);
 | 
						|
		putc('\n', stderr);
 | 
						|
		ut_error;
 | 
						|
	}
 | 
						|
 | 
						|
  	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 ((user_thd->lex->sql_command == SQLCOM_ALTER_TABLE
 | 
						|
	    || user_thd->lex->sql_command == SQLCOM_OPTIMIZE
 | 
						|
	    || user_thd->lex->sql_command == SQLCOM_CREATE_INDEX
 | 
						|
	    || user_thd->lex->sql_command == SQLCOM_DROP_INDEX)
 | 
						|
	    && 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;
 | 
						|
		ulint		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, 1);
 | 
						|
			/* Note that this transaction is still active. */
 | 
						|
			prebuilt->trx->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, 1);
 | 
						|
			/* Note that this transaction is still active. */
 | 
						|
			prebuilt->trx->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;
 | 
						|
 | 
						|
		innobase_release_stat_resources(prebuilt->trx);
 | 
						|
	}
 | 
						|
 | 
						|
  	if (table->next_number_field && record == table->record[0]) {
 | 
						|
		/* This is the case where the table has an
 | 
						|
		auto-increment column */
 | 
						|
 | 
						|
		/* Initialize the auto-inc counter if it has not been
 | 
						|
		initialized yet */
 | 
						|
 | 
						|
		if (0 == dict_table_autoinc_peek(prebuilt->table)) {
 | 
						|
 | 
						|
			/* This call initializes the counter */
 | 
						|
		        error = innobase_read_and_init_auto_inc(&dummy);
 | 
						|
 | 
						|
			if (error) {
 | 
						|
				/* Deadlock or lock wait timeout */
 | 
						|
 | 
						|
				goto func_exit;
 | 
						|
			}
 | 
						|
 | 
						|
			/* We have to set sql_stat_start to TRUE because
 | 
						|
			the above call probably has called a select, and
 | 
						|
			has reset that flag; row_insert_for_mysql has to
 | 
						|
			know to set the IX intention lock on the table,
 | 
						|
			something it only does at the start of each
 | 
						|
			statement */
 | 
						|
 | 
						|
			prebuilt->sql_stat_start = TRUE;
 | 
						|
		}
 | 
						|
 | 
						|
		/* We have to use the transactional lock mechanism on the
 | 
						|
		auto-inc counter of the table to ensure that replication and
 | 
						|
		roll-forward of the binlog exactly imitates also the given
 | 
						|
		auto-inc values. The lock is released at each SQL statement's
 | 
						|
		end. This lock also prevents a race where two threads would
 | 
						|
		call ::get_auto_increment() simultaneously. */
 | 
						|
 | 
						|
		error = row_lock_table_autoinc_for_mysql(prebuilt);
 | 
						|
 | 
						|
		if (error != DB_SUCCESS) {
 | 
						|
			/* Deadlock or lock wait timeout */
 | 
						|
 | 
						|
			error = convert_error_code_to_mysql(error, user_thd);
 | 
						|
 | 
						|
			goto func_exit;
 | 
						|
		}
 | 
						|
 | 
						|
		/* We must use the handler code to update the auto-increment
 | 
						|
                value to be sure that we increment it correctly. */
 | 
						|
 | 
						|
    		if ((error= update_auto_increment()))
 | 
						|
			goto func_exit;
 | 
						|
                auto_inc_used = 1;
 | 
						|
 | 
						|
	}
 | 
						|
 | 
						|
	if (prebuilt->mysql_template == NULL
 | 
						|
			|| prebuilt->template_type != ROW_MYSQL_WHOLE_ROW) {
 | 
						|
		/* Build the template used in converting quickly between
 | 
						|
		the two database formats */
 | 
						|
 | 
						|
		build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 | 
						|
	}
 | 
						|
 | 
						|
	innodb_srv_conc_enter_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	error = row_insert_for_mysql((byte*) record, prebuilt);
 | 
						|
 | 
						|
	if (error == DB_SUCCESS && auto_inc_used) {
 | 
						|
 | 
						|
        	/* Fetch the value that was set in the autoincrement field */
 | 
						|
 | 
						|
          	auto_inc = table->next_number_field->val_int();
 | 
						|
 | 
						|
          	if (auto_inc != 0) {
 | 
						|
			/* This call will update the counter according to the
 | 
						|
			value that was inserted in the table */
 | 
						|
 | 
						|
            		dict_table_autoinc_update(prebuilt->table, auto_inc);
 | 
						|
          	}
 | 
						|
        }
 | 
						|
 | 
						|
        /* A REPLACE command and LOAD DATA INFILE REPLACE handle a duplicate
 | 
						|
        key error themselves, and we must update the autoinc counter if we are
 | 
						|
        performing those statements. */
 | 
						|
 | 
						|
        if (error == DB_DUPLICATE_KEY && auto_inc_used
 | 
						|
            && (user_thd->lex->sql_command == SQLCOM_REPLACE
 | 
						|
                || user_thd->lex->sql_command == SQLCOM_REPLACE_SELECT
 | 
						|
                || (user_thd->lex->sql_command == SQLCOM_LOAD
 | 
						|
                    && user_thd->lex->duplicates == DUP_REPLACE))) {
 | 
						|
 | 
						|
                auto_inc = table->next_number_field->val_int();
 | 
						|
 | 
						|
                if (auto_inc != 0) {
 | 
						|
                        dict_table_autoinc_update(prebuilt->table, auto_inc);
 | 
						|
                }
 | 
						|
        }
 | 
						|
 | 
						|
	innodb_srv_conc_exit_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, user_thd);
 | 
						|
 | 
						|
	/* Tell InnoDB server that there might be work for
 | 
						|
	utility threads: */
 | 
						|
func_exit:
 | 
						|
	innobase_active_small();
 | 
						|
 | 
						|
  	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Checks which fields have changed in a row and stores information
 | 
						|
of them to an update vector. */
 | 
						|
static
 | 
						|
int
 | 
						|
calc_row_difference(
 | 
						|
/*================*/
 | 
						|
					/* out: error number or 0 */
 | 
						|
	upd_t*		uvect,		/* in/out: update vector */
 | 
						|
	mysql_byte* 	old_row,	/* in: old row in MySQL format */
 | 
						|
	mysql_byte* 	new_row,	/* in: new row in MySQL format */
 | 
						|
	struct st_table* table,		/* in: table in MySQL data
 | 
						|
					dictionary */
 | 
						|
	mysql_byte*	upd_buff,	/* in: buffer to use */
 | 
						|
	ulint		buff_len,	/* in: buffer length */
 | 
						|
	row_prebuilt_t*	prebuilt,	/* in: InnoDB prebuilt struct */
 | 
						|
	THD*		thd)		/* in: user thread */
 | 
						|
{
 | 
						|
	mysql_byte*	original_upd_buff = upd_buff;
 | 
						|
	Field*		field;
 | 
						|
	enum_field_types field_mysql_type;
 | 
						|
	uint		n_fields;
 | 
						|
	ulint		o_len;
 | 
						|
	ulint		n_len;
 | 
						|
	ulint		col_pack_len;
 | 
						|
	byte*		new_mysql_row_col;
 | 
						|
	byte*	        o_ptr;
 | 
						|
        byte*	        n_ptr;
 | 
						|
        byte*	        buf;
 | 
						|
	upd_field_t*	ufield;
 | 
						|
	ulint		col_type;
 | 
						|
	ulint		n_changed = 0;
 | 
						|
	dfield_t	dfield;
 | 
						|
	uint		i;
 | 
						|
 | 
						|
	n_fields = table->s->fields;
 | 
						|
 | 
						|
	/* We use upd_buff to convert changed fields */
 | 
						|
	buf = (byte*) upd_buff;
 | 
						|
 | 
						|
	for (i = 0; i < n_fields; i++) {
 | 
						|
		field = table->field[i];
 | 
						|
 | 
						|
		/* if (thd->query_id != field->query_id) { */
 | 
						|
			/* TODO: check that these fields cannot have
 | 
						|
			changed! */
 | 
						|
 | 
						|
		/*	goto skip_field;
 | 
						|
		}*/
 | 
						|
 | 
						|
		o_ptr = (byte*) old_row + get_field_offset(table, field);
 | 
						|
		n_ptr = (byte*) new_row + get_field_offset(table, field);
 | 
						|
 | 
						|
		/* Use new_mysql_row_col and col_pack_len save the values */
 | 
						|
 | 
						|
		new_mysql_row_col = n_ptr;
 | 
						|
		col_pack_len = field->pack_length();
 | 
						|
 | 
						|
		o_len = col_pack_len;
 | 
						|
		n_len = col_pack_len;
 | 
						|
 | 
						|
		/* We use o_ptr and n_ptr to dig up the actual data for
 | 
						|
		comparison. */
 | 
						|
 | 
						|
		field_mysql_type = field->type();
 | 
						|
 | 
						|
		col_type = prebuilt->table->cols[i].type.mtype;
 | 
						|
 | 
						|
		switch (col_type) {
 | 
						|
 | 
						|
		case DATA_BLOB:
 | 
						|
			o_ptr = row_mysql_read_blob_ref(&o_len, o_ptr, o_len);
 | 
						|
			n_ptr = row_mysql_read_blob_ref(&n_len, n_ptr, n_len);
 | 
						|
 | 
						|
			break;
 | 
						|
 | 
						|
		case DATA_VARCHAR:
 | 
						|
		case DATA_BINARY:
 | 
						|
		case DATA_VARMYSQL:
 | 
						|
			if (field_mysql_type == MYSQL_TYPE_VARCHAR) {
 | 
						|
				/* This is a >= 5.0.3 type true VARCHAR where
 | 
						|
				the real payload data length is stored in
 | 
						|
				1 or 2 bytes */
 | 
						|
 | 
						|
				o_ptr = row_mysql_read_true_varchar(
 | 
						|
						&o_len, o_ptr,
 | 
						|
				    (ulint)
 | 
						|
				    (((Field_varstring*)field)->length_bytes));
 | 
						|
 | 
						|
				n_ptr = row_mysql_read_true_varchar(
 | 
						|
						&n_len, n_ptr,
 | 
						|
				    (ulint)
 | 
						|
				    (((Field_varstring*)field)->length_bytes));
 | 
						|
			}
 | 
						|
 | 
						|
			break;
 | 
						|
		default:
 | 
						|
			;
 | 
						|
		}
 | 
						|
 | 
						|
		if (field->null_ptr) {
 | 
						|
			if (field_in_record_is_null(table, field,
 | 
						|
							(char*) old_row)) {
 | 
						|
				o_len = UNIV_SQL_NULL;
 | 
						|
			}
 | 
						|
 | 
						|
			if (field_in_record_is_null(table, field,
 | 
						|
							(char*) new_row)) {
 | 
						|
				n_len = UNIV_SQL_NULL;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		if (o_len != n_len || (o_len != UNIV_SQL_NULL &&
 | 
						|
					0 != memcmp(o_ptr, n_ptr, o_len))) {
 | 
						|
			/* The field has changed */
 | 
						|
 | 
						|
			ufield = uvect->fields + n_changed;
 | 
						|
 | 
						|
			/* Let us use a dummy dfield to make the conversion
 | 
						|
			from the MySQL column format to the InnoDB format */
 | 
						|
 | 
						|
			dfield.type = (prebuilt->table->cols + i)->type;
 | 
						|
 | 
						|
			if (n_len != UNIV_SQL_NULL) {
 | 
						|
				buf = row_mysql_store_col_in_innobase_format(
 | 
						|
						&dfield,
 | 
						|
						(byte*)buf,
 | 
						|
						TRUE,
 | 
						|
						new_mysql_row_col,
 | 
						|
						col_pack_len,
 | 
						|
						prebuilt->table->comp);
 | 
						|
				ufield->new_val.data = dfield.data;
 | 
						|
				ufield->new_val.len = dfield.len;
 | 
						|
			} else {
 | 
						|
				ufield->new_val.data = NULL;
 | 
						|
				ufield->new_val.len = UNIV_SQL_NULL;
 | 
						|
			}
 | 
						|
 | 
						|
			ufield->exp = NULL;
 | 
						|
			ufield->field_no = prebuilt->table->cols[i].clust_pos;
 | 
						|
			n_changed++;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	uvect->n_fields = n_changed;
 | 
						|
	uvect->info_bits = 0;
 | 
						|
 | 
						|
	ut_a(buf <= (byte*)original_upd_buff + buff_len);
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Updates a row given as a parameter to a new value. Note that we are given
 | 
						|
whole rows, not just the fields which are updated: this incurs some
 | 
						|
overhead for CPU when we check which fields are actually updated.
 | 
						|
TODO: currently InnoDB does not prevent the 'Halloween problem':
 | 
						|
in a searched update a single row can get updated several times
 | 
						|
if its index columns are updated! */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::update_row(
 | 
						|
/*====================*/
 | 
						|
					/* out: error number or 0 */
 | 
						|
	const mysql_byte* 	old_row,/* in: old row in MySQL format */
 | 
						|
	mysql_byte* 		new_row)/* in: new row in MySQL format */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	upd_t*		uvect;
 | 
						|
	int		error = 0;
 | 
						|
 | 
						|
	DBUG_ENTER("ha_innobase::update_row");
 | 
						|
 | 
						|
	ut_ad(prebuilt->trx ==
 | 
						|
                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
        if (table->timestamp_field_type & TIMESTAMP_AUTO_SET_ON_UPDATE)
 | 
						|
                table->timestamp_field->set_time();
 | 
						|
 | 
						|
	if (last_query_id != user_thd->query_id) {
 | 
						|
	        prebuilt->sql_stat_start = TRUE;
 | 
						|
                last_query_id = user_thd->query_id;
 | 
						|
 | 
						|
		innobase_release_stat_resources(prebuilt->trx);
 | 
						|
	}
 | 
						|
 | 
						|
	if (prebuilt->upd_node) {
 | 
						|
		uvect = prebuilt->upd_node->update;
 | 
						|
	} else {
 | 
						|
		uvect = row_get_prebuilt_update_vector(prebuilt);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Build an update vector from the modified fields in the rows
 | 
						|
	(uses upd_buff of the handle) */
 | 
						|
 | 
						|
	calc_row_difference(uvect, (mysql_byte*) old_row, new_row, table,
 | 
						|
			upd_buff, (ulint)upd_and_key_val_buff_len,
 | 
						|
			prebuilt, user_thd);
 | 
						|
 | 
						|
	/* This is not a delete */
 | 
						|
	prebuilt->upd_node->is_delete = FALSE;
 | 
						|
 | 
						|
	assert(prebuilt->template_type == ROW_MYSQL_WHOLE_ROW);
 | 
						|
 | 
						|
	innodb_srv_conc_enter_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	error = row_update_for_mysql((byte*) old_row, prebuilt);
 | 
						|
 | 
						|
	innodb_srv_conc_exit_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, user_thd);
 | 
						|
 | 
						|
	/* Tell InnoDB server that there might be work for
 | 
						|
	utility threads: */
 | 
						|
 | 
						|
	innobase_active_small();
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Deletes a row given as the parameter. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::delete_row(
 | 
						|
/*====================*/
 | 
						|
					/* out: error number or 0 */
 | 
						|
	const mysql_byte* record)	/* in: a row in MySQL format */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	int		error = 0;
 | 
						|
 | 
						|
	DBUG_ENTER("ha_innobase::delete_row");
 | 
						|
 | 
						|
	ut_ad(prebuilt->trx ==
 | 
						|
                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
	if (last_query_id != user_thd->query_id) {
 | 
						|
	        prebuilt->sql_stat_start = TRUE;
 | 
						|
                last_query_id = user_thd->query_id;
 | 
						|
 | 
						|
		innobase_release_stat_resources(prebuilt->trx);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!prebuilt->upd_node) {
 | 
						|
		row_get_prebuilt_update_vector(prebuilt);
 | 
						|
	}
 | 
						|
 | 
						|
	/* This is a delete */
 | 
						|
 | 
						|
	prebuilt->upd_node->is_delete = TRUE;
 | 
						|
 | 
						|
	innodb_srv_conc_enter_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	error = row_update_for_mysql((byte*) record, prebuilt);
 | 
						|
 | 
						|
	innodb_srv_conc_exit_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, user_thd);
 | 
						|
 | 
						|
	/* Tell the InnoDB server that there might be work for
 | 
						|
	utility threads: */
 | 
						|
 | 
						|
	innobase_active_small();
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Removes a new lock set on a row. This method does nothing unless the
 | 
						|
option innodb_locks_unsafe_for_binlog is set.*/
 | 
						|
 | 
						|
void
 | 
						|
ha_innobase::unlock_row(void)
 | 
						|
/*=========================*/
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
 | 
						|
	DBUG_ENTER("ha_innobase::unlock_row");
 | 
						|
 | 
						|
	if (last_query_id != user_thd->query_id) {
 | 
						|
		ut_print_timestamp(stderr);
 | 
						|
		sql_print_error("last_query_id is %lu != user_thd_query_id is "
 | 
						|
				"%lu", (ulong) last_query_id,
 | 
						|
				(ulong) user_thd->query_id);
 | 
						|
		mem_analyze_corruption((byte *) prebuilt->trx);
 | 
						|
		ut_error;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Consistent read does not take any locks, thus there is
 | 
						|
	nothing to unlock. */
 | 
						|
 | 
						|
	if (prebuilt->select_lock_type == LOCK_NONE) {
 | 
						|
		DBUG_VOID_RETURN;
 | 
						|
	}
 | 
						|
 | 
						|
	if (srv_locks_unsafe_for_binlog) {
 | 
						|
		row_unlock_for_mysql(prebuilt, FALSE);
 | 
						|
	}
 | 
						|
 | 
						|
	DBUG_VOID_RETURN;
 | 
						|
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Initializes a handle to use an index. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_init(
 | 
						|
/*====================*/
 | 
						|
			/* out: 0 or error number */
 | 
						|
	uint 	keynr)	/* in: key (index) number */
 | 
						|
{
 | 
						|
	int 	error	= 0;
 | 
						|
  	DBUG_ENTER("index_init");
 | 
						|
 | 
						|
	error = change_active_index(keynr);
 | 
						|
 | 
						|
  	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Currently does nothing. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_end(void)
 | 
						|
/*========================*/
 | 
						|
{
 | 
						|
	int 	error	= 0;
 | 
						|
  	DBUG_ENTER("index_end");
 | 
						|
        active_index=MAX_KEY;
 | 
						|
  	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Converts a search mode flag understood by MySQL to a flag understood
 | 
						|
by InnoDB. */
 | 
						|
inline
 | 
						|
ulint
 | 
						|
convert_search_mode_to_innobase(
 | 
						|
/*============================*/
 | 
						|
	enum ha_rkey_function	find_flag)
 | 
						|
{
 | 
						|
	switch (find_flag) {
 | 
						|
  		case HA_READ_KEY_EXACT:		return(PAGE_CUR_GE);
 | 
						|
  			/* the above does not require the index to be UNIQUE */
 | 
						|
  		case HA_READ_KEY_OR_NEXT:	return(PAGE_CUR_GE);
 | 
						|
		case HA_READ_KEY_OR_PREV:	return(PAGE_CUR_LE);
 | 
						|
		case HA_READ_AFTER_KEY:		return(PAGE_CUR_G);
 | 
						|
		case HA_READ_BEFORE_KEY:	return(PAGE_CUR_L);
 | 
						|
		case HA_READ_PREFIX:		return(PAGE_CUR_GE);
 | 
						|
	        case HA_READ_PREFIX_LAST:       return(PAGE_CUR_LE);
 | 
						|
                case HA_READ_PREFIX_LAST_OR_PREV:return(PAGE_CUR_LE);
 | 
						|
		  /* In MySQL-4.0 HA_READ_PREFIX and HA_READ_PREFIX_LAST always
 | 
						|
		  pass a complete-field prefix of a key value as the search
 | 
						|
		  tuple. I.e., it is not allowed that the last field would
 | 
						|
		  just contain n first bytes of the full field value.
 | 
						|
		  MySQL uses a 'padding' trick to convert LIKE 'abc%'
 | 
						|
		  type queries so that it can use as a search tuple
 | 
						|
		  a complete-field-prefix of a key value. Thus, the InnoDB
 | 
						|
		  search mode PAGE_CUR_LE_OR_EXTENDS is never used.
 | 
						|
		  TODO: when/if MySQL starts to use also partial-field
 | 
						|
		  prefixes, we have to deal with stripping of spaces
 | 
						|
		  and comparison of non-latin1 char type fields in
 | 
						|
		  innobase_mysql_cmp() to get PAGE_CUR_LE_OR_EXTENDS to
 | 
						|
		  work correctly. */
 | 
						|
 | 
						|
		default:			assert(0);
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/*
 | 
						|
   BACKGROUND INFO: HOW A SELECT SQL QUERY IS EXECUTED
 | 
						|
   ---------------------------------------------------
 | 
						|
The following does not cover all the details, but explains how we determine
 | 
						|
the start of a new SQL statement, and what is associated with it.
 | 
						|
 | 
						|
For each table in the database the MySQL interpreter may have several
 | 
						|
table handle instances in use, also in a single SQL query. For each table
 | 
						|
handle instance there is an InnoDB  'prebuilt' struct which contains most
 | 
						|
of the InnoDB data associated with this table handle instance.
 | 
						|
 | 
						|
  A) if the user has not explicitly set any MySQL table level locks:
 | 
						|
 | 
						|
  1) MySQL calls ::external_lock to set an 'intention' table level lock on
 | 
						|
the table of the handle instance. There we set
 | 
						|
prebuilt->sql_stat_start = TRUE. The flag sql_stat_start should be set
 | 
						|
true if we are taking this table handle instance to use in a new SQL
 | 
						|
statement issued by the user. We also increment trx->n_mysql_tables_in_use.
 | 
						|
 | 
						|
  2) If prebuilt->sql_stat_start == TRUE we 'pre-compile' the MySQL search
 | 
						|
instructions to prebuilt->template of the table handle instance in
 | 
						|
::index_read. The template is used to save CPU time in large joins.
 | 
						|
 | 
						|
  3) In row_search_for_mysql, if prebuilt->sql_stat_start is true, we
 | 
						|
allocate a new consistent read view for the trx if it does not yet have one,
 | 
						|
or in the case of a locking read, set an InnoDB 'intention' table level
 | 
						|
lock on the table.
 | 
						|
 | 
						|
  4) We do the SELECT. MySQL may repeatedly call ::index_read for the
 | 
						|
same table handle instance, if it is a join.
 | 
						|
 | 
						|
  5) When the SELECT ends, MySQL removes its intention table level locks
 | 
						|
in ::external_lock. When trx->n_mysql_tables_in_use drops to zero,
 | 
						|
 (a) we execute a COMMIT there if the autocommit is on,
 | 
						|
 (b) we also release possible 'SQL statement level resources' InnoDB may
 | 
						|
have for this SQL statement. The MySQL interpreter does NOT execute
 | 
						|
autocommit for pure read transactions, though it should. That is why the
 | 
						|
table handler in that case has to execute the COMMIT in ::external_lock.
 | 
						|
 | 
						|
  B) If the user has explicitly set MySQL table level locks, then MySQL
 | 
						|
does NOT call ::external_lock at the start of the statement. To determine
 | 
						|
when we are at the start of a new SQL statement we at the start of
 | 
						|
::index_read also compare the query id to the latest query id where the
 | 
						|
table handle instance was used. If it has changed, we know we are at the
 | 
						|
start of a new SQL statement. Since the query id can theoretically
 | 
						|
overwrap, we use this test only as a secondary way of determining the
 | 
						|
start of a new SQL statement. */
 | 
						|
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Positions an index cursor to the index specified in the handle. Fetches the
 | 
						|
row if any. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_read(
 | 
						|
/*====================*/
 | 
						|
					/* out: 0, HA_ERR_KEY_NOT_FOUND,
 | 
						|
					or error number */
 | 
						|
	mysql_byte*		buf,	/* in/out: buffer for the returned
 | 
						|
					row */
 | 
						|
	const mysql_byte* 	key_ptr,/* in: key value; if this is NULL
 | 
						|
					we position the cursor at the
 | 
						|
					start or end of index; this can
 | 
						|
					also contain an InnoDB row id, in
 | 
						|
					which case key_len is the InnoDB
 | 
						|
					row id length; the key value can
 | 
						|
					also be a prefix of a full key value,
 | 
						|
					and the last column can be a prefix
 | 
						|
					of a full column */
 | 
						|
	uint			key_len,/* in: key value length */
 | 
						|
	enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	ulint		mode;
 | 
						|
	dict_index_t*	index;
 | 
						|
	ulint		match_mode 	= 0;
 | 
						|
	int 		error;
 | 
						|
	ulint		ret;
 | 
						|
 | 
						|
  	DBUG_ENTER("index_read");
 | 
						|
 | 
						|
	ut_ad(prebuilt->trx ==
 | 
						|
                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
  	statistic_increment(current_thd->status_var.ha_read_key_count,
 | 
						|
			    &LOCK_status);
 | 
						|
 | 
						|
	if (last_query_id != user_thd->query_id) {
 | 
						|
	        prebuilt->sql_stat_start = TRUE;
 | 
						|
                last_query_id = user_thd->query_id;
 | 
						|
 | 
						|
		innobase_release_stat_resources(prebuilt->trx);
 | 
						|
	}
 | 
						|
 | 
						|
	index = prebuilt->index;
 | 
						|
 | 
						|
	/* Note that if the index for which the search template is built is not
 | 
						|
        necessarily prebuilt->index, but can also be the clustered index */
 | 
						|
 | 
						|
	if (prebuilt->sql_stat_start) {
 | 
						|
		build_template(prebuilt, user_thd, table,
 | 
						|
							ROW_MYSQL_REC_FIELDS);
 | 
						|
	}
 | 
						|
 | 
						|
	if (key_ptr) {
 | 
						|
	        /* Convert the search key value to InnoDB format into
 | 
						|
		prebuilt->search_tuple */
 | 
						|
 | 
						|
		row_sel_convert_mysql_key_to_innobase(prebuilt->search_tuple,
 | 
						|
					(byte*) key_val_buff,
 | 
						|
					(ulint)upd_and_key_val_buff_len,
 | 
						|
					index,
 | 
						|
					(byte*) key_ptr,
 | 
						|
					(ulint) key_len, prebuilt->trx);
 | 
						|
	} else {
 | 
						|
		/* We position the cursor to the last or the first entry
 | 
						|
		in the index */
 | 
						|
 | 
						|
 		dtuple_set_n_fields(prebuilt->search_tuple, 0);
 | 
						|
	}
 | 
						|
 | 
						|
	mode = convert_search_mode_to_innobase(find_flag);
 | 
						|
 | 
						|
	match_mode = 0;
 | 
						|
 | 
						|
	if (find_flag == HA_READ_KEY_EXACT) {
 | 
						|
		match_mode = ROW_SEL_EXACT;
 | 
						|
 | 
						|
	} else if (find_flag == HA_READ_PREFIX
 | 
						|
				|| find_flag == HA_READ_PREFIX_LAST) {
 | 
						|
		match_mode = ROW_SEL_EXACT_PREFIX;
 | 
						|
	}
 | 
						|
 | 
						|
	last_match_mode = (uint) match_mode;
 | 
						|
 | 
						|
	innodb_srv_conc_enter_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	ret = row_search_for_mysql((byte*) buf, mode, prebuilt, match_mode, 0);
 | 
						|
 | 
						|
	innodb_srv_conc_exit_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	if (ret == DB_SUCCESS) {
 | 
						|
		error = 0;
 | 
						|
		table->status = 0;
 | 
						|
 | 
						|
	} else if (ret == DB_RECORD_NOT_FOUND) {
 | 
						|
		error = HA_ERR_KEY_NOT_FOUND;
 | 
						|
		table->status = STATUS_NOT_FOUND;
 | 
						|
 | 
						|
	} else if (ret == DB_END_OF_INDEX) {
 | 
						|
		error = HA_ERR_KEY_NOT_FOUND;
 | 
						|
		table->status = STATUS_NOT_FOUND;
 | 
						|
	} else {
 | 
						|
		error = convert_error_code_to_mysql((int) ret, user_thd);
 | 
						|
		table->status = STATUS_NOT_FOUND;
 | 
						|
	}
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
The following functions works like index_read, but it find the last
 | 
						|
row with the current key value or prefix. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_read_last(
 | 
						|
/*=========================*/
 | 
						|
			           /* out: 0, HA_ERR_KEY_NOT_FOUND, or an
 | 
						|
				   error code */
 | 
						|
        mysql_byte*       buf,     /* out: fetched row */
 | 
						|
        const mysql_byte* key_ptr, /* in: key value, or a prefix of a full
 | 
						|
				   key value */
 | 
						|
	uint              key_len) /* in: length of the key val or prefix
 | 
						|
				   in bytes */
 | 
						|
{
 | 
						|
        return(index_read(buf, key_ptr, key_len, HA_READ_PREFIX_LAST));
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
Changes the active index of a handle. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::change_active_index(
 | 
						|
/*=============================*/
 | 
						|
			/* out: 0 or error code */
 | 
						|
	uint 	keynr)	/* in: use this index; MAX_KEY means always clustered
 | 
						|
			index, even if it was internally generated by
 | 
						|
			InnoDB */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	KEY*		key=0;
 | 
						|
	statistic_increment(current_thd->status_var.ha_read_key_count,
 | 
						|
			    &LOCK_status);
 | 
						|
	DBUG_ENTER("change_active_index");
 | 
						|
 | 
						|
	ut_ad(user_thd == current_thd);
 | 
						|
	ut_ad(prebuilt->trx ==
 | 
						|
             (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
	active_index = keynr;
 | 
						|
 | 
						|
	if (keynr != MAX_KEY && table->s->keys > 0) {
 | 
						|
		key = table->key_info + active_index;
 | 
						|
 | 
						|
		prebuilt->index = dict_table_get_index_noninline(
 | 
						|
						     prebuilt->table,
 | 
						|
						     key->name);
 | 
						|
        } else {
 | 
						|
		prebuilt->index = dict_table_get_first_index_noninline(
 | 
						|
							   prebuilt->table);
 | 
						|
	}
 | 
						|
 | 
						|
	if (!prebuilt->index) {
 | 
						|
	       sql_print_error("Innodb could not find key n:o %u with name %s "
 | 
						|
			       "from dict cache for table %s",
 | 
						|
			       keynr, key ? key->name : "NULL",
 | 
						|
			       prebuilt->table->name);
 | 
						|
	      DBUG_RETURN(1);
 | 
						|
	}
 | 
						|
 | 
						|
	assert(prebuilt->search_tuple != 0);
 | 
						|
 | 
						|
	dtuple_set_n_fields(prebuilt->search_tuple, prebuilt->index->n_fields);
 | 
						|
 | 
						|
	dict_index_copy_types(prebuilt->search_tuple, prebuilt->index,
 | 
						|
			prebuilt->index->n_fields);
 | 
						|
 | 
						|
	/* MySQL changes the active index for a handle also during some
 | 
						|
	queries, for example SELECT MAX(a), SUM(a) first retrieves the MAX()
 | 
						|
	and then calculates the sum. Previously we played safe and used
 | 
						|
	the flag ROW_MYSQL_WHOLE_ROW below, but that caused unnecessary
 | 
						|
	copying. Starting from MySQL-4.1 we use a more efficient flag here. */
 | 
						|
 | 
						|
	build_template(prebuilt, user_thd, table, ROW_MYSQL_REC_FIELDS);
 | 
						|
 | 
						|
	DBUG_RETURN(0);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Positions an index cursor to the index specified in keynr. Fetches the
 | 
						|
row if any. */
 | 
						|
/* ??? This is only used to read whole keys ??? */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_read_idx(
 | 
						|
/*========================*/
 | 
						|
					/* out: error number or 0 */
 | 
						|
	mysql_byte*	buf,		/* in/out: buffer for the returned
 | 
						|
					row */
 | 
						|
	uint 		keynr,		/* in: use this index */
 | 
						|
	const mysql_byte* key,		/* in: key value; if this is NULL
 | 
						|
					we position the cursor at the
 | 
						|
					start or end of index */
 | 
						|
	uint		key_len,	/* in: key value length */
 | 
						|
	enum ha_rkey_function find_flag)/* in: search flags from my_base.h */
 | 
						|
{
 | 
						|
	if (change_active_index(keynr)) {
 | 
						|
 | 
						|
		return(1);
 | 
						|
	}
 | 
						|
 | 
						|
	return(index_read(buf, key, key_len, find_flag));
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************
 | 
						|
Reads the next or previous row from a cursor, which must have previously been
 | 
						|
positioned using index_read. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::general_fetch(
 | 
						|
/*=======================*/
 | 
						|
				/* out: 0, HA_ERR_END_OF_FILE, or error
 | 
						|
				number */
 | 
						|
	mysql_byte* 	buf,	/* in/out: buffer for next row in MySQL
 | 
						|
				format */
 | 
						|
	uint 	direction,	/* in: ROW_SEL_NEXT or ROW_SEL_PREV */
 | 
						|
	uint	match_mode)	/* in: 0, ROW_SEL_EXACT, or
 | 
						|
				ROW_SEL_EXACT_PREFIX */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	ulint		ret;
 | 
						|
	int		error	= 0;
 | 
						|
 | 
						|
	DBUG_ENTER("general_fetch");
 | 
						|
 | 
						|
	ut_ad(prebuilt->trx ==
 | 
						|
             (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
	innodb_srv_conc_enter_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	ret = row_search_for_mysql((byte*)buf, 0, prebuilt, match_mode,
 | 
						|
								direction);
 | 
						|
	innodb_srv_conc_exit_innodb(prebuilt->trx);
 | 
						|
 | 
						|
	if (ret == DB_SUCCESS) {
 | 
						|
		error = 0;
 | 
						|
		table->status = 0;
 | 
						|
 | 
						|
	} else if (ret == DB_RECORD_NOT_FOUND) {
 | 
						|
		error = HA_ERR_END_OF_FILE;
 | 
						|
		table->status = STATUS_NOT_FOUND;
 | 
						|
 | 
						|
	} else if (ret == DB_END_OF_INDEX) {
 | 
						|
		error = HA_ERR_END_OF_FILE;
 | 
						|
		table->status = STATUS_NOT_FOUND;
 | 
						|
	} else {
 | 
						|
		error = convert_error_code_to_mysql((int) ret, user_thd);
 | 
						|
		table->status = STATUS_NOT_FOUND;
 | 
						|
	}
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************
 | 
						|
Reads the next row from a cursor, which must have previously been
 | 
						|
positioned using index_read. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_next(
 | 
						|
/*====================*/
 | 
						|
				/* out: 0, HA_ERR_END_OF_FILE, or error
 | 
						|
				number */
 | 
						|
	mysql_byte* 	buf)	/* in/out: buffer for next row in MySQL
 | 
						|
				format */
 | 
						|
{
 | 
						|
  	statistic_increment(current_thd->status_var.ha_read_next_count,
 | 
						|
			    &LOCK_status);
 | 
						|
 | 
						|
	return(general_fetch(buf, ROW_SEL_NEXT, 0));
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Reads the next row matching to the key value given as the parameter. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_next_same(
 | 
						|
/*=========================*/
 | 
						|
				/* out: 0, HA_ERR_END_OF_FILE, or error
 | 
						|
				number */
 | 
						|
	mysql_byte* 	buf,	/* in/out: buffer for the row */
 | 
						|
	const mysql_byte* key,	/* in: key value */
 | 
						|
	uint 		keylen)	/* in: key value length */
 | 
						|
{
 | 
						|
  	statistic_increment(current_thd->status_var.ha_read_next_count,
 | 
						|
			    &LOCK_status);
 | 
						|
 | 
						|
	return(general_fetch(buf, ROW_SEL_NEXT, last_match_mode));
 | 
						|
}
 | 
						|
 | 
						|
/***************************************************************************
 | 
						|
Reads the previous row from a cursor, which must have previously been
 | 
						|
positioned using index_read. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_prev(
 | 
						|
/*====================*/
 | 
						|
				/* out: 0, HA_ERR_END_OF_FILE, or error
 | 
						|
				number */
 | 
						|
	mysql_byte* 	buf)	/* in/out: buffer for previous row in MySQL
 | 
						|
				format */
 | 
						|
{
 | 
						|
  	statistic_increment(current_thd->status_var.ha_read_prev_count,
 | 
						|
			    &LOCK_status);
 | 
						|
 | 
						|
	return(general_fetch(buf, ROW_SEL_PREV, 0));
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
Positions a cursor on the first record in an index and reads the
 | 
						|
corresponding row to buf. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_first(
 | 
						|
/*=====================*/
 | 
						|
				/* out: 0, HA_ERR_END_OF_FILE,
 | 
						|
				or error code */
 | 
						|
	mysql_byte*	buf)	/* in/out: buffer for the row */
 | 
						|
{
 | 
						|
	int	error;
 | 
						|
 | 
						|
  	DBUG_ENTER("index_first");
 | 
						|
  	statistic_increment(current_thd->status_var.ha_read_first_count,
 | 
						|
			    &LOCK_status);
 | 
						|
 | 
						|
  	error = index_read(buf, NULL, 0, HA_READ_AFTER_KEY);
 | 
						|
 | 
						|
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 | 
						|
 | 
						|
  	if (error == HA_ERR_KEY_NOT_FOUND) {
 | 
						|
  		error = HA_ERR_END_OF_FILE;
 | 
						|
  	}
 | 
						|
 | 
						|
  	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/************************************************************************
 | 
						|
Positions a cursor on the last record in an index and reads the
 | 
						|
corresponding row to buf. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::index_last(
 | 
						|
/*====================*/
 | 
						|
				/* out: 0, HA_ERR_END_OF_FILE, or error code */
 | 
						|
	mysql_byte*	buf)	/* in/out: buffer for the row */
 | 
						|
{
 | 
						|
	int	error;
 | 
						|
 | 
						|
  	DBUG_ENTER("index_last");
 | 
						|
  	statistic_increment(current_thd->status_var.ha_read_last_count,
 | 
						|
			    &LOCK_status);
 | 
						|
 | 
						|
  	error = index_read(buf, NULL, 0, HA_READ_BEFORE_KEY);
 | 
						|
 | 
						|
        /* MySQL does not seem to allow this to return HA_ERR_KEY_NOT_FOUND */
 | 
						|
 | 
						|
  	if (error == HA_ERR_KEY_NOT_FOUND) {
 | 
						|
  		error = HA_ERR_END_OF_FILE;
 | 
						|
  	}
 | 
						|
 | 
						|
  	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/********************************************************************
 | 
						|
Initialize a table scan. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::rnd_init(
 | 
						|
/*==================*/
 | 
						|
			/* out: 0 or error number */
 | 
						|
	bool	scan)	/* in: ???????? */
 | 
						|
{
 | 
						|
	int	err;
 | 
						|
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
 | 
						|
	/* Store the active index value so that we can restore the original
 | 
						|
	value after a scan */
 | 
						|
 | 
						|
	if (prebuilt->clust_index_was_generated) {
 | 
						|
		err = change_active_index(MAX_KEY);
 | 
						|
	} else {
 | 
						|
		err = change_active_index(primary_key);
 | 
						|
	}
 | 
						|
 | 
						|
  	start_of_scan = 1;
 | 
						|
 | 
						|
 	return(err);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Ends a table scan. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::rnd_end(void)
 | 
						|
/*======================*/
 | 
						|
				/* out: 0 or error number */
 | 
						|
{
 | 
						|
	return(index_end());
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Reads the next row in a table scan (also used to read the FIRST row
 | 
						|
in a table scan). */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::rnd_next(
 | 
						|
/*==================*/
 | 
						|
			/* out: 0, HA_ERR_END_OF_FILE, or error number */
 | 
						|
	mysql_byte* buf)/* in/out: returns the row in this buffer,
 | 
						|
			in MySQL format */
 | 
						|
{
 | 
						|
	int	error;
 | 
						|
 | 
						|
  	DBUG_ENTER("rnd_next");
 | 
						|
  	statistic_increment(current_thd->status_var.ha_read_rnd_next_count,
 | 
						|
			    &LOCK_status);
 | 
						|
 | 
						|
  	if (start_of_scan) {
 | 
						|
		error = index_first(buf);
 | 
						|
		if (error == HA_ERR_KEY_NOT_FOUND) {
 | 
						|
			error = HA_ERR_END_OF_FILE;
 | 
						|
		}
 | 
						|
		start_of_scan = 0;
 | 
						|
	} else {
 | 
						|
		error = general_fetch(buf, ROW_SEL_NEXT, 0);
 | 
						|
	}
 | 
						|
 | 
						|
  	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Fetches a row from the table based on a row reference. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::rnd_pos(
 | 
						|
/*=================*/
 | 
						|
				/* out: 0, HA_ERR_KEY_NOT_FOUND,
 | 
						|
				or error code */
 | 
						|
	mysql_byte* 	buf,	/* in/out: buffer for the row */
 | 
						|
	mysql_byte*	pos)	/* in: primary key value of the row in the
 | 
						|
				MySQL format, or the row id if the clustered
 | 
						|
				index was internally generated by InnoDB;
 | 
						|
				the length of data in pos has to be
 | 
						|
				ref_length */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	int		error;
 | 
						|
	uint		keynr	= active_index;
 | 
						|
	DBUG_ENTER("rnd_pos");
 | 
						|
	DBUG_DUMP("key", (char*) pos, ref_length);
 | 
						|
 | 
						|
	statistic_increment(current_thd->status_var.ha_read_rnd_count,
 | 
						|
			    &LOCK_status);
 | 
						|
 | 
						|
	ut_ad(prebuilt->trx ==
 | 
						|
                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
	if (prebuilt->clust_index_was_generated) {
 | 
						|
		/* No primary key was defined for the table and we
 | 
						|
		generated the clustered index from the row id: the
 | 
						|
		row reference is the row id, not any key value
 | 
						|
		that MySQL knows of */
 | 
						|
 | 
						|
		error = change_active_index(MAX_KEY);
 | 
						|
	} else {
 | 
						|
		error = change_active_index(primary_key);
 | 
						|
	}
 | 
						|
 | 
						|
	if (error) {
 | 
						|
	        DBUG_PRINT("error", ("Got error: %d", error));
 | 
						|
		DBUG_RETURN(error);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Note that we assume the length of the row reference is fixed
 | 
						|
        for the table, and it is == ref_length */
 | 
						|
 | 
						|
	error = index_read(buf, pos, ref_length, HA_READ_KEY_EXACT);
 | 
						|
 | 
						|
	if (error) {
 | 
						|
		DBUG_PRINT("error", ("Got error: %d", error));
 | 
						|
	}
 | 
						|
 | 
						|
	change_active_index(keynr);
 | 
						|
 | 
						|
  	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Stores a reference to the current row to 'ref' field of the handle. Note
 | 
						|
that in the case where we have generated the clustered index for the
 | 
						|
table, the function parameter is illogical: we MUST ASSUME that 'record'
 | 
						|
is the current 'position' of the handle, because if row ref is actually
 | 
						|
the row id internally generated in InnoDB, then 'record' does not contain
 | 
						|
it. We just guess that the row id must be for the record where the handle
 | 
						|
was positioned the last time. */
 | 
						|
 | 
						|
void
 | 
						|
ha_innobase::position(
 | 
						|
/*==================*/
 | 
						|
	const mysql_byte*	record)	/* in: row in MySQL format */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	uint		len;
 | 
						|
 | 
						|
	ut_ad(prebuilt->trx ==
 | 
						|
                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
	if (prebuilt->clust_index_was_generated) {
 | 
						|
		/* No primary key was defined for the table and we
 | 
						|
		generated the clustered index from row id: the
 | 
						|
		row reference will be the row id, not any key value
 | 
						|
		that MySQL knows of */
 | 
						|
 | 
						|
		len = DATA_ROW_ID_LEN;
 | 
						|
 | 
						|
		memcpy(ref, prebuilt->row_id, len);
 | 
						|
	} else {
 | 
						|
		len = store_key_val_for_row(primary_key, (char*)ref,
 | 
						|
							 ref_length, record);
 | 
						|
	}
 | 
						|
 | 
						|
	/* We assume that the 'ref' value len is always fixed for the same
 | 
						|
	table. */
 | 
						|
 | 
						|
	if (len != ref_length) {
 | 
						|
	  sql_print_error("Stored ref len is %lu, but table ref len is %lu",
 | 
						|
			  (ulong) len, (ulong) ref_length);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Creates a table definition to an InnoDB database. */
 | 
						|
static
 | 
						|
int
 | 
						|
create_table_def(
 | 
						|
/*=============*/
 | 
						|
	trx_t*		trx,		/* in: InnoDB transaction handle */
 | 
						|
	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
 | 
						|
					created by the user with the
 | 
						|
					TEMPORARY keyword, then this
 | 
						|
					parameter is the dir path where the
 | 
						|
					table should be placed if we create
 | 
						|
					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;
 | 
						|
	ulint		n_cols;
 | 
						|
  	int 		error;
 | 
						|
  	ulint		col_type;
 | 
						|
	ulint		col_len;
 | 
						|
  	ulint		nulls_allowed;
 | 
						|
	ulint		unsigned_type;
 | 
						|
	ulint		binary_type;
 | 
						|
	ulint		long_true_varchar;
 | 
						|
	ulint		charset_no;
 | 
						|
  	ulint		i;
 | 
						|
 | 
						|
  	DBUG_ENTER("create_table_def");
 | 
						|
  	DBUG_PRINT("enter", ("table_name: %s", table_name));
 | 
						|
 | 
						|
	n_cols = form->s->fields;
 | 
						|
 | 
						|
	/* 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(table_name, 0, n_cols, comp);
 | 
						|
 | 
						|
	if (path_of_temp_table) {
 | 
						|
		table->dir_path_of_temp_table =
 | 
						|
			mem_heap_strdup(table->heap, path_of_temp_table);
 | 
						|
	}
 | 
						|
 | 
						|
	for (i = 0; i < n_cols; i++) {
 | 
						|
		field = form->field[i];
 | 
						|
 | 
						|
		col_type = get_innobase_type_from_mysql_type(&unsigned_type,
 | 
						|
									field);
 | 
						|
		if (field->null_ptr) {
 | 
						|
			nulls_allowed = 0;
 | 
						|
		} else {
 | 
						|
			nulls_allowed = DATA_NOT_NULL;
 | 
						|
		}
 | 
						|
 | 
						|
		if (field->binary()) {
 | 
						|
			binary_type = DATA_BINARY_TYPE;
 | 
						|
		} else {
 | 
						|
			binary_type = 0;
 | 
						|
		}
 | 
						|
 | 
						|
		charset_no = 0;
 | 
						|
 | 
						|
		if (dtype_is_string_type(col_type)) {
 | 
						|
 | 
						|
			charset_no = (ulint)field->charset()->number;
 | 
						|
 | 
						|
			ut_a(charset_no < 256); /* in data0type.h we assume
 | 
						|
						that the number fits in one
 | 
						|
						byte */
 | 
						|
		}
 | 
						|
 | 
						|
		ut_a(field->type() < 256); /* we assume in dtype_form_prtype()
 | 
						|
					   that this fits in one byte */
 | 
						|
		col_len = field->pack_length();
 | 
						|
 | 
						|
		/* The MySQL pack length contains 1 or 2 bytes length field
 | 
						|
		for a true VARCHAR. Let us subtract that, so that the InnoDB
 | 
						|
		column length in the InnoDB data dictionary is the real
 | 
						|
		maximum byte length of the actual data. */
 | 
						|
 | 
						|
		long_true_varchar = 0;
 | 
						|
 | 
						|
		if (field->type() == MYSQL_TYPE_VARCHAR) {
 | 
						|
			col_len -= ((Field_varstring*)field)->length_bytes;
 | 
						|
 | 
						|
			if (((Field_varstring*)field)->length_bytes == 2) {
 | 
						|
				long_true_varchar = DATA_LONG_TRUE_VARCHAR;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		dict_mem_table_add_col(table,
 | 
						|
					(char*) field->field_name,
 | 
						|
					col_type,
 | 
						|
					dtype_form_prtype(
 | 
						|
					    (ulint)field->type()
 | 
						|
					     | nulls_allowed | unsigned_type
 | 
						|
					     | binary_type | long_true_varchar,
 | 
						|
					    charset_no),
 | 
						|
					col_len,
 | 
						|
					0);
 | 
						|
	}
 | 
						|
 | 
						|
	error = row_create_table_for_mysql(table, trx);
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, NULL);
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Creates an index in an InnoDB database. */
 | 
						|
static
 | 
						|
int
 | 
						|
create_index(
 | 
						|
/*=========*/
 | 
						|
	trx_t*		trx,		/* in: InnoDB transaction handle */
 | 
						|
	TABLE*		form,		/* in: information on table
 | 
						|
					columns and indexes */
 | 
						|
	const char*	table_name,	/* in: table name */
 | 
						|
	uint		key_num)	/* in: index number */
 | 
						|
{
 | 
						|
	Field*		field;
 | 
						|
	dict_index_t*	index;
 | 
						|
  	int 		error;
 | 
						|
	ulint		n_fields;
 | 
						|
	KEY*		key;
 | 
						|
	KEY_PART_INFO*	key_part;
 | 
						|
	ulint		ind_type;
 | 
						|
	ulint		col_type;
 | 
						|
	ulint		prefix_len;
 | 
						|
	ulint		is_unsigned;
 | 
						|
  	ulint		i;
 | 
						|
  	ulint		j;
 | 
						|
	ulint*		field_lengths;
 | 
						|
 | 
						|
  	DBUG_ENTER("create_index");
 | 
						|
 | 
						|
	key = form->key_info + key_num;
 | 
						|
 | 
						|
    	n_fields = key->key_parts;
 | 
						|
 | 
						|
    	ind_type = 0;
 | 
						|
 | 
						|
    	if (key_num == form->s->primary_key) {
 | 
						|
		ind_type = ind_type | DICT_CLUSTERED;
 | 
						|
	}
 | 
						|
 | 
						|
	if (key->flags & HA_NOSAME ) {
 | 
						|
		ind_type = ind_type | DICT_UNIQUE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* We pass 0 as the space id, and determine at a lower level the space
 | 
						|
	id where to store the table */
 | 
						|
 | 
						|
	index = dict_mem_index_create((char*) table_name, key->name, 0,
 | 
						|
						ind_type, n_fields);
 | 
						|
 | 
						|
	field_lengths = (ulint*) my_malloc(sizeof(ulint) * n_fields,
 | 
						|
		MYF(MY_FAE));
 | 
						|
 | 
						|
	for (i = 0; i < n_fields; i++) {
 | 
						|
		key_part = key->key_part + i;
 | 
						|
 | 
						|
		/* (The flag HA_PART_KEY_SEG denotes in MySQL a column prefix
 | 
						|
		field in an index: we only store a specified number of first
 | 
						|
		bytes of the column to the index field.) The flag does not
 | 
						|
		seem to be properly set by MySQL. Let us fall back on testing
 | 
						|
		the length of the key part versus the column. */
 | 
						|
 | 
						|
		field = NULL;
 | 
						|
		for (j = 0; j < form->s->fields; j++) {
 | 
						|
 | 
						|
			field = form->field[j];
 | 
						|
 | 
						|
			if (0 == innobase_strcasecmp(
 | 
						|
					field->field_name,
 | 
						|
					key_part->field->field_name)) {
 | 
						|
				/* Found the corresponding column */
 | 
						|
 | 
						|
				break;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		ut_a(j < form->s->fields);
 | 
						|
 | 
						|
		col_type = get_innobase_type_from_mysql_type(
 | 
						|
					&is_unsigned, key_part->field);
 | 
						|
 | 
						|
		if (DATA_BLOB == col_type
 | 
						|
		    || (key_part->length < field->pack_length()
 | 
						|
			&& field->type() != MYSQL_TYPE_VARCHAR)
 | 
						|
		    || (field->type() == MYSQL_TYPE_VARCHAR
 | 
						|
			&& key_part->length < field->pack_length()
 | 
						|
			          - ((Field_varstring*)field)->length_bytes)) {
 | 
						|
 | 
						|
		        prefix_len = key_part->length;
 | 
						|
 | 
						|
			if (col_type == DATA_INT
 | 
						|
			    || col_type == DATA_FLOAT
 | 
						|
			    || col_type == DATA_DOUBLE
 | 
						|
			    || col_type == DATA_DECIMAL) {
 | 
						|
			  sql_print_error("MySQL is trying to create a column "
 | 
						|
					  "prefix index field, on an "
 | 
						|
					  "inappropriate data type. Table "
 | 
						|
					  "name %s, column name %s.",
 | 
						|
					  table_name,
 | 
						|
					  key_part->field->field_name);
 | 
						|
 | 
						|
			        prefix_len = 0;
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
		        prefix_len = 0;
 | 
						|
		}
 | 
						|
 | 
						|
		field_lengths[i] = key_part->length;
 | 
						|
 | 
						|
		/* We assume all fields should be sorted in ascending
 | 
						|
		order, hence the '0': */
 | 
						|
 | 
						|
		dict_mem_index_add_field(index,
 | 
						|
				(char*) key_part->field->field_name,
 | 
						|
				0, prefix_len);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Even though we've defined max_supported_key_part_length, we
 | 
						|
	still do our own checking using field_lengths to be absolutely
 | 
						|
	sure we don't create too long indexes. */
 | 
						|
	error = row_create_index_for_mysql(index, trx, field_lengths);
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, NULL);
 | 
						|
 | 
						|
	my_free((gptr) field_lengths, MYF(0));
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Creates an index to an InnoDB table when the user has defined no
 | 
						|
primary index. */
 | 
						|
static
 | 
						|
int
 | 
						|
create_clustered_index_when_no_primary(
 | 
						|
/*===================================*/
 | 
						|
	trx_t*		trx,		/* in: InnoDB transaction handle */
 | 
						|
	const char*	table_name)	/* in: table name */
 | 
						|
{
 | 
						|
	dict_index_t*	index;
 | 
						|
  	int 		error;
 | 
						|
 | 
						|
	/* We pass 0 as the space id, and determine at a lower level the space
 | 
						|
	id where to store the table */
 | 
						|
 | 
						|
	index = dict_mem_index_create((char*) table_name,
 | 
						|
				      (char*) "GEN_CLUST_INDEX",
 | 
						|
				      0, DICT_CLUSTERED, 0);
 | 
						|
	error = row_create_index_for_mysql(index, trx, NULL);
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, NULL);
 | 
						|
 | 
						|
	return(error);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Creates a new table to an InnoDB database. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::create(
 | 
						|
/*================*/
 | 
						|
					/* out: error number */
 | 
						|
	const char*	name,		/* in: table name */
 | 
						|
	TABLE*		form,		/* in: information on table
 | 
						|
					columns and indexes */
 | 
						|
	HA_CREATE_INFO*	create_info)	/* in: more information of the
 | 
						|
					created table, contains also the
 | 
						|
					create statement string */
 | 
						|
{
 | 
						|
	int		error;
 | 
						|
	dict_table_t*	innobase_table;
 | 
						|
	trx_t*		parent_trx;
 | 
						|
	trx_t*		trx;
 | 
						|
	int		primary_key_no;
 | 
						|
	uint		i;
 | 
						|
	char		name2[FN_REFLEN];
 | 
						|
	char		norm_name[FN_REFLEN];
 | 
						|
	THD		*thd= current_thd;
 | 
						|
	ib_longlong     auto_inc_value;
 | 
						|
 | 
						|
  	DBUG_ENTER("ha_innobase::create");
 | 
						|
 | 
						|
	DBUG_ASSERT(thd != NULL);
 | 
						|
 | 
						|
	if (form->s->fields > 1000) {
 | 
						|
		/* The limit probably should be REC_MAX_N_FIELDS - 3 = 1020,
 | 
						|
		but we play safe here */
 | 
						|
 | 
						|
	        DBUG_RETURN(HA_ERR_TO_BIG_ROW);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Get the transaction associated with the current thd, or create one
 | 
						|
	if not yet created */
 | 
						|
 | 
						|
	parent_trx = check_trx_exists(current_thd);
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query, release
 | 
						|
	possible adaptive hash latch to avoid deadlocks of threads */
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(parent_trx);
 | 
						|
 | 
						|
	trx = trx_allocate_for_mysql();
 | 
						|
 | 
						|
	trx->mysql_thd = thd;
 | 
						|
	trx->mysql_query_str = &((*thd).query);
 | 
						|
 | 
						|
	if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
 | 
						|
		trx->check_foreigns = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
 | 
						|
		trx->check_unique_secondary = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	if (lower_case_table_names) {
 | 
						|
		srv_lower_case_table_names = TRUE;
 | 
						|
	} else {
 | 
						|
		srv_lower_case_table_names = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	fn_format(name2, name, "", "", 2);	// Remove the .frm extension
 | 
						|
 | 
						|
	normalize_table_name(norm_name, name2);
 | 
						|
 | 
						|
	/* Latch the InnoDB data dictionary exclusively so that no deadlocks
 | 
						|
	or lock waits can happen in it during a table create operation.
 | 
						|
	Drop table etc. do this latching in row0mysql.c. */
 | 
						|
 | 
						|
	row_mysql_lock_data_dictionary(trx);
 | 
						|
 | 
						|
	/* Create the table definition in InnoDB */
 | 
						|
 | 
						|
	error = create_table_def(trx, form, norm_name,
 | 
						|
		create_info->options & HA_LEX_CREATE_TMP_TABLE ? name2 : NULL,
 | 
						|
		form->s->row_type != ROW_TYPE_REDUNDANT);
 | 
						|
 | 
						|
  	if (error) {
 | 
						|
		goto cleanup;
 | 
						|
 	}
 | 
						|
 | 
						|
	/* Look for a primary key */
 | 
						|
 | 
						|
	primary_key_no= (table->s->primary_key != MAX_KEY ?
 | 
						|
			 (int) table->s->primary_key :
 | 
						|
			 -1);
 | 
						|
 | 
						|
	/* Our function row_get_mysql_key_number_for_index assumes
 | 
						|
	the primary key is always number 0, if it exists */
 | 
						|
 | 
						|
	DBUG_ASSERT(primary_key_no == -1 || primary_key_no == 0);
 | 
						|
 | 
						|
	/* Create the keys */
 | 
						|
 | 
						|
	if (form->s->keys == 0 || primary_key_no == -1) {
 | 
						|
		/* Create an index which is used as the clustered index;
 | 
						|
		order the rows by their row id which is internally generated
 | 
						|
		by InnoDB */
 | 
						|
 | 
						|
		error = create_clustered_index_when_no_primary(trx,
 | 
						|
							norm_name);
 | 
						|
  		if (error) {
 | 
						|
			goto cleanup;
 | 
						|
      		}
 | 
						|
	}
 | 
						|
 | 
						|
	if (primary_key_no != -1) {
 | 
						|
		/* In InnoDB the clustered index must always be created
 | 
						|
		first */
 | 
						|
	    	if ((error = create_index(trx, form, norm_name,
 | 
						|
					  (uint) primary_key_no))) {
 | 
						|
			goto cleanup;
 | 
						|
      		}
 | 
						|
      	}
 | 
						|
 | 
						|
	for (i = 0; i < form->s->keys; i++) {
 | 
						|
 | 
						|
		if (i != (uint) primary_key_no) {
 | 
						|
 | 
						|
    			if ((error = create_index(trx, form, norm_name, i))) {
 | 
						|
				goto cleanup;
 | 
						|
      			}
 | 
						|
      		}
 | 
						|
  	}
 | 
						|
 | 
						|
	if (current_thd->query != NULL) {
 | 
						|
		LEX_STRING q;
 | 
						|
 | 
						|
		if (thd->convert_string(&q, system_charset_info,
 | 
						|
					current_thd->query,
 | 
						|
					current_thd->query_length,
 | 
						|
					current_thd->charset())) {
 | 
						|
			error = HA_ERR_OUT_OF_MEM;
 | 
						|
 | 
						|
			goto cleanup;
 | 
						|
		}
 | 
						|
 | 
						|
		error = row_table_add_foreign_constraints(trx,
 | 
						|
			q.str, norm_name,
 | 
						|
			create_info->options & HA_LEX_CREATE_TMP_TABLE);
 | 
						|
 | 
						|
		error = convert_error_code_to_mysql(error, NULL);
 | 
						|
 | 
						|
		if (error) {
 | 
						|
			goto cleanup;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
  	innobase_commit_low(trx);
 | 
						|
 | 
						|
	row_mysql_unlock_data_dictionary(trx);
 | 
						|
 | 
						|
	/* Flush the log to reduce probability that the .frm files and
 | 
						|
	the InnoDB data dictionary get out-of-sync if the user runs
 | 
						|
	with innodb_flush_log_at_trx_commit = 0 */
 | 
						|
 | 
						|
	log_buffer_flush_to_disk();
 | 
						|
 | 
						|
	innobase_table = dict_table_get(norm_name, NULL);
 | 
						|
 | 
						|
	DBUG_ASSERT(innobase_table != 0);
 | 
						|
 | 
						|
	if ((create_info->used_fields & HA_CREATE_USED_AUTO) &&
 | 
						|
	   (create_info->auto_increment_value != 0)) {
 | 
						|
 | 
						|
		/* Query was ALTER TABLE...AUTO_INCREMENT = x; or
 | 
						|
		CREATE TABLE ...AUTO_INCREMENT = x; Find out a table
 | 
						|
		definition from the dictionary and get the current value
 | 
						|
		of the auto increment field. Set a new value to the
 | 
						|
		auto increment field if the value is greater than the
 | 
						|
		maximum value in the column. */
 | 
						|
 | 
						|
		auto_inc_value = create_info->auto_increment_value;
 | 
						|
		dict_table_autoinc_initialize(innobase_table, auto_inc_value);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Tell the InnoDB server that there might be work for
 | 
						|
	utility threads: */
 | 
						|
 | 
						|
	srv_active_wake_master_thread();
 | 
						|
 | 
						|
  	trx_free_for_mysql(trx);
 | 
						|
 | 
						|
	DBUG_RETURN(0);
 | 
						|
 | 
						|
cleanup:
 | 
						|
	innobase_commit_low(trx);
 | 
						|
 | 
						|
	row_mysql_unlock_data_dictionary(trx);
 | 
						|
 | 
						|
	trx_free_for_mysql(trx);
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Discards or imports an InnoDB tablespace. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::discard_or_import_tablespace(
 | 
						|
/*======================================*/
 | 
						|
				/* out: 0 == success, -1 == error */
 | 
						|
	my_bool discard)	/* in: TRUE if discard, else import */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	dict_table_t*	dict_table;
 | 
						|
	trx_t*		trx;
 | 
						|
	int		err;
 | 
						|
 | 
						|
 	DBUG_ENTER("ha_innobase::discard_or_import_tablespace");
 | 
						|
 | 
						|
	ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
 | 
						|
	ut_a(prebuilt->trx ==
 | 
						|
                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
	dict_table = prebuilt->table;
 | 
						|
	trx = prebuilt->trx;
 | 
						|
 | 
						|
	if (discard) {
 | 
						|
		err = row_discard_tablespace_for_mysql(dict_table->name, trx);
 | 
						|
	} else {
 | 
						|
		err = row_import_tablespace_for_mysql(dict_table->name, trx);
 | 
						|
	}
 | 
						|
 | 
						|
	err = convert_error_code_to_mysql(err, NULL);
 | 
						|
 | 
						|
	DBUG_RETURN(err);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Deletes all rows of an InnoDB table. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::delete_all_rows(void)
 | 
						|
/*==============================*/
 | 
						|
				/* out: error number */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt	= (row_prebuilt_t*)innobase_prebuilt;
 | 
						|
	int		error;
 | 
						|
	trx_t*		trx;
 | 
						|
	THD*		thd		= current_thd;
 | 
						|
 | 
						|
	DBUG_ENTER("ha_innobase::delete_all_rows");
 | 
						|
 | 
						|
	if (thd->lex->sql_command != SQLCOM_TRUNCATE) {
 | 
						|
	fallback:
 | 
						|
		/* We only handle TRUNCATE TABLE t as a special case.
 | 
						|
		DELETE FROM t will have to use ha_innobase::delete_row(). */
 | 
						|
		DBUG_RETURN(my_errno=HA_ERR_WRONG_COMMAND);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Get the transaction associated with the current thd, or create one
 | 
						|
	if not yet created */
 | 
						|
 | 
						|
	trx = check_trx_exists(thd);
 | 
						|
 | 
						|
	/* Truncate the table in InnoDB */
 | 
						|
 | 
						|
	error = row_truncate_table_for_mysql(prebuilt->table, trx);
 | 
						|
	if (error == DB_ERROR) {
 | 
						|
		/* Cannot truncate; resort to ha_innobase::delete_row() */
 | 
						|
		goto fallback;
 | 
						|
	}
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, NULL);
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Drops a table from an InnoDB database. Before calling this function,
 | 
						|
MySQL calls innobase_commit to commit the transaction of the current user.
 | 
						|
Then the current user cannot have locks set on the table. Drop table
 | 
						|
operation inside InnoDB will remove all locks any user has on the table
 | 
						|
inside InnoDB. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::delete_table(
 | 
						|
/*======================*/
 | 
						|
				/* out: error number */
 | 
						|
	const char*	name)	/* in: table name */
 | 
						|
{
 | 
						|
	ulint	name_len;
 | 
						|
	int	error;
 | 
						|
	trx_t*	parent_trx;
 | 
						|
	trx_t*	trx;
 | 
						|
	THD     *thd= current_thd;
 | 
						|
	char	norm_name[1000];
 | 
						|
 | 
						|
 	DBUG_ENTER("ha_innobase::delete_table");
 | 
						|
 | 
						|
	/* Get the transaction associated with the current thd, or create one
 | 
						|
	if not yet created */
 | 
						|
 | 
						|
	parent_trx = check_trx_exists(current_thd);
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query, release
 | 
						|
	possible adaptive hash latch to avoid deadlocks of threads */
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(parent_trx);
 | 
						|
 | 
						|
	if (lower_case_table_names) {
 | 
						|
		srv_lower_case_table_names = TRUE;
 | 
						|
	} else {
 | 
						|
		srv_lower_case_table_names = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	trx = trx_allocate_for_mysql();
 | 
						|
 | 
						|
	trx->mysql_thd = current_thd;
 | 
						|
	trx->mysql_query_str = &((*current_thd).query);
 | 
						|
 | 
						|
	if (thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
 | 
						|
		trx->check_foreigns = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	if (thd->options & OPTION_RELAXED_UNIQUE_CHECKS) {
 | 
						|
		trx->check_unique_secondary = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	name_len = strlen(name);
 | 
						|
 | 
						|
	assert(name_len < 1000);
 | 
						|
 | 
						|
	/* Strangely, MySQL passes the table name without the '.frm'
 | 
						|
	extension, in contrast to ::create */
 | 
						|
 | 
						|
	normalize_table_name(norm_name, name);
 | 
						|
 | 
						|
  	/* Drop the table in InnoDB */
 | 
						|
 | 
						|
	error = row_drop_table_for_mysql(norm_name, trx,
 | 
						|
		thd->lex->sql_command == SQLCOM_DROP_DB);
 | 
						|
 | 
						|
	/* Flush the log to reduce probability that the .frm files and
 | 
						|
	the InnoDB data dictionary get out-of-sync if the user runs
 | 
						|
	with innodb_flush_log_at_trx_commit = 0 */
 | 
						|
 | 
						|
	log_buffer_flush_to_disk();
 | 
						|
 | 
						|
	/* Tell the InnoDB server that there might be work for
 | 
						|
	utility threads: */
 | 
						|
 | 
						|
	srv_active_wake_master_thread();
 | 
						|
 | 
						|
  	innobase_commit_low(trx);
 | 
						|
 | 
						|
  	trx_free_for_mysql(trx);
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, NULL);
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Removes all tables in the named database inside InnoDB. */
 | 
						|
 | 
						|
int
 | 
						|
innobase_drop_database(
 | 
						|
/*===================*/
 | 
						|
			/* out: error number */
 | 
						|
	char*	path)	/* in: database path; inside InnoDB the name
 | 
						|
			of the last directory in the path is used as
 | 
						|
			the database name: for example, in 'mysql/data/test'
 | 
						|
			the database name is 'test' */
 | 
						|
{
 | 
						|
	ulint	len		= 0;
 | 
						|
	trx_t*	parent_trx;
 | 
						|
	trx_t*	trx;
 | 
						|
	char*	ptr;
 | 
						|
	int	error;
 | 
						|
	char*	namebuf;
 | 
						|
 | 
						|
	/* Get the transaction associated with the current thd, or create one
 | 
						|
	if not yet created */
 | 
						|
 | 
						|
	parent_trx = check_trx_exists(current_thd);
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query, release
 | 
						|
	possible adaptive hash latch to avoid deadlocks of threads */
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(parent_trx);
 | 
						|
 | 
						|
	ptr = strend(path) - 2;
 | 
						|
 | 
						|
	while (ptr >= path && *ptr != '\\' && *ptr != '/') {
 | 
						|
		ptr--;
 | 
						|
		len++;
 | 
						|
	}
 | 
						|
 | 
						|
	ptr++;
 | 
						|
	namebuf = my_malloc((uint) len + 2, MYF(0));
 | 
						|
 | 
						|
	memcpy(namebuf, ptr, len);
 | 
						|
	namebuf[len] = '/';
 | 
						|
	namebuf[len + 1] = '\0';
 | 
						|
#ifdef  __WIN__
 | 
						|
	innobase_casedn_str(namebuf);
 | 
						|
#endif
 | 
						|
	trx = trx_allocate_for_mysql();
 | 
						|
	trx->mysql_thd = current_thd;
 | 
						|
	trx->mysql_query_str = &((*current_thd).query);
 | 
						|
 | 
						|
	if (current_thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
 | 
						|
		trx->check_foreigns = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
  	error = row_drop_database_for_mysql(namebuf, trx);
 | 
						|
	my_free(namebuf, MYF(0));
 | 
						|
 | 
						|
	/* Flush the log to reduce probability that the .frm files and
 | 
						|
	the InnoDB data dictionary get out-of-sync if the user runs
 | 
						|
	with innodb_flush_log_at_trx_commit = 0 */
 | 
						|
 | 
						|
	log_buffer_flush_to_disk();
 | 
						|
 | 
						|
	/* Tell the InnoDB server that there might be work for
 | 
						|
	utility threads: */
 | 
						|
 | 
						|
	srv_active_wake_master_thread();
 | 
						|
 | 
						|
  	innobase_commit_low(trx);
 | 
						|
  	trx_free_for_mysql(trx);
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, NULL);
 | 
						|
 | 
						|
	return(error);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Renames an InnoDB table. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::rename_table(
 | 
						|
/*======================*/
 | 
						|
				/* out: 0 or error code */
 | 
						|
	const char*	from,	/* in: old name of the table */
 | 
						|
	const char*	to)	/* in: new name of the table */
 | 
						|
{
 | 
						|
	ulint	name_len1;
 | 
						|
	ulint	name_len2;
 | 
						|
	int	error;
 | 
						|
	trx_t*	parent_trx;
 | 
						|
	trx_t*	trx;
 | 
						|
	char	norm_from[1000];
 | 
						|
	char	norm_to[1000];
 | 
						|
 | 
						|
  	DBUG_ENTER("ha_innobase::rename_table");
 | 
						|
 | 
						|
	/* Get the transaction associated with the current thd, or create one
 | 
						|
	if not yet created */
 | 
						|
 | 
						|
	parent_trx = check_trx_exists(current_thd);
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query, release
 | 
						|
	possible adaptive hash latch to avoid deadlocks of threads */
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(parent_trx);
 | 
						|
 | 
						|
	if (lower_case_table_names) {
 | 
						|
		srv_lower_case_table_names = TRUE;
 | 
						|
	} else {
 | 
						|
		srv_lower_case_table_names = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	trx = trx_allocate_for_mysql();
 | 
						|
	trx->mysql_thd = current_thd;
 | 
						|
	trx->mysql_query_str = &((*current_thd).query);
 | 
						|
 | 
						|
	if (current_thd->options & OPTION_NO_FOREIGN_KEY_CHECKS) {
 | 
						|
		trx->check_foreigns = FALSE;
 | 
						|
	}
 | 
						|
 | 
						|
	name_len1 = strlen(from);
 | 
						|
	name_len2 = strlen(to);
 | 
						|
 | 
						|
	assert(name_len1 < 1000);
 | 
						|
	assert(name_len2 < 1000);
 | 
						|
 | 
						|
	normalize_table_name(norm_from, from);
 | 
						|
	normalize_table_name(norm_to, to);
 | 
						|
 | 
						|
  	/* Rename the table in InnoDB */
 | 
						|
 | 
						|
  	error = row_rename_table_for_mysql(norm_from, norm_to, trx);
 | 
						|
 | 
						|
	/* Flush the log to reduce probability that the .frm files and
 | 
						|
	the InnoDB data dictionary get out-of-sync if the user runs
 | 
						|
	with innodb_flush_log_at_trx_commit = 0 */
 | 
						|
 | 
						|
	log_buffer_flush_to_disk();
 | 
						|
 | 
						|
	/* Tell the InnoDB server that there might be work for
 | 
						|
	utility threads: */
 | 
						|
 | 
						|
	srv_active_wake_master_thread();
 | 
						|
 | 
						|
  	innobase_commit_low(trx);
 | 
						|
  	trx_free_for_mysql(trx);
 | 
						|
 | 
						|
	error = convert_error_code_to_mysql(error, NULL);
 | 
						|
 | 
						|
	DBUG_RETURN(error);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Estimates the number of index records in a range. */
 | 
						|
 | 
						|
ha_rows
 | 
						|
ha_innobase::records_in_range(
 | 
						|
/*==========================*/
 | 
						|
						/* out: estimated number of
 | 
						|
						rows */
 | 
						|
	uint 			keynr,		/* in: index number */
 | 
						|
        key_range		*min_key,	/* in: start key value of the
 | 
						|
                                                   range, may also be 0 */
 | 
						|
	key_range		*max_key)	/* in: range end key val, may
 | 
						|
                                                   also be 0 */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	KEY*		key;
 | 
						|
	dict_index_t*	index;
 | 
						|
	mysql_byte*	key_val_buff2 	= (mysql_byte*) my_malloc(
 | 
						|
						  table->s->reclength
 | 
						|
      					+ table->s->max_key_length + 100,
 | 
						|
								MYF(MY_FAE));
 | 
						|
	ulint		buff2_len = table->s->reclength
 | 
						|
      					+ table->s->max_key_length + 100;
 | 
						|
	dtuple_t*	range_start;
 | 
						|
	dtuple_t*	range_end;
 | 
						|
	ib_longlong	n_rows;
 | 
						|
	ulint		mode1;
 | 
						|
	ulint		mode2;
 | 
						|
	void*           heap1;
 | 
						|
	void*           heap2;
 | 
						|
 | 
						|
   	DBUG_ENTER("records_in_range");
 | 
						|
 | 
						|
	prebuilt->trx->op_info = (char*)"estimating records in index range";
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query, release
 | 
						|
	possible adaptive hash latch to avoid deadlocks of threads */
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(prebuilt->trx);
 | 
						|
 | 
						|
	active_index = keynr;
 | 
						|
 | 
						|
	key = table->key_info + active_index;
 | 
						|
 | 
						|
	index = dict_table_get_index_noninline(prebuilt->table, key->name);
 | 
						|
 | 
						|
	range_start = dtuple_create_for_mysql(&heap1, key->key_parts);
 | 
						|
 	dict_index_copy_types(range_start, index, key->key_parts);
 | 
						|
 | 
						|
	range_end = dtuple_create_for_mysql(&heap2, key->key_parts);
 | 
						|
 	dict_index_copy_types(range_end, index, key->key_parts);
 | 
						|
 | 
						|
	row_sel_convert_mysql_key_to_innobase(
 | 
						|
				range_start, (byte*) key_val_buff,
 | 
						|
				(ulint)upd_and_key_val_buff_len,
 | 
						|
				index,
 | 
						|
				(byte*) (min_key ? min_key->key :
 | 
						|
                                         (const mysql_byte*) 0),
 | 
						|
				(ulint) (min_key ? min_key->length : 0),
 | 
						|
				prebuilt->trx);
 | 
						|
 | 
						|
	row_sel_convert_mysql_key_to_innobase(
 | 
						|
				range_end, (byte*) key_val_buff2,
 | 
						|
				buff2_len, index,
 | 
						|
				(byte*) (max_key ? max_key->key :
 | 
						|
                                         (const mysql_byte*) 0),
 | 
						|
				(ulint) (max_key ? max_key->length : 0),
 | 
						|
				prebuilt->trx);
 | 
						|
 | 
						|
	mode1 = convert_search_mode_to_innobase(min_key ? min_key->flag :
 | 
						|
                                                HA_READ_KEY_EXACT);
 | 
						|
	mode2 = convert_search_mode_to_innobase(max_key ? max_key->flag :
 | 
						|
                                                HA_READ_KEY_EXACT);
 | 
						|
 | 
						|
	n_rows = btr_estimate_n_rows_in_range(index, range_start,
 | 
						|
						mode1, range_end, mode2);
 | 
						|
	dtuple_free_for_mysql(heap1);
 | 
						|
	dtuple_free_for_mysql(heap2);
 | 
						|
 | 
						|
    	my_free((gptr) key_val_buff2, MYF(0));
 | 
						|
 | 
						|
	prebuilt->trx->op_info = (char*)"";
 | 
						|
 | 
						|
	/* The MySQL optimizer seems to believe an estimate of 0 rows is
 | 
						|
	always accurate and may return the result 'Empty set' based on that.
 | 
						|
	The accuracy is not guaranteed, and even if it were, for a locking
 | 
						|
	read we should anyway perform the search to set the next-key lock.
 | 
						|
	Add 1 to the value to make sure MySQL does not make the assumption! */
 | 
						|
 | 
						|
	if (n_rows == 0) {
 | 
						|
	        n_rows = 1;
 | 
						|
	}
 | 
						|
 | 
						|
	DBUG_RETURN((ha_rows) n_rows);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Gives an UPPER BOUND to the number of rows in a table. This is used in
 | 
						|
filesort.cc. */
 | 
						|
 | 
						|
ha_rows
 | 
						|
ha_innobase::estimate_rows_upper_bound(void)
 | 
						|
/*======================================*/
 | 
						|
			/* out: upper bound of rows */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	dict_index_t*	index;
 | 
						|
	ulonglong	estimate;
 | 
						|
	ulonglong	local_data_file_length;
 | 
						|
 | 
						|
 	DBUG_ENTER("estimate_rows_upper_bound");
 | 
						|
 | 
						|
	/* We do not know if MySQL can call this function before calling
 | 
						|
	external_lock(). To be safe, update the thd of the current table
 | 
						|
	handle. */
 | 
						|
 | 
						|
	update_thd(current_thd);
 | 
						|
 | 
						|
	prebuilt->trx->op_info = (char*)
 | 
						|
	                         "calculating upper bound for table rows";
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query, release
 | 
						|
	possible adaptive hash latch to avoid deadlocks of threads */
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(prebuilt->trx);
 | 
						|
 | 
						|
	index = dict_table_get_first_index_noninline(prebuilt->table);
 | 
						|
 | 
						|
	local_data_file_length = ((ulonglong) index->stat_n_leaf_pages)
 | 
						|
    							* UNIV_PAGE_SIZE;
 | 
						|
 | 
						|
	/* Calculate a minimum length for a clustered index record and from
 | 
						|
	that an upper bound for the number of rows. Since we only calculate
 | 
						|
	new statistics in row0mysql.c when a table has grown by a threshold
 | 
						|
	factor, we must add a safety factor 2 in front of the formula below. */
 | 
						|
 | 
						|
	estimate = 2 * local_data_file_length /
 | 
						|
					 dict_index_calc_min_rec_len(index);
 | 
						|
 | 
						|
	prebuilt->trx->op_info = (char*)"";
 | 
						|
 | 
						|
	DBUG_RETURN((ha_rows) estimate);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
How many seeks it will take to read through the table. This is to be
 | 
						|
comparable to the number returned by records_in_range so that we can
 | 
						|
decide if we should scan the table or use keys. */
 | 
						|
 | 
						|
double
 | 
						|
ha_innobase::scan_time()
 | 
						|
/*====================*/
 | 
						|
			/* out: estimated time measured in disk seeks */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
 | 
						|
	/* Since MySQL seems to favor table scans too much over index
 | 
						|
	searches, we pretend that a sequential read takes the same time
 | 
						|
	as a random disk read, that is, we do not divide the following
 | 
						|
	by 10, which would be physically realistic. */
 | 
						|
 | 
						|
	return((double) (prebuilt->table->stat_clustered_index_size));
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Calculate the time it takes to read a set of ranges through an index
 | 
						|
This enables us to optimise reads for clustered indexes. */
 | 
						|
 | 
						|
double
 | 
						|
ha_innobase::read_time(
 | 
						|
/*===================*/
 | 
						|
			/* out: estimated time measured in disk seeks */
 | 
						|
	uint    index,	/* in: key number */
 | 
						|
	uint	ranges,	/* in: how many ranges */
 | 
						|
	ha_rows rows)	/* in: estimated number of rows in the ranges */
 | 
						|
{
 | 
						|
	ha_rows total_rows;
 | 
						|
	double  time_for_scan;
 | 
						|
 | 
						|
	if (index != table->s->primary_key) {
 | 
						|
		/* Not clustered */
 | 
						|
	  	return(handler::read_time(index, ranges, rows));
 | 
						|
	}
 | 
						|
 | 
						|
	if (rows <= 2) {
 | 
						|
 | 
						|
		return((double) rows);
 | 
						|
	}
 | 
						|
 | 
						|
	/* Assume that the read time is proportional to the scan time for all
 | 
						|
	rows + at most one seek per range. */
 | 
						|
 | 
						|
	time_for_scan = scan_time();
 | 
						|
 | 
						|
	if ((total_rows = estimate_rows_upper_bound()) < rows) {
 | 
						|
 | 
						|
	  	return(time_for_scan);
 | 
						|
	}
 | 
						|
 | 
						|
	return(ranges + (double) rows / (double) total_rows * time_for_scan);
 | 
						|
}
 | 
						|
 | 
						|
/*************************************************************************
 | 
						|
Returns statistics information of the table to the MySQL interpreter,
 | 
						|
in various fields of the handle object. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::info(
 | 
						|
/*==============*/
 | 
						|
	uint flag)	/* in: what information MySQL requests */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	dict_table_t*	ib_table;
 | 
						|
	dict_index_t*	index;
 | 
						|
	ha_rows		rec_per_key;
 | 
						|
	ib_longlong	n_rows;
 | 
						|
	ulong		j;
 | 
						|
	ulong		i;
 | 
						|
	char		path[FN_REFLEN];
 | 
						|
	os_file_stat_t  stat_info;
 | 
						|
 | 
						|
 	DBUG_ENTER("info");
 | 
						|
 | 
						|
        /* If we are forcing recovery at a high level, we will suppress
 | 
						|
	statistics calculation on tables, because that may crash the
 | 
						|
	server if an index is badly corrupted. */
 | 
						|
 | 
						|
        if (srv_force_recovery >= SRV_FORCE_NO_IBUF_MERGE) {
 | 
						|
 | 
						|
                DBUG_RETURN(HA_ERR_CRASHED);
 | 
						|
        }
 | 
						|
 | 
						|
	/* We do not know if MySQL can call this function before calling
 | 
						|
	external_lock(). To be safe, update the thd of the current table
 | 
						|
	handle. */
 | 
						|
 | 
						|
	update_thd(current_thd);
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query, release
 | 
						|
	possible adaptive hash latch to avoid deadlocks of threads */
 | 
						|
 | 
						|
	prebuilt->trx->op_info = (char*)"returning various info to MySQL";
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(prebuilt->trx);
 | 
						|
 | 
						|
 	ib_table = prebuilt->table;
 | 
						|
 | 
						|
 	if (flag & HA_STATUS_TIME) {
 | 
						|
 		/* In sql_show we call with this flag: update then statistics
 | 
						|
 		so that they are up-to-date */
 | 
						|
 | 
						|
	        prebuilt->trx->op_info = (char*)"updating table statistics";
 | 
						|
 | 
						|
 		dict_update_statistics(ib_table);
 | 
						|
 | 
						|
		prebuilt->trx->op_info = (char*)
 | 
						|
		                          "returning various info to MySQL";
 | 
						|
		my_snprintf(path, sizeof(path), "%s/%s%s",
 | 
						|
				    mysql_data_home, ib_table->name,
 | 
						|
				    reg_ext);
 | 
						|
 | 
						|
		unpack_filename(path,path);
 | 
						|
 | 
						|
		/* Note that we do not know the access time of the table,
 | 
						|
		nor the CHECK TABLE time, nor the UPDATE or INSERT time. */
 | 
						|
 | 
						|
		if (os_file_get_status(path,&stat_info)) {
 | 
						|
			create_time = stat_info.ctime;
 | 
						|
		}
 | 
						|
 	}
 | 
						|
 | 
						|
	if (flag & HA_STATUS_VARIABLE) {
 | 
						|
		n_rows = ib_table->stat_n_rows;
 | 
						|
 | 
						|
		/* Because we do not protect stat_n_rows by any mutex in a
 | 
						|
		delete, it is theoretically possible that the value can be
 | 
						|
		smaller than zero! TODO: fix this race.
 | 
						|
 | 
						|
		The MySQL optimizer seems to assume in a left join that n_rows
 | 
						|
		is an accurate estimate if it is zero. Of course, it is not,
 | 
						|
		since we do not have any locks on the rows yet at this phase.
 | 
						|
		Since SHOW TABLE STATUS seems to call this function with the
 | 
						|
		HA_STATUS_TIME flag set, while the left join optimizer does not
 | 
						|
		set that flag, we add one to a zero value if the flag is not
 | 
						|
		set. That way SHOW TABLE STATUS will show the best estimate,
 | 
						|
		while the optimizer never sees the table empty. */
 | 
						|
 | 
						|
		if (n_rows < 0) {
 | 
						|
			n_rows = 0;
 | 
						|
		}
 | 
						|
 | 
						|
		if (n_rows == 0 && !(flag & HA_STATUS_TIME)) {
 | 
						|
			n_rows++;
 | 
						|
		}
 | 
						|
 | 
						|
    		records = (ha_rows)n_rows;
 | 
						|
    		deleted = 0;
 | 
						|
    		data_file_length = ((ulonglong)
 | 
						|
				ib_table->stat_clustered_index_size)
 | 
						|
    					* UNIV_PAGE_SIZE;
 | 
						|
    		index_file_length = ((ulonglong)
 | 
						|
				ib_table->stat_sum_of_other_index_sizes)
 | 
						|
    					* UNIV_PAGE_SIZE;
 | 
						|
    		delete_length = 0;
 | 
						|
    		check_time = 0;
 | 
						|
 | 
						|
    		if (records == 0) {
 | 
						|
    			mean_rec_length = 0;
 | 
						|
    		} else {
 | 
						|
    			mean_rec_length = (ulong) (data_file_length / records);
 | 
						|
    		}
 | 
						|
    	}
 | 
						|
 | 
						|
	if (flag & HA_STATUS_CONST) {
 | 
						|
		index = dict_table_get_first_index_noninline(ib_table);
 | 
						|
 | 
						|
		if (prebuilt->clust_index_was_generated) {
 | 
						|
			index = dict_table_get_next_index_noninline(index);
 | 
						|
		}
 | 
						|
 | 
						|
		for (i = 0; i < table->s->keys; i++) {
 | 
						|
			if (index == NULL) {
 | 
						|
				ut_print_timestamp(stderr);
 | 
						|
				sql_print_error("Table %s contains fewer "
 | 
						|
						"indexes inside InnoDB than "
 | 
						|
						"are defined in the MySQL "
 | 
						|
						".frm file. Have you mixed up "
 | 
						|
						".frm files from different "
 | 
						|
						"installations? See "
 | 
						|
"http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n",
 | 
						|
 | 
						|
						ib_table->name);
 | 
						|
				break;
 | 
						|
			}
 | 
						|
 | 
						|
			for (j = 0; j < table->key_info[i].key_parts; j++) {
 | 
						|
 | 
						|
				if (j + 1 > index->n_uniq) {
 | 
						|
				        ut_print_timestamp(stderr);
 | 
						|
					sql_print_error(
 | 
						|
"Index %s of %s has %lu columns unique inside InnoDB, but MySQL is asking "
 | 
						|
"statistics for %lu columns. Have you mixed up .frm files from different "
 | 
						|
"installations? "
 | 
						|
"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n",
 | 
						|
							index->name,
 | 
						|
							ib_table->name,
 | 
						|
							(unsigned long)
 | 
						|
							index->n_uniq, j + 1);
 | 
						|
				        break;
 | 
						|
				}
 | 
						|
 | 
						|
				if (index->stat_n_diff_key_vals[j + 1] == 0) {
 | 
						|
 | 
						|
					rec_per_key = records;
 | 
						|
				} else {
 | 
						|
					rec_per_key = (ha_rows)(records /
 | 
						|
   				         index->stat_n_diff_key_vals[j + 1]);
 | 
						|
				}
 | 
						|
 | 
						|
				/* Since MySQL seems to favor table scans
 | 
						|
				too much over index searches, we pretend
 | 
						|
				index selectivity is 2 times better than
 | 
						|
				our estimate: */
 | 
						|
 | 
						|
				rec_per_key = rec_per_key / 2;
 | 
						|
 | 
						|
				if (rec_per_key == 0) {
 | 
						|
					rec_per_key = 1;
 | 
						|
				}
 | 
						|
 | 
						|
 				table->key_info[i].rec_per_key[j]=
 | 
						|
				  rec_per_key >= ~(ulong) 0 ? ~(ulong) 0 :
 | 
						|
				  rec_per_key;
 | 
						|
			}
 | 
						|
 | 
						|
			index = dict_table_get_next_index_noninline(index);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
  	if (flag & HA_STATUS_ERRKEY) {
 | 
						|
		ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
 | 
						|
 | 
						|
		errkey = (unsigned int) row_get_mysql_key_number_for_index(
 | 
						|
				       (dict_index_t*)
 | 
						|
				       trx_get_error_info(prebuilt->trx));
 | 
						|
  	}
 | 
						|
 | 
						|
	if (flag & HA_STATUS_AUTO && table->found_next_number_field) {
 | 
						|
		longlong	auto_inc;
 | 
						|
		int		ret;
 | 
						|
 | 
						|
		/* The following function call can the first time fail in
 | 
						|
		a lock wait timeout error because it reserves the auto-inc
 | 
						|
		lock on the table. If it fails, then someone is already initing
 | 
						|
		the auto-inc counter, and the second call is guaranteed to
 | 
						|
		succeed. */
 | 
						|
 | 
						|
		ret = innobase_read_and_init_auto_inc(&auto_inc);
 | 
						|
 | 
						|
		if (ret != 0) {
 | 
						|
			ret = innobase_read_and_init_auto_inc(&auto_inc);
 | 
						|
 | 
						|
			if (ret != 0) {
 | 
						|
				ut_print_timestamp(stderr);
 | 
						|
				sql_print_error("Cannot get table %s auto-inc"
 | 
						|
						"counter value in ::info\n",
 | 
						|
						ib_table->name);
 | 
						|
				auto_inc = 0;
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		auto_increment_value = auto_inc;
 | 
						|
	}
 | 
						|
 | 
						|
	prebuilt->trx->op_info = (char*)"";
 | 
						|
 | 
						|
  	DBUG_RETURN(0);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
Updates index cardinalities of the table, based on 8 random dives into
 | 
						|
each index tree. This does NOT calculate exact statistics on the table. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::analyze(
 | 
						|
/*=================*/
 | 
						|
					/* out: returns always 0 (success) */
 | 
						|
	THD*		thd,		/* in: connection thread handle */
 | 
						|
	HA_CHECK_OPT*	check_opt)	/* in: currently ignored */
 | 
						|
{
 | 
						|
	/* Simply call ::info() with all the flags */
 | 
						|
	info(HA_STATUS_TIME | HA_STATUS_CONST | HA_STATUS_VARIABLE);
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/**************************************************************************
 | 
						|
This is mapped to "ALTER TABLE tablename TYPE=InnoDB", which rebuilds
 | 
						|
the table in MySQL. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::optimize(
 | 
						|
/*==================*/
 | 
						|
	THD*		thd,		/* in: connection thread handle */
 | 
						|
	HA_CHECK_OPT*	check_opt)	/* in: currently ignored */
 | 
						|
{
 | 
						|
        return(HA_ADMIN_TRY_ALTER);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Tries to check that an InnoDB table is not corrupted. If corruption is
 | 
						|
noticed, prints to stderr information about it. In case of corruption
 | 
						|
may also assert a failure and crash the server. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::check(
 | 
						|
/*===============*/
 | 
						|
					/* out: HA_ADMIN_CORRUPT or
 | 
						|
					HA_ADMIN_OK */
 | 
						|
	THD* 		thd,		/* in: user thread handle */
 | 
						|
	HA_CHECK_OPT* 	check_opt)	/* in: check options, currently
 | 
						|
					ignored */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	ulint		ret;
 | 
						|
 | 
						|
	ut_a(prebuilt->trx && prebuilt->trx->magic_n == TRX_MAGIC_N);
 | 
						|
	ut_a(prebuilt->trx ==
 | 
						|
                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
 | 
						|
	if (prebuilt->mysql_template == NULL) {
 | 
						|
		/* Build the template; we will use a dummy template
 | 
						|
		in index scans done in checking */
 | 
						|
 | 
						|
		build_template(prebuilt, NULL, table, ROW_MYSQL_WHOLE_ROW);
 | 
						|
	}
 | 
						|
 | 
						|
	ret = row_check_table_for_mysql(prebuilt);
 | 
						|
 | 
						|
	if (ret == DB_SUCCESS) {
 | 
						|
		return(HA_ADMIN_OK);
 | 
						|
	}
 | 
						|
 | 
						|
  	return(HA_ADMIN_CORRUPT);
 | 
						|
}
 | 
						|
 | 
						|
/*****************************************************************
 | 
						|
Adds information about free space in the InnoDB tablespace to a table comment
 | 
						|
which is printed out when a user calls SHOW TABLE STATUS. Adds also info on
 | 
						|
foreign keys. */
 | 
						|
 | 
						|
char*
 | 
						|
ha_innobase::update_table_comment(
 | 
						|
/*==============================*/
 | 
						|
				/* out: table comment + InnoDB free space +
 | 
						|
				info on foreign keys */
 | 
						|
        const char*	comment)/* in: table comment defined by user */
 | 
						|
{
 | 
						|
	uint	length			= (uint) strlen(comment);
 | 
						|
	char*				str;
 | 
						|
	row_prebuilt_t*	prebuilt	= (row_prebuilt_t*)innobase_prebuilt;
 | 
						|
	long	flen;
 | 
						|
 | 
						|
	/* We do not know if MySQL can call this function before calling
 | 
						|
	external_lock(). To be safe, update the thd of the current table
 | 
						|
	handle. */
 | 
						|
 | 
						|
	if (length > 64000 - 3) {
 | 
						|
		return((char*)comment); /* string too long */
 | 
						|
	}
 | 
						|
 | 
						|
	update_thd(current_thd);
 | 
						|
 | 
						|
	prebuilt->trx->op_info = (char*)"returning table comment";
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query, release
 | 
						|
	possible adaptive hash latch to avoid deadlocks of threads */
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(prebuilt->trx);
 | 
						|
	str = NULL;
 | 
						|
 | 
						|
	/* output the data to a temporary file */
 | 
						|
 | 
						|
	mutex_enter_noninline(&srv_dict_tmpfile_mutex);
 | 
						|
	rewind(srv_dict_tmpfile);
 | 
						|
 | 
						|
	fprintf(srv_dict_tmpfile, "InnoDB free: %lu kB",
 | 
						|
      		   (ulong) fsp_get_available_space_in_free_extents(
 | 
						|
      					prebuilt->table->space));
 | 
						|
 | 
						|
	dict_print_info_on_foreign_keys(FALSE, srv_dict_tmpfile,
 | 
						|
				prebuilt->trx, prebuilt->table);
 | 
						|
	flen = ftell(srv_dict_tmpfile);
 | 
						|
	if (flen < 0) {
 | 
						|
		flen = 0;
 | 
						|
	} else if (length + flen + 3 > 64000) {
 | 
						|
		flen = 64000 - 3 - length;
 | 
						|
	}
 | 
						|
 | 
						|
	/* allocate buffer for the full string, and
 | 
						|
	read the contents of the temporary file */
 | 
						|
 | 
						|
	str = my_malloc(length + flen + 3, MYF(0));
 | 
						|
 | 
						|
	if (str) {
 | 
						|
		char* pos	= str + length;
 | 
						|
		if (length) {
 | 
						|
			memcpy(str, comment, length);
 | 
						|
			*pos++ = ';';
 | 
						|
			*pos++ = ' ';
 | 
						|
		}
 | 
						|
		rewind(srv_dict_tmpfile);
 | 
						|
		flen = (uint) fread(pos, 1, flen, srv_dict_tmpfile);
 | 
						|
		pos[flen] = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
 | 
						|
 | 
						|
        prebuilt->trx->op_info = (char*)"";
 | 
						|
 | 
						|
  	return(str ? str : (char*) comment);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Gets the foreign key create info for a table stored in InnoDB. */
 | 
						|
 | 
						|
char*
 | 
						|
ha_innobase::get_foreign_key_create_info(void)
 | 
						|
/*==========================================*/
 | 
						|
			/* out, own: character string in the form which
 | 
						|
			can be inserted to the CREATE TABLE statement,
 | 
						|
			MUST be freed with ::free_foreign_key_create_info */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
 | 
						|
	char*	str	= 0;
 | 
						|
	long	flen;
 | 
						|
 | 
						|
	ut_a(prebuilt != NULL);
 | 
						|
 | 
						|
	/* We do not know if MySQL can call this function before calling
 | 
						|
	external_lock(). To be safe, update the thd of the current table
 | 
						|
	handle. */
 | 
						|
 | 
						|
	update_thd(current_thd);
 | 
						|
 | 
						|
	prebuilt->trx->op_info = (char*)"getting info on foreign keys";
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query,
 | 
						|
	release possible adaptive hash latch to avoid
 | 
						|
	deadlocks of threads */
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(prebuilt->trx);
 | 
						|
 | 
						|
	mutex_enter_noninline(&srv_dict_tmpfile_mutex);
 | 
						|
	rewind(srv_dict_tmpfile);
 | 
						|
 | 
						|
	/* output the data to a temporary file */
 | 
						|
	dict_print_info_on_foreign_keys(TRUE, srv_dict_tmpfile,
 | 
						|
				prebuilt->trx, prebuilt->table);
 | 
						|
	prebuilt->trx->op_info = (char*)"";
 | 
						|
 | 
						|
	flen = ftell(srv_dict_tmpfile);
 | 
						|
	if (flen < 0) {
 | 
						|
		flen = 0;
 | 
						|
	} else if (flen > 64000 - 1) {
 | 
						|
		flen = 64000 - 1;
 | 
						|
	}
 | 
						|
 | 
						|
	/* allocate buffer for the string, and
 | 
						|
	read the contents of the temporary file */
 | 
						|
 | 
						|
	str = my_malloc(flen + 1, MYF(0));
 | 
						|
 | 
						|
	if (str) {
 | 
						|
		rewind(srv_dict_tmpfile);
 | 
						|
		flen = (uint) fread(str, 1, flen, srv_dict_tmpfile);
 | 
						|
		str[flen] = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	mutex_exit_noninline(&srv_dict_tmpfile_mutex);
 | 
						|
 | 
						|
  	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, 0, tmp_buff,
 | 
						|
                                          (uint) 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, 0,
 | 
						|
                                              tmp_buff, i, 1);
 | 
						|
    tmp_buff+= i + 1;
 | 
						|
    f_key_info.referenced_table= make_lex_string(thd, 0, tmp_buff,
 | 
						|
                                               (uint) strlen(tmp_buff), 1);
 | 
						|
 | 
						|
    for (i= 0;;)
 | 
						|
    {
 | 
						|
      tmp_buff= foreign->foreign_col_names[i];
 | 
						|
      name= make_lex_string(thd, name, tmp_buff, (uint) 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, (uint) 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 ALTER TABLE may change the storage engine of the table.
 | 
						|
Changing storage engines is not allowed for tables for which there
 | 
						|
are foreign key constraints (parent or child tables). */
 | 
						|
 | 
						|
bool
 | 
						|
ha_innobase::can_switch_engines(void)
 | 
						|
/*=================================*/
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	bool	can_switch;
 | 
						|
 | 
						|
 	DBUG_ENTER("ha_innobase::can_switch_engines");
 | 
						|
	prebuilt->trx->op_info =
 | 
						|
			"determining if there are foreign key constraints";
 | 
						|
	row_mysql_lock_data_dictionary(prebuilt->trx);
 | 
						|
 | 
						|
	can_switch = !UT_LIST_GET_FIRST(prebuilt->table->referenced_list)
 | 
						|
			&& !UT_LIST_GET_FIRST(prebuilt->table->foreign_list);
 | 
						|
 | 
						|
	row_mysql_unlock_data_dictionary(prebuilt->trx);
 | 
						|
	prebuilt->trx->op_info = "";
 | 
						|
 | 
						|
	DBUG_RETURN(can_switch);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
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
 | 
						|
delete is then allowed internally to resolve a duplicate key conflict in
 | 
						|
REPLACE, not an update. */
 | 
						|
 | 
						|
uint
 | 
						|
ha_innobase::referenced_by_foreign_key(void)
 | 
						|
/*========================================*/
 | 
						|
			/* out: > 0 if referenced by a FOREIGN KEY */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt = (row_prebuilt_t*)innobase_prebuilt;
 | 
						|
 | 
						|
	if (dict_table_referenced_by_foreign_key(prebuilt->table)) {
 | 
						|
 | 
						|
		return(1);
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Frees the foreign key create info for a table stored in InnoDB, if it is
 | 
						|
non-NULL. */
 | 
						|
 | 
						|
void
 | 
						|
ha_innobase::free_foreign_key_create_info(
 | 
						|
/*======================================*/
 | 
						|
	char*	str)	/* in, own: create info string to free  */
 | 
						|
{
 | 
						|
	if (str) {
 | 
						|
		my_free(str, MYF(0));
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Tells something additional to the handler about how to do things. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::extra(
 | 
						|
/*===============*/
 | 
						|
			   /* out: 0 or error number */
 | 
						|
	enum ha_extra_function operation)
 | 
						|
                           /* in: HA_EXTRA_RETRIEVE_ALL_COLS or some
 | 
						|
			   other flag */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
 | 
						|
	/* Warning: since it is not sure that MySQL calls external_lock
 | 
						|
	before calling this function, the trx field in prebuilt can be
 | 
						|
	obsolete! */
 | 
						|
 | 
						|
	switch (operation) {
 | 
						|
                case HA_EXTRA_FLUSH:
 | 
						|
                        if (prebuilt->blob_heap) {
 | 
						|
                                row_mysql_prebuilt_free_blob_heap(prebuilt);
 | 
						|
                        }
 | 
						|
                        break;
 | 
						|
                case HA_EXTRA_RESET:
 | 
						|
                        if (prebuilt->blob_heap) {
 | 
						|
                                row_mysql_prebuilt_free_blob_heap(prebuilt);
 | 
						|
                        }
 | 
						|
                        prebuilt->keep_other_fields_on_keyread = 0;
 | 
						|
                        prebuilt->read_just_key = 0;
 | 
						|
                        break;
 | 
						|
  		case HA_EXTRA_RESET_STATE:
 | 
						|
	        	prebuilt->keep_other_fields_on_keyread = 0;
 | 
						|
	        	prebuilt->read_just_key = 0;
 | 
						|
    	        	break;
 | 
						|
		case HA_EXTRA_NO_KEYREAD:
 | 
						|
    			prebuilt->read_just_key = 0;
 | 
						|
    			break;
 | 
						|
	        case HA_EXTRA_RETRIEVE_ALL_COLS:
 | 
						|
			prebuilt->hint_need_to_fetch_extra_cols
 | 
						|
					= ROW_RETRIEVE_ALL_COLS;
 | 
						|
			break;
 | 
						|
	        case HA_EXTRA_RETRIEVE_PRIMARY_KEY:
 | 
						|
			if (prebuilt->hint_need_to_fetch_extra_cols == 0) {
 | 
						|
				prebuilt->hint_need_to_fetch_extra_cols
 | 
						|
					= ROW_RETRIEVE_PRIMARY_KEY;
 | 
						|
			}
 | 
						|
			break;
 | 
						|
	        case HA_EXTRA_KEYREAD:
 | 
						|
	        	prebuilt->read_just_key = 1;
 | 
						|
	        	break;
 | 
						|
		case HA_EXTRA_KEYREAD_PRESERVE_FIELDS:
 | 
						|
			prebuilt->keep_other_fields_on_keyread = 1;
 | 
						|
			break;
 | 
						|
		default:/* Do nothing */
 | 
						|
			;
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
MySQL calls this function at the start of each SQL statement inside LOCK
 | 
						|
TABLES. Inside LOCK TABLES the ::external_lock method does not work to
 | 
						|
mark SQL statement borders. Note also a special case: if a temporary table
 | 
						|
is created inside LOCK TABLES, MySQL has not called external_lock() at all
 | 
						|
on that table.
 | 
						|
MySQL-5.0 also calls this before each statement in an execution of a stored
 | 
						|
procedure. To make the execution more deterministic for binlogging, MySQL-5.0
 | 
						|
locks all tables involved in a stored procedure with full explicit table
 | 
						|
locks (thd->in_lock_tables is true in ::store_lock()) before executing the
 | 
						|
procedure. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::start_stmt(
 | 
						|
/*====================*/
 | 
						|
	              /* out: 0 or error code */
 | 
						|
	THD*    thd,  /* in: handle to the user thread */
 | 
						|
        thr_lock_type lock_type)
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	trx_t*		trx;
 | 
						|
 | 
						|
	update_thd(thd);
 | 
						|
 | 
						|
	trx = prebuilt->trx;
 | 
						|
 | 
						|
	/* Here we release the search latch and the InnoDB thread FIFO ticket
 | 
						|
	if they were reserved. They should have been released already at the
 | 
						|
	end of the previous statement, but because inside LOCK TABLES the
 | 
						|
	lock count method does not work to mark the end of a SELECT statement,
 | 
						|
	that may not be the case. We MUST release the search latch before an
 | 
						|
	INSERT, for example. */
 | 
						|
 | 
						|
	innobase_release_stat_resources(trx);
 | 
						|
 | 
						|
	prebuilt->sql_stat_start = TRUE;
 | 
						|
	prebuilt->hint_need_to_fetch_extra_cols = 0;
 | 
						|
	prebuilt->read_just_key = 0;
 | 
						|
        prebuilt->keep_other_fields_on_keyread = FALSE;
 | 
						|
 | 
						|
	if (!prebuilt->mysql_has_locked) {
 | 
						|
	        /* This handle is for a temporary table created inside
 | 
						|
	        this same LOCK TABLES; since MySQL does NOT call external_lock
 | 
						|
	        in this case, we must use x-row locks inside InnoDB to be
 | 
						|
	        prepared for an update of a row */
 | 
						|
 | 
						|
	        prebuilt->select_lock_type = LOCK_X;
 | 
						|
	} else {
 | 
						|
		if (trx->isolation_level != TRX_ISO_SERIALIZABLE
 | 
						|
		    && thd->lex->sql_command == SQLCOM_SELECT
 | 
						|
		    && lock_type == TL_READ) {
 | 
						|
 | 
						|
			/* For other than temporary tables, we obtain
 | 
						|
			no lock for consistent read (plain SELECT). */
 | 
						|
 | 
						|
			prebuilt->select_lock_type = LOCK_NONE;
 | 
						|
		} else {
 | 
						|
			/* Not a consistent read: restore the
 | 
						|
			select_lock_type value. The value of
 | 
						|
			stored_select_lock_type was decided in:
 | 
						|
			1) ::store_lock(),
 | 
						|
			2) ::external_lock(),
 | 
						|
			3) ::init_table_handle_for_HANDLER(), and
 | 
						|
			4) :.transactional_table_lock(). */
 | 
						|
 | 
						|
			prebuilt->select_lock_type =
 | 
						|
				prebuilt->stored_select_lock_type;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	trx->detailed_error[0] = '\0';
 | 
						|
 | 
						|
	/* Set the MySQL flag to mark that there is an active transaction */
 | 
						|
        if (trx->active_trans == 0) {
 | 
						|
 | 
						|
                innobase_register_trx_and_stmt(thd);
 | 
						|
                trx->active_trans = 1;
 | 
						|
        } else {
 | 
						|
		innobase_register_stmt(thd);
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
Maps a MySQL trx isolation level code to the InnoDB isolation level code */
 | 
						|
inline
 | 
						|
ulint
 | 
						|
innobase_map_isolation_level(
 | 
						|
/*=========================*/
 | 
						|
					/* out: InnoDB isolation level */
 | 
						|
	enum_tx_isolation	iso)	/* in: MySQL isolation level code */
 | 
						|
{
 | 
						|
	switch(iso) {
 | 
						|
		case ISO_REPEATABLE_READ: return(TRX_ISO_REPEATABLE_READ);
 | 
						|
		case ISO_READ_COMMITTED: return(TRX_ISO_READ_COMMITTED);
 | 
						|
		case ISO_SERIALIZABLE: return(TRX_ISO_SERIALIZABLE);
 | 
						|
		case ISO_READ_UNCOMMITTED: return(TRX_ISO_READ_UNCOMMITTED);
 | 
						|
		default: ut_a(0); return(0);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
As MySQL will execute an external lock for every new table it uses when it
 | 
						|
starts to process an SQL statement (an exception is when MySQL calls
 | 
						|
start_stmt for the handle) we can use this function to store the pointer to
 | 
						|
the THD in the handle. We will also use this function to communicate
 | 
						|
to InnoDB that a new SQL statement has started and that we must store a
 | 
						|
savepoint to our transaction handle, so that we are able to roll back
 | 
						|
the SQL statement in case of an error. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::external_lock(
 | 
						|
/*=======================*/
 | 
						|
			        /* out: 0 */
 | 
						|
	THD*	thd,		/* in: handle to the user thread */
 | 
						|
	int 	lock_type)	/* in: lock type */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	trx_t*		trx;
 | 
						|
 | 
						|
  	DBUG_ENTER("ha_innobase::external_lock");
 | 
						|
	DBUG_PRINT("enter",("lock_type: %d", lock_type));
 | 
						|
 | 
						|
	update_thd(thd);
 | 
						|
 | 
						|
	trx = prebuilt->trx;
 | 
						|
 | 
						|
	prebuilt->sql_stat_start = TRUE;
 | 
						|
	prebuilt->hint_need_to_fetch_extra_cols = 0;
 | 
						|
 | 
						|
	prebuilt->read_just_key = 0;
 | 
						|
	prebuilt->keep_other_fields_on_keyread = FALSE;
 | 
						|
 | 
						|
	if (lock_type == F_WRLCK) {
 | 
						|
 | 
						|
		/* If this is a SELECT, then it is in UPDATE TABLE ...
 | 
						|
		or SELECT ... FOR UPDATE */
 | 
						|
		prebuilt->select_lock_type = LOCK_X;
 | 
						|
		prebuilt->stored_select_lock_type = LOCK_X;
 | 
						|
	}
 | 
						|
 | 
						|
	if (lock_type != F_UNLCK) {
 | 
						|
		/* MySQL is setting a new table lock */
 | 
						|
 | 
						|
		trx->detailed_error[0] = '\0';
 | 
						|
 | 
						|
		/* Set the MySQL flag to mark that there is an active
 | 
						|
		transaction */
 | 
						|
                if (trx->active_trans == 0) {
 | 
						|
 | 
						|
                        innobase_register_trx_and_stmt(thd);
 | 
						|
                        trx->active_trans = 1;
 | 
						|
                } else if (trx->n_mysql_tables_in_use == 0) {
 | 
						|
			innobase_register_stmt(thd);
 | 
						|
		}
 | 
						|
 | 
						|
		trx->n_mysql_tables_in_use++;
 | 
						|
		prebuilt->mysql_has_locked = TRUE;
 | 
						|
 | 
						|
		if (trx->n_mysql_tables_in_use == 1) {
 | 
						|
		        trx->isolation_level = innobase_map_isolation_level(
 | 
						|
						(enum_tx_isolation)
 | 
						|
						thd->variables.tx_isolation);
 | 
						|
		}
 | 
						|
 | 
						|
		if (trx->isolation_level == TRX_ISO_SERIALIZABLE
 | 
						|
		    && prebuilt->select_lock_type == LOCK_NONE
 | 
						|
		    && (thd->options
 | 
						|
				& (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 | 
						|
 | 
						|
			/* To get serializable execution, we let InnoDB
 | 
						|
			conceptually add 'LOCK IN SHARE MODE' to all SELECTs
 | 
						|
			which otherwise would have been consistent reads. An
 | 
						|
			exception is consistent reads in the AUTOCOMMIT=1 mode:
 | 
						|
			we know that they are read-only transactions, and they
 | 
						|
			can be serialized also if performed as consistent
 | 
						|
			reads. */
 | 
						|
 | 
						|
			prebuilt->select_lock_type = LOCK_S;
 | 
						|
			prebuilt->stored_select_lock_type = LOCK_S;
 | 
						|
		}
 | 
						|
 | 
						|
		/* Starting from 4.1.9, no InnoDB table lock is taken in LOCK
 | 
						|
		TABLES if AUTOCOMMIT=1. It does not make much sense to acquire
 | 
						|
		an InnoDB table lock if it is released immediately at the end
 | 
						|
		of LOCK TABLES, and InnoDB's table locks in that case cause
 | 
						|
		VERY easily deadlocks.
 | 
						|
 | 
						|
		We do not set InnoDB table locks if user has not explicitly
 | 
						|
		requested a table lock. Note that thd->in_lock_tables
 | 
						|
		can  be TRUE on some cases e.g. at the start of a stored
 | 
						|
		procedure call (SQLCOM_CALL). */
 | 
						|
 | 
						|
		if (prebuilt->select_lock_type != LOCK_NONE) {
 | 
						|
 | 
						|
			if (thd->in_lock_tables &&
 | 
						|
			    thd->lex->sql_command == SQLCOM_LOCK_TABLES &&
 | 
						|
			    thd->variables.innodb_table_locks &&
 | 
						|
			    (thd->options & OPTION_NOT_AUTOCOMMIT)) {
 | 
						|
 | 
						|
				ulint	error;
 | 
						|
				error = row_lock_table_for_mysql(prebuilt,
 | 
						|
							NULL, 0);
 | 
						|
 | 
						|
				if (error != DB_SUCCESS) {
 | 
						|
					error = convert_error_code_to_mysql(
 | 
						|
						(int) error, user_thd);
 | 
						|
					DBUG_RETURN((int) error);
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
		  	trx->mysql_n_tables_locked++;
 | 
						|
		}
 | 
						|
 | 
						|
		DBUG_RETURN(0);
 | 
						|
	}
 | 
						|
 | 
						|
	/* MySQL is releasing a table lock */
 | 
						|
 | 
						|
	trx->n_mysql_tables_in_use--;
 | 
						|
	prebuilt->mysql_has_locked = FALSE;
 | 
						|
 | 
						|
	/* If the MySQL lock count drops to zero we know that the current SQL
 | 
						|
	statement has ended */
 | 
						|
 | 
						|
	if (trx->n_mysql_tables_in_use == 0) {
 | 
						|
 | 
						|
	        trx->mysql_n_tables_locked = 0;
 | 
						|
		prebuilt->used_in_HANDLER = FALSE;
 | 
						|
 | 
						|
		/* Release a possible FIFO ticket and search latch. Since we
 | 
						|
		may reserve the kernel mutex, we have to release the search
 | 
						|
		system latch first to obey the latching order. */
 | 
						|
 | 
						|
		innobase_release_stat_resources(trx);
 | 
						|
 | 
						|
		if (!(thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN))) {
 | 
						|
                        if (trx->active_trans != 0) {
 | 
						|
                                innobase_commit(thd, TRUE);
 | 
						|
			}
 | 
						|
		} else {
 | 
						|
			if (trx->isolation_level <= TRX_ISO_READ_COMMITTED
 | 
						|
	    					&& trx->global_read_view) {
 | 
						|
 | 
						|
				/* At low transaction isolation levels we let
 | 
						|
				each consistent read set its own snapshot */
 | 
						|
 | 
						|
				read_view_close_for_mysql(trx);
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	DBUG_RETURN(0);
 | 
						|
}
 | 
						|
 | 
						|
/**********************************************************************
 | 
						|
With this function MySQL request a transactional lock to a table when
 | 
						|
user issued query LOCK TABLES..WHERE ENGINE = InnoDB. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::transactional_table_lock(
 | 
						|
/*==================================*/
 | 
						|
			        /* out: error code */
 | 
						|
	THD*	thd,		/* in: handle to the user thread */
 | 
						|
	int 	lock_type)	/* in: lock type */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	trx_t*		trx;
 | 
						|
 | 
						|
  	DBUG_ENTER("ha_innobase::transactional_table_lock");
 | 
						|
	DBUG_PRINT("enter",("lock_type: %d", lock_type));
 | 
						|
 | 
						|
	/* We do not know if MySQL can call this function before calling
 | 
						|
	external_lock(). To be safe, update the thd of the current table
 | 
						|
	handle. */
 | 
						|
 | 
						|
	update_thd(thd);
 | 
						|
 | 
						|
 	if (prebuilt->table->ibd_file_missing && !current_thd->tablespace_op) {
 | 
						|
	        ut_print_timestamp(stderr);
 | 
						|
	        fprintf(stderr, "  InnoDB error:\n"
 | 
						|
"MySQL is trying to use a table handle but the .ibd file for\n"
 | 
						|
"table %s does not exist.\n"
 | 
						|
"Have you deleted the .ibd file from the database directory under\n"
 | 
						|
"the MySQL datadir?"
 | 
						|
"See http://dev.mysql.com/doc/refman/5.0/en/innodb-troubleshooting.html\n"
 | 
						|
"how you can resolve the problem.\n",
 | 
						|
				prebuilt->table->name);
 | 
						|
		DBUG_RETURN(HA_ERR_CRASHED);
 | 
						|
	}
 | 
						|
 | 
						|
	trx = prebuilt->trx;
 | 
						|
 | 
						|
	prebuilt->sql_stat_start = TRUE;
 | 
						|
	prebuilt->hint_need_to_fetch_extra_cols = 0;
 | 
						|
 | 
						|
	prebuilt->read_just_key = 0;
 | 
						|
	prebuilt->keep_other_fields_on_keyread = FALSE;
 | 
						|
 | 
						|
	if (lock_type == F_WRLCK) {
 | 
						|
		prebuilt->select_lock_type = LOCK_X;
 | 
						|
		prebuilt->stored_select_lock_type = LOCK_X;
 | 
						|
	} else if (lock_type == F_RDLCK) {
 | 
						|
		prebuilt->select_lock_type = LOCK_S;
 | 
						|
		prebuilt->stored_select_lock_type = LOCK_S;
 | 
						|
	} else {
 | 
						|
	        ut_print_timestamp(stderr);
 | 
						|
	        fprintf(stderr, "  InnoDB error:\n"
 | 
						|
"MySQL is trying to set transactional table lock with corrupted lock type\n"
 | 
						|
"to table %s, lock type %d does not exist.\n",
 | 
						|
				prebuilt->table->name, lock_type);
 | 
						|
		DBUG_RETURN(HA_ERR_CRASHED);
 | 
						|
	}
 | 
						|
 | 
						|
	/* MySQL is setting a new transactional table lock */
 | 
						|
 | 
						|
	/* Set the MySQL flag to mark that there is an active transaction */
 | 
						|
        if (trx->active_trans == 0) {
 | 
						|
 | 
						|
                innobase_register_trx_and_stmt(thd);
 | 
						|
                trx->active_trans = 1;
 | 
						|
        }
 | 
						|
 | 
						|
	if (thd->in_lock_tables && thd->variables.innodb_table_locks) {
 | 
						|
		ulint	error = DB_SUCCESS;
 | 
						|
 | 
						|
		error = row_lock_table_for_mysql(prebuilt, NULL, 0);
 | 
						|
 | 
						|
		if (error != DB_SUCCESS) {
 | 
						|
			error = convert_error_code_to_mysql((int) error, user_thd);
 | 
						|
			DBUG_RETURN((int) error);
 | 
						|
		}
 | 
						|
 | 
						|
		if (thd->options & (OPTION_NOT_AUTOCOMMIT | OPTION_BEGIN)) {
 | 
						|
 | 
						|
			/* 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);
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	DBUG_RETURN(0);
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
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. */
 | 
						|
 | 
						|
bool
 | 
						|
innodb_show_status(
 | 
						|
/*===============*/
 | 
						|
	THD*	thd)	/* in: the MySQL query thread of the caller */
 | 
						|
{
 | 
						|
	Protocol*		protocol = thd->protocol;
 | 
						|
	trx_t*			trx;
 | 
						|
	static const char	truncated_msg[] = "... truncated...\n";
 | 
						|
	const long		MAX_STATUS_SIZE = 64000;
 | 
						|
	ulint			trx_list_start = ULINT_UNDEFINED;
 | 
						|
	ulint			trx_list_end = ULINT_UNDEFINED;
 | 
						|
 | 
						|
        DBUG_ENTER("innodb_show_status");
 | 
						|
 | 
						|
        if (have_innodb != SHOW_OPTION_YES) {
 | 
						|
                my_message(ER_NOT_SUPPORTED_YET,
 | 
						|
          "Cannot call SHOW INNODB STATUS because skip-innodb is defined",
 | 
						|
                           MYF(0));
 | 
						|
                DBUG_RETURN(TRUE);
 | 
						|
        }
 | 
						|
 | 
						|
	trx = check_trx_exists(thd);
 | 
						|
 | 
						|
	innobase_release_stat_resources(trx);
 | 
						|
 | 
						|
	/* We let the InnoDB Monitor to output at most MAX_STATUS_SIZE
 | 
						|
	bytes of text. */
 | 
						|
 | 
						|
	long	flen, usable_len;
 | 
						|
	char*	str;
 | 
						|
 | 
						|
	mutex_enter_noninline(&srv_monitor_file_mutex);
 | 
						|
	rewind(srv_monitor_file);
 | 
						|
	srv_printf_innodb_monitor(srv_monitor_file,
 | 
						|
				&trx_list_start, &trx_list_end);
 | 
						|
	flen = ftell(srv_monitor_file);
 | 
						|
	os_file_set_eof(srv_monitor_file);
 | 
						|
 | 
						|
	if (flen < 0) {
 | 
						|
		flen = 0;
 | 
						|
	}
 | 
						|
 | 
						|
	if (flen > MAX_STATUS_SIZE) {
 | 
						|
		usable_len = MAX_STATUS_SIZE;
 | 
						|
	} else {
 | 
						|
		usable_len = flen;
 | 
						|
	}
 | 
						|
 | 
						|
	/* allocate buffer for the string, and
 | 
						|
	read the contents of the temporary file */
 | 
						|
 | 
						|
	if (!(str = my_malloc(usable_len + 1, MYF(0))))
 | 
						|
        {
 | 
						|
          mutex_exit_noninline(&srv_monitor_file_mutex);
 | 
						|
          DBUG_RETURN(TRUE);
 | 
						|
        }
 | 
						|
 | 
						|
	rewind(srv_monitor_file);
 | 
						|
	if (flen < MAX_STATUS_SIZE) {
 | 
						|
		/* Display the entire output. */
 | 
						|
		flen = (long) fread(str, 1, flen, srv_monitor_file);
 | 
						|
	} else if (trx_list_end < (ulint) flen
 | 
						|
			&& trx_list_start < trx_list_end
 | 
						|
			&& trx_list_start + (flen - trx_list_end)
 | 
						|
			< MAX_STATUS_SIZE - sizeof truncated_msg - 1) {
 | 
						|
		/* Omit the beginning of the list of active transactions. */
 | 
						|
		long len = (long) fread(str, 1, trx_list_start, srv_monitor_file);
 | 
						|
		memcpy(str + len, truncated_msg, sizeof truncated_msg - 1);
 | 
						|
		len += sizeof truncated_msg - 1;
 | 
						|
		usable_len = (MAX_STATUS_SIZE - 1) - len;
 | 
						|
		fseek(srv_monitor_file, flen - usable_len, SEEK_SET);
 | 
						|
		len += (long) fread(str + len, 1, usable_len, srv_monitor_file);
 | 
						|
		flen = len;
 | 
						|
	} else {
 | 
						|
		/* Omit the end of the output. */
 | 
						|
		flen = (long) fread(str, 1, MAX_STATUS_SIZE - 1, srv_monitor_file);
 | 
						|
	}
 | 
						|
 | 
						|
	mutex_exit_noninline(&srv_monitor_file_mutex);
 | 
						|
 | 
						|
	List<Item> field_list;
 | 
						|
 | 
						|
	field_list.push_back(new Item_empty_string("Status", flen));
 | 
						|
 | 
						|
	if (protocol->send_fields(&field_list, Protocol::SEND_NUM_ROWS |
 | 
						|
                                               Protocol::SEND_EOF)) {
 | 
						|
		my_free(str, MYF(0));
 | 
						|
 | 
						|
		DBUG_RETURN(TRUE);
 | 
						|
	}
 | 
						|
 | 
						|
        protocol->prepare_for_resend();
 | 
						|
        protocol->store(str, flen, system_charset_info);
 | 
						|
        my_free(str, MYF(0));
 | 
						|
 | 
						|
        if (protocol->write()) {
 | 
						|
 | 
						|
        	DBUG_RETURN(TRUE);
 | 
						|
	}
 | 
						|
	send_eof(thd);
 | 
						|
 | 
						|
  	DBUG_RETURN(FALSE);
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
Implements the SHOW MUTEX STATUS command. . */
 | 
						|
 | 
						|
bool
 | 
						|
innodb_mutex_show_status(
 | 
						|
/*===============*/
 | 
						|
  THD*  thd)  /* in: the MySQL query thread of the caller */
 | 
						|
{
 | 
						|
  Protocol        *protocol= thd->protocol;
 | 
						|
  List<Item> field_list;
 | 
						|
  mutex_t*  mutex;
 | 
						|
#ifdef UNIV_DEBUG
 | 
						|
  ulint   rw_lock_count= 0;
 | 
						|
  ulint   rw_lock_count_spin_loop= 0;
 | 
						|
  ulint   rw_lock_count_spin_rounds= 0;
 | 
						|
  ulint   rw_lock_count_os_wait= 0;
 | 
						|
  ulint   rw_lock_count_os_yield= 0;
 | 
						|
  ulonglong rw_lock_wait_time= 0;
 | 
						|
#endif /* UNIV_DEBUG */
 | 
						|
  DBUG_ENTER("innodb_mutex_show_status");
 | 
						|
 | 
						|
#ifdef UNIV_DEBUG
 | 
						|
  field_list.push_back(new Item_empty_string("Mutex", FN_REFLEN));
 | 
						|
  field_list.push_back(new Item_empty_string("Module", FN_REFLEN));
 | 
						|
  field_list.push_back(new Item_uint("Count", 21));
 | 
						|
  field_list.push_back(new Item_uint("Spin_waits", 21));
 | 
						|
  field_list.push_back(new Item_uint("Spin_rounds", 21));
 | 
						|
  field_list.push_back(new Item_uint("OS_waits", 21));
 | 
						|
  field_list.push_back(new Item_uint("OS_yields", 21));
 | 
						|
  field_list.push_back(new Item_uint("OS_waits_time", 21));
 | 
						|
#else /* UNIV_DEBUG */
 | 
						|
  field_list.push_back(new Item_empty_string("File", FN_REFLEN));
 | 
						|
  field_list.push_back(new Item_uint("Line", 21));
 | 
						|
  field_list.push_back(new Item_uint("OS_waits", 21));
 | 
						|
#endif /* UNIV_DEBUG */
 | 
						|
 | 
						|
  if (protocol->send_fields(&field_list,
 | 
						|
                            Protocol::SEND_NUM_ROWS | Protocol::SEND_EOF))
 | 
						|
    DBUG_RETURN(TRUE);
 | 
						|
 | 
						|
  mutex_enter_noninline(&mutex_list_mutex);
 | 
						|
 | 
						|
  mutex = UT_LIST_GET_FIRST(mutex_list);
 | 
						|
 | 
						|
  while ( mutex != NULL )
 | 
						|
  {
 | 
						|
#ifdef UNIV_DEBUG
 | 
						|
    if (mutex->mutex_type != 1)
 | 
						|
    {
 | 
						|
      if (mutex->count_using > 0)
 | 
						|
      {
 | 
						|
        protocol->prepare_for_resend();
 | 
						|
        protocol->store(mutex->cmutex_name, system_charset_info);
 | 
						|
        protocol->store(mutex->cfile_name, system_charset_info);
 | 
						|
        protocol->store((ulonglong)mutex->count_using);
 | 
						|
        protocol->store((ulonglong)mutex->count_spin_loop);
 | 
						|
        protocol->store((ulonglong)mutex->count_spin_rounds);
 | 
						|
        protocol->store((ulonglong)mutex->count_os_wait);
 | 
						|
        protocol->store((ulonglong)mutex->count_os_yield);
 | 
						|
        protocol->store((ulonglong)mutex->lspent_time/1000);
 | 
						|
 | 
						|
        if (protocol->write())
 | 
						|
        {
 | 
						|
          mutex_exit_noninline(&mutex_list_mutex);
 | 
						|
          DBUG_RETURN(1);
 | 
						|
        }
 | 
						|
      }
 | 
						|
    }
 | 
						|
    else
 | 
						|
    {
 | 
						|
      rw_lock_count += mutex->count_using;
 | 
						|
      rw_lock_count_spin_loop += mutex->count_spin_loop;
 | 
						|
      rw_lock_count_spin_rounds += mutex->count_spin_rounds;
 | 
						|
      rw_lock_count_os_wait += mutex->count_os_wait;
 | 
						|
      rw_lock_count_os_yield += mutex->count_os_yield;
 | 
						|
      rw_lock_wait_time += mutex->lspent_time;
 | 
						|
    }
 | 
						|
#else /* UNIV_DEBUG */
 | 
						|
    protocol->prepare_for_resend();
 | 
						|
    protocol->store(mutex->cfile_name, system_charset_info);
 | 
						|
    protocol->store((ulonglong)mutex->cline);
 | 
						|
    protocol->store((ulonglong)mutex->count_os_wait);
 | 
						|
 | 
						|
    if (protocol->write())
 | 
						|
    {
 | 
						|
      mutex_exit_noninline(&mutex_list_mutex);
 | 
						|
      DBUG_RETURN(1);
 | 
						|
    }
 | 
						|
#endif /* UNIV_DEBUG */
 | 
						|
 | 
						|
    mutex = UT_LIST_GET_NEXT(list, mutex);
 | 
						|
  }
 | 
						|
 | 
						|
  mutex_exit_noninline(&mutex_list_mutex);
 | 
						|
 | 
						|
#ifdef UNIV_DEBUG
 | 
						|
  protocol->prepare_for_resend();
 | 
						|
  protocol->store("rw_lock_mutexes", system_charset_info);
 | 
						|
  protocol->store("", system_charset_info);
 | 
						|
  protocol->store((ulonglong)rw_lock_count);
 | 
						|
  protocol->store((ulonglong)rw_lock_count_spin_loop);
 | 
						|
  protocol->store((ulonglong)rw_lock_count_spin_rounds);
 | 
						|
  protocol->store((ulonglong)rw_lock_count_os_wait);
 | 
						|
  protocol->store((ulonglong)rw_lock_count_os_yield);
 | 
						|
  protocol->store((ulonglong)rw_lock_wait_time/1000);
 | 
						|
 | 
						|
  if (protocol->write())
 | 
						|
  {
 | 
						|
    DBUG_RETURN(1);
 | 
						|
  }
 | 
						|
#endif /* UNIV_DEBUG */
 | 
						|
 | 
						|
  send_eof(thd);
 | 
						|
  DBUG_RETURN(FALSE);
 | 
						|
}
 | 
						|
 | 
						|
/****************************************************************************
 | 
						|
 Handling the shared INNOBASE_SHARE structure that is needed to provide table
 | 
						|
 locking.
 | 
						|
****************************************************************************/
 | 
						|
 | 
						|
static mysql_byte* innobase_get_key(INNOBASE_SHARE *share,uint *length,
 | 
						|
			      my_bool not_used __attribute__((unused)))
 | 
						|
{
 | 
						|
  *length=share->table_name_length;
 | 
						|
  return (mysql_byte*) share->table_name;
 | 
						|
}
 | 
						|
 | 
						|
static INNOBASE_SHARE *get_share(const char *table_name)
 | 
						|
{
 | 
						|
	INNOBASE_SHARE *share;
 | 
						|
	pthread_mutex_lock(&innobase_share_mutex);
 | 
						|
	uint length=(uint) strlen(table_name);
 | 
						|
 | 
						|
	if (!(share=(INNOBASE_SHARE*) hash_search(&innobase_open_tables,
 | 
						|
				(mysql_byte*) table_name,
 | 
						|
				length))) {
 | 
						|
 | 
						|
		share = (INNOBASE_SHARE *) my_malloc(sizeof(*share)+length+1,
 | 
						|
			MYF(MY_FAE | MY_ZEROFILL));
 | 
						|
 | 
						|
		share->table_name_length=length;
 | 
						|
		share->table_name=(char*) (share+1);
 | 
						|
		strmov(share->table_name,table_name);
 | 
						|
 | 
						|
		if (my_hash_insert(&innobase_open_tables,
 | 
						|
				(mysql_byte*) share)) {
 | 
						|
			pthread_mutex_unlock(&innobase_share_mutex);
 | 
						|
			my_free((gptr) share,0);
 | 
						|
 | 
						|
			return 0;
 | 
						|
		}
 | 
						|
 | 
						|
		thr_lock_init(&share->lock);
 | 
						|
		pthread_mutex_init(&share->mutex,MY_MUTEX_INIT_FAST);
 | 
						|
	}
 | 
						|
 | 
						|
	share->use_count++;
 | 
						|
	pthread_mutex_unlock(&innobase_share_mutex);
 | 
						|
 | 
						|
	return share;
 | 
						|
}
 | 
						|
 | 
						|
static void free_share(INNOBASE_SHARE *share)
 | 
						|
{
 | 
						|
  pthread_mutex_lock(&innobase_share_mutex);
 | 
						|
  if (!--share->use_count)
 | 
						|
  {
 | 
						|
    hash_delete(&innobase_open_tables, (mysql_byte*) share);
 | 
						|
    thr_lock_delete(&share->lock);
 | 
						|
    pthread_mutex_destroy(&share->mutex);
 | 
						|
    my_free((gptr) share, MYF(0));
 | 
						|
  }
 | 
						|
  pthread_mutex_unlock(&innobase_share_mutex);
 | 
						|
}
 | 
						|
 | 
						|
/*********************************************************************
 | 
						|
Converts a MySQL table lock stored in the 'lock' field of the handle to
 | 
						|
a proper type before storing pointer to the lock into an array of pointers.
 | 
						|
MySQL also calls this if it wants to reset some table locks to a not-locked
 | 
						|
state during the processing of an SQL query. An example is that during a
 | 
						|
SELECT the read lock is released early on the 'const' tables where we only
 | 
						|
fetch one row. MySQL does not call this when it releases all locks at the
 | 
						|
end of an SQL statement. */
 | 
						|
 | 
						|
THR_LOCK_DATA**
 | 
						|
ha_innobase::store_lock(
 | 
						|
/*====================*/
 | 
						|
						/* out: pointer to the next
 | 
						|
						element in the 'to' array */
 | 
						|
	THD*			thd,		/* in: user thread handle */
 | 
						|
	THR_LOCK_DATA**		to,		/* in: pointer to an array
 | 
						|
						of pointers to lock structs;
 | 
						|
						pointer to the 'lock' field
 | 
						|
						of current handle is stored
 | 
						|
						next to this array */
 | 
						|
	enum thr_lock_type 	lock_type)	/* in: lock type to store in
 | 
						|
						'lock'; this may also be
 | 
						|
						TL_IGNORE */
 | 
						|
{
 | 
						|
	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
 | 
						|
	/* NOTE: MySQL  can call this function with lock 'type' TL_IGNORE!
 | 
						|
	Be careful to ignore TL_IGNORE if we are going to do something with
 | 
						|
	only 'real' locks! */
 | 
						|
 | 
						|
	if ((lock_type == TL_READ && thd->in_lock_tables) ||
 | 
						|
	    (lock_type == TL_READ_HIGH_PRIORITY && thd->in_lock_tables) ||
 | 
						|
	    lock_type == TL_READ_WITH_SHARED_LOCKS ||
 | 
						|
	    lock_type == TL_READ_NO_INSERT ||
 | 
						|
	    (thd->lex->sql_command != SQLCOM_SELECT
 | 
						|
	     && lock_type != TL_IGNORE)) {
 | 
						|
 | 
						|
		/* The OR cases above are in this order:
 | 
						|
		1) MySQL is doing LOCK TABLES ... READ LOCAL, or we
 | 
						|
		are processing a stored procedure or function, or
 | 
						|
		2) (we do not know when TL_READ_HIGH_PRIORITY is used), or
 | 
						|
		3) this is a SELECT ... IN SHARE MODE, or
 | 
						|
		4) we are doing a complex SQL statement like
 | 
						|
		INSERT INTO ... SELECT ... and the logical logging (MySQL
 | 
						|
		binlog) requires the use of a locking read, or
 | 
						|
		MySQL is doing LOCK TABLES ... READ.
 | 
						|
		5) we let InnoDB do locking reads for all SQL statements that
 | 
						|
		are not simple SELECTs; note that select_lock_type in this
 | 
						|
		case may get strengthened in ::external_lock() to LOCK_X.
 | 
						|
		Note that we MUST use a locking read in all data modifying
 | 
						|
		SQL statements, because otherwise the execution would not be
 | 
						|
		serializable, and also the results from the update could be
 | 
						|
		unexpected if an obsolete consistent read view would be
 | 
						|
		used. */
 | 
						|
 | 
						|
		if (srv_locks_unsafe_for_binlog &&
 | 
						|
		    prebuilt->trx->isolation_level != TRX_ISO_SERIALIZABLE &&
 | 
						|
		    (lock_type == TL_READ || lock_type == TL_READ_NO_INSERT) &&
 | 
						|
		    (thd->lex->sql_command == SQLCOM_INSERT_SELECT ||
 | 
						|
		     thd->lex->sql_command == SQLCOM_UPDATE ||
 | 
						|
		     thd->lex->sql_command == SQLCOM_CREATE_TABLE)) {
 | 
						|
 | 
						|
			/* In case we have innobase_locks_unsafe_for_binlog
 | 
						|
			option set and isolation level of the transaction
 | 
						|
			is not set to serializable and MySQL is doing
 | 
						|
			INSERT INTO...SELECT or UPDATE ... = (SELECT ...) or
 | 
						|
			CREATE  ... SELECT... without FOR UPDATE or
 | 
						|
			IN SHARE MODE in select, then we use consistent
 | 
						|
			read for select. */
 | 
						|
 | 
						|
			prebuilt->select_lock_type = LOCK_NONE;
 | 
						|
			prebuilt->stored_select_lock_type = LOCK_NONE;
 | 
						|
		} else if (thd->lex->sql_command == SQLCOM_CHECKSUM) {
 | 
						|
			/* Use consistent read for checksum table */
 | 
						|
 | 
						|
			prebuilt->select_lock_type = LOCK_NONE;
 | 
						|
			prebuilt->stored_select_lock_type = LOCK_NONE;
 | 
						|
		} else {
 | 
						|
			prebuilt->select_lock_type = LOCK_S;
 | 
						|
			prebuilt->stored_select_lock_type = LOCK_S;
 | 
						|
		}
 | 
						|
 | 
						|
	} else if (lock_type != TL_IGNORE) {
 | 
						|
 | 
						|
		/* We set possible LOCK_X value in external_lock, not yet
 | 
						|
		here even if this would be SELECT ... FOR UPDATE */
 | 
						|
 | 
						|
		prebuilt->select_lock_type = LOCK_NONE;
 | 
						|
		prebuilt->stored_select_lock_type = LOCK_NONE;
 | 
						|
	}
 | 
						|
 | 
						|
	if (lock_type != TL_IGNORE && lock.type == TL_UNLOCK) {
 | 
						|
 | 
						|
		/* Starting from 5.0.7, we weaken also the table locks
 | 
						|
		set at the start of a MySQL stored procedure call, just like
 | 
						|
		we weaken the locks set at the start of an SQL statement.
 | 
						|
		MySQL does set thd->in_lock_tables TRUE there, but in reality
 | 
						|
		we do not need table locks to make the execution of a
 | 
						|
		single transaction stored procedure call deterministic
 | 
						|
		(if it does not use a consistent read). */
 | 
						|
 | 
						|
		if (lock_type == TL_READ
 | 
						|
		    && thd->lex->sql_command == SQLCOM_LOCK_TABLES) {
 | 
						|
			/* We come here if MySQL is processing LOCK TABLES
 | 
						|
			... READ LOCAL. MyISAM under that table lock type
 | 
						|
			reads the table as it was at the time the lock was
 | 
						|
			granted (new inserts are allowed, but not seen by the
 | 
						|
			reader). To get a similar effect on an InnoDB table,
 | 
						|
			we must use LOCK TABLES ... READ. We convert the lock
 | 
						|
			type here, so that for InnoDB, READ LOCAL is
 | 
						|
			equivalent to READ. This will change the InnoDB
 | 
						|
			behavior in mysqldump, so that dumps of InnoDB tables
 | 
						|
			are consistent with dumps of MyISAM tables. */
 | 
						|
 | 
						|
			lock_type = TL_READ_NO_INSERT;
 | 
						|
		}
 | 
						|
 | 
						|
		/* If we are not doing a LOCK TABLE, DISCARD/IMPORT
 | 
						|
		TABLESPACE or TRUNCATE TABLE then allow multiple
 | 
						|
		writers. Note that ALTER TABLE uses a TL_WRITE_ALLOW_READ
 | 
						|
		< TL_WRITE_CONCURRENT_INSERT.
 | 
						|
 | 
						|
		We especially allow multiple writers if MySQL is at the
 | 
						|
		start of a stored procedure call (SQLCOM_CALL) or a
 | 
						|
		stored function call (MySQL does have thd->in_lock_tables
 | 
						|
		TRUE there). */
 | 
						|
 | 
						|
    		if ((lock_type >= TL_WRITE_CONCURRENT_INSERT
 | 
						|
		    && lock_type <= TL_WRITE)
 | 
						|
		    && !(thd->in_lock_tables
 | 
						|
			    && thd->lex->sql_command == SQLCOM_LOCK_TABLES)
 | 
						|
		    && !thd->tablespace_op
 | 
						|
		    && thd->lex->sql_command != SQLCOM_TRUNCATE
 | 
						|
		    && thd->lex->sql_command != SQLCOM_OPTIMIZE
 | 
						|
 | 
						|
#ifdef __WIN__
 | 
						|
                /* For alter table on win32 for succesful operation
 | 
						|
                completion it is used TL_WRITE(=10) lock instead of
 | 
						|
                TL_WRITE_ALLOW_READ(=6), however here in innodb handler
 | 
						|
                TL_WRITE is lifted to TL_WRITE_ALLOW_WRITE, which causes
 | 
						|
                race condition when several clients do alter table
 | 
						|
                simultaneously (bug #17264). This fix avoids the problem. */
 | 
						|
		    && thd->lex->sql_command != SQLCOM_ALTER_TABLE
 | 
						|
#endif
 | 
						|
 | 
						|
		    && thd->lex->sql_command != SQLCOM_CREATE_TABLE) {
 | 
						|
 | 
						|
			lock_type = TL_WRITE_ALLOW_WRITE;
 | 
						|
      		}
 | 
						|
 | 
						|
		/* In queries of type INSERT INTO t1 SELECT ... FROM t2 ...
 | 
						|
		MySQL would use the lock TL_READ_NO_INSERT on t2, and that
 | 
						|
		would conflict with TL_WRITE_ALLOW_WRITE, blocking all inserts
 | 
						|
		to t2. Convert the lock to a normal read lock to allow
 | 
						|
		concurrent inserts to t2.
 | 
						|
 | 
						|
		We especially allow concurrent inserts if MySQL is at the
 | 
						|
		start of a stored procedure call (SQLCOM_CALL)
 | 
						|
		(MySQL does have thd->in_lock_tables TRUE there). */
 | 
						|
 | 
						|
		if (lock_type == TL_READ_NO_INSERT
 | 
						|
		    && thd->lex->sql_command != SQLCOM_LOCK_TABLES) {
 | 
						|
 | 
						|
			lock_type = TL_READ;
 | 
						|
		}
 | 
						|
 | 
						|
		lock.type = lock_type;
 | 
						|
	}
 | 
						|
 | 
						|
	*to++= &lock;
 | 
						|
 | 
						|
	return(to);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
This function initializes the auto-inc counter if it has not been
 | 
						|
initialized yet. This function does not change the value of the auto-inc
 | 
						|
counter if it already has been initialized. In parameter ret returns
 | 
						|
the value of the auto-inc counter. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::innobase_read_and_init_auto_inc(
 | 
						|
/*=========================================*/
 | 
						|
				/* out: 0 or error code: deadlock or lock wait
 | 
						|
				timeout */
 | 
						|
	longlong*	ret)	/* out: auto-inc value */
 | 
						|
{
 | 
						|
  	row_prebuilt_t* prebuilt	= (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
    	longlong        auto_inc;
 | 
						|
	ulint		old_select_lock_type;
 | 
						|
	ibool		trx_was_not_started	= FALSE;
 | 
						|
  	int     	error;
 | 
						|
 | 
						|
  	ut_a(prebuilt);
 | 
						|
	ut_a(prebuilt->trx ==
 | 
						|
                (trx_t*) current_thd->ha_data[innobase_hton.slot]);
 | 
						|
	ut_a(prebuilt->table);
 | 
						|
 | 
						|
	if (prebuilt->trx->conc_state == TRX_NOT_STARTED) {
 | 
						|
		trx_was_not_started = TRUE;
 | 
						|
	}
 | 
						|
 | 
						|
	/* In case MySQL calls this in the middle of a SELECT query, release
 | 
						|
	possible adaptive hash latch to avoid deadlocks of threads */
 | 
						|
 | 
						|
	trx_search_latch_release_if_reserved(prebuilt->trx);
 | 
						|
 | 
						|
	auto_inc = dict_table_autoinc_read(prebuilt->table);
 | 
						|
 | 
						|
	if (auto_inc != 0) {
 | 
						|
		/* Already initialized */
 | 
						|
		*ret = auto_inc;
 | 
						|
 | 
						|
		error = 0;
 | 
						|
 | 
						|
		goto func_exit_early;
 | 
						|
	}
 | 
						|
 | 
						|
	error = row_lock_table_autoinc_for_mysql(prebuilt);
 | 
						|
 | 
						|
	if (error != DB_SUCCESS) {
 | 
						|
		error = convert_error_code_to_mysql(error, user_thd);
 | 
						|
 | 
						|
		goto func_exit_early;
 | 
						|
	}
 | 
						|
 | 
						|
	/* Check again if someone has initialized the counter meanwhile */
 | 
						|
	auto_inc = dict_table_autoinc_read(prebuilt->table);
 | 
						|
 | 
						|
	if (auto_inc != 0) {
 | 
						|
		*ret = auto_inc;
 | 
						|
 | 
						|
		error = 0;
 | 
						|
 | 
						|
		goto func_exit_early;
 | 
						|
	}
 | 
						|
 | 
						|
  	(void) extra(HA_EXTRA_KEYREAD);
 | 
						|
  	index_init(table->s->next_number_index);
 | 
						|
 | 
						|
	/* Starting from 5.0.9, we use a consistent read to read the auto-inc
 | 
						|
	column maximum value. This eliminates the spurious deadlocks caused
 | 
						|
	by the row X-lock that we previously used. Note the following flaw
 | 
						|
	in our algorithm: if some other user meanwhile UPDATEs the auto-inc
 | 
						|
	column, our consistent read will not return the largest value. We
 | 
						|
	accept this flaw, since the deadlocks were a bigger trouble. */
 | 
						|
 | 
						|
  	/* Fetch all the columns in the key */
 | 
						|
 | 
						|
	prebuilt->hint_need_to_fetch_extra_cols = ROW_RETRIEVE_ALL_COLS;
 | 
						|
 | 
						|
	old_select_lock_type = prebuilt->select_lock_type;
 | 
						|
  	prebuilt->select_lock_type = LOCK_NONE;
 | 
						|
 | 
						|
	/* Eliminate an InnoDB error print that happens when we try to SELECT
 | 
						|
	from a table when no table has been locked in ::external_lock(). */
 | 
						|
	prebuilt->trx->n_mysql_tables_in_use++;
 | 
						|
 | 
						|
	error = index_last(table->record[1]);
 | 
						|
 | 
						|
	prebuilt->trx->n_mysql_tables_in_use--;
 | 
						|
  	prebuilt->select_lock_type = old_select_lock_type;
 | 
						|
 | 
						|
  	if (error) {
 | 
						|
		if (error == HA_ERR_END_OF_FILE) {
 | 
						|
			/* The table was empty, initialize to 1 */
 | 
						|
			auto_inc = 1;
 | 
						|
 | 
						|
			error = 0;
 | 
						|
		} else {
 | 
						|
			/* This should not happen in a consistent read */
 | 
						|
		  sql_print_error("Consistent read of auto-inc column "
 | 
						|
				  "returned %lu", (ulong) error);
 | 
						|
  			auto_inc = -1;
 | 
						|
 | 
						|
  			goto func_exit;
 | 
						|
  		}
 | 
						|
  	} else {
 | 
						|
		/* Initialize to max(col) + 1; we use
 | 
						|
		'found_next_number_field' below because MySQL in SHOW TABLE
 | 
						|
		STATUS does not seem to set 'next_number_field'. The comment
 | 
						|
		in table.h says that 'next_number_field' is set when it is
 | 
						|
		'active'. */
 | 
						|
 | 
						|
    		auto_inc = (longlong) table->found_next_number_field->
 | 
						|
                        	val_int_offset(table->s->rec_buff_length) + 1;
 | 
						|
  	}
 | 
						|
 | 
						|
	dict_table_autoinc_initialize(prebuilt->table, auto_inc);
 | 
						|
 | 
						|
func_exit:
 | 
						|
  	(void) extra(HA_EXTRA_NO_KEYREAD);
 | 
						|
 | 
						|
	index_end();
 | 
						|
 | 
						|
	*ret = auto_inc;
 | 
						|
 | 
						|
func_exit_early:
 | 
						|
	/* Since MySQL does not seem to call autocommit after SHOW TABLE
 | 
						|
	STATUS (even if we would register the trx here), we commit our
 | 
						|
	transaction here if it was started here. This is to eliminate a
 | 
						|
	dangling transaction. If the user had AUTOCOMMIT=0, then SHOW
 | 
						|
	TABLE STATUS does leave a dangling transaction if the user does not
 | 
						|
	himself call COMMIT. */
 | 
						|
 | 
						|
	if (trx_was_not_started) {
 | 
						|
 | 
						|
		innobase_commit_low(prebuilt->trx);
 | 
						|
	}
 | 
						|
 | 
						|
 	return(error);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
This function initializes the auto-inc counter if it has not been
 | 
						|
initialized yet. This function does not change the value of the auto-inc
 | 
						|
counter if it already has been initialized. Returns the value of the
 | 
						|
auto-inc counter. */
 | 
						|
 | 
						|
ulonglong
 | 
						|
ha_innobase::get_auto_increment()
 | 
						|
/*=============================*/
 | 
						|
                         /* out: auto-increment column value, -1 if error
 | 
						|
                         (deadlock or lock wait timeout) */
 | 
						|
{
 | 
						|
  	longlong        nr;
 | 
						|
  	int     	error;
 | 
						|
 | 
						|
	error = innobase_read_and_init_auto_inc(&nr);
 | 
						|
 | 
						|
	if (error) {
 | 
						|
		/* This should never happen in the current (5.0.6) code, since
 | 
						|
		we call this function only after the counter has been
 | 
						|
		initialized. */
 | 
						|
 | 
						|
		ut_print_timestamp(stderr);
 | 
						|
		sql_print_error("Error %lu in ::get_auto_increment()",
 | 
						|
				(ulong) error);
 | 
						|
          	return(~(ulonglong) 0);
 | 
						|
	}
 | 
						|
 | 
						|
	return((ulonglong) nr);
 | 
						|
}
 | 
						|
 | 
						|
/* See comment in handler.h */
 | 
						|
int
 | 
						|
ha_innobase::reset_auto_increment(ulonglong value)
 | 
						|
{
 | 
						|
	DBUG_ENTER("ha_innobase::reset_auto_increment");
 | 
						|
 | 
						|
	row_prebuilt_t* prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
  	int     	error;
 | 
						|
 | 
						|
	error = row_lock_table_autoinc_for_mysql(prebuilt);
 | 
						|
 | 
						|
	if (error != DB_SUCCESS) {
 | 
						|
		error = convert_error_code_to_mysql(error, user_thd);
 | 
						|
 | 
						|
		DBUG_RETURN(error);
 | 
						|
	}
 | 
						|
 | 
						|
	dict_table_autoinc_initialize(prebuilt->table, value);
 | 
						|
 | 
						|
	DBUG_RETURN(0);
 | 
						|
}
 | 
						|
 | 
						|
/* See comment in handler.cc */
 | 
						|
bool
 | 
						|
ha_innobase::get_error_message(int error, String *buf)
 | 
						|
{
 | 
						|
	trx_t*	    trx = check_trx_exists(current_thd);
 | 
						|
 | 
						|
	buf->copy(trx->detailed_error, strlen(trx->detailed_error),
 | 
						|
		system_charset_info);
 | 
						|
 | 
						|
	return FALSE;
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Compares two 'refs'. A 'ref' is the (internal) primary key value of the row.
 | 
						|
If there is no explicitly declared non-null unique key or a primary key, then
 | 
						|
InnoDB internally uses the row id as the primary key. */
 | 
						|
 | 
						|
int
 | 
						|
ha_innobase::cmp_ref(
 | 
						|
/*=================*/
 | 
						|
				/* out: < 0 if ref1 < ref2, 0 if equal, else
 | 
						|
				> 0 */
 | 
						|
	const mysql_byte* ref1,	/* in: an (internal) primary key value in the
 | 
						|
				MySQL key value format */
 | 
						|
	const mysql_byte* ref2)	/* in: an (internal) primary key value in the
 | 
						|
				MySQL key value format */
 | 
						|
{
 | 
						|
	row_prebuilt_t*	prebuilt = (row_prebuilt_t*) innobase_prebuilt;
 | 
						|
	enum_field_types mysql_type;
 | 
						|
	Field*		field;
 | 
						|
	KEY_PART_INFO*	key_part;
 | 
						|
	KEY_PART_INFO*	key_part_end;
 | 
						|
	uint		len1;
 | 
						|
	uint		len2;
 | 
						|
	int 		result;
 | 
						|
 | 
						|
	if (prebuilt->clust_index_was_generated) {
 | 
						|
		/* The 'ref' is an InnoDB row id */
 | 
						|
 | 
						|
		return(memcmp(ref1, ref2, DATA_ROW_ID_LEN));
 | 
						|
	}
 | 
						|
 | 
						|
	/* Do a type-aware comparison of primary key fields. PK fields
 | 
						|
	are always NOT NULL, so no checks for NULL are performed. */
 | 
						|
 | 
						|
	key_part = table->key_info[table->s->primary_key].key_part;
 | 
						|
 | 
						|
	key_part_end = key_part
 | 
						|
			+ table->key_info[table->s->primary_key].key_parts;
 | 
						|
 | 
						|
	for (; key_part != key_part_end; ++key_part) {
 | 
						|
		field = key_part->field;
 | 
						|
		mysql_type = field->type();
 | 
						|
 | 
						|
		if (mysql_type == FIELD_TYPE_TINY_BLOB
 | 
						|
		    || mysql_type == FIELD_TYPE_MEDIUM_BLOB
 | 
						|
		    || mysql_type == FIELD_TYPE_BLOB
 | 
						|
		    || mysql_type == FIELD_TYPE_LONG_BLOB) {
 | 
						|
 | 
						|
			/* In the MySQL key value format, a column prefix of
 | 
						|
			a BLOB is preceded by a 2-byte length field */
 | 
						|
 | 
						|
			len1 = innobase_read_from_2_little_endian(ref1);
 | 
						|
			len2 = innobase_read_from_2_little_endian(ref2);
 | 
						|
 | 
						|
			ref1 += 2;
 | 
						|
			ref2 += 2;
 | 
						|
			result = ((Field_blob*)field)->cmp(
 | 
						|
						    (const char*)ref1, len1,
 | 
						|
			                            (const char*)ref2, len2);
 | 
						|
		} else {
 | 
						|
			result = field->key_cmp(ref1, ref2);
 | 
						|
		}
 | 
						|
 | 
						|
		if (result) {
 | 
						|
 | 
						|
			return(result);
 | 
						|
		}
 | 
						|
 | 
						|
		ref1 += key_part->store_length;
 | 
						|
		ref2 += key_part->store_length;
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
 | 
						|
char*
 | 
						|
ha_innobase::get_mysql_bin_log_name()
 | 
						|
{
 | 
						|
	return(trx_sys_mysql_bin_log_name);
 | 
						|
}
 | 
						|
 | 
						|
ulonglong
 | 
						|
ha_innobase::get_mysql_bin_log_pos()
 | 
						|
{
 | 
						|
  	/* trx... is ib_longlong, which is a typedef for a 64-bit integer
 | 
						|
	(__int64 or longlong) so it's ok to cast it to ulonglong. */
 | 
						|
 | 
						|
  	return(trx_sys_mysql_bin_log_pos);
 | 
						|
}
 | 
						|
 | 
						|
extern "C" {
 | 
						|
/**********************************************************************
 | 
						|
This function is used to find the storage length in bytes of the first n
 | 
						|
characters for prefix indexes using a multibyte character set. The function
 | 
						|
finds charset information and returns length of prefix_len characters in the
 | 
						|
index field in bytes.
 | 
						|
 | 
						|
NOTE: the prototype of this function is copied to data0type.c! If you change
 | 
						|
this function, you MUST change also data0type.c! */
 | 
						|
 | 
						|
ulint
 | 
						|
innobase_get_at_most_n_mbchars(
 | 
						|
/*===========================*/
 | 
						|
				/* out: number of bytes occupied by the first
 | 
						|
				n characters */
 | 
						|
	ulint charset_id,	/* in: character set id */
 | 
						|
	ulint prefix_len,	/* in: prefix length in bytes of the index
 | 
						|
				(this has to be divided by mbmaxlen to get the
 | 
						|
				number of CHARACTERS n in the prefix) */
 | 
						|
	ulint data_len,         /* in: length of the string in bytes */
 | 
						|
	const char* str)	/* in: character string */
 | 
						|
{
 | 
						|
	ulint char_length;	/* character length in bytes */
 | 
						|
	ulint n_chars;		/* number of characters in prefix */
 | 
						|
	CHARSET_INFO* charset;	/* charset used in the field */
 | 
						|
 | 
						|
	charset = get_charset((uint) charset_id, MYF(MY_WME));
 | 
						|
 | 
						|
	ut_ad(charset);
 | 
						|
	ut_ad(charset->mbmaxlen);
 | 
						|
 | 
						|
	/* Calculate how many characters at most the prefix index contains */
 | 
						|
 | 
						|
	n_chars = prefix_len / charset->mbmaxlen;
 | 
						|
 | 
						|
	/* If the charset is multi-byte, then we must find the length of the
 | 
						|
	first at most n chars in the string. If the string contains less
 | 
						|
	characters than n, then we return the length to the end of the last
 | 
						|
	character. */
 | 
						|
 | 
						|
	if (charset->mbmaxlen > 1) {
 | 
						|
		/* my_charpos() returns the byte length of the first n_chars
 | 
						|
		characters, or a value bigger than the length of str, if
 | 
						|
		there were not enough full characters in str.
 | 
						|
 | 
						|
		Why does the code below work:
 | 
						|
		Suppose that we are looking for n UTF-8 characters.
 | 
						|
 | 
						|
		1) If the string is long enough, then the prefix contains at
 | 
						|
		least n complete UTF-8 characters + maybe some extra
 | 
						|
		characters + an incomplete UTF-8 character. No problem in
 | 
						|
		this case. The function returns the pointer to the
 | 
						|
		end of the nth character.
 | 
						|
 | 
						|
		2) If the string is not long enough, then the string contains
 | 
						|
		the complete value of a column, that is, only complete UTF-8
 | 
						|
		characters, and we can store in the column prefix index the
 | 
						|
		whole string. */
 | 
						|
 | 
						|
		char_length = my_charpos(charset, str,
 | 
						|
						str + data_len, (int) n_chars);
 | 
						|
		if (char_length > data_len) {
 | 
						|
			char_length = data_len;
 | 
						|
		}
 | 
						|
	} else {
 | 
						|
		if (data_len < prefix_len) {
 | 
						|
			char_length = data_len;
 | 
						|
		} else {
 | 
						|
			char_length = prefix_len;
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return(char_length);
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
extern "C" {
 | 
						|
/**********************************************************************
 | 
						|
This function returns true if
 | 
						|
 | 
						|
1) SQL-query in the current thread
 | 
						|
is either REPLACE or LOAD DATA INFILE REPLACE.
 | 
						|
 | 
						|
2) SQL-query in the current thread
 | 
						|
is INSERT ON DUPLICATE KEY UPDATE.
 | 
						|
 | 
						|
NOTE that /mysql/innobase/row/row0ins.c must contain the
 | 
						|
prototype for this function ! */
 | 
						|
 | 
						|
ibool
 | 
						|
innobase_query_is_update(void)
 | 
						|
/*==========================*/
 | 
						|
{
 | 
						|
	THD*	thd;
 | 
						|
 | 
						|
	thd = (THD *)innobase_current_thd();
 | 
						|
 | 
						|
	if (thd->lex->sql_command == SQLCOM_REPLACE ||
 | 
						|
	    thd->lex->sql_command == SQLCOM_REPLACE_SELECT ||
 | 
						|
	    (thd->lex->sql_command == SQLCOM_LOAD &&
 | 
						|
	     thd->lex->duplicates == DUP_REPLACE)) {
 | 
						|
 | 
						|
		return(1);
 | 
						|
	}
 | 
						|
 | 
						|
	if (thd->lex->sql_command == SQLCOM_INSERT &&
 | 
						|
	    thd->lex->duplicates  == DUP_UPDATE) {
 | 
						|
 | 
						|
		return(1);
 | 
						|
	}
 | 
						|
 | 
						|
	return(0);
 | 
						|
}
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
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 = check_trx_exists(thd);
 | 
						|
 | 
						|
        if (thd->lex->sql_command != SQLCOM_XA_PREPARE) {
 | 
						|
 | 
						|
                /* For ibbackup to work the order of transactions in binlog
 | 
						|
                and InnoDB must be the same. Consider the situation
 | 
						|
 | 
						|
                  thread1> prepare; write to binlog; ...
 | 
						|
                          <context switch>
 | 
						|
                  thread2> prepare; write to binlog; commit
 | 
						|
                  thread1>                           ... commit
 | 
						|
 | 
						|
                To ensure this will not happen we're taking the mutex on
 | 
						|
                prepare, and releasing it on commit.
 | 
						|
 | 
						|
                Note: only do it for normal commits, done via ha_commit_trans.
 | 
						|
                If 2pc protocol is executed by external transaction
 | 
						|
                coordinator, it will be just a regular MySQL client
 | 
						|
                executing XA PREPARE and XA COMMIT commands.
 | 
						|
                In this case we cannot know how many minutes or hours
 | 
						|
                will be between XA PREPARE and XA COMMIT, and we don't want
 | 
						|
                to block for undefined period of time.
 | 
						|
                */
 | 
						|
                pthread_mutex_lock(&prepare_commit_mutex);
 | 
						|
                trx->active_trans = 2;
 | 
						|
        }
 | 
						|
 | 
						|
	if (!thd->variables.innodb_support_xa) {
 | 
						|
 | 
						|
		return(0);
 | 
						|
	}
 | 
						|
 | 
						|
        trx->xid=thd->transaction.xid_state.xid;
 | 
						|
 | 
						|
	/* 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) {
 | 
						|
 | 
						|
	  sql_print_error("trx->active_trans == 0, but trx->conc_state != "
 | 
						|
			  "TRX_NOT_STARTED");
 | 
						|
	}
 | 
						|
 | 
						|
	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 */
 | 
						|
 | 
						|
                ut_ad(trx->active_trans);
 | 
						|
 | 
						|
		error = (int) 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 identification */
 | 
						|
{
 | 
						|
	trx_t*	trx;
 | 
						|
 | 
						|
	trx = trx_get_trx_by_xid(xid);
 | 
						|
 | 
						|
	if (trx) {
 | 
						|
		return(innobase_rollback_trx(trx));
 | 
						|
	} else {
 | 
						|
		return(XAER_NOTA);
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Create a consistent view for a cursor based on current transaction
 | 
						|
which is created if the corresponding MySQL thread still lacks one.
 | 
						|
This consistent view is then used inside of MySQL when accessing records
 | 
						|
using a cursor. */
 | 
						|
 | 
						|
void*
 | 
						|
innobase_create_cursor_view(void)
 | 
						|
/*=============================*/
 | 
						|
			/* out: Pointer to cursor view or NULL */
 | 
						|
{
 | 
						|
	return(read_cursor_view_create_for_mysql(
 | 
						|
					check_trx_exists(current_thd)));
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Close the given consistent cursor view of a transaction and restore
 | 
						|
global read view to a transaction read view. Transaction is created if the
 | 
						|
corresponding MySQL thread still lacks one. */
 | 
						|
 | 
						|
void
 | 
						|
innobase_close_cursor_view(
 | 
						|
/*=======================*/
 | 
						|
	void*	curview)/* in: Consistent read view to be closed */
 | 
						|
{
 | 
						|
	read_cursor_view_close_for_mysql(check_trx_exists(current_thd),
 | 
						|
						(cursor_view_t*) curview);
 | 
						|
}
 | 
						|
 | 
						|
/***********************************************************************
 | 
						|
Set the given consistent cursor view to a transaction which is created
 | 
						|
if the corresponding MySQL thread still lacks one. If the given
 | 
						|
consistent cursor view is NULL global read view of a transaction is
 | 
						|
restored to a transaction read view. */
 | 
						|
 | 
						|
void
 | 
						|
innobase_set_cursor_view(
 | 
						|
/*=====================*/
 | 
						|
	void*	curview)/* in: Consistent cursor view to be set */
 | 
						|
{
 | 
						|
	read_cursor_set_for_mysql(check_trx_exists(current_thd),
 | 
						|
						(cursor_view_t*) curview);
 | 
						|
}
 | 
						|
 | 
						|
#endif /* HAVE_INNOBASE_DB */
 |